mirror of
https://github.com/servo/servo.git
synced 2025-08-02 12:10:29 +01:00
webgl: Lazily clear the canvas right before the first webgl command of the next frame.
This commit is contained in:
parent
4d7110aca5
commit
c53680b282
8 changed files with 138 additions and 124 deletions
|
@ -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]
|
||||
|
|
|
@ -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()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue