diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-10-16 15:36:42 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-16 15:36:42 -0500 |
commit | 3209d22968046b5c3d29a37b79a655497db2050a (patch) | |
tree | 143e736c18adfee6de958614129690250b265a0a /components/script | |
parent | d3d2b0261a8aacd4f74e330f8c007a91f829a96e (diff) | |
parent | 8ae0739bab8a3c74e0685d9f53bbb155e4458aba (diff) | |
download | servo-3209d22968046b5c3d29a37b79a655497db2050a.tar.gz servo-3209d22968046b5c3d29a37b79a655497db2050a.zip |
Auto merge of #18592 - MortimerGoro:dom_texture, r=jdm
Implement DOM to texture
<!-- Please describe your changes on the following line: -->
This is a prototype of the WebGL DOMToTexture feature. The API should be fine as a privileged extension for now due to security concerns. The working group has been investigating the viability of unprivileged usage but the spec is not ready yet.
Demo video: https://www.youtube.com/watch?v=hpZqEM5hPao
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [x] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18592)
<!-- Reviewable:end -->
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/bindings/trace.rs | 3 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 41 | ||||
-rw-r--r-- | components/script/dom/webgltexture.rs | 12 | ||||
-rw-r--r-- | components/script/dom/webidls/WebGLRenderingContext.webidl | 3 | ||||
-rw-r--r-- | components/script/dom/window.rs | 11 | ||||
-rw-r--r-- | components/script/script_thread.rs | 7 |
6 files changed, 75 insertions, 2 deletions
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. |