aboutsummaryrefslogtreecommitdiffstats
path: root/components/canvas/webgl_thread.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/canvas/webgl_thread.rs')
-rw-r--r--components/canvas/webgl_thread.rs29
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