aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--components/canvas/Cargo.toml1
-rw-r--r--components/canvas/lib.rs1
-rw-r--r--components/canvas/webgl_mode/inprocess.rs56
-rw-r--r--components/canvas/webgl_thread.rs62
-rw-r--r--components/canvas_traits/webgl.rs28
-rw-r--r--components/config/prefs.rs4
-rw-r--r--components/constellation/pipeline.rs1
-rw-r--r--components/script/dom/bindings/trace.rs3
-rw-r--r--components/script/dom/webglrenderingcontext.rs41
-rw-r--r--components/script/dom/webgltexture.rs12
-rw-r--r--components/script/dom/webidls/WebGLRenderingContext.webidl3
-rw-r--r--components/script/dom/window.rs11
-rw-r--r--components/script/script_thread.rs7
-rw-r--r--components/script_traits/lib.rs6
-rw-r--r--components/servo/lib.rs13
-rw-r--r--resources/prefs.json1
17 files changed, 238 insertions, 13 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 19ac18f08fd..fcd4895f3da 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -312,6 +312,7 @@ dependencies = [
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"offscreen_gl_context 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "servo_config 0.0.1",
"webrender 0.52.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.52.1 (git+https://github.com/servo/webrender)",
]
diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml
index 00eb302369a..651531ef783 100644
--- a/components/canvas/Cargo.toml
+++ b/components/canvas/Cargo.toml
@@ -21,5 +21,6 @@ ipc-channel = "0.8"
log = "0.3.5"
num-traits = "0.1.32"
offscreen_gl_context = { version = "0.11", features = ["serde", "osmesa"] }
+servo_config = {path = "../config"}
webrender = {git = "https://github.com/servo/webrender"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
diff --git a/components/canvas/lib.rs b/components/canvas/lib.rs
index e26d8c2b582..809a69237c0 100644
--- a/components/canvas/lib.rs
+++ b/components/canvas/lib.rs
@@ -15,6 +15,7 @@ extern crate ipc_channel;
#[macro_use] extern crate log;
extern crate num_traits;
extern crate offscreen_gl_context;
+extern crate servo_config;
extern crate webrender;
extern crate webrender_api;
diff --git a/components/canvas/webgl_mode/inprocess.rs b/components/canvas/webgl_mode/inprocess.rs
index 71ab8d8a934..d8d4b4656f1 100644
--- a/components/canvas/webgl_mode/inprocess.rs
+++ b/components/canvas/webgl_mode/inprocess.rs
@@ -6,9 +6,12 @@ use ::gl_context::GLContextFactory;
use ::webgl_thread::{WebGLExternalImageApi, WebGLExternalImageHandler, WebGLThreadObserver, WebGLThread};
use canvas_traits::webgl::{WebGLChan, WebGLContextId, WebGLMsg, WebGLPipeline, WebGLReceiver};
use canvas_traits::webgl::{WebGLSender, WebVRCommand, WebVRRenderHandler};
+use canvas_traits::webgl::DOMToTextureCommand;
use canvas_traits::webgl::webgl_channel;
use euclid::Size2D;
+use fnv::FnvHashMap;
use gleam::gl;
+use servo_config::prefs::PREFS;
use std::marker::PhantomData;
use std::rc::Rc;
use webrender;
@@ -23,14 +26,19 @@ impl WebGLThreads {
webrender_gl: Rc<gl::Gl>,
webrender_api_sender: webrender_api::RenderApiSender,
webvr_compositor: Option<Box<WebVRRenderHandler>>)
- -> (WebGLThreads, Box<webrender::ExternalImageHandler>) {
+ -> (WebGLThreads, Box<webrender::ExternalImageHandler>, Option<Box<webrender::OutputImageHandler>>) {
// This implementation creates a single `WebGLThread` for all the pipelines.
let channel = WebGLThread::start(gl_factory,
webrender_api_sender,
webvr_compositor.map(|c| WebVRRenderWrapper(c)),
PhantomData);
+ let output_handler = if PREFS.is_dom_to_texture_enabled() {
+ Some(Box::new(OutputHandler::new(webrender_gl.clone(), channel.clone())))
+ } else {
+ None
+ };
let external = WebGLExternalImageHandler::new(WebGLExternalImages::new(webrender_gl, channel.clone()));
- (WebGLThreads(channel), Box::new(external))
+ (WebGLThreads(channel), Box::new(external), output_handler.map(|b| b as Box<_>))
}
/// Gets the WebGLThread handle for each script pipeline.
@@ -105,3 +113,47 @@ impl WebVRRenderHandler for WebVRRenderWrapper {
self.0.handle(command, texture);
}
}
+
+/// struct used to implement DOMToTexture feature and webrender::OutputImageHandler trait.
+type OutputHandlerData = Option<(u32, Size2D<i32>)>;
+struct OutputHandler {
+ webrender_gl: Rc<gl::Gl>,
+ webgl_channel: WebGLSender<WebGLMsg>,
+ // Used to avoid creating a new channel on each received WebRender request.
+ lock_channel: (WebGLSender<OutputHandlerData>, WebGLReceiver<OutputHandlerData>),
+ sync_objects: FnvHashMap<webrender_api::PipelineId, gl::GLsync>,
+}
+
+impl OutputHandler {
+ fn new(webrender_gl: Rc<gl::Gl>, channel: WebGLSender<WebGLMsg>) -> Self {
+ Self {
+ webrender_gl,
+ webgl_channel: channel,
+ lock_channel: webgl_channel().unwrap(),
+ sync_objects: Default::default(),
+ }
+ }
+}
+
+/// Bridge between the WR frame outputs and WebGL to implement DOMToTexture synchronization.
+impl webrender::OutputImageHandler for OutputHandler {
+ fn lock(&mut self, id: webrender_api::PipelineId) -> Option<(u32, webrender_api::DeviceIntSize)> {
+ // Insert a fence in the WR command queue
+ let gl_sync = self.webrender_gl.fence_sync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0);
+ // The lock command adds a WaitSync call on the WebGL command flow.
+ let command = DOMToTextureCommand::Lock(id, gl_sync as usize, self.lock_channel.0.clone());
+ self.webgl_channel.send(WebGLMsg::DOMToTextureCommand(command)).unwrap();
+ self.lock_channel.1.recv().unwrap().map(|(tex_id, size)| {
+ (tex_id, webrender_api::DeviceIntSize::new(size.width, size.height))
+ })
+ }
+
+ fn unlock(&mut self, id: webrender_api::PipelineId) {
+ if let Some(gl_sync) = self.sync_objects.remove(&id) {
+ // Flush the Sync object into the GPU's command queue to guarantee that it it's signaled.
+ self.webrender_gl.flush();
+ // Mark the sync object for deletion.
+ self.webrender_gl.delete_sync(gl_sync);
+ }
+ }
+}
diff --git a/components/canvas/webgl_thread.rs b/components/canvas/webgl_thread.rs
index 2bb9077954a..76dfa752ade 100644
--- a/components/canvas/webgl_thread.rs
+++ b/components/canvas/webgl_thread.rs
@@ -36,6 +36,8 @@ pub struct WebGLThread<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver
webvr_compositor: Option<VR>,
/// Generic observer that listens WebGLContext creation, resize or removal events.
observer: OB,
+ /// Texture ids and sizes used in DOM to texture outputs.
+ dom_outputs: FnvHashMap<webrender_api::PipelineId, DOMToTextureData>,
}
impl<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> WebGLThread<VR, OB> {
@@ -52,6 +54,7 @@ impl<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> WebGLThread<VR,
next_webgl_id: 0,
webvr_compositor,
observer: observer,
+ dom_outputs: Default::default(),
}
}
@@ -117,6 +120,9 @@ impl<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> WebGLThread<VR,
WebGLMsg::UpdateWebRenderImage(ctx_id, sender) => {
self.handle_update_wr_image(ctx_id, sender);
},
+ WebGLMsg::DOMToTextureCommand(command) => {
+ self.handle_dom_to_texture(command);
+ },
WebGLMsg::Exit => {
return true;
}
@@ -323,6 +329,54 @@ impl<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> WebGLThread<VR,
sender.send(image_key).unwrap();
}
+ fn handle_dom_to_texture(&mut self, command: DOMToTextureCommand) {
+ match command {
+ DOMToTextureCommand::Attach(context_id, texture_id, document_id, pipeline_id, size) => {
+ let ctx = Self::make_current_if_needed(context_id, &self.contexts, &mut self.bound_context_id)
+ .expect("WebGLContext not found in a WebGL DOMToTextureCommand::Attach command");
+ // Initialize the texture that WR will use for frame outputs.
+ ctx.gl().tex_image_2d(gl::TEXTURE_2D,
+ 0,
+ gl::RGBA as gl::GLint,
+ size.width,
+ size.height,
+ 0,
+ gl::RGBA,
+ gl::UNSIGNED_BYTE,
+ None);
+ self.dom_outputs.insert(pipeline_id, DOMToTextureData {
+ context_id, texture_id, document_id, size
+ });
+ self.webrender_api.enable_frame_output(document_id, pipeline_id, true);
+ },
+ DOMToTextureCommand::Lock(pipeline_id, gl_sync, sender) => {
+ let contexts = &self.contexts;
+ let bound_context_id = &mut self.bound_context_id;
+ let result = self.dom_outputs.get(&pipeline_id).and_then(|data| {
+ let ctx = Self::make_current_if_needed(data.context_id, contexts, bound_context_id);
+ ctx.and_then(|ctx| {
+ // The next glWaitSync call is used to synchronize the two flows of
+ // OpenGL commands (WR and WebGL) in order to avoid using semi-ready WR textures.
+ // glWaitSync doesn't block WebGL CPU thread.
+ ctx.gl().wait_sync(gl_sync as gl::GLsync, 0, gl::TIMEOUT_IGNORED);
+ Some((data.texture_id.get(), data.size))
+ })
+ });
+
+ // Send the texture id and size to WR.
+ sender.send(result).unwrap();
+ },
+ DOMToTextureCommand::Detach(texture_id) => {
+ if let Some((pipeline_id, document_id)) = self.dom_outputs.iter()
+ .find(|&(_, v)| v.texture_id == texture_id)
+ .map(|(k, v)| (*k, v.document_id)) {
+ self.webrender_api.enable_frame_output(document_id, pipeline_id, false);
+ self.dom_outputs.remove(&pipeline_id);
+ }
+ },
+ }
+ }
+
/// Gets a reference to a GLContextWrapper for a given WebGLContextId and makes it current if required.
fn make_current_if_needed<'a>(context_id: WebGLContextId,
contexts: &'a FnvHashMap<WebGLContextId, GLContextWrapper>,
@@ -552,6 +606,14 @@ impl<T: WebGLExternalImageApi> webrender::ExternalImageHandler for WebGLExternal
}
}
+/// Data about the linked DOM<->WebGLTexture elements.
+struct DOMToTextureData {
+ context_id: WebGLContextId,
+ texture_id: WebGLTextureId,
+ document_id: webrender_api::DocumentId,
+ size: Size2D<i32>,
+}
+
/// WebGL Commands Implementation
pub struct WebGLImpl;
diff --git a/components/canvas_traits/webgl.rs b/components/canvas_traits/webgl.rs
index 98c4115c69c..fb555b265b3 100644
--- a/components/canvas_traits/webgl.rs
+++ b/components/canvas_traits/webgl.rs
@@ -6,7 +6,7 @@ use euclid::Size2D;
use nonzero::NonZeroU32;
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use std::fmt;
-use webrender_api;
+use webrender_api::{DocumentId, ImageKey, PipelineId};
/// Sender type used in WebGLCommands.
pub use ::webgl_channel::WebGLSender;
@@ -46,7 +46,9 @@ pub enum WebGLMsg {
/// Unlock messages are always sent after a Lock message.
Unlock(WebGLContextId),
/// Creates or updates the image keys required for WebRender.
- UpdateWebRenderImage(WebGLContextId, WebGLSender<webrender_api::ImageKey>),
+ UpdateWebRenderImage(WebGLContextId, WebGLSender<ImageKey>),
+ /// Commands used for the DOMToTexture feature.
+ DOMToTextureCommand(DOMToTextureCommand),
/// Frees all resources and closes the thread.
Exit,
}
@@ -86,6 +88,11 @@ impl WebGLMsgSender {
}
}
+ /// Returns the WebGLContextId associated to this sender
+ pub fn context_id(&self) -> WebGLContextId {
+ self.ctx_id
+ }
+
/// Send a WebGLCommand message
#[inline]
pub fn send(&self, command: WebGLCommand) -> WebGLSendResult {
@@ -113,9 +120,13 @@ impl WebGLMsgSender {
}
#[inline]
- pub fn send_update_wr_image(&self, sender: WebGLSender<webrender_api::ImageKey>) -> WebGLSendResult {
+ pub fn send_update_wr_image(&self, sender: WebGLSender<ImageKey>) -> WebGLSendResult {
self.sender.send(WebGLMsg::UpdateWebRenderImage(self.ctx_id, sender))
}
+
+ pub fn send_dom_to_texture(&self, command: DOMToTextureCommand) -> WebGLSendResult {
+ self.sender.send(WebGLMsg::DOMToTextureCommand(command))
+ }
}
/// WebGL Commands for a specific WebGLContext
@@ -379,6 +390,17 @@ pub trait WebVRRenderHandler: Send {
fn handle(&mut self, command: WebVRCommand, texture: Option<(u32, Size2D<i32>)>);
}
+/// WebGL commands required to implement DOMToTexture feature.
+#[derive(Clone, Deserialize, Serialize)]
+pub enum DOMToTextureCommand {
+ /// Attaches a HTMLIFrameElement to a WebGLTexture.
+ Attach(WebGLContextId, WebGLTextureId, DocumentId, PipelineId, Size2D<i32>),
+ /// Releases the HTMLIFrameElement to WebGLTexture attachment.
+ Detach(WebGLTextureId),
+ /// Lock message used for a correct synchronization with WebRender GL flow.
+ Lock(PipelineId, usize, WebGLSender<Option<(u32, Size2D<i32>)>>),
+}
+
impl fmt::Debug for WebGLCommand {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::WebGLCommand::*;
diff --git a/components/config/prefs.rs b/components/config/prefs.rs
index 3bfb94772b1..397b060cc03 100644
--- a/components/config/prefs.rs
+++ b/components/config/prefs.rs
@@ -273,4 +273,8 @@ impl Preferences {
pub fn is_webvr_enabled(&self) -> bool {
self.get("dom.webvr.enabled").as_boolean().unwrap_or(false)
}
+
+ pub fn is_dom_to_texture_enabled(&self) -> bool {
+ self.get("dom.webgl.dom_to_texture.enabled").as_boolean().unwrap_or(false)
+ }
}
diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs
index 57cf07d07d8..d5a41df4460 100644
--- a/components/constellation/pipeline.rs
+++ b/components/constellation/pipeline.rs
@@ -511,6 +511,7 @@ impl UnprivilegedPipelineContent {
content_process_shutdown_chan: self.script_content_process_shutdown_chan,
webgl_chan: self.webgl_chan,
webvr_chan: self.webvr_chan,
+ webrender_document: self.webrender_document,
}, self.load_data.clone());
LTF::create(self.id,
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index f7d582ffee8..5c7723f17de 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -110,7 +110,7 @@ use style::stylesheets::keyframes_rule::Keyframe;
use style::values::specified::Length;
use time::Duration;
use uuid::Uuid;
-use webrender_api::ImageKey;
+use webrender_api::{DocumentId, ImageKey};
use webvr_traits::WebVRGamepadHand;
/// A trait to allow tracing (only) DOM objects.
@@ -397,6 +397,7 @@ unsafe_no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
unsafe_no_jsmanaged_fields!(PathBuf);
unsafe_no_jsmanaged_fields!(CSSErrorReporter);
unsafe_no_jsmanaged_fields!(DrawAPaintImageResult);
+unsafe_no_jsmanaged_fields!(DocumentId);
unsafe_no_jsmanaged_fields!(ImageKey);
unsafe_no_jsmanaged_fields!(WebGLBufferId);
unsafe_no_jsmanaged_fields!(WebGLChan);
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index c20b2273123..d4624d3eb85 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -6,6 +6,7 @@ use byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt};
use canvas_traits::canvas::{byte_swap, multiply_u8_pixel};
use canvas_traits::webgl::{WebGLContextShareMode, WebGLCommand, WebGLError};
use canvas_traits::webgl::{WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender, WebGLParameter, WebVRCommand};
+use canvas_traits::webgl::DOMToTextureCommand;
use canvas_traits::webgl::WebGLError::*;
use canvas_traits::webgl::webgl_channel;
use core::cell::Ref;
@@ -25,6 +26,7 @@ use dom::bindings::str::DOMString;
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::htmlcanvaselement::HTMLCanvasElement;
use dom::htmlcanvaselement::utils as canvas_utils;
+use dom::htmliframeelement::HTMLIFrameElement;
use dom::node::{Node, NodeDamage, window_from_node};
use dom::webgl_extensions::WebGLExtensions;
use dom::webgl_validations::WebGLValidator;
@@ -3261,6 +3263,45 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
+ fn TexImageDOM(&self,
+ target: u32,
+ level: i32,
+ internal_format: u32,
+ width: i32,
+ height: i32,
+ format: u32,
+ data_type: u32,
+ source: &HTMLIFrameElement) -> Fallible<()> {
+ // Currently DOMToTexture only supports TEXTURE_2D, RGBA, UNSIGNED_BYTE and no levels.
+ if target != constants::TEXTURE_2D || level != 0 || internal_format != constants::RGBA ||
+ format != constants::RGBA || data_type != constants::UNSIGNED_BYTE {
+ return Ok(self.webgl_error(InvalidValue));
+ }
+
+ // Get bound texture
+ let texture = match self.bound_texture(constants::TEXTURE_2D) {
+ Some(texture) => texture,
+ None => {
+ return Ok(self.webgl_error(InvalidOperation));
+ }
+ };
+
+ let pipeline_id = source.pipeline_id().ok_or(Error::InvalidState)?;
+ let document_id = self.global().downcast::<Window>().ok_or(Error::InvalidState)?.webrender_document();
+
+ texture.set_attached_to_dom();
+
+ let command = DOMToTextureCommand::Attach(self.webgl_sender.context_id(),
+ texture.id(),
+ document_id,
+ pipeline_id.to_webrender(),
+ Size2D::new(width, height));
+ self.webgl_sender.send_dom_to_texture(command).unwrap();
+
+ Ok(())
+ }
+
+ // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
#[allow(unsafe_code)]
unsafe fn TexSubImage2D(&self,
cx: *mut JSContext,
diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs
index 59be8681337..6927fd10a48 100644
--- a/components/script/dom/webgltexture.rs
+++ b/components/script/dom/webgltexture.rs
@@ -5,6 +5,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLError, WebGLMsgSender, WebGLResult, WebGLTextureId};
+use canvas_traits::webgl::DOMToTextureCommand;
use dom::bindings::cell::DomRefCell;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use dom::bindings::codegen::Bindings::WebGLTextureBinding;
@@ -45,6 +46,8 @@ pub struct WebGLTexture {
mag_filter: Cell<Option<u32>>,
#[ignore_heap_size_of = "Defined in ipc-channel"]
renderer: WebGLMsgSender,
+ /// True if this texture is used for the DOMToTexture feature.
+ attached_to_dom: Cell<bool>,
}
impl WebGLTexture {
@@ -62,6 +65,7 @@ impl WebGLTexture {
mag_filter: Cell::new(None),
image_info_array: DomRefCell::new([ImageInfo::new(); MAX_LEVEL_COUNT * MAX_FACE_COUNT]),
renderer: renderer,
+ attached_to_dom: Cell::new(false),
}
}
@@ -179,6 +183,10 @@ impl WebGLTexture {
pub fn delete(&self) {
if !self.is_deleted.get() {
self.is_deleted.set(true);
+ // Notify WR to release the frame output when using DOMToTexture feature
+ if self.attached_to_dom.get() {
+ let _ = self.renderer.send_dom_to_texture(DOMToTextureCommand::Detach(self.id));
+ }
let _ = self.renderer.send(WebGLCommand::DeleteTexture(self.id));
}
}
@@ -374,6 +382,10 @@ impl WebGLTexture {
Some(self.image_info_at_face(0, self.base_mipmap_level))
}
+
+ pub fn set_attached_to_dom(&self) {
+ self.attached_to_dom.set(true);
+ }
}
impl Drop for WebGLTexture {
diff --git a/components/script/dom/webidls/WebGLRenderingContext.webidl b/components/script/dom/webidls/WebGLRenderingContext.webidl
index 885ad9486bb..ec729d1b5fb 100644
--- a/components/script/dom/webidls/WebGLRenderingContext.webidl
+++ b/components/script/dom/webidls/WebGLRenderingContext.webidl
@@ -654,6 +654,9 @@ interface WebGLRenderingContextBase
[Throws]
void texImage2D(GLenum target, GLint level, GLenum internalformat,
GLenum format, GLenum type, TexImageSource? source); // May throw DOMException
+ [Throws, Pref="dom.webgl.dom_to_texture.enabled"]
+ void texImageDOM(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, HTMLIFrameElement source); // May throw DOMException
void texParameterf(GLenum target, GLenum pname, GLfloat param);
void texParameteri(GLenum target, GLenum pname, GLint param);
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 1e4bf803427..047cc1678ea 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -123,7 +123,7 @@ use timers::{IsInterval, TimerCallback};
use tinyfiledialogs::{self, MessageBoxIcon};
use url::Position;
use webdriver_handlers::jsval_to_webdriver;
-use webrender_api::ClipId;
+use webrender_api::{ClipId, DocumentId};
use webvr_traits::WebVRMsg;
/// Current state of the window object
@@ -289,6 +289,9 @@ pub struct Window {
test_worklet: MutNullableDom<Worklet>,
/// https://drafts.css-houdini.org/css-paint-api-1/#paint-worklet
paint_worklet: MutNullableDom<Worklet>,
+ /// The Webrender Document id associated with this window.
+ #[ignore_heap_size_of = "defined in webrender_api"]
+ webrender_document: DocumentId,
}
impl Window {
@@ -1760,6 +1763,10 @@ impl Window {
.send(msg)
.unwrap();
}
+
+ pub fn webrender_document(&self) -> DocumentId {
+ self.webrender_document
+ }
}
impl Window {
@@ -1794,6 +1801,7 @@ impl Window {
webgl_chan: WebGLChan,
webvr_chan: Option<IpcSender<WebVRMsg>>,
microtask_queue: Rc<MicrotaskQueue>,
+ webrender_document: DocumentId,
) -> DomRoot<Self> {
let layout_rpc: Box<LayoutRPC + Send> = {
let (rpc_send, rpc_recv) = channel();
@@ -1868,6 +1876,7 @@ impl Window {
unminified_js_dir: Default::default(),
test_worklet: Default::default(),
paint_worklet: Default::default(),
+ webrender_document,
});
unsafe {
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 119fe4bec2c..6c722cec865 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -124,6 +124,7 @@ use time::{get_time, precise_time_ns, Tm};
use url::Position;
use url::percent_encoding::percent_decode;
use webdriver_handlers;
+use webrender_api::DocumentId;
use webvr_traits::{WebVREvent, WebVRMsg};
pub type ImageCacheMsg = (PipelineId, PendingImageResponse);
@@ -495,6 +496,9 @@ pub struct ScriptThread {
/// https://html.spec.whatwg.org/multipage/#custom-element-reactions-stack
custom_element_reaction_stack: CustomElementReactionStack,
+
+ /// The Webrender Document ID associated with this thread.
+ webrender_document: DocumentId,
}
/// In the event of thread panic, all data on the stack runs its destructor. However, there
@@ -871,6 +875,8 @@ impl ScriptThread {
transitioning_nodes: Default::default(),
custom_element_reaction_stack: CustomElementReactionStack::new(),
+
+ webrender_document: state.webrender_document,
}
}
@@ -2062,6 +2068,7 @@ impl ScriptThread {
self.webgl_chan.channel(),
self.webvr_chan.clone(),
self.microtask_queue.clone(),
+ self.webrender_document,
);
// Initialize the browsing context for the window.
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index 8b2c98b1eb6..e8081c9eeaf 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -69,7 +69,7 @@ use std::sync::mpsc::{Receiver, Sender, RecvTimeoutError};
use style_traits::CSSPixel;
use style_traits::SpeculativePainter;
use webdriver_msg::{LoadStatus, WebDriverScriptCommand};
-use webrender_api::{ClipId, DevicePixel, ImageKey};
+use webrender_api::{ClipId, DevicePixel, DocumentId, ImageKey};
use webvr_traits::{WebVREvent, WebVRMsg};
pub use script_msg::{LayoutMsg, ScriptMsg, EventResult, LogEntry};
@@ -554,7 +554,9 @@ pub struct InitialScriptState {
/// A channel to the webgl thread used in this pipeline.
pub webgl_chan: WebGLPipeline,
/// A channel to the webvr thread, if available.
- pub webvr_chan: Option<IpcSender<WebVRMsg>>
+ pub webvr_chan: Option<IpcSender<WebVRMsg>>,
+ /// The Webrender document ID associated with this thread.
+ pub webrender_document: DocumentId,
}
/// This trait allows creating a `ScriptThread` without depending on the `script`
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index 262f5a22130..75b07015037 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -553,13 +553,18 @@ fn create_constellation(user_agent: Cow<'static, str>,
};
// Initialize WebGL Thread entry point.
- let (webgl_threads, image_handler) = WebGLThreads::new(gl_factory,
- window_gl,
- webrender_api_sender.clone(),
- webvr_compositor.map(|c| c as Box<_>));
+ let (webgl_threads, image_handler, output_handler) = WebGLThreads::new(gl_factory,
+ window_gl,
+ webrender_api_sender.clone(),
+ webvr_compositor.map(|c| c as Box<_>));
// Set webrender external image handler for WebGL textures
webrender.set_external_image_handler(image_handler);
+ // Set DOM to texture handler, if enabled.
+ if let Some(output_handler) = output_handler {
+ webrender.set_output_image_handler(output_handler);
+ }
+
let initial_state = InitialConstellationState {
compositor_proxy,
embedder_proxy,
diff --git a/resources/prefs.json b/resources/prefs.json
index 74d2302f68c..f5d85ae9dc6 100644
--- a/resources/prefs.json
+++ b/resources/prefs.json
@@ -15,6 +15,7 @@
"dom.servoparser.async_html_tokenizer.enabled": false,
"dom.testable_crash.enabled": false,
"dom.testbinding.enabled": false,
+ "dom.webgl.dom_to_texture.enabled": false,
"dom.webvr.enabled": false,
"dom.webvr.event_polling_interval": 500,
"js.asmjs.enabled": true,