diff options
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/bindings/trace.rs | 5 | ||||
-rw-r--r-- | components/script/dom/document.rs | 22 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 46 | ||||
-rw-r--r-- | components/script/dom/window.rs | 7 |
4 files changed, 46 insertions, 34 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 5fbc9629f68..e86c96e0a9e 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -48,7 +48,9 @@ use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, use canvas_traits::webgl::WebGLVertexArrayId; use canvas_traits::webgl::{ActiveAttribInfo, ActiveUniformInfo, GlType, TexDataType, TexFormat}; use canvas_traits::webgl::{GLFormats, GLLimits, WebGLQueryId, WebGLSamplerId}; -use canvas_traits::webgl::{WebGLBufferId, WebGLChan, WebGLContextShareMode, WebGLError}; +use canvas_traits::webgl::{ + WebGLBufferId, WebGLChan, WebGLContextId, WebGLContextShareMode, WebGLError, +}; use canvas_traits::webgl::{WebGLFramebufferId, WebGLMsgSender, WebGLPipeline, WebGLProgramId}; use canvas_traits::webgl::{WebGLReceiver, WebGLRenderbufferId, WebGLSLVersion, WebGLSender}; use canvas_traits::webgl::{WebGLShaderId, WebGLSyncId, WebGLTextureId, WebGLVersion}; @@ -519,6 +521,7 @@ unsafe_no_jsmanaged_fields!(Rect<f32>); unsafe_no_jsmanaged_fields!(CascadeData); unsafe_no_jsmanaged_fields!(WindowGLContext); unsafe_no_jsmanaged_fields!(Frame); +unsafe_no_jsmanaged_fields!(WebGLContextId); unsafe impl<'a> JSTraceable for &'a str { #[inline] diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index da44169ce59..452212a2b3c 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -109,6 +109,7 @@ use crate::stylesheet_set::StylesheetSetRef; use crate::task::TaskBox; use crate::task_source::{TaskSource, TaskSourceName}; use crate::timers::OneshotTimerCallback; +use canvas_traits::webgl::{self, WebGLContextId, WebGLMsg}; use cookie::Cookie; use devtools_traits::ScriptToDevtoolsControlMsg; use dom_struct::dom_struct; @@ -395,6 +396,8 @@ pub struct Document { /// where `id` needs to match any of the registered ShadowRoots /// hosting the media controls UI. media_controls: DomRefCell<HashMap<String, Dom<ShadowRoot>>>, + /// List of all WebGL context IDs that need flushing. + dirty_webgl_contexts: DomRefCell<HashSet<WebGLContextId>>, } #[derive(JSTraceable, MallocSizeOf)] @@ -2490,6 +2493,24 @@ impl Document { debug_assert!(false, "Trying to unregister unknown media controls"); } } + + pub fn add_dirty_canvas(&self, context_id: WebGLContextId) { + self.dirty_webgl_contexts.borrow_mut().insert(context_id); + } + + pub fn flush_dirty_canvases(&self) { + let dirty_context_ids: Vec<_> = self.dirty_webgl_contexts.borrow_mut().drain().collect(); + if dirty_context_ids.is_empty() { + return; + } + let (sender, receiver) = webgl::webgl_channel().unwrap(); + self.window + .webgl_chan() + .expect("Where's the WebGL channel?") + .send(WebGLMsg::SwapBuffers(dirty_context_ids, sender)) + .unwrap(); + receiver.recv().unwrap(); + } } #[derive(MallocSizeOf, PartialEq)] @@ -2784,6 +2805,7 @@ impl Document { shadow_roots: DomRefCell::new(HashSet::new()), shadow_roots_styles_changed: Cell::new(false), media_controls: DomRefCell::new(HashMap::new()), + dirty_webgl_contexts: DomRefCell::new(HashSet::new()), } } diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 06141d5b5e7..f19664ad0ad 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -81,7 +81,6 @@ use std::cell::Cell; use std::cmp; use std::ptr::{self, NonNull}; use std::rc::Rc; -use webrender_api::ImageKey; // From the GLES 2.0.25 spec, page 85: // @@ -130,7 +129,7 @@ pub struct WebGLRenderingContext { #[ignore_malloc_size_of = "Channels are hard"] webgl_sender: WebGLMessageSender, #[ignore_malloc_size_of = "Defined in webrender"] - webrender_image: Cell<Option<webrender_api::ImageKey>>, + webrender_image: webrender_api::ImageKey, share_mode: WebGLContextShareMode, webgl_version: WebGLVersion, glsl_version: WebGLSLVersion, @@ -195,7 +194,7 @@ impl WebGLRenderingContext { ctx_data.sender, window.get_event_loop_waker(), ), - webrender_image: Cell::new(None), + webrender_image: ctx_data.image_key, share_mode: ctx_data.share_mode, webgl_version, glsl_version: ctx_data.glsl_version, @@ -453,13 +452,17 @@ impl WebGLRenderingContext { } fn mark_as_dirty(&self) { - // If we don't have a bound framebuffer, then don't mark the canvas - // as dirty. - if self.bound_framebuffer.get().is_none() { - self.canvas - .upcast::<Node>() - .dirty(NodeDamage::OtherNodeDamage); + // If we have a bound framebuffer, then don't mark the canvas as dirty. + if self.bound_framebuffer.get().is_some() { + return; } + + self.canvas + .upcast::<Node>() + .dirty(NodeDamage::OtherNodeDamage); + + let document = document_from_node(&*self.canvas); + document.add_dirty_canvas(self.context_id()); } fn vertex_attrib(&self, indx: u32, x: f32, y: f32, z: f32, w: f32) { @@ -808,26 +811,7 @@ impl WebGLRenderingContext { } pub fn layout_handle(&self) -> webrender_api::ImageKey { - match self.share_mode { - WebGLContextShareMode::SharedTexture => { - // WR using ExternalTexture requires a single update message. - self.webrender_image.get().unwrap_or_else(|| { - let (sender, receiver) = webgl_channel().unwrap(); - self.webgl_sender.send_update_wr_image(sender).unwrap(); - let image_key = receiver.recv().unwrap(); - self.webrender_image.set(Some(image_key)); - - image_key - }) - }, - WebGLContextShareMode::Readback => { - // WR using Readback requires to update WR image every frame - // in order to send the new raw pixels. - let (sender, receiver) = webgl_channel().unwrap(); - self.webgl_sender.send_update_wr_image(sender).unwrap(); - receiver.recv().unwrap() - }, - } + self.webrender_image } // https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/ @@ -4438,10 +4422,6 @@ impl WebGLMessageSender { self.wake_after_send(|| self.sender.send_remove()) } - pub fn send_update_wr_image(&self, sender: WebGLSender<ImageKey>) -> WebGLSendResult { - self.wake_after_send(|| self.sender.send_update_wr_image(sender)) - } - pub fn send_dom_to_texture(&self, command: DOMToTextureCommand) -> WebGLSendResult { self.wake_after_send(|| self.sender.send_dom_to_texture(command)) } diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 8e139158427..565308ff36f 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1520,6 +1520,13 @@ impl Window { let stylesheets_changed = document.flush_stylesheets_for_reflow(); + // If this reflow is for display, ensure webgl canvases are composited with + // up-to-date contents. + match reflow_goal { + ReflowGoal::Full => document.flush_dirty_canvases(), + ReflowGoal::TickAnimations | ReflowGoal::LayoutQuery(..) => {}, + } + // Send new document and relevant styles to layout. let needs_display = reflow_goal.needs_display(); let reflow = ScriptReflow { |