diff options
Diffstat (limited to 'components/canvas/webgl_thread.rs')
-rw-r--r-- | components/canvas/webgl_thread.rs | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/components/canvas/webgl_thread.rs b/components/canvas/webgl_thread.rs index 93134dd7487..2add67cfd2a 100644 --- a/components/canvas/webgl_thread.rs +++ b/components/canvas/webgl_thread.rs @@ -9,7 +9,9 @@ use euclid::Size2D; use fnv::FnvHashMap; use gleam::gl; use half::f16; -use offscreen_gl_context::{GLContext, GLContextAttributes, GLLimits, NativeGLContextMethods}; +use offscreen_gl_context::{ + DrawBuffer, GLContext, GLContextAttributes, GLLimits, NativeGLContextMethods, +}; use pixels::{self, PixelFormat}; use std::borrow::Cow; use std::thread; @@ -228,6 +230,7 @@ impl<VR: WebVRRenderHandler + 'static> WebGLThread<VR> { Self::make_current_if_needed(context_id, &self.contexts, &mut self.bound_context_id) .expect("WebGLContext not found in a WebGLMsg::Lock message"); let info = self.cached_context_info.get_mut(&context_id).unwrap(); + info.render_state = ContextRenderState::Locked(None); // Insert a OpenGL Fence sync object that sends a signal when all the WebGL commands are finished. // The related gl().wait_sync call is performed in the WR thread. See WebGLExternalImageApi for mor details. let gl_sync = data.ctx.gl().fence_sync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0); @@ -247,6 +250,7 @@ impl<VR: WebVRRenderHandler + 'static> WebGLThread<VR> { Self::make_current_if_needed(context_id, &self.contexts, &mut self.bound_context_id) .expect("WebGLContext not found in a WebGLMsg::Unlock message"); let info = self.cached_context_info.get_mut(&context_id).unwrap(); + info.render_state = ContextRenderState::Unlocked; if let Some(gl_sync) = info.gl_sync.take() { // Release the GLSync object. data.ctx.gl().delete_sync(gl_sync); @@ -299,6 +303,7 @@ impl<VR: WebVRRenderHandler + 'static> WebGLThread<VR> { image_key: None, share_mode, gl_sync: None, + render_state: ContextRenderState::Unlocked, }, ); @@ -319,9 +324,19 @@ impl<VR: WebVRRenderHandler + 'static> WebGLThread<VR> { ) .expect("Missing WebGL context!"); match data.ctx.resize(size) { - Ok(_) => { + Ok(old_draw_buffer) => { let (real_size, texture_id, _) = data.ctx.get_info(); let info = self.cached_context_info.get_mut(&context_id).unwrap(); + if let ContextRenderState::Locked(ref mut in_use) = info.render_state { + // If there's already an outdated draw buffer present, we can ignore + // the newly resized one since it's not in use by the renderer. + if in_use.is_none() { + // We're resizing the context while WR is actively rendering + // it, so we need to retain the GL resources until WR is + // finished with them. + *in_use = Some(old_draw_buffer); + } + } // Update webgl texture size. Texture id may change too. info.texture_id = texture_id; info.size = real_size; @@ -682,6 +697,14 @@ impl<VR: WebVRRenderHandler + 'static> Drop for WebGLThread<VR> { } } +enum ContextRenderState { + /// The context is not being actively rendered. + Unlocked, + /// The context is actively being rendered. If a DrawBuffer value is present, + /// it is outdated but in use as long as the context is locked. + Locked(Option<DrawBuffer>), +} + /// Helper struct to store cached WebGLContext information. struct WebGLContextInfo { /// Render to texture identifier used by the WebGLContext. @@ -696,6 +719,8 @@ struct WebGLContextInfo { share_mode: WebGLContextShareMode, /// GLSync Object used for a correct synchronization with Webrender external image callbacks. gl_sync: Option<gl::GLsync>, + /// The status of this context with respect to external consumers. + render_state: ContextRenderState, } /// This trait is used as a bridge between the `WebGLThreads` implementation and |