diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index ce202d1ea..6244840b1 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -10,6 +10,20 @@ use crate::state::State; use crate::utils::uuid_from_u32_quartet; static mut STATE: Option> = None; +extern "C" { + fn emscripten_GetProcAddress( + name: *const ::std::os::raw::c_char, + ) -> *const ::std::os::raw::c_void; +} + +fn init_gl() { + unsafe { + gl::load_with(|addr| { + let addr = std::ffi::CString::new(addr).unwrap(); + emscripten_GetProcAddress(addr.into_raw() as *const _) as *const _ + }); + } +} /// This is called from JS after the WebGL context has been created. #[no_mangle] @@ -25,8 +39,7 @@ pub extern "C" fn init(width: i32, height: i32) { #[no_mangle] pub unsafe extern "C" fn resize_surface(width: i32, height: i32) { let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); - let surface = render::create_surface(&mut state.render_state.gpu_state, width, height); - state.set_surface(surface); + state.render_state.resize(width, height); } #[no_mangle] @@ -137,5 +150,5 @@ pub extern "C" fn set_shape_blend_mode(mode: i32) { } fn main() { - render::init_gl(); + init_gl(); } diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 9dc0b6bcf..fab6878a2 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -5,76 +5,69 @@ use uuid::Uuid; use crate::shapes::Shape; use crate::state::State; -extern "C" { - pub fn emscripten_GetProcAddress( - name: *const ::std::os::raw::c_char, - ) -> *const ::std::os::raw::c_void; -} - -pub(crate) struct GpuState { +struct GpuState { pub context: DirectContext, framebuffer_info: FramebufferInfo, } +impl GpuState { + fn new() -> Self { + let interface = skia_safe::gpu::gl::Interface::new_native().unwrap(); + let context = skia_safe::gpu::direct_contexts::make_gl(interface, None).unwrap(); + let framebuffer_info = { + let mut fboid: gl::types::GLint = 0; + unsafe { gl::GetIntegerv(gl::FRAMEBUFFER_BINDING, &mut fboid) }; + + FramebufferInfo { + fboid: fboid.try_into().unwrap(), + format: skia_safe::gpu::gl::Format::RGBA8.into(), + protected: skia_safe::gpu::Protected::No, + } + }; + + GpuState { + context, + framebuffer_info, + } + } + + /// Create a Skia surface that will be used for rendering. + fn create_surface(&mut self, width: i32, height: i32) -> skia::Surface { + let backend_render_target = + gpu::backend_render_targets::make_gl((width, height), 1, 8, self.framebuffer_info); + + gpu::surfaces::wrap_backend_render_target( + &mut self.context, + &backend_render_target, + skia_safe::gpu::SurfaceOrigin::BottomLeft, + skia_safe::ColorType::RGBA8888, + None, + None, + ) + .unwrap() + } +} + pub(crate) struct RenderState { - pub gpu_state: GpuState, + gpu_state: GpuState, pub surface: skia::Surface, } impl RenderState { pub fn new(width: i32, height: i32) -> RenderState { - let mut gpu_state = create_gpu_state(); - let surface = create_surface(&mut gpu_state, width, height); + // This needs to be done once per WebGL context. + let mut gpu_state = GpuState::new(); + let surface = gpu_state.create_surface(width, height); + RenderState { gpu_state, surface } } -} -pub(crate) fn init_gl() { - unsafe { - gl::load_with(|addr| { - let addr = std::ffi::CString::new(addr).unwrap(); - emscripten_GetProcAddress(addr.into_raw() as *const _) as *const _ - }); + pub fn resize(&mut self, width: i32, height: i32) { + let surface = self.gpu_state.create_surface(width, height); + self.surface = surface; } } -/// This needs to be done once per WebGL context. -pub(crate) fn create_gpu_state() -> GpuState { - let interface = skia_safe::gpu::gl::Interface::new_native().unwrap(); - let context = skia_safe::gpu::direct_contexts::make_gl(interface, None).unwrap(); - let framebuffer_info = { - let mut fboid: gl::types::GLint = 0; - unsafe { gl::GetIntegerv(gl::FRAMEBUFFER_BINDING, &mut fboid) }; - - FramebufferInfo { - fboid: fboid.try_into().unwrap(), - format: skia_safe::gpu::gl::Format::RGBA8.into(), - protected: skia_safe::gpu::Protected::No, - } - }; - - GpuState { - context, - framebuffer_info, - } -} - -/// Create the Skia surface that will be used for rendering. -pub(crate) fn create_surface(gpu_state: &mut GpuState, width: i32, height: i32) -> skia::Surface { - let backend_render_target = - gpu::backend_render_targets::make_gl((width, height), 1, 8, gpu_state.framebuffer_info); - - gpu::surfaces::wrap_backend_render_target( - &mut gpu_state.context, - &backend_render_target, - skia_safe::gpu::SurfaceOrigin::BottomLeft, - skia_safe::ColorType::RGBA8888, - None, - None, - ) - .unwrap() -} - pub(crate) fn flush(state: &mut State) { state .render_state diff --git a/render-wasm/src/state.rs b/render-wasm/src/state.rs index 90f0b3656..3672f40cf 100644 --- a/render-wasm/src/state.rs +++ b/render-wasm/src/state.rs @@ -27,10 +27,6 @@ impl<'a> State<'a> { } } - pub fn set_surface(&mut self, surface: skia::Surface) { - self.render_state.surface = surface; - } - pub fn use_shape(&'a mut self, id: Uuid) { if !self.shapes.contains_key(&id) { let new_shape = Shape::new(id);