Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[gl] Add Instance struct in web version to align API with other backends. #3506

Merged
merged 2 commits into from
Dec 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 20 additions & 32 deletions examples/quad/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,48 +102,36 @@ fn main() {
.with_title("quad".to_string());

// instantiate backend
#[cfg(not(target_arch = "wasm32"))]
let (_window, instance, mut adapters, surface) = {
let window = wb.build(&event_loop).unwrap();
let instance =
back::Instance::create("gfx-rs quad", 1).expect("Failed to create an instance!");
let adapters = instance.enumerate_adapters();
let surface = unsafe {
instance
.create_surface(&window)
.expect("Failed to create a surface!")
};
// Return `window` so it is not dropped: dropping it invalidates `surface`.
(window, Some(instance), adapters, surface)
};
let window = wb.build(&event_loop).unwrap();

#[cfg(target_arch = "wasm32")]
let (_window, instance, mut adapters, surface) = {
let (window, surface) = {
let window = wb.build(&event_loop).unwrap();
web_sys::window()
.unwrap()
.document()
.unwrap()
.body()
.unwrap()
.append_child(&winit::platform::web::WindowExtWebSys::canvas(&window))
.unwrap();
let surface = back::Surface::from_raw_handle(&window);
(window, surface)
};

let adapters = surface.enumerate_adapters();
(window, None, adapters, surface)
web_sys::window()
.unwrap()
.document()
.unwrap()
.body()
.unwrap()
.append_child(&winit::platform::web::WindowExtWebSys::canvas(&window))
.unwrap();

let instance =
back::Instance::create("gfx-rs quad", 1).expect("Failed to create an instance!");

let surface = unsafe {
instance
.create_surface(&window)
.expect("Failed to create a surface!")
};

let mut adapters = instance.enumerate_adapters();

for adapter in &adapters {
println!("{:?}", adapter.info);
}

let adapter = adapters.remove(0);

let mut renderer = Renderer::new(instance, surface, adapter);
let mut renderer = Renderer::new(Some(instance), surface, adapter);

renderer.render();

Expand Down
8 changes: 2 additions & 6 deletions src/backend/gl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ mod window;

// Web implementation
#[cfg(target_arch = "wasm32")]
pub use window::web::{Surface, Swapchain};
pub use window::web::{Instance, Surface, Swapchain};

#[cfg(not(target_arch = "wasm32"))]
pub use crate::window::egl::{Instance, Surface, Swapchain};
pub use window::egl::{Instance, Surface, Swapchain};

pub use glow::Context as GlContext;
use glow::HasContext;
Expand Down Expand Up @@ -101,12 +101,8 @@ impl Deref for GlContainer {
pub enum Backend {}

impl hal::Backend for Backend {
#[cfg(not(target_arch = "wasm32"))]
type Instance = Instance;

#[cfg(target_arch = "wasm32")]
type Instance = Surface;

type PhysicalDevice = PhysicalDevice;
type Device = Device;
type Surface = Surface;
Expand Down
104 changes: 59 additions & 45 deletions src/backend/gl/src/window/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use crate::{
use arrayvec::ArrayVec;
use glow::HasContext;
use hal::{adapter::Adapter, format as f, image, window};
use std::iter;
use parking_lot::Mutex;
use std::{iter, sync::Arc};
use wasm_bindgen::JsCast;

#[derive(Clone, Debug)]
Expand All @@ -15,38 +16,74 @@ pub struct Swapchain {
pub(crate) frame_buffers: ArrayVec<[native::RawFrameBuffer; 3]>,
}

#[derive(Clone, Debug)]
pub struct Surface {
canvas: Starc<web_sys::HtmlCanvasElement>,
pub(crate) swapchain: Option<Swapchain>,
renderbuffer: Option<native::Renderbuffer>,
#[derive(Debug)]
pub struct Instance {
canvas: Mutex<Option<Starc<web_sys::HtmlCanvasElement>>>,
}

impl Surface {
pub fn from_canvas(canvas: web_sys::HtmlCanvasElement) -> Self {
Surface {
canvas: Starc::new(canvas),
swapchain: None,
renderbuffer: None,
impl hal::Instance<B> for Instance {
fn create(_name: &str, _version: u32) -> Result<Self, hal::UnsupportedBackend> {
Ok(Instance {
canvas: Mutex::new(None),
})
}

fn enumerate_adapters(&self) -> Vec<Adapter<B>> {
if let Some(canvas) = self.canvas.lock().as_ref() {
let adapter = PhysicalDevice::new_adapter(GlContainer::from_canvas(canvas));
vec![adapter]
} else {
vec![]
}
}

pub fn from_raw_handle(has_handle: &impl raw_window_handle::HasRawWindowHandle) -> Self {
unsafe fn create_surface(
&self,
has_handle: &impl raw_window_handle::HasRawWindowHandle,
) -> Result<Surface, window::InitError> {
if let raw_window_handle::RawWindowHandle::Web(handle) = has_handle.raw_window_handle() {
let canvas = web_sys::window()
.and_then(|win| win.document())
.expect("Cannot get document")
.query_selector(&format!("canvas[data-raw-handle=\"{}\"]", handle.id))
.expect("Cannot query for canvas")
.expect("Canvas is not found")
.dyn_into()
.expect("Failed to downcast to canvas type");
Self::from_canvas(canvas)
let canvas: Starc<web_sys::HtmlCanvasElement> = Starc::new(
web_sys::window()
.and_then(|win| win.document())
.expect("Cannot get document")
.query_selector(&format!("canvas[data-raw-handle=\"{}\"]", handle.id))
.expect("Cannot query for canvas")
.expect("Canvas is not found")
.dyn_into()
.expect("Failed to downcast to canvas type"),
);

*self.canvas.lock() = Some(canvas.clone());

Ok(Surface {
canvas,
swapchain: None,
renderbuffer: None,
})
} else {
unreachable!()
}
}

unsafe fn destroy_surface(&self, surface: Surface) {
let mut canvas_option_ref = self.canvas.lock();

if let Some(canvas) = canvas_option_ref.as_ref() {
if Arc::ptr_eq(&canvas.arc, &surface.canvas.arc) {
*canvas_option_ref = None;
}
}
}
}

#[derive(Clone, Debug)]
pub struct Surface {
canvas: Starc<web_sys::HtmlCanvasElement>,
pub(crate) swapchain: Option<Swapchain>,
renderbuffer: Option<native::Renderbuffer>,
}

impl Surface {
fn swapchain_formats(&self) -> Vec<f::Format> {
vec![f::Format::Rgba8Unorm, f::Format::Bgra8Unorm]
}
Expand Down Expand Up @@ -175,26 +212,3 @@ impl window::PresentationSurface<B> for Surface {
Ok((swapchain_image, None))
}
}

impl hal::Instance<B> for Surface {
fn create(_name: &str, _version: u32) -> Result<Self, hal::UnsupportedBackend> {
unimplemented!()
}

fn enumerate_adapters(&self) -> Vec<Adapter<B>> {
// TODO: Move to `self` like native/window
let adapter = PhysicalDevice::new_adapter(GlContainer::from_canvas(&self.canvas));
vec![adapter]
}

unsafe fn create_surface(
&self,
_: &impl raw_window_handle::HasRawWindowHandle,
) -> Result<Surface, window::InitError> {
unimplemented!()
}

unsafe fn destroy_surface(&self, _surface: Surface) {
// TODO: Implement Surface cleanup
}
}