diff options
54 files changed, 1426 insertions, 3154 deletions
diff --git a/Cargo.lock b/Cargo.lock index 4455b98c203..759122f23e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -325,7 +325,6 @@ version = "0.0.1" dependencies = [ "azure 0.20.1 (git+https://github.com/servo/rust-azure)", "canvas_traits 0.0.1", - "compositing 0.0.1", "cssparser 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -333,7 +332,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.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.48.0 (git+https://github.com/servo/webrender)", + "servo_config 0.0.1", "webrender_api 0.48.0 (git+https://github.com/servo/webrender)", ] @@ -346,10 +345,7 @@ dependencies = [ "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "offscreen_gl_context 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_config 0.0.1", "webrender_api 0.48.0 (git+https://github.com/servo/webrender)", ] @@ -530,6 +526,7 @@ dependencies = [ "msg 0.0.1", "net 0.0.1", "net_traits 0.0.1", + "offscreen_gl_context 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "profile_traits 0.0.1", "script_traits 0.0.1", "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2599,6 +2596,7 @@ dependencies = [ "metrics 0.0.1", "msg 0.0.1", "net_traits 0.0.1", + "offscreen_gl_context 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "profile_traits 0.0.1", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3531,13 +3529,12 @@ dependencies = [ name = "webvr" version = "0.0.1" dependencies = [ - "canvas_traits 0.0.1", - "euclid 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "script_traits 0.0.1", "servo_config 0.0.1", + "webrender_api 0.48.0 (git+https://github.com/servo/webrender)", "webvr_traits 0.0.1", ] diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml index e8bf234a052..ad149daccb6 100644 --- a/components/canvas/Cargo.toml +++ b/components/canvas/Cargo.toml @@ -12,7 +12,6 @@ path = "lib.rs" [dependencies] azure = {git = "https://github.com/servo/rust-azure"} canvas_traits = {path = "../canvas_traits"} -compositing = {path = "../compositing"} cssparser = "0.19" euclid = "0.15" gleam = "0.4" @@ -20,5 +19,5 @@ ipc-channel = "0.8" log = "0.3.5" num-traits = "0.1.32" offscreen_gl_context = { version = "0.11", features = ["serde"] } -webrender = {git = "https://github.com/servo/webrender"} +servo_config = {path = "../config"} webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs index 8fe05d1f6a9..b7e21777001 100644 --- a/components/canvas/canvas_paint_thread.rs +++ b/components/canvas/canvas_paint_thread.rs @@ -8,7 +8,7 @@ use azure::azure_hl::{BackendType, DrawOptions, DrawTarget, Pattern, StrokeOptio use azure::azure_hl::{Color, ColorPattern, DrawSurfaceOptions, Filter, PathBuilder}; use azure::azure_hl::{ExtendMode, GradientStop, LinearGradientPattern, RadialGradientPattern}; use azure::azure_hl::SurfacePattern; -use canvas_traits::canvas::*; +use canvas_traits::*; use cssparser::RGBA; use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D}; use ipc_channel::ipc::{self, IpcSender}; @@ -193,8 +193,12 @@ impl<'a> CanvasPaintThread<'a> { Canvas2dMsg::SetShadowColor(ref color) => painter.set_shadow_color(color.to_azure_style()), } }, - CanvasMsg::Close => break, - CanvasMsg::Recreate(size) => painter.recreate(size), + CanvasMsg::Common(message) => { + match message { + CanvasCommonMsg::Close => break, + CanvasCommonMsg::Recreate(size) => painter.recreate(size), + } + }, CanvasMsg::FromScript(message) => { match message { FromScriptMsg::SendPixels(chan) => { @@ -209,6 +213,8 @@ impl<'a> CanvasPaintThread<'a> { } } } + CanvasMsg::WebGL(_) => panic!("Wrong WebGL message sent to Canvas2D thread"), + CanvasMsg::WebVR(_) => panic!("Wrong WebVR message sent to Canvas2D thread"), } } }).expect("Thread spawning failed"); @@ -565,7 +571,7 @@ impl<'a> CanvasPaintThread<'a> { }) } - fn send_data(&mut self, chan: IpcSender<CanvasImageData>) { + fn send_data(&mut self, chan: IpcSender<CanvasData>) { self.drawtarget.snapshot().get_data_surface().with_data(|element| { let size = self.drawtarget.get_size(); @@ -608,7 +614,7 @@ impl<'a> CanvasPaintThread<'a> { let data = CanvasImageData { image_key: self.image_key.unwrap(), }; - chan.send(data).unwrap(); + chan.send(CanvasData::Image(data)).unwrap(); }) } diff --git a/components/canvas/gl_context.rs b/components/canvas/gl_context.rs deleted file mode 100644 index 69a26c0e03c..00000000000 --- a/components/canvas/gl_context.rs +++ /dev/null @@ -1,203 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use canvas_traits::webgl::WebGLCommand; -use compositing::compositor_thread::{CompositorProxy, self}; -use euclid::Size2D; -use gleam::gl; -use offscreen_gl_context::{ColorAttachmentType, GLContext, GLContextAttributes, GLContextDispatcher, GLLimits}; -use offscreen_gl_context::{NativeGLContext, NativeGLContextHandle, NativeGLContextMethods}; -use offscreen_gl_context::{OSMesaContext, OSMesaContextHandle}; -use std::sync::{Arc, Mutex}; -use super::webgl_thread::WebGLImpl; - -/// The GLContextFactory is used to create shared GL contexts with the main thread GL context. -/// Currently, shared textures are used to render WebGL textures into the WR compositor. -/// In order to create a shared context, the GLContextFactory stores the handle of the main GL context. -pub enum GLContextFactory { - Native(NativeGLContextHandle, Option<MainThreadDispatcher>), - OSMesa(OSMesaContextHandle), -} - -impl GLContextFactory { - /// Creates a new GLContextFactory that uses the currently bound GL context to create shared contexts. - pub fn current_native_handle(proxy: &CompositorProxy) -> Option<GLContextFactory> { - NativeGLContext::current_handle().map(|handle| { - if cfg!(target_os = "windows") { - // Used to dispatch functions from the GLContext thread to the main thread's event loop. - // Required to allow WGL GLContext sharing in Windows. - GLContextFactory::Native(handle, Some(MainThreadDispatcher::new(proxy.clone_compositor_proxy()))) - } else { - GLContextFactory::Native(handle, None) - } - }) - } - - /// Creates a new GLContextFactory that uses the currently bound OSMesa context to create shared contexts. - pub fn current_osmesa_handle() -> Option<GLContextFactory> { - OSMesaContext::current_handle().map(GLContextFactory::OSMesa) - } - - /// Creates a new shared GLContext with the main GLContext - pub fn new_shared_context(&self, - size: Size2D<i32>, - attributes: GLContextAttributes) -> Result<GLContextWrapper, &'static str> { - match *self { - GLContextFactory::Native(ref handle, ref dispatcher) => { - let dispatcher = dispatcher.as_ref().map(|d| Box::new(d.clone()) as Box<_>); - let ctx = GLContext::<NativeGLContext>::new_shared_with_dispatcher(size, - attributes, - ColorAttachmentType::Texture, - gl::GlType::default(), - Some(handle), - dispatcher); - ctx.map(GLContextWrapper::Native) - } - GLContextFactory::OSMesa(ref handle) => { - let ctx = GLContext::<OSMesaContext>::new_shared_with_dispatcher(size.to_untyped(), - attributes, - ColorAttachmentType::Texture, - gl::GlType::default(), - Some(handle), - None); - ctx.map(GLContextWrapper::OSMesa) - } - } - } - - /// Creates a new non-shared GLContext - pub fn new_context(&self, - size: Size2D<i32>, - attributes: GLContextAttributes) -> Result<GLContextWrapper, &'static str> { - match *self { - GLContextFactory::Native(..) => { - let ctx = GLContext::<NativeGLContext>::new_shared_with_dispatcher(size, - attributes, - ColorAttachmentType::Texture, - gl::GlType::default(), - None, - None); - ctx.map(GLContextWrapper::Native) - } - GLContextFactory::OSMesa(_) => { - let ctx = GLContext::<OSMesaContext>::new_shared_with_dispatcher(size.to_untyped(), - attributes, - ColorAttachmentType::Texture, - gl::GlType::default(), - None, - None); - ctx.map(GLContextWrapper::OSMesa) - } - } - } -} - - -/// GLContextWrapper used to abstract NativeGLContext and OSMesaContext types -pub enum GLContextWrapper { - Native(GLContext<NativeGLContext>), - OSMesa(GLContext<OSMesaContext>), -} - -impl GLContextWrapper { - pub fn make_current(&self) { - match *self { - GLContextWrapper::Native(ref ctx) => { - ctx.make_current().unwrap(); - } - GLContextWrapper::OSMesa(ref ctx) => { - ctx.make_current().unwrap(); - } - } - } - - pub fn unbind(&self) { - match *self { - GLContextWrapper::Native(ref ctx) => { - ctx.unbind().unwrap(); - } - GLContextWrapper::OSMesa(ref ctx) => { - ctx.unbind().unwrap(); - } - } - } - - pub fn apply_command(&self, cmd: WebGLCommand) { - match *self { - GLContextWrapper::Native(ref ctx) => { - WebGLImpl::apply(ctx, cmd); - } - GLContextWrapper::OSMesa(ref ctx) => { - WebGLImpl::apply(ctx, cmd); - } - } - } - - pub fn gl(&self) -> &gl::Gl { - match *self { - GLContextWrapper::Native(ref ctx) => { - ctx.gl() - } - GLContextWrapper::OSMesa(ref ctx) => { - ctx.gl() - } - } - } - - pub fn get_info(&self) -> (Size2D<i32>, u32, GLLimits) { - match *self { - GLContextWrapper::Native(ref ctx) => { - let (real_size, texture_id) = { - let draw_buffer = ctx.borrow_draw_buffer().unwrap(); - (draw_buffer.size(), draw_buffer.get_bound_texture_id().unwrap()) - }; - - let limits = ctx.borrow_limits().clone(); - - (real_size, texture_id, limits) - } - GLContextWrapper::OSMesa(ref ctx) => { - let (real_size, texture_id) = { - let draw_buffer = ctx.borrow_draw_buffer().unwrap(); - (draw_buffer.size(), draw_buffer.get_bound_texture_id().unwrap()) - }; - - let limits = ctx.borrow_limits().clone(); - - (real_size, texture_id, limits) - } - } - } - - pub fn resize(&mut self, size: Size2D<i32>) -> Result<(), &'static str> { - match *self { - GLContextWrapper::Native(ref mut ctx) => { - ctx.resize(size) - } - GLContextWrapper::OSMesa(ref mut ctx) => { - ctx.resize(size) - } - } - } -} - -/// Implements GLContextDispatcher to dispatch functions from GLContext threads to the main thread's event loop. -/// It's used in Windows to allow WGL GLContext sharing. -#[derive(Clone)] -pub struct MainThreadDispatcher { - compositor_proxy: Arc<Mutex<CompositorProxy>> -} - -impl MainThreadDispatcher { - fn new(proxy: CompositorProxy) -> Self { - Self { - compositor_proxy: Arc::new(Mutex::new(proxy)), - } - } -} -impl GLContextDispatcher for MainThreadDispatcher { - fn dispatch(&self, f: Box<Fn() + Send>) { - self.compositor_proxy.lock().unwrap().send(compositor_thread::Msg::Dispatch(f)); - } -} diff --git a/components/canvas/lib.rs b/components/canvas/lib.rs index b9f0823a07d..a3d90909637 100644 --- a/components/canvas/lib.rs +++ b/components/canvas/lib.rs @@ -6,18 +6,16 @@ extern crate azure; extern crate canvas_traits; -extern crate compositing; extern crate cssparser; extern crate euclid; extern crate gleam; extern crate ipc_channel; -#[macro_use] extern crate log; +#[macro_use] +extern crate log; extern crate num_traits; extern crate offscreen_gl_context; -extern crate webrender; +extern crate servo_config; extern crate webrender_api; pub mod canvas_paint_thread; -pub mod gl_context; -mod webgl_mode; -pub mod webgl_thread; +pub mod webgl_paint_thread; diff --git a/components/canvas/webgl_mode/inprocess.rs b/components/canvas/webgl_mode/inprocess.rs deleted file mode 100644 index 257f1395545..00000000000 --- a/components/canvas/webgl_mode/inprocess.rs +++ /dev/null @@ -1,95 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -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::webgl_channel; -use euclid::Size2D; -use std::marker::PhantomData; -use webrender; -use webrender_api; - -/// WebGL Threading API entry point that lives in the constellation. -pub struct WebGLThreads(WebGLSender<WebGLMsg>); - -impl WebGLThreads { - /// Creates a new WebGLThreads object - pub fn new(gl_factory: GLContextFactory, - webrender_api_sender: webrender_api::RenderApiSender, - webvr_compositor: Option<Box<WebVRRenderHandler>>) - -> (WebGLThreads, Box<webrender::ExternalImageHandler>) { - // 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 external = WebGLExternalImageHandler::new(WebGLExternalImages::new(channel.clone())); - (WebGLThreads(channel), Box::new(external)) - } - - /// Gets the WebGLThread handle for each script pipeline. - pub fn pipeline(&self) -> WebGLPipeline { - // This mode creates a single thread, so the existing WebGLChan is just cloned. - WebGLPipeline(WebGLChan(self.0.clone())) - } - - /// Sends a exit message to close the WebGLThreads and release all WebGLContexts. - pub fn exit(&self) -> Result<(), &'static str> { - self.0.send(WebGLMsg::Exit).map_err(|_| "Failed to send Exit message") - } -} - -/// Bridge between the webrender::ExternalImage callbacks and the WebGLThreads. -struct WebGLExternalImages { - webgl_channel: WebGLSender<WebGLMsg>, - // Used to avoid creating a new channel on each received WebRender request. - lock_channel: (WebGLSender<(u32, Size2D<i32>)>, WebGLReceiver<(u32, Size2D<i32>)>), -} - -impl WebGLExternalImages { - fn new(channel: WebGLSender<WebGLMsg>) -> Self { - Self { - webgl_channel: channel, - lock_channel: webgl_channel().unwrap(), - } - } -} - -impl WebGLExternalImageApi for WebGLExternalImages { - fn lock(&mut self, ctx_id: WebGLContextId) -> (u32, Size2D<i32>) { - self.webgl_channel.send(WebGLMsg::Lock(ctx_id, self.lock_channel.0.clone())).unwrap(); - self.lock_channel.1.recv().unwrap() - } - - fn unlock(&mut self, ctx_id: WebGLContextId) { - self.webgl_channel.send(WebGLMsg::Unlock(ctx_id)).unwrap(); - } -} - -/// Custom observer used in a `WebGLThread`. -impl WebGLThreadObserver for PhantomData<()> { - fn on_context_create(&mut self, ctx_id: WebGLContextId, texture_id: u32, size: Size2D<i32>) { - debug!("WebGLContext created (ctx_id: {:?} texture_id: {:?} size: {:?}", ctx_id, texture_id, size); - } - - fn on_context_resize(&mut self, ctx_id: WebGLContextId, texture_id: u32, size: Size2D<i32>) { - debug!("WebGLContext resized (ctx_id: {:?} texture_id: {:?} size: {:?}", ctx_id, texture_id, size); - } - - fn on_context_delete(&mut self, ctx_id: WebGLContextId) { - debug!("WebGLContext deleted (ctx_id: {:?})", ctx_id); - } -} - - -/// Wrapper to send WebVR commands used in `WebGLThread`. -struct WebVRRenderWrapper(Box<WebVRRenderHandler>); - -impl WebVRRenderHandler for WebVRRenderWrapper { - fn handle(&mut self, command: WebVRCommand, texture: Option<(u32, Size2D<i32>)>) { - self.0.handle(command, texture); - } -} diff --git a/components/canvas/webgl_mode/mod.rs b/components/canvas/webgl_mode/mod.rs deleted file mode 100644 index 660818fb096..00000000000 --- a/components/canvas/webgl_mode/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -mod inprocess; -pub use self::inprocess::WebGLThreads; diff --git a/components/canvas/webgl_paint_thread.rs b/components/canvas/webgl_paint_thread.rs new file mode 100644 index 00000000000..2b6819effba --- /dev/null +++ b/components/canvas/webgl_paint_thread.rs @@ -0,0 +1,379 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use canvas_traits::{CanvasCommonMsg, CanvasData, CanvasMsg, CanvasImageData}; +use canvas_traits::{FromLayoutMsg, FromScriptMsg, byte_swap}; +use euclid::Size2D; +use gleam::gl; +use ipc_channel::ipc::{self, IpcSender}; +use offscreen_gl_context::{ColorAttachmentType, GLContext, GLLimits}; +use offscreen_gl_context::{GLContextAttributes, NativeGLContext, OSMesaContext}; +use servo_config::opts; +use std::borrow::ToOwned; +use std::mem; +use std::sync::Arc; +use std::sync::mpsc::channel; +use std::thread; +use webrender_api; + +enum GLContextWrapper { + Native(GLContext<NativeGLContext>), + OSMesa(GLContext<OSMesaContext>), +} + +impl GLContextWrapper { + fn new(size: Size2D<i32>, + attributes: GLContextAttributes, + gl_type: gl::GlType) -> Result<GLContextWrapper, &'static str> { + if opts::get().should_use_osmesa() { + let ctx = GLContext::<OSMesaContext>::new(size, + attributes, + ColorAttachmentType::Texture, + gl_type, + None); + ctx.map(GLContextWrapper::OSMesa) + } else { + let ctx = GLContext::<NativeGLContext>::new(size, + attributes, + ColorAttachmentType::Texture, + gl_type, + None); + ctx.map(GLContextWrapper::Native) + } + } + + pub fn get_limits(&self) -> GLLimits { + match *self { + GLContextWrapper::Native(ref ctx) => { + ctx.borrow_limits().clone() + } + GLContextWrapper::OSMesa(ref ctx) => { + ctx.borrow_limits().clone() + } + } + } + + fn resize(&mut self, size: Size2D<i32>) -> Result<Size2D<i32>, &'static str> { + match *self { + GLContextWrapper::Native(ref mut ctx) => { + ctx.resize(size)?; + Ok(ctx.borrow_draw_buffer().unwrap().size()) + } + GLContextWrapper::OSMesa(ref mut ctx) => { + ctx.resize(size)?; + Ok(ctx.borrow_draw_buffer().unwrap().size()) + } + } + } + + fn gl(&self) -> &gl::Gl { + match *self { + GLContextWrapper::Native(ref ctx) => { + ctx.gl() + } + GLContextWrapper::OSMesa(ref ctx) => { + ctx.gl() + } + } + } + + pub fn make_current(&self) { + match *self { + GLContextWrapper::Native(ref ctx) => { + ctx.make_current().unwrap(); + } + GLContextWrapper::OSMesa(ref ctx) => { + ctx.make_current().unwrap(); + } + } + } + + pub fn apply_command(&self, cmd: webrender_api::WebGLCommand) { + match *self { + GLContextWrapper::Native(ref ctx) => { + cmd.apply(ctx); + } + GLContextWrapper::OSMesa(ref ctx) => { + cmd.apply(ctx); + } + } + } +} + +enum WebGLPaintTaskData { + WebRender(webrender_api::RenderApi, webrender_api::WebGLContextId), + Readback { + context: GLContextWrapper, + webrender_api: webrender_api::RenderApi, + image_key: Option<webrender_api::ImageKey>, + /// An old webrender image key that can be deleted when the next epoch ends. + old_image_key: Option<webrender_api::ImageKey>, + /// An old webrender image key that can be deleted when the current epoch ends. + very_old_image_key: Option<webrender_api::ImageKey>, + }, +} + +pub struct WebGLPaintThread { + size: Size2D<i32>, + data: WebGLPaintTaskData, +} + +fn create_readback_painter(size: Size2D<i32>, + attrs: GLContextAttributes, + webrender_api: webrender_api::RenderApi, + gl_type: gl::GlType) + -> Result<(WebGLPaintThread, GLLimits), String> { + let context = GLContextWrapper::new(size, attrs, gl_type)?; + let limits = context.get_limits(); + let painter = WebGLPaintThread { + size: size, + data: WebGLPaintTaskData::Readback { + context: context, + webrender_api: webrender_api, + image_key: None, + old_image_key: None, + very_old_image_key: None, + }, + }; + + Ok((painter, limits)) +} + +impl WebGLPaintThread { + fn new(size: Size2D<i32>, + attrs: GLContextAttributes, + webrender_api_sender: webrender_api::RenderApiSender, + gl_type: gl::GlType) + -> Result<(WebGLPaintThread, GLLimits), String> { + let wr_api = webrender_api_sender.create_api(); + let device_size = webrender_api::DeviceIntSize::from_untyped(&size); + match wr_api.request_webgl_context(&device_size, attrs) { + Ok((id, limits)) => { + let painter = WebGLPaintThread { + data: WebGLPaintTaskData::WebRender(wr_api, id), + size: size + }; + Ok((painter, limits)) + }, + Err(msg) => { + warn!("Initial context creation failed, falling back to readback: {}", msg); + create_readback_painter(size, attrs, wr_api, gl_type) + } + } + } + + fn handle_webgl_message(&self, message: webrender_api::WebGLCommand) { + debug!("WebGL message: {:?}", message); + match self.data { + WebGLPaintTaskData::WebRender(ref api, id) => { + api.send_webgl_command(id, message); + } + WebGLPaintTaskData::Readback { ref context, .. } => { + context.apply_command(message); + } + } + } + + fn handle_webvr_message(&self, message: webrender_api::VRCompositorCommand) { + match self.data { + WebGLPaintTaskData::WebRender(ref api, id) => { + api.send_vr_compositor_command(id, message); + } + WebGLPaintTaskData::Readback { .. } => { + error!("Webrender is required for WebVR implementation"); + } + } + } + + + /// Creates a new `WebGLPaintThread` and returns an `IpcSender` to + /// communicate with it. + pub fn start(size: Size2D<i32>, + attrs: GLContextAttributes, + webrender_api_sender: webrender_api::RenderApiSender) + -> Result<(IpcSender<CanvasMsg>, GLLimits), String> { + let (sender, receiver) = ipc::channel::<CanvasMsg>().unwrap(); + let (result_chan, result_port) = channel(); + thread::Builder::new().name("WebGLThread".to_owned()).spawn(move || { + let gl_type = gl::GlType::default(); + let mut painter = match WebGLPaintThread::new(size, attrs, webrender_api_sender, gl_type) { + Ok((thread, limits)) => { + result_chan.send(Ok(limits)).unwrap(); + thread + }, + Err(e) => { + result_chan.send(Err(e)).unwrap(); + return + } + }; + painter.init(); + loop { + match receiver.recv().unwrap() { + CanvasMsg::WebGL(message) => painter.handle_webgl_message(message), + CanvasMsg::Common(message) => { + match message { + CanvasCommonMsg::Close => break, + // TODO(emilio): handle error nicely + CanvasCommonMsg::Recreate(size) => painter.recreate(size).unwrap(), + } + }, + CanvasMsg::FromScript(message) => { + match message { + FromScriptMsg::SendPixels(chan) =>{ + // Read the comment on + // HTMLCanvasElement::fetch_all_data. + chan.send(None).unwrap(); + } + } + } + CanvasMsg::FromLayout(message) => { + match message { + FromLayoutMsg::SendData(chan) => + painter.send_data(chan), + } + } + CanvasMsg::Canvas2d(_) => panic!("Wrong message sent to WebGLThread"), + CanvasMsg::WebVR(message) => painter.handle_webvr_message(message) + } + } + }).expect("Thread spawning failed"); + + result_port.recv().unwrap().map(|limits| (sender, limits)) + } + + fn send_data(&mut self, chan: IpcSender<CanvasData>) { + match self.data { + WebGLPaintTaskData::Readback { + ref context, + ref webrender_api, + ref mut image_key, + ref mut old_image_key, + ref mut very_old_image_key, + } => { + let width = self.size.width as usize; + let height = self.size.height as usize; + + let mut pixels = context.gl().read_pixels(0, 0, + self.size.width as gl::GLsizei, + self.size.height as gl::GLsizei, + gl::RGBA, gl::UNSIGNED_BYTE); + // flip image vertically (texture is upside down) + let orig_pixels = pixels.clone(); + let stride = width * 4; + for y in 0..height { + let dst_start = y * stride; + let src_start = (height - y - 1) * stride; + let src_slice = &orig_pixels[src_start .. src_start + stride]; + (&mut pixels[dst_start .. dst_start + stride]).clone_from_slice(&src_slice[..stride]); + } + + // rgba -> bgra + byte_swap(&mut pixels); + + let descriptor = webrender_api::ImageDescriptor { + width: width as u32, + height: height as u32, + stride: None, + format: webrender_api::ImageFormat::BGRA8, + offset: 0, + is_opaque: false, + }; + let data = webrender_api::ImageData::Raw(Arc::new(pixels)); + + let mut updates = webrender_api::ResourceUpdates::new(); + + match *image_key { + Some(image_key) => { + updates.update_image(image_key, + descriptor, + data, + None); + } + None => { + *image_key = Some(webrender_api.generate_image_key()); + updates.add_image(image_key.unwrap(), + descriptor, + data, + None); + } + } + + if let Some(image_key) = mem::replace(very_old_image_key, old_image_key.take()) { + updates.delete_image(image_key); + } + + webrender_api.update_resources(updates); + + let image_data = CanvasImageData { + image_key: image_key.unwrap(), + }; + + chan.send(CanvasData::Image(image_data)).unwrap(); + } + WebGLPaintTaskData::WebRender(_, id) => { + chan.send(CanvasData::WebGL(id)).unwrap(); + } + } + } + + #[allow(unsafe_code)] + fn recreate(&mut self, size: Size2D<i32>) -> Result<(), &'static str> { + match self.data { + WebGLPaintTaskData::Readback { ref mut context, ref mut image_key, ref mut old_image_key, .. } => { + if size.width > self.size.width || + size.height > self.size.height { + self.size = context.resize(size)?; + } else { + self.size = size; + context.gl().scissor(0, 0, size.width, size.height); + } + // Webrender doesn't let images change size, so we clear the webrender image key. + if let Some(image_key) = image_key.take() { + // If this executes, then we are in a new epoch since we last recreated the canvas, + // so `old_image_key` must be `None`. + debug_assert!(old_image_key.is_none()); + *old_image_key = Some(image_key); + } + } + WebGLPaintTaskData::WebRender(ref api, id) => { + let device_size = webrender_api::DeviceIntSize::from_untyped(&size); + api.resize_webgl_context(id, &device_size); + } + } + + Ok(()) + } + + fn init(&mut self) { + if let WebGLPaintTaskData::Readback { ref context, .. } = self.data { + context.make_current(); + } + } +} + +impl Drop for WebGLPaintThread { + fn drop(&mut self) { + if let WebGLPaintTaskData::Readback { + ref mut webrender_api, + image_key, + old_image_key, + very_old_image_key, + .. + } = self.data { + let mut updates = webrender_api::ResourceUpdates::new(); + + if let Some(image_key) = image_key { + updates.delete_image(image_key); + } + if let Some(image_key) = old_image_key { + updates.delete_image(image_key); + } + if let Some(image_key) = very_old_image_key { + updates.delete_image(image_key); + } + + webrender_api.update_resources(updates); + } + } +} diff --git a/components/canvas/webgl_thread.rs b/components/canvas/webgl_thread.rs deleted file mode 100644 index 907233a3b89..00000000000 --- a/components/canvas/webgl_thread.rs +++ /dev/null @@ -1,1204 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use canvas_traits::canvas::byte_swap; -use canvas_traits::webgl::*; -use euclid::Size2D; -use gleam::gl; -use offscreen_gl_context::{GLContext, GLContextAttributes, GLLimits, NativeGLContextMethods}; -use std::collections::HashMap; -use std::mem; -use std::thread; -use super::gl_context::{GLContextFactory, GLContextWrapper}; -use webrender; -use webrender_api; - -/// WebGL Threading API entry point that lives in the constellation. -/// It allows to get a WebGLThread handle for each script pipeline. -pub use ::webgl_mode::WebGLThreads; - -/// A WebGLThread manages the life cycle and message multiplexing of -/// a set of WebGLContexts living in the same thread. -pub struct WebGLThread<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> { - /// Factory used to create a new GLContext shared with the WR/Main thread. - gl_factory: GLContextFactory, - /// Channel used to generate/update or delete `webrender_api::ImageKey`s. - webrender_api: webrender_api::RenderApi, - /// Map of live WebGLContexts. - contexts: HashMap<WebGLContextId, GLContextWrapper>, - /// Cached information for WebGLContexts. - cached_context_info: HashMap<WebGLContextId, WebGLContextInfo>, - /// Current bound context. - bound_context_id: Option<WebGLContextId>, - /// Id generator for new WebGLContexts. - next_webgl_id: usize, - /// Handler user to send WebVR commands. - webvr_compositor: Option<VR>, - /// Generic observer that listens WebGLContext creation, resize or removal events. - observer: OB, -} - -impl<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> WebGLThread<VR, OB> { - pub fn new(gl_factory: GLContextFactory, - webrender_api_sender: webrender_api::RenderApiSender, - webvr_compositor: Option<VR>, - observer: OB) -> Self { - WebGLThread { - gl_factory, - webrender_api: webrender_api_sender.create_api(), - contexts: HashMap::new(), - cached_context_info: HashMap::new(), - bound_context_id: None, - next_webgl_id: 0, - webvr_compositor, - observer: observer, - } - } - - /// Creates a new `WebGLThread` and returns a Sender to - /// communicate with it. - pub fn start(gl_factory: GLContextFactory, - webrender_api_sender: webrender_api::RenderApiSender, - webvr_compositor: Option<VR>, - observer: OB) - -> WebGLSender<WebGLMsg> { - let (sender, receiver) = webgl_channel::<WebGLMsg>().unwrap(); - let result = sender.clone(); - thread::Builder::new().name("WebGLThread".to_owned()).spawn(move || { - let mut renderer = WebGLThread::new(gl_factory, - webrender_api_sender, - webvr_compositor, - observer); - let webgl_chan = WebGLChan(sender); - loop { - let msg = receiver.recv().unwrap(); - let exit = renderer.handle_msg(msg, &webgl_chan); - if exit { - return; - } - } - }).expect("Thread spawning failed"); - - result - } - - /// Handles a generic WebGLMsg message - #[inline] - fn handle_msg(&mut self, msg: WebGLMsg, webgl_chan: &WebGLChan) -> bool { - match msg { - WebGLMsg::CreateContext(size, attributes, result_sender) => { - let result = self.create_webgl_context(size, attributes); - result_sender.send(result.map(|(id, limits, share_mode)| - WebGLCreateContextResult { - sender: WebGLMsgSender::new(id, webgl_chan.clone()), - limits: limits, - share_mode: share_mode, - } - )).unwrap(); - }, - WebGLMsg::ResizeContext(ctx_id, size, sender) => { - self.resize_webgl_context(ctx_id, size, sender); - }, - WebGLMsg::RemoveContext(ctx_id) => { - self.remove_webgl_context(ctx_id); - }, - WebGLMsg::WebGLCommand(ctx_id, command) => { - self.handle_webgl_command(ctx_id, command); - }, - WebGLMsg::WebVRCommand(ctx_id, command) => { - self.handle_webvr_command(ctx_id, command); - }, - WebGLMsg::Lock(ctx_id, sender) => { - self.handle_lock(ctx_id, sender); - }, - WebGLMsg::Unlock(ctx_id) => { - self.handle_unlock(ctx_id); - }, - WebGLMsg::UpdateWebRenderImage(ctx_id, sender) => { - self.handle_update_wr_image(ctx_id, sender); - }, - WebGLMsg::Exit => { - return true; - } - } - - false - } - - /// Handles a WebGLCommand for a specific WebGLContext - fn handle_webgl_command(&mut self, context_id: WebGLContextId, command: WebGLCommand) { - if let Some(ctx) = Self::make_current_if_needed(context_id, &self.contexts, &mut self.bound_context_id) { - ctx.apply_command(command); - } - } - - /// Handles a WebVRCommand for a specific WebGLContext - fn handle_webvr_command(&mut self, context_id: WebGLContextId, command: WebVRCommand) { - Self::make_current_if_needed(context_id, &self.contexts, &mut self.bound_context_id); - let texture = match command { - WebVRCommand::SubmitFrame(..) => { - self.cached_context_info.get(&context_id) - }, - _ => None - }; - self.webvr_compositor.as_mut().unwrap().handle(command, texture.map(|t| (t.texture_id, t.size))); - } - - /// Handles a lock external callback received from webrender::ExternalImageHandler - fn handle_lock(&mut self, context_id: WebGLContextId, sender: WebGLSender<(u32, Size2D<i32>)>) { - let ctx = 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(); - // Use a OpenGL Fence to perform the lock. - info.gl_sync = Some(ctx.gl().fence_sync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0)); - - sender.send((info.texture_id, info.size)).unwrap(); - } - - /// Handles an unlock external callback received from webrender::ExternalImageHandler - fn handle_unlock(&mut self, context_id: WebGLContextId) { - let ctx = 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(); - if let Some(gl_sync) = info.gl_sync.take() { - // glFlush must be called before glWaitSync. - ctx.gl().flush(); - // Wait until the GLSync object is signaled. - ctx.gl().wait_sync(gl_sync, 0, gl::TIMEOUT_IGNORED); - // Release the GLSync object. - ctx.gl().delete_sync(gl_sync); - } - } - - /// Creates a new WebGLContext - fn create_webgl_context(&mut self, - size: Size2D<i32>, - attributes: GLContextAttributes) - -> Result<(WebGLContextId, GLLimits, WebGLContextShareMode), String> { - // First try to create a shared context for the best performance. - // Fallback to readback mode if the shared context creation fails. - let result = self.gl_factory.new_shared_context(size, attributes) - .map(|r| (r, WebGLContextShareMode::SharedTexture)) - .or_else(|_| { - let ctx = self.gl_factory.new_context(size, attributes); - ctx.map(|r| (r, WebGLContextShareMode::Readback)) - }); - - // Creating a new GLContext may make the current bound context_id dirty. - // Clear it to ensure that make_current() is called in subsequent commands. - self.bound_context_id = None; - - match result { - Ok((ctx, share_mode)) => { - let id = WebGLContextId(self.next_webgl_id); - let (size, texture_id, limits) = ctx.get_info(); - self.next_webgl_id += 1; - self.contexts.insert(id, ctx); - self.cached_context_info.insert(id, WebGLContextInfo { - texture_id, - size, - alpha: attributes.alpha, - image_key: None, - share_mode, - gl_sync: None, - old_image_key: None, - very_old_image_key: None, - }); - - self.observer.on_context_create(id, texture_id, size); - - Ok((id, limits, share_mode)) - }, - Err(msg) => { - Err(msg.to_owned()) - } - } - } - - /// Resizes a WebGLContext - fn resize_webgl_context(&mut self, - context_id: WebGLContextId, - size: Size2D<i32>, - sender: WebGLSender<Result<(), String>>) { - let ctx = Self::make_current_if_needed_mut(context_id, &mut self.contexts, &mut self.bound_context_id); - match ctx.resize(size) { - Ok(_) => { - let (real_size, texture_id, _) = ctx.get_info(); - self.observer.on_context_resize(context_id, texture_id, real_size); - - let info = self.cached_context_info.get_mut(&context_id).unwrap(); - // Update webgl texture size. Texture id may change too. - info.texture_id = texture_id; - info.size = real_size; - // WR doesn't support resizing and requires to create a new `ImageKey`. - // Mark the current image_key to be deleted later in the next epoch. - if let Some(image_key) = info.image_key.take() { - // If this executes, then we are in a new epoch since we last recreated the canvas, - // so `old_image_key` must be `None`. - debug_assert!(info.old_image_key.is_none()); - info.old_image_key = Some(image_key); - } - - sender.send(Ok(())).unwrap(); - }, - Err(msg) => { - sender.send(Err(msg.into())).unwrap(); - } - } - } - - /// Removes a WebGLContext and releases attached resources. - fn remove_webgl_context(&mut self, context_id: WebGLContextId) { - // Release webrender image keys. - if let Some(info) = self.cached_context_info.remove(&context_id) { - let mut updates = webrender_api::ResourceUpdates::new(); - - if let Some(image_key) = info.image_key { - updates.delete_image(image_key); - } - if let Some(image_key) = info.old_image_key { - updates.delete_image(image_key); - } - if let Some(image_key) = info.very_old_image_key { - updates.delete_image(image_key); - } - - self.webrender_api.update_resources(updates) - } - - // Release GL context. - if self.contexts.remove(&context_id).is_some() { - self.observer.on_context_delete(context_id); - } - - // Removing a GLContext may make the current bound context_id dirty. - self.bound_context_id = None; - } - - /// Handles the creation/update of webrender_api::ImageKeys fpr a specific WebGLContext. - /// This method is invoked from a UpdateWebRenderImage message sent by the layout thread. - /// If SharedTexture is used the UpdateWebRenderImage message is sent only after a WebGLContext creation or resize. - /// If Readback is used UpdateWebRenderImage message is sent always on each layout iteration in order to - /// submit the updated raw pixels. - fn handle_update_wr_image(&mut self, context_id: WebGLContextId, sender: WebGLSender<webrender_api::ImageKey>) { - let info = self.cached_context_info.get_mut(&context_id).unwrap(); - let webrender_api = &self.webrender_api; - - let image_key = match info.share_mode { - WebGLContextShareMode::SharedTexture => { - let size = info.size; - let alpha = info.alpha; - // Reuse existing ImageKey or generate a new one. - // When using a shared texture ImageKeys are only generated after a WebGLContext creation or resize. - *info.image_key.get_or_insert_with(|| { - Self::create_wr_external_image(webrender_api, size, alpha, context_id) - }) - }, - WebGLContextShareMode::Readback => { - let pixels = Self::raw_pixels(&self.contexts[&context_id], info.size); - match info.image_key.clone() { - Some(image_key) => { - // ImageKey was already created, but WR Images must - // be updated every frame in readback mode to send the new raw pixels. - Self::update_wr_readback_image(webrender_api, - info.size, - info.alpha, - image_key, - pixels); - - image_key - }, - None => { - // Generate a new ImageKey for Readback mode. - let image_key = Self::create_wr_readback_image(webrender_api, - info.size, - info.alpha, - pixels); - info.image_key = Some(image_key); - image_key - } - } - } - }; - - // Delete old image - if let Some(image_key) = mem::replace(&mut info.very_old_image_key, info.old_image_key.take()) { - let mut updates = webrender_api::ResourceUpdates::new(); - updates.delete_image(image_key); - self.webrender_api.update_resources(updates); - } - - // Send the ImageKey to the Layout thread. - sender.send(image_key).unwrap(); - } - - /// 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 HashMap<WebGLContextId, GLContextWrapper>, - bound_id: &mut Option<WebGLContextId>) -> Option<&'a GLContextWrapper> { - contexts.get(&context_id).and_then(|ctx| { - if Some(context_id) != *bound_id { - ctx.make_current(); - *bound_id = Some(context_id); - } - - Some(ctx) - }) - } - - /// Gets a mutable reference to a GLContextWrapper for a WebGLContextId and makes it current if required. - fn make_current_if_needed_mut<'a>(context_id: WebGLContextId, - contexts: &'a mut HashMap<WebGLContextId, GLContextWrapper>, - bound_id: &mut Option<WebGLContextId>) -> &'a mut GLContextWrapper { - let ctx = contexts.get_mut(&context_id).expect("WebGLContext not found!"); - if Some(context_id) != *bound_id { - ctx.make_current(); - *bound_id = Some(context_id); - } - ctx - } - - /// Creates a `webrender_api::ImageKey` that uses shared textures. - fn create_wr_external_image(webrender_api: &webrender_api::RenderApi, - size: Size2D<i32>, - alpha: bool, - context_id: WebGLContextId) -> webrender_api::ImageKey { - let descriptor = Self::image_descriptor(size, alpha); - - let data = webrender_api::ExternalImageData { - id: webrender_api::ExternalImageId(context_id.0 as u64), - channel_index: 0, - image_type: webrender_api::ExternalImageType::Texture2DHandle, - }; - let data = webrender_api::ImageData::External(data); - - let image_key = webrender_api.generate_image_key(); - let mut updates = webrender_api::ResourceUpdates::new(); - updates.add_image(image_key, - descriptor, - data, - None); - webrender_api.update_resources(updates); - - image_key - } - - /// Creates a `webrender_api::ImageKey` that uses raw pixels. - fn create_wr_readback_image(webrender_api: &webrender_api::RenderApi, - size: Size2D<i32>, - alpha: bool, - data: Vec<u8>) -> webrender_api::ImageKey { - let descriptor = Self::image_descriptor(size, alpha); - let data = webrender_api::ImageData::new(data); - - let image_key = webrender_api.generate_image_key(); - let mut updates = webrender_api::ResourceUpdates::new(); - updates.add_image(image_key, - descriptor, - data, - None); - webrender_api.update_resources(updates); - - image_key - } - - /// Updates a `webrender_api::ImageKey` that uses raw pixels. - fn update_wr_readback_image(webrender_api: &webrender_api::RenderApi, - size: Size2D<i32>, - alpha: bool, - image_key: webrender_api::ImageKey, - data: Vec<u8>) { - let descriptor = Self::image_descriptor(size, alpha); - let data = webrender_api::ImageData::new(data); - - let mut updates = webrender_api::ResourceUpdates::new(); - updates.update_image(image_key, - descriptor, - data, - None); - webrender_api.update_resources(updates); - } - - /// Helper function to create a `webrender_api::ImageDescriptor`. - fn image_descriptor(size: Size2D<i32>, alpha: bool) -> webrender_api::ImageDescriptor { - webrender_api::ImageDescriptor { - width: size.width as u32, - height: size.height as u32, - stride: None, - format: if alpha { webrender_api::ImageFormat::BGRA8 } else { webrender_api::ImageFormat::RGB8 }, - offset: 0, - is_opaque: !alpha, - } - } - - /// Helper function to fetch the raw pixels used in readback mode. - fn raw_pixels(context: &GLContextWrapper, size: Size2D<i32>) -> Vec<u8> { - let width = size.width as usize; - let height = size.height as usize; - - let mut pixels = context.gl().read_pixels(0, 0, - size.width as gl::GLsizei, - size.height as gl::GLsizei, - gl::RGBA, gl::UNSIGNED_BYTE); - // flip image vertically (texture is upside down) - let orig_pixels = pixels.clone(); - let stride = width * 4; - for y in 0..height { - let dst_start = y * stride; - let src_start = (height - y - 1) * stride; - let src_slice = &orig_pixels[src_start .. src_start + stride]; - (&mut pixels[dst_start .. dst_start + stride]).clone_from_slice(&src_slice[..stride]); - } - byte_swap(&mut pixels); - pixels - } -} - -impl<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> Drop for WebGLThread<VR, OB> { - fn drop(&mut self) { - // Call remove_context functions in order to correctly delete WebRender image keys. - let context_ids: Vec<WebGLContextId> = self.contexts.keys().map(|id| *id).collect(); - for id in context_ids { - self.remove_webgl_context(id); - } - } -} - -/// Helper struct to store cached WebGLContext information. -struct WebGLContextInfo { - /// Render to texture identifier used by the WebGLContext. - texture_id: u32, - /// Size of the WebGLContext. - size: Size2D<i32>, - /// True if the WebGLContext uses an alpha channel. - alpha: bool, - /// Currently used WebRender image key. - image_key: Option<webrender_api::ImageKey>, - /// The sharing mode used to send the image to WebRender. - share_mode: WebGLContextShareMode, - /// GLSync Object used for a correct synchronization with Webrender external image callbacks. - gl_sync: Option<gl::GLsync>, - /// An old WebRender image key that can be deleted when the next epoch ends. - old_image_key: Option<webrender_api::ImageKey>, - /// An old WebRender image key that can be deleted when the current epoch ends. - very_old_image_key: Option<webrender_api::ImageKey>, -} - -/// Trait used to observe events in a WebGL Thread. -/// Used in webrender::ExternalImageHandler when multiple WebGL threads are used. -pub trait WebGLThreadObserver: Send + 'static { - fn on_context_create(&mut self, ctx_id: WebGLContextId, texture_id: u32, size: Size2D<i32>); - fn on_context_resize(&mut self, ctx_id: WebGLContextId, texture_id: u32, size: Size2D<i32>); - fn on_context_delete(&mut self, ctx_id: WebGLContextId); -} - -/// This trait is used as a bridge between the `WebGLThreads` implementation and -/// the WR ExternalImageHandler API implemented in the `WebGLExternalImageHandler` struct. -/// `WebGLExternalImageHandler<T>` takes care of type conversions between WR and WebGL info (e.g keys, uvs). -/// It uses this trait to notify lock/unlock messages and get the required info that WR needs. -/// `WebGLThreads` receives lock/unlock message notifications and takes care of sending -/// the unlock/lock messages to the appropiate `WebGLThread`. -pub trait WebGLExternalImageApi { - fn lock(&mut self, ctx_id: WebGLContextId) -> (u32, Size2D<i32>); - fn unlock(&mut self, ctx_id: WebGLContextId); -} - -/// WebRender External Image Handler implementation -pub struct WebGLExternalImageHandler<T: WebGLExternalImageApi> { - handler: T, -} - -impl<T: WebGLExternalImageApi> WebGLExternalImageHandler<T> { - pub fn new(handler: T) -> Self { - Self { - handler: handler - } - } -} - -impl<T: WebGLExternalImageApi> webrender::ExternalImageHandler for WebGLExternalImageHandler<T> { - /// Lock the external image. Then, WR could start to read the image content. - /// The WR client should not change the image content until the unlock() call. - fn lock(&mut self, - key: webrender_api::ExternalImageId, - _channel_index: u8) -> webrender::ExternalImage { - let ctx_id = WebGLContextId(key.0 as _); - let (texture_id, size) = self.handler.lock(ctx_id); - - webrender::ExternalImage { - u0: 0.0, - u1: size.width as f32, - v1: 0.0, - v0: size.height as f32, - source: webrender::ExternalImageSource::NativeTexture(texture_id), - } - - } - /// Unlock the external image. The WR should not read the image content - /// after this call. - fn unlock(&mut self, - key: webrender_api::ExternalImageId, - _channel_index: u8) { - let ctx_id = WebGLContextId(key.0 as _); - self.handler.unlock(ctx_id); - } -} - -/// WebGL Commands Implementation -pub struct WebGLImpl; - -impl WebGLImpl { - pub fn apply<Native: NativeGLContextMethods>(ctx: &GLContext<Native>, command: WebGLCommand) { - match command { - WebGLCommand::GetContextAttributes(sender) => - sender.send(*ctx.borrow_attributes()).unwrap(), - WebGLCommand::ActiveTexture(target) => - ctx.gl().active_texture(target), - WebGLCommand::AttachShader(program_id, shader_id) => - ctx.gl().attach_shader(program_id.get(), shader_id.get()), - WebGLCommand::DetachShader(program_id, shader_id) => - ctx.gl().detach_shader(program_id.get(), shader_id.get()), - WebGLCommand::BindAttribLocation(program_id, index, name) => - ctx.gl().bind_attrib_location(program_id.get(), index, &name), - WebGLCommand::BlendColor(r, g, b, a) => - ctx.gl().blend_color(r, g, b, a), - WebGLCommand::BlendEquation(mode) => - ctx.gl().blend_equation(mode), - WebGLCommand::BlendEquationSeparate(mode_rgb, mode_alpha) => - ctx.gl().blend_equation_separate(mode_rgb, mode_alpha), - WebGLCommand::BlendFunc(src, dest) => - ctx.gl().blend_func(src, dest), - WebGLCommand::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha) => - ctx.gl().blend_func_separate(src_rgb, dest_rgb, src_alpha, dest_alpha), - WebGLCommand::BufferData(buffer_type, data, usage) => - gl::buffer_data(ctx.gl(), buffer_type, &data, usage), - WebGLCommand::BufferSubData(buffer_type, offset, data) => - gl::buffer_sub_data(ctx.gl(), buffer_type, offset, &data), - WebGLCommand::Clear(mask) => - ctx.gl().clear(mask), - WebGLCommand::ClearColor(r, g, b, a) => - ctx.gl().clear_color(r, g, b, a), - WebGLCommand::ClearDepth(depth) => - ctx.gl().clear_depth(depth), - WebGLCommand::ClearStencil(stencil) => - ctx.gl().clear_stencil(stencil), - WebGLCommand::ColorMask(r, g, b, a) => - ctx.gl().color_mask(r, g, b, a), - WebGLCommand::CopyTexImage2D(target, level, internal_format, x, y, width, height, border) => - ctx.gl().copy_tex_image_2d(target, level, internal_format, x, y, width, height, border), - WebGLCommand::CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height) => - ctx.gl().copy_tex_sub_image_2d(target, level, xoffset, yoffset, x, y, width, height), - WebGLCommand::CullFace(mode) => - ctx.gl().cull_face(mode), - WebGLCommand::DepthFunc(func) => - ctx.gl().depth_func(func), - WebGLCommand::DepthMask(flag) => - ctx.gl().depth_mask(flag), - WebGLCommand::DepthRange(near, far) => - ctx.gl().depth_range(near, far), - WebGLCommand::Disable(cap) => - ctx.gl().disable(cap), - WebGLCommand::Enable(cap) => - ctx.gl().enable(cap), - WebGLCommand::FramebufferRenderbuffer(target, attachment, renderbuffertarget, rb) => - ctx.gl().framebuffer_renderbuffer(target, attachment, renderbuffertarget, - rb.map_or(0, WebGLRenderbufferId::get)), - WebGLCommand::FramebufferTexture2D(target, attachment, textarget, texture, level) => - ctx.gl().framebuffer_texture_2d(target, attachment, textarget, - texture.map_or(0, WebGLTextureId::get), level), - WebGLCommand::FrontFace(mode) => - ctx.gl().front_face(mode), - WebGLCommand::DisableVertexAttribArray(attrib_id) => - ctx.gl().disable_vertex_attrib_array(attrib_id), - WebGLCommand::DrawArrays(mode, first, count) => - ctx.gl().draw_arrays(mode, first, count), - WebGLCommand::DrawElements(mode, count, type_, offset) => - ctx.gl().draw_elements(mode, count, type_, offset as u32), - WebGLCommand::EnableVertexAttribArray(attrib_id) => - ctx.gl().enable_vertex_attrib_array(attrib_id), - WebGLCommand::Hint(name, val) => - ctx.gl().hint(name, val), - WebGLCommand::IsEnabled(cap, chan) => - chan.send(ctx.gl().is_enabled(cap) != 0).unwrap(), - WebGLCommand::LineWidth(width) => - ctx.gl().line_width(width), - WebGLCommand::PixelStorei(name, val) => - ctx.gl().pixel_store_i(name, val), - WebGLCommand::PolygonOffset(factor, units) => - ctx.gl().polygon_offset(factor, units), - WebGLCommand::ReadPixels(x, y, width, height, format, pixel_type, chan) => - Self::read_pixels(ctx.gl(), x, y, width, height, format, pixel_type, chan), - WebGLCommand::RenderbufferStorage(target, format, width, height) => - ctx.gl().renderbuffer_storage(target, format, width, height), - WebGLCommand::SampleCoverage(value, invert) => - ctx.gl().sample_coverage(value, invert), - WebGLCommand::Scissor(x, y, width, height) => - ctx.gl().scissor(x, y, width, height), - WebGLCommand::StencilFunc(func, ref_, mask) => - ctx.gl().stencil_func(func, ref_, mask), - WebGLCommand::StencilFuncSeparate(face, func, ref_, mask) => - ctx.gl().stencil_func_separate(face, func, ref_, mask), - WebGLCommand::StencilMask(mask) => - ctx.gl().stencil_mask(mask), - WebGLCommand::StencilMaskSeparate(face, mask) => - ctx.gl().stencil_mask_separate(face, mask), - WebGLCommand::StencilOp(fail, zfail, zpass) => - ctx.gl().stencil_op(fail, zfail, zpass), - WebGLCommand::StencilOpSeparate(face, fail, zfail, zpass) => - ctx.gl().stencil_op_separate(face, fail, zfail, zpass), - WebGLCommand::GetActiveAttrib(program_id, index, chan) => - Self::active_attrib(ctx.gl(), program_id, index, chan), - WebGLCommand::GetActiveUniform(program_id, index, chan) => - Self::active_uniform(ctx.gl(), program_id, index, chan), - WebGLCommand::GetAttribLocation(program_id, name, chan) => - Self::attrib_location(ctx.gl(), program_id, name, chan), - WebGLCommand::GetVertexAttrib(index, pname, chan) => - Self::vertex_attrib(ctx.gl(), index, pname, chan), - WebGLCommand::GetVertexAttribOffset(index, pname, chan) => - Self::vertex_attrib_offset(ctx.gl(), index, pname, chan), - WebGLCommand::GetBufferParameter(target, param_id, chan) => - Self::buffer_parameter(ctx.gl(), target, param_id, chan), - WebGLCommand::GetParameter(param_id, chan) => - Self::parameter(ctx.gl(), param_id, chan), - WebGLCommand::GetProgramParameter(program_id, param_id, chan) => - Self::program_parameter(ctx.gl(), program_id, param_id, chan), - WebGLCommand::GetShaderParameter(shader_id, param_id, chan) => - Self::shader_parameter(ctx.gl(), shader_id, param_id, chan), - WebGLCommand::GetShaderPrecisionFormat(shader_type, precision_type, chan) => - Self::shader_precision_format(ctx.gl(), shader_type, precision_type, chan), - WebGLCommand::GetExtensions(chan) => - Self::get_extensions(ctx.gl(), chan), - WebGLCommand::GetUniformLocation(program_id, name, chan) => - Self::uniform_location(ctx.gl(), program_id, name, chan), - WebGLCommand::GetShaderInfoLog(shader_id, chan) => - Self::shader_info_log(ctx.gl(), shader_id, chan), - WebGLCommand::GetProgramInfoLog(program_id, chan) => - Self::program_info_log(ctx.gl(), program_id, chan), - WebGLCommand::CompileShader(shader_id, source) => - Self::compile_shader(ctx.gl(), shader_id, source), - WebGLCommand::CreateBuffer(chan) => - Self::create_buffer(ctx.gl(), chan), - WebGLCommand::CreateFramebuffer(chan) => - Self::create_framebuffer(ctx.gl(), chan), - WebGLCommand::CreateRenderbuffer(chan) => - Self::create_renderbuffer(ctx.gl(), chan), - WebGLCommand::CreateTexture(chan) => - Self::create_texture(ctx.gl(), chan), - WebGLCommand::CreateProgram(chan) => - Self::create_program(ctx.gl(), chan), - WebGLCommand::CreateShader(shader_type, chan) => - Self::create_shader(ctx.gl(), shader_type, chan), - WebGLCommand::DeleteBuffer(id) => - ctx.gl().delete_buffers(&[id.get()]), - WebGLCommand::DeleteFramebuffer(id) => - ctx.gl().delete_framebuffers(&[id.get()]), - WebGLCommand::DeleteRenderbuffer(id) => - ctx.gl().delete_renderbuffers(&[id.get()]), - WebGLCommand::DeleteTexture(id) => - ctx.gl().delete_textures(&[id.get()]), - WebGLCommand::DeleteProgram(id) => - ctx.gl().delete_program(id.get()), - WebGLCommand::DeleteShader(id) => - ctx.gl().delete_shader(id.get()), - WebGLCommand::BindBuffer(target, id) => - ctx.gl().bind_buffer(target, id.map_or(0, WebGLBufferId::get)), - WebGLCommand::BindFramebuffer(target, request) => - Self::bind_framebuffer(ctx.gl(), target, request, ctx), - WebGLCommand::BindRenderbuffer(target, id) => - ctx.gl().bind_renderbuffer(target, id.map_or(0, WebGLRenderbufferId::get)), - WebGLCommand::BindTexture(target, id) => - ctx.gl().bind_texture(target, id.map_or(0, WebGLTextureId::get)), - WebGLCommand::LinkProgram(program_id) => - ctx.gl().link_program(program_id.get()), - WebGLCommand::Uniform1f(uniform_id, v) => - ctx.gl().uniform_1f(uniform_id, v), - WebGLCommand::Uniform1fv(uniform_id, v) => - ctx.gl().uniform_1fv(uniform_id, &v), - WebGLCommand::Uniform1i(uniform_id, v) => - ctx.gl().uniform_1i(uniform_id, v), - WebGLCommand::Uniform1iv(uniform_id, v) => - ctx.gl().uniform_1iv(uniform_id, &v), - WebGLCommand::Uniform2f(uniform_id, x, y) => - ctx.gl().uniform_2f(uniform_id, x, y), - WebGLCommand::Uniform2fv(uniform_id, v) => - ctx.gl().uniform_2fv(uniform_id, &v), - WebGLCommand::Uniform2i(uniform_id, x, y) => - ctx.gl().uniform_2i(uniform_id, x, y), - WebGLCommand::Uniform2iv(uniform_id, v) => - ctx.gl().uniform_2iv(uniform_id, &v), - WebGLCommand::Uniform3f(uniform_id, x, y, z) => - ctx.gl().uniform_3f(uniform_id, x, y, z), - WebGLCommand::Uniform3fv(uniform_id, v) => - ctx.gl().uniform_3fv(uniform_id, &v), - WebGLCommand::Uniform3i(uniform_id, x, y, z) => - ctx.gl().uniform_3i(uniform_id, x, y, z), - WebGLCommand::Uniform3iv(uniform_id, v) => - ctx.gl().uniform_3iv(uniform_id, &v), - WebGLCommand::Uniform4f(uniform_id, x, y, z, w) => - ctx.gl().uniform_4f(uniform_id, x, y, z, w), - WebGLCommand::Uniform4fv(uniform_id, v) => - ctx.gl().uniform_4fv(uniform_id, &v), - WebGLCommand::Uniform4i(uniform_id, x, y, z, w) => - ctx.gl().uniform_4i(uniform_id, x, y, z, w), - WebGLCommand::Uniform4iv(uniform_id, v) => - ctx.gl().uniform_4iv(uniform_id, &v), - WebGLCommand::UniformMatrix2fv(uniform_id, transpose, v) => - ctx.gl().uniform_matrix_2fv(uniform_id, transpose, &v), - WebGLCommand::UniformMatrix3fv(uniform_id, transpose, v) => - ctx.gl().uniform_matrix_3fv(uniform_id, transpose, &v), - WebGLCommand::UniformMatrix4fv(uniform_id, transpose, v) => - ctx.gl().uniform_matrix_4fv(uniform_id, transpose, &v), - WebGLCommand::UseProgram(program_id) => - ctx.gl().use_program(program_id.get()), - WebGLCommand::ValidateProgram(program_id) => - ctx.gl().validate_program(program_id.get()), - WebGLCommand::VertexAttrib(attrib_id, x, y, z, w) => - ctx.gl().vertex_attrib_4f(attrib_id, x, y, z, w), - WebGLCommand::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset) => - ctx.gl().vertex_attrib_pointer_f32(attrib_id, size, normalized, stride, offset), - WebGLCommand::VertexAttribPointer(attrib_id, size, data_type, normalized, stride, offset) => - ctx.gl().vertex_attrib_pointer(attrib_id, size, data_type, normalized, stride, offset), - WebGLCommand::Viewport(x, y, width, height) => - ctx.gl().viewport(x, y, width, height), - WebGLCommand::TexImage2D(target, level, internal, width, height, format, data_type, data) => - ctx.gl().tex_image_2d(target, level, internal, width, height, - /*border*/0, format, data_type, Some(&data)), - WebGLCommand::TexParameteri(target, name, value) => - ctx.gl().tex_parameter_i(target, name, value), - WebGLCommand::TexParameterf(target, name, value) => - ctx.gl().tex_parameter_f(target, name, value), - WebGLCommand::TexSubImage2D(target, level, xoffset, yoffset, x, y, width, height, data) => - ctx.gl().tex_sub_image_2d(target, level, xoffset, yoffset, x, y, width, height, &data), - WebGLCommand::DrawingBufferWidth(sender) => - sender.send(ctx.borrow_draw_buffer().unwrap().size().width).unwrap(), - WebGLCommand::DrawingBufferHeight(sender) => - sender.send(ctx.borrow_draw_buffer().unwrap().size().height).unwrap(), - WebGLCommand::Finish(sender) => - Self::finish(ctx.gl(), sender), - WebGLCommand::Flush => - ctx.gl().flush(), - WebGLCommand::GenerateMipmap(target) => - ctx.gl().generate_mipmap(target), - WebGLCommand::CreateVertexArray(chan) => - Self::create_vertex_array(ctx.gl(), chan), - WebGLCommand::DeleteVertexArray(id) => - ctx.gl().delete_vertex_arrays(&[id.get()]), - WebGLCommand::BindVertexArray(id) => - ctx.gl().bind_vertex_array(id.map_or(0, WebGLVertexArrayId::get)), - } - - // TODO: update test expectations in order to enable debug assertions - //if cfg!(debug_assertions) { - let error = ctx.gl().get_error(); - assert!(error == gl::NO_ERROR, "Unexpected WebGL error: 0x{:x} ({})", error, error); - //} - } - - fn read_pixels(gl: &gl::Gl, x: i32, y: i32, width: i32, height: i32, format: u32, pixel_type: u32, - chan: WebGLSender<Vec<u8>>) { - let result = gl.read_pixels(x, y, width, height, format, pixel_type); - chan.send(result).unwrap() - } - - fn active_attrib(gl: &gl::Gl, - program_id: WebGLProgramId, - index: u32, - chan: WebGLSender<WebGLResult<(i32, u32, String)>>) { - let result = if index >= gl.get_program_iv(program_id.get(), gl::ACTIVE_ATTRIBUTES) as u32 { - Err(WebGLError::InvalidValue) - } else { - Ok(gl.get_active_attrib(program_id.get(), index)) - }; - chan.send(result).unwrap(); - } - - fn active_uniform(gl: &gl::Gl, - program_id: WebGLProgramId, - index: u32, - chan: WebGLSender<WebGLResult<(i32, u32, String)>>) { - let result = if index >= gl.get_program_iv(program_id.get(), gl::ACTIVE_UNIFORMS) as u32 { - Err(WebGLError::InvalidValue) - } else { - Ok(gl.get_active_uniform(program_id.get(), index)) - }; - chan.send(result).unwrap(); - } - - fn attrib_location(gl: &gl::Gl, - program_id: WebGLProgramId, - name: String, - chan: WebGLSender<Option<i32>> ) { - let attrib_location = gl.get_attrib_location(program_id.get(), &name); - - let attrib_location = if attrib_location == -1 { - None - } else { - Some(attrib_location) - }; - - chan.send(attrib_location).unwrap(); - } - - fn parameter(gl: &gl::Gl, - param_id: u32, - chan: WebGLSender<WebGLResult<WebGLParameter>>) { - let result = match param_id { - gl::ACTIVE_TEXTURE | - gl::ALPHA_BITS | - gl::BLEND_DST_ALPHA | - gl::BLEND_DST_RGB | - gl::BLEND_EQUATION_ALPHA | - gl::BLEND_EQUATION_RGB | - gl::BLEND_SRC_ALPHA | - gl::BLEND_SRC_RGB | - gl::BLUE_BITS | - gl::CULL_FACE_MODE | - gl::DEPTH_BITS | - gl::DEPTH_FUNC | - gl::FRONT_FACE | - //gl::GENERATE_MIPMAP_HINT | - gl::GREEN_BITS | - //gl::IMPLEMENTATION_COLOR_READ_FORMAT | - //gl::IMPLEMENTATION_COLOR_READ_TYPE | - gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS | - gl::MAX_CUBE_MAP_TEXTURE_SIZE | - //gl::MAX_FRAGMENT_UNIFORM_VECTORS | - gl::MAX_RENDERBUFFER_SIZE | - gl::MAX_TEXTURE_IMAGE_UNITS | - gl::MAX_TEXTURE_SIZE | - //gl::MAX_VARYING_VECTORS | - gl::MAX_VERTEX_ATTRIBS | - gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS | - //gl::MAX_VERTEX_UNIFORM_VECTORS | - gl::PACK_ALIGNMENT | - gl::RED_BITS | - gl::SAMPLE_BUFFERS | - gl::SAMPLES | - gl::STENCIL_BACK_FAIL | - gl::STENCIL_BACK_FUNC | - gl::STENCIL_BACK_PASS_DEPTH_FAIL | - gl::STENCIL_BACK_PASS_DEPTH_PASS | - gl::STENCIL_BACK_REF | - gl::STENCIL_BACK_VALUE_MASK | - gl::STENCIL_BACK_WRITEMASK | - gl::STENCIL_BITS | - gl::STENCIL_CLEAR_VALUE | - gl::STENCIL_FAIL | - gl::STENCIL_FUNC | - gl::STENCIL_PASS_DEPTH_FAIL | - gl::STENCIL_PASS_DEPTH_PASS | - gl::STENCIL_REF | - gl::STENCIL_VALUE_MASK | - gl::STENCIL_WRITEMASK | - gl::SUBPIXEL_BITS | - gl::UNPACK_ALIGNMENT => - //gl::UNPACK_COLORSPACE_CONVERSION_WEBGL => - Ok(WebGLParameter::Int(gl.get_integer_v(param_id))), - - gl::BLEND | - gl::CULL_FACE | - gl::DEPTH_TEST | - gl::DEPTH_WRITEMASK | - gl::DITHER | - gl::POLYGON_OFFSET_FILL | - gl::SAMPLE_COVERAGE_INVERT | - gl::STENCIL_TEST => - //gl::UNPACK_FLIP_Y_WEBGL | - //gl::UNPACK_PREMULTIPLY_ALPHA_WEBGL => - Ok(WebGLParameter::Bool(gl.get_boolean_v(param_id) != 0)), - - gl::DEPTH_CLEAR_VALUE | - gl::LINE_WIDTH | - gl::POLYGON_OFFSET_FACTOR | - gl::POLYGON_OFFSET_UNITS | - gl::SAMPLE_COVERAGE_VALUE => - Ok(WebGLParameter::Float(gl.get_float_v(param_id))), - - gl::VERSION => Ok(WebGLParameter::String("WebGL 1.0".to_owned())), - gl::RENDERER | - gl::VENDOR => Ok(WebGLParameter::String("Mozilla/Servo".to_owned())), - gl::SHADING_LANGUAGE_VERSION => Ok(WebGLParameter::String("WebGL GLSL ES 1.0".to_owned())), - - // TODO(zbarsky, emilio): Implement support for the following valid parameters - // Float32Array - gl::ALIASED_LINE_WIDTH_RANGE | - //gl::ALIASED_POINT_SIZE_RANGE | - //gl::BLEND_COLOR | - gl::COLOR_CLEAR_VALUE | - gl::DEPTH_RANGE | - - // WebGLBuffer - gl::ARRAY_BUFFER_BINDING | - gl::ELEMENT_ARRAY_BUFFER_BINDING | - - // WebGLFrameBuffer - gl::FRAMEBUFFER_BINDING | - - // WebGLRenderBuffer - gl::RENDERBUFFER_BINDING | - - // WebGLProgram - gl::CURRENT_PROGRAM | - - // WebGLTexture - gl::TEXTURE_BINDING_2D | - gl::TEXTURE_BINDING_CUBE_MAP | - - // sequence<GlBoolean> - gl::COLOR_WRITEMASK | - - // Uint32Array - gl::COMPRESSED_TEXTURE_FORMATS | - - // Int32Array - gl::MAX_VIEWPORT_DIMS | - gl::SCISSOR_BOX | - gl::VIEWPORT => Err(WebGLError::InvalidEnum), - - // Invalid parameters - _ => Err(WebGLError::InvalidEnum) - }; - - chan.send(result).unwrap(); - } - - fn finish(gl: &gl::Gl, chan: WebGLSender<()>) { - gl.finish(); - chan.send(()).unwrap(); - } - - fn vertex_attrib(gl: &gl::Gl, - index: u32, - pname: u32, - chan: WebGLSender<WebGLResult<WebGLParameter>>) { - let result = if index >= gl.get_integer_v(gl::MAX_VERTEX_ATTRIBS) as u32 { - Err(WebGLError::InvalidValue) - } else { - match pname { - gl::VERTEX_ATTRIB_ARRAY_ENABLED | - gl::VERTEX_ATTRIB_ARRAY_NORMALIZED => - Ok(WebGLParameter::Bool(gl.get_vertex_attrib_iv(index, pname) != 0)), - gl::VERTEX_ATTRIB_ARRAY_SIZE | - gl::VERTEX_ATTRIB_ARRAY_STRIDE | - gl::VERTEX_ATTRIB_ARRAY_TYPE => - Ok(WebGLParameter::Int(gl.get_vertex_attrib_iv(index, pname))), - gl::CURRENT_VERTEX_ATTRIB => - Ok(WebGLParameter::FloatArray(gl.get_vertex_attrib_fv(index, pname))), - // gl::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING should return WebGLBuffer - _ => Err(WebGLError::InvalidEnum), - } - }; - - chan.send(result).unwrap(); - } - - fn vertex_attrib_offset(gl: &gl::Gl, - index: u32, - pname: u32, - chan: WebGLSender<WebGLResult<isize>>) { - let result = match pname { - gl::VERTEX_ATTRIB_ARRAY_POINTER => Ok(gl.get_vertex_attrib_pointer_v(index, pname)), - _ => Err(WebGLError::InvalidEnum), - }; - - chan.send(result).unwrap(); - } - - fn buffer_parameter(gl: &gl::Gl, - target: u32, - param_id: u32, - chan: WebGLSender<WebGLResult<WebGLParameter>>) { - let result = match param_id { - gl::BUFFER_SIZE | - gl::BUFFER_USAGE => - Ok(WebGLParameter::Int(gl.get_buffer_parameter_iv(target, param_id))), - _ => Err(WebGLError::InvalidEnum), - }; - - chan.send(result).unwrap(); - } - - fn program_parameter(gl: &gl::Gl, - program_id: WebGLProgramId, - param_id: u32, - chan: WebGLSender<WebGLResult<WebGLParameter>>) { - let result = match param_id { - gl::DELETE_STATUS | - gl::LINK_STATUS | - gl::VALIDATE_STATUS => - Ok(WebGLParameter::Bool(gl.get_program_iv(program_id.get(), param_id) != 0)), - gl::ATTACHED_SHADERS | - gl::ACTIVE_ATTRIBUTES | - gl::ACTIVE_UNIFORMS => - Ok(WebGLParameter::Int(gl.get_program_iv(program_id.get(), param_id))), - _ => Err(WebGLError::InvalidEnum), - }; - - chan.send(result).unwrap(); - } - - fn shader_parameter(gl: &gl::Gl, - shader_id: WebGLShaderId, - param_id: u32, - chan: WebGLSender<WebGLResult<WebGLParameter>>) { - let result = match param_id { - gl::SHADER_TYPE => - Ok(WebGLParameter::Int(gl.get_shader_iv(shader_id.get(), param_id))), - gl::DELETE_STATUS | - gl::COMPILE_STATUS => - Ok(WebGLParameter::Bool(gl.get_shader_iv(shader_id.get(), param_id) != 0)), - _ => Err(WebGLError::InvalidEnum), - }; - - chan.send(result).unwrap(); - } - - fn shader_precision_format(gl: &gl::Gl, - shader_type: u32, - precision_type: u32, - chan: WebGLSender<WebGLResult<(i32, i32, i32)>>) { - let result = match precision_type { - gl::LOW_FLOAT | - gl::MEDIUM_FLOAT | - gl::HIGH_FLOAT | - gl::LOW_INT | - gl::MEDIUM_INT | - gl::HIGH_INT => { - Ok(gl.get_shader_precision_format(shader_type, precision_type)) - }, - _=> { - Err(WebGLError::InvalidEnum) - } - }; - - chan.send(result).unwrap(); - } - - fn get_extensions(gl: &gl::Gl, chan: WebGLSender<String>) { - chan.send(gl.get_string(gl::EXTENSIONS)).unwrap(); - } - - fn uniform_location(gl: &gl::Gl, - program_id: WebGLProgramId, - name: String, - chan: WebGLSender<Option<i32>>) { - let location = gl.get_uniform_location(program_id.get(), &name); - let location = if location == -1 { - None - } else { - Some(location) - }; - - chan.send(location).unwrap(); - } - - - fn shader_info_log(gl: &gl::Gl, shader_id: WebGLShaderId, chan: WebGLSender<String>) { - let log = gl.get_shader_info_log(shader_id.get()); - chan.send(log).unwrap(); - } - - fn program_info_log(gl: &gl::Gl, program_id: WebGLProgramId, chan: WebGLSender<String>) { - let log = gl.get_program_info_log(program_id.get()); - chan.send(log).unwrap(); - } - - #[allow(unsafe_code)] - fn create_buffer(gl: &gl::Gl, chan: WebGLSender<Option<WebGLBufferId>>) { - let buffer = gl.gen_buffers(1)[0]; - let buffer = if buffer == 0 { - None - } else { - Some(unsafe { WebGLBufferId::new(buffer) }) - }; - chan.send(buffer).unwrap(); - } - - #[allow(unsafe_code)] - fn create_framebuffer(gl: &gl::Gl, chan: WebGLSender<Option<WebGLFramebufferId>>) { - let framebuffer = gl.gen_framebuffers(1)[0]; - let framebuffer = if framebuffer == 0 { - None - } else { - Some(unsafe { WebGLFramebufferId::new(framebuffer) }) - }; - chan.send(framebuffer).unwrap(); - } - - #[allow(unsafe_code)] - fn create_renderbuffer(gl: &gl::Gl, chan: WebGLSender<Option<WebGLRenderbufferId>>) { - let renderbuffer = gl.gen_renderbuffers(1)[0]; - let renderbuffer = if renderbuffer == 0 { - None - } else { - Some(unsafe { WebGLRenderbufferId::new(renderbuffer) }) - }; - chan.send(renderbuffer).unwrap(); - } - - #[allow(unsafe_code)] - fn create_texture(gl: &gl::Gl, chan: WebGLSender<Option<WebGLTextureId>>) { - let texture = gl.gen_textures(1)[0]; - let texture = if texture == 0 { - None - } else { - Some(unsafe { WebGLTextureId::new(texture) }) - }; - chan.send(texture).unwrap(); - } - - #[allow(unsafe_code)] - fn create_program(gl: &gl::Gl, chan: WebGLSender<Option<WebGLProgramId>>) { - let program = gl.create_program(); - let program = if program == 0 { - None - } else { - Some(unsafe { WebGLProgramId::new(program) }) - }; - chan.send(program).unwrap(); - } - - #[allow(unsafe_code)] - fn create_shader(gl: &gl::Gl, shader_type: u32, chan: WebGLSender<Option<WebGLShaderId>>) { - let shader = gl.create_shader(shader_type); - let shader = if shader == 0 { - None - } else { - Some(unsafe { WebGLShaderId::new(shader) }) - }; - chan.send(shader).unwrap(); - } - - #[allow(unsafe_code)] - fn create_vertex_array(gl: &gl::Gl, chan: WebGLSender<Option<WebGLVertexArrayId>>) { - let vao = gl.gen_vertex_arrays(1)[0]; - let vao = if vao == 0 { - None - } else { - Some(unsafe { WebGLVertexArrayId::new(vao) }) - }; - chan.send(vao).unwrap(); - } - - #[inline] - fn bind_framebuffer<Native: NativeGLContextMethods>(gl: &gl::Gl, - target: u32, - request: WebGLFramebufferBindingRequest, - ctx: &GLContext<Native>) { - let id = match request { - WebGLFramebufferBindingRequest::Explicit(id) => id.get(), - WebGLFramebufferBindingRequest::Default => - ctx.borrow_draw_buffer().unwrap().get_framebuffer(), - }; - - gl.bind_framebuffer(target, id); - } - - - #[inline] - fn compile_shader(gl: &gl::Gl, shader_id: WebGLShaderId, source: String) { - gl.shader_source(shader_id.get(), &[source.as_bytes()]); - gl.compile_shader(shader_id.get()); - } -} diff --git a/components/canvas_traits/Cargo.toml b/components/canvas_traits/Cargo.toml index 43cc74e60b1..afc23f4a2e0 100644 --- a/components/canvas_traits/Cargo.toml +++ b/components/canvas_traits/Cargo.toml @@ -15,8 +15,5 @@ euclid = "0.15" heapsize = "0.4" heapsize_derive = "0.1" ipc-channel = "0.8" -lazy_static = "0.2" -offscreen_gl_context = { version = "0.11", features = ["serde"] } serde = "1.0" -servo_config = {path = "../config"} webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} diff --git a/components/canvas_traits/canvas.rs b/components/canvas_traits/canvas.rs deleted file mode 100644 index 92444d03799..00000000000 --- a/components/canvas_traits/canvas.rs +++ /dev/null @@ -1,409 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use cssparser::RGBA; -use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D}; -use ipc_channel::ipc::IpcSender; -use std::default::Default; -use std::str::FromStr; -use webrender_api; - -#[derive(Clone, Deserialize, Serialize)] -pub enum FillRule { - Nonzero, - Evenodd, -} - -#[derive(Clone, Deserialize, Serialize)] -pub enum CanvasMsg { - Canvas2d(Canvas2dMsg), - FromLayout(FromLayoutMsg), - FromScript(FromScriptMsg), - Recreate(Size2D<i32>), - Close, -} - -#[derive(Clone, Deserialize, Serialize)] -pub struct CanvasImageData { - pub image_key: webrender_api::ImageKey, -} - -#[derive(Clone, Deserialize, Serialize)] -pub enum Canvas2dMsg { - Arc(Point2D<f32>, f32, f32, f32, bool), - ArcTo(Point2D<f32>, Point2D<f32>, f32), - DrawImage(Vec<u8>, Size2D<f64>, Rect<f64>, Rect<f64>, bool), - DrawImageSelf(Size2D<f64>, Rect<f64>, Rect<f64>, bool), - DrawImageInOther( - IpcSender<CanvasMsg>, Size2D<f64>, Rect<f64>, Rect<f64>, bool, IpcSender<()>), - BeginPath, - BezierCurveTo(Point2D<f32>, Point2D<f32>, Point2D<f32>), - ClearRect(Rect<f32>), - Clip, - ClosePath, - Fill, - FillRect(Rect<f32>), - GetImageData(Rect<i32>, Size2D<f64>, IpcSender<Vec<u8>>), - IsPointInPath(f64, f64, FillRule, IpcSender<bool>), - LineTo(Point2D<f32>), - MoveTo(Point2D<f32>), - PutImageData(Vec<u8>, Vector2D<f64>, Size2D<f64>, Rect<f64>), - QuadraticCurveTo(Point2D<f32>, Point2D<f32>), - Rect(Rect<f32>), - RestoreContext, - SaveContext, - StrokeRect(Rect<f32>), - Stroke, - SetFillStyle(FillOrStrokeStyle), - SetStrokeStyle(FillOrStrokeStyle), - SetLineWidth(f32), - SetLineCap(LineCapStyle), - SetLineJoin(LineJoinStyle), - SetMiterLimit(f32), - SetGlobalAlpha(f32), - SetGlobalComposition(CompositionOrBlending), - SetTransform(Transform2D<f32>), - SetShadowOffsetX(f64), - SetShadowOffsetY(f64), - SetShadowBlur(f64), - SetShadowColor(RGBA), -} - -#[derive(Clone, Deserialize, Serialize)] -pub enum FromLayoutMsg { - SendData(IpcSender<CanvasImageData>), -} - -#[derive(Clone, Deserialize, Serialize)] -pub enum FromScriptMsg { - SendPixels(IpcSender<Option<Vec<u8>>>), -} - -#[derive(Clone, Deserialize, Serialize, HeapSizeOf)] -pub struct CanvasGradientStop { - pub offset: f64, - pub color: RGBA, -} - -#[derive(Clone, Deserialize, Serialize, HeapSizeOf)] -pub struct LinearGradientStyle { - pub x0: f64, - pub y0: f64, - pub x1: f64, - pub y1: f64, - pub stops: Vec<CanvasGradientStop> -} - -impl LinearGradientStyle { - pub fn new(x0: f64, y0: f64, x1: f64, y1: f64, stops: Vec<CanvasGradientStop>) - -> LinearGradientStyle { - LinearGradientStyle { - x0: x0, - y0: y0, - x1: x1, - y1: y1, - stops: stops, - } - } -} - -#[derive(Clone, Deserialize, Serialize, HeapSizeOf)] -pub struct RadialGradientStyle { - pub x0: f64, - pub y0: f64, - pub r0: f64, - pub x1: f64, - pub y1: f64, - pub r1: f64, - pub stops: Vec<CanvasGradientStop> -} - -impl RadialGradientStyle { - pub fn new(x0: f64, y0: f64, r0: f64, x1: f64, y1: f64, r1: f64, stops: Vec<CanvasGradientStop>) - -> RadialGradientStyle { - RadialGradientStyle { - x0: x0, - y0: y0, - r0: r0, - x1: x1, - y1: y1, - r1: r1, - stops: stops, - } - } -} - -#[derive(Clone, Deserialize, Serialize)] -pub struct SurfaceStyle { - pub surface_data: Vec<u8>, - pub surface_size: Size2D<i32>, - pub repeat_x: bool, - pub repeat_y: bool, -} - -impl SurfaceStyle { - pub fn new(surface_data: Vec<u8>, surface_size: Size2D<i32>, repeat_x: bool, repeat_y: bool) - -> SurfaceStyle { - SurfaceStyle { - surface_data: surface_data, - surface_size: surface_size, - repeat_x: repeat_x, - repeat_y: repeat_y, - } - } -} - - -#[derive(Clone, Deserialize, Serialize)] -pub enum FillOrStrokeStyle { - Color(RGBA), - LinearGradient(LinearGradientStyle), - RadialGradient(RadialGradientStyle), - Surface(SurfaceStyle), -} - -#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)] -pub enum LineCapStyle { - Butt = 0, - Round = 1, - Square = 2, -} - -impl FromStr for LineCapStyle { - type Err = (); - - fn from_str(string: &str) -> Result<LineCapStyle, ()> { - match string { - "butt" => Ok(LineCapStyle::Butt), - "round" => Ok(LineCapStyle::Round), - "square" => Ok(LineCapStyle::Square), - _ => Err(()), - } - } -} - -#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)] -pub enum LineJoinStyle { - Round = 0, - Bevel = 1, - Miter = 2, -} - -impl FromStr for LineJoinStyle { - type Err = (); - - fn from_str(string: &str) -> Result<LineJoinStyle, ()> { - match string { - "round" => Ok(LineJoinStyle::Round), - "bevel" => Ok(LineJoinStyle::Bevel), - "miter" => Ok(LineJoinStyle::Miter), - _ => Err(()), - } - } -} - -#[derive(Copy, Clone, PartialEq, Deserialize, Serialize)] -pub enum RepetitionStyle { - Repeat, - RepeatX, - RepeatY, - NoRepeat, -} - -impl FromStr for RepetitionStyle { - type Err = (); - - fn from_str(string: &str) -> Result<RepetitionStyle, ()> { - match string { - "repeat" => Ok(RepetitionStyle::Repeat), - "repeat-x" => Ok(RepetitionStyle::RepeatX), - "repeat-y" => Ok(RepetitionStyle::RepeatY), - "no-repeat" => Ok(RepetitionStyle::NoRepeat), - _ => Err(()), - } - } -} - -#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)] -pub enum CompositionStyle { - SrcIn, - SrcOut, - SrcOver, - SrcAtop, - DestIn, - DestOut, - DestOver, - DestAtop, - Copy, - Lighter, - Xor, -} - -impl FromStr for CompositionStyle { - type Err = (); - - fn from_str(string: &str) -> Result<CompositionStyle, ()> { - match string { - "source-in" => Ok(CompositionStyle::SrcIn), - "source-out" => Ok(CompositionStyle::SrcOut), - "source-over" => Ok(CompositionStyle::SrcOver), - "source-atop" => Ok(CompositionStyle::SrcAtop), - "destination-in" => Ok(CompositionStyle::DestIn), - "destination-out" => Ok(CompositionStyle::DestOut), - "destination-over" => Ok(CompositionStyle::DestOver), - "destination-atop" => Ok(CompositionStyle::DestAtop), - "copy" => Ok(CompositionStyle::Copy), - "lighter" => Ok(CompositionStyle::Lighter), - "xor" => Ok(CompositionStyle::Xor), - _ => Err(()) - } - } -} - -impl CompositionStyle { - pub fn to_str(&self) -> &str { - match *self { - CompositionStyle::SrcIn => "source-in", - CompositionStyle::SrcOut => "source-out", - CompositionStyle::SrcOver => "source-over", - CompositionStyle::SrcAtop => "source-atop", - CompositionStyle::DestIn => "destination-in", - CompositionStyle::DestOut => "destination-out", - CompositionStyle::DestOver => "destination-over", - CompositionStyle::DestAtop => "destination-atop", - CompositionStyle::Copy => "copy", - CompositionStyle::Lighter => "lighter", - CompositionStyle::Xor => "xor", - } - } -} - -#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)] -pub enum BlendingStyle { - Multiply, - Screen, - Overlay, - Darken, - Lighten, - ColorDodge, - ColorBurn, - HardLight, - SoftLight, - Difference, - Exclusion, - Hue, - Saturation, - Color, - Luminosity, -} - -impl FromStr for BlendingStyle { - type Err = (); - - fn from_str(string: &str) -> Result<BlendingStyle, ()> { - match string { - "multiply" => Ok(BlendingStyle::Multiply), - "screen" => Ok(BlendingStyle::Screen), - "overlay" => Ok(BlendingStyle::Overlay), - "darken" => Ok(BlendingStyle::Darken), - "lighten" => Ok(BlendingStyle::Lighten), - "color-dodge" => Ok(BlendingStyle::ColorDodge), - "color-burn" => Ok(BlendingStyle::ColorBurn), - "hard-light" => Ok(BlendingStyle::HardLight), - "soft-light" => Ok(BlendingStyle::SoftLight), - "difference" => Ok(BlendingStyle::Difference), - "exclusion" => Ok(BlendingStyle::Exclusion), - "hue" => Ok(BlendingStyle::Hue), - "saturation" => Ok(BlendingStyle::Saturation), - "color" => Ok(BlendingStyle::Color), - "luminosity" => Ok(BlendingStyle::Luminosity), - _ => Err(()) - } - } -} - -impl BlendingStyle { - pub fn to_str(&self) -> &str { - match *self { - BlendingStyle::Multiply => "multiply", - BlendingStyle::Screen => "screen", - BlendingStyle::Overlay => "overlay", - BlendingStyle::Darken => "darken", - BlendingStyle::Lighten => "lighten", - BlendingStyle::ColorDodge => "color-dodge", - BlendingStyle::ColorBurn => "color-burn", - BlendingStyle::HardLight => "hard-light", - BlendingStyle::SoftLight => "soft-light", - BlendingStyle::Difference => "difference", - BlendingStyle::Exclusion => "exclusion", - BlendingStyle::Hue => "hue", - BlendingStyle::Saturation => "saturation", - BlendingStyle::Color => "color", - BlendingStyle::Luminosity => "luminosity", - } - } -} - -#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)] -pub enum CompositionOrBlending { - Composition(CompositionStyle), - Blending(BlendingStyle), -} - -impl Default for CompositionOrBlending { - fn default() -> CompositionOrBlending { - CompositionOrBlending::Composition(CompositionStyle::SrcOver) - } -} - -impl FromStr for CompositionOrBlending { - type Err = (); - - fn from_str(string: &str) -> Result<CompositionOrBlending, ()> { - if let Ok(op) = CompositionStyle::from_str(string) { - return Ok(CompositionOrBlending::Composition(op)); - } - - if let Ok(op) = BlendingStyle::from_str(string) { - return Ok(CompositionOrBlending::Blending(op)); - } - - Err(()) - } -} - -// TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this. -pub fn byte_swap(data: &mut [u8]) { - let length = data.len(); - // FIXME(rust #27741): Range::step_by is not stable yet as of this writing. - let mut i = 0; - while i < length { - let r = data[i + 2]; - data[i + 2] = data[i + 0]; - data[i + 0] = r; - i += 4; - } -} - -pub fn multiply_u8_pixel(a: u8, b: u8) -> u8 { - return (a as u32 * b as u32 / 255) as u8; -} - -pub fn byte_swap_and_premultiply(data: &mut [u8]) { - let length = data.len(); - - let mut i = 0; - while i < length { - let r = data[i + 2]; - let g = data[i + 1]; - let b = data[i + 0]; - let a = data[i + 3]; - - data[i + 0] = multiply_u8_pixel(r, a); - data[i + 1] = multiply_u8_pixel(g, a); - data[i + 2] = multiply_u8_pixel(b, a); - - i += 4; - } -} diff --git a/components/canvas_traits/lib.rs b/components/canvas_traits/lib.rs index 7830d669e3e..1f6d9eda087 100644 --- a/components/canvas_traits/lib.rs +++ b/components/canvas_traits/lib.rs @@ -4,22 +4,432 @@ #![crate_name = "canvas_traits"] #![crate_type = "rlib"] -#![feature(nonzero)] #![deny(unsafe_code)] -extern crate core; extern crate cssparser; extern crate euclid; extern crate heapsize; #[macro_use] extern crate heapsize_derive; extern crate ipc_channel; -#[macro_use] extern crate lazy_static; -extern crate offscreen_gl_context; #[macro_use] extern crate serde; -extern crate servo_config; extern crate webrender_api; -pub mod canvas; -pub mod webgl; -mod webgl_channel; +use cssparser::RGBA; +use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D}; +use ipc_channel::ipc::IpcSender; +use std::default::Default; +use std::str::FromStr; +use webrender_api::{WebGLCommand, WebGLContextId, VRCompositorCommand}; + +#[derive(Clone, Deserialize, Serialize)] +pub enum FillRule { + Nonzero, + Evenodd, +} + +#[derive(Clone, Deserialize, Serialize)] +pub enum CanvasMsg { + Canvas2d(Canvas2dMsg), + Common(CanvasCommonMsg), + FromLayout(FromLayoutMsg), + FromScript(FromScriptMsg), + WebGL(WebGLCommand), + WebVR(VRCompositorCommand) +} + +#[derive(Clone, Deserialize, Serialize)] +pub enum CanvasCommonMsg { + Close, + Recreate(Size2D<i32>), +} + +#[derive(Clone, Deserialize, Serialize)] +pub enum CanvasData { + Image(CanvasImageData), + WebGL(WebGLContextId), +} + +#[derive(Clone, Deserialize, Serialize)] +pub struct CanvasImageData { + pub image_key: webrender_api::ImageKey, +} + +#[derive(Clone, Deserialize, Serialize)] +pub enum FromLayoutMsg { + SendData(IpcSender<CanvasData>), +} + +#[derive(Clone, Deserialize, Serialize)] +pub enum FromScriptMsg { + SendPixels(IpcSender<Option<Vec<u8>>>), +} + +#[derive(Clone, Deserialize, Serialize)] +pub enum Canvas2dMsg { + Arc(Point2D<f32>, f32, f32, f32, bool), + ArcTo(Point2D<f32>, Point2D<f32>, f32), + DrawImage(Vec<u8>, Size2D<f64>, Rect<f64>, Rect<f64>, bool), + DrawImageSelf(Size2D<f64>, Rect<f64>, Rect<f64>, bool), + DrawImageInOther( + IpcSender<CanvasMsg>, Size2D<f64>, Rect<f64>, Rect<f64>, bool, IpcSender<()>), + BeginPath, + BezierCurveTo(Point2D<f32>, Point2D<f32>, Point2D<f32>), + ClearRect(Rect<f32>), + Clip, + ClosePath, + Fill, + FillRect(Rect<f32>), + GetImageData(Rect<i32>, Size2D<f64>, IpcSender<Vec<u8>>), + IsPointInPath(f64, f64, FillRule, IpcSender<bool>), + LineTo(Point2D<f32>), + MoveTo(Point2D<f32>), + PutImageData(Vec<u8>, Vector2D<f64>, Size2D<f64>, Rect<f64>), + QuadraticCurveTo(Point2D<f32>, Point2D<f32>), + Rect(Rect<f32>), + RestoreContext, + SaveContext, + StrokeRect(Rect<f32>), + Stroke, + SetFillStyle(FillOrStrokeStyle), + SetStrokeStyle(FillOrStrokeStyle), + SetLineWidth(f32), + SetLineCap(LineCapStyle), + SetLineJoin(LineJoinStyle), + SetMiterLimit(f32), + SetGlobalAlpha(f32), + SetGlobalComposition(CompositionOrBlending), + SetTransform(Transform2D<f32>), + SetShadowOffsetX(f64), + SetShadowOffsetY(f64), + SetShadowBlur(f64), + SetShadowColor(RGBA), +} + +#[derive(Clone, Deserialize, Serialize, HeapSizeOf)] +pub struct CanvasGradientStop { + pub offset: f64, + pub color: RGBA, +} + +#[derive(Clone, Deserialize, Serialize, HeapSizeOf)] +pub struct LinearGradientStyle { + pub x0: f64, + pub y0: f64, + pub x1: f64, + pub y1: f64, + pub stops: Vec<CanvasGradientStop> +} + +impl LinearGradientStyle { + pub fn new(x0: f64, y0: f64, x1: f64, y1: f64, stops: Vec<CanvasGradientStop>) + -> LinearGradientStyle { + LinearGradientStyle { + x0: x0, + y0: y0, + x1: x1, + y1: y1, + stops: stops, + } + } +} + +#[derive(Clone, Deserialize, Serialize, HeapSizeOf)] +pub struct RadialGradientStyle { + pub x0: f64, + pub y0: f64, + pub r0: f64, + pub x1: f64, + pub y1: f64, + pub r1: f64, + pub stops: Vec<CanvasGradientStop> +} + +impl RadialGradientStyle { + pub fn new(x0: f64, y0: f64, r0: f64, x1: f64, y1: f64, r1: f64, stops: Vec<CanvasGradientStop>) + -> RadialGradientStyle { + RadialGradientStyle { + x0: x0, + y0: y0, + r0: r0, + x1: x1, + y1: y1, + r1: r1, + stops: stops, + } + } +} + +#[derive(Clone, Deserialize, Serialize)] +pub struct SurfaceStyle { + pub surface_data: Vec<u8>, + pub surface_size: Size2D<i32>, + pub repeat_x: bool, + pub repeat_y: bool, +} + +impl SurfaceStyle { + pub fn new(surface_data: Vec<u8>, surface_size: Size2D<i32>, repeat_x: bool, repeat_y: bool) + -> SurfaceStyle { + SurfaceStyle { + surface_data: surface_data, + surface_size: surface_size, + repeat_x: repeat_x, + repeat_y: repeat_y, + } + } +} + + +#[derive(Clone, Deserialize, Serialize)] +pub enum FillOrStrokeStyle { + Color(RGBA), + LinearGradient(LinearGradientStyle), + RadialGradient(RadialGradientStyle), + Surface(SurfaceStyle), +} + +#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)] +pub enum LineCapStyle { + Butt = 0, + Round = 1, + Square = 2, +} + +impl FromStr for LineCapStyle { + type Err = (); + + fn from_str(string: &str) -> Result<LineCapStyle, ()> { + match string { + "butt" => Ok(LineCapStyle::Butt), + "round" => Ok(LineCapStyle::Round), + "square" => Ok(LineCapStyle::Square), + _ => Err(()), + } + } +} + +#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)] +pub enum LineJoinStyle { + Round = 0, + Bevel = 1, + Miter = 2, +} + +impl FromStr for LineJoinStyle { + type Err = (); + + fn from_str(string: &str) -> Result<LineJoinStyle, ()> { + match string { + "round" => Ok(LineJoinStyle::Round), + "bevel" => Ok(LineJoinStyle::Bevel), + "miter" => Ok(LineJoinStyle::Miter), + _ => Err(()), + } + } +} + +#[derive(Copy, Clone, PartialEq, Deserialize, Serialize)] +pub enum RepetitionStyle { + Repeat, + RepeatX, + RepeatY, + NoRepeat, +} + +impl FromStr for RepetitionStyle { + type Err = (); + + fn from_str(string: &str) -> Result<RepetitionStyle, ()> { + match string { + "repeat" => Ok(RepetitionStyle::Repeat), + "repeat-x" => Ok(RepetitionStyle::RepeatX), + "repeat-y" => Ok(RepetitionStyle::RepeatY), + "no-repeat" => Ok(RepetitionStyle::NoRepeat), + _ => Err(()), + } + } +} + +#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)] +pub enum CompositionStyle { + SrcIn, + SrcOut, + SrcOver, + SrcAtop, + DestIn, + DestOut, + DestOver, + DestAtop, + Copy, + Lighter, + Xor, +} + +impl FromStr for CompositionStyle { + type Err = (); + + fn from_str(string: &str) -> Result<CompositionStyle, ()> { + match string { + "source-in" => Ok(CompositionStyle::SrcIn), + "source-out" => Ok(CompositionStyle::SrcOut), + "source-over" => Ok(CompositionStyle::SrcOver), + "source-atop" => Ok(CompositionStyle::SrcAtop), + "destination-in" => Ok(CompositionStyle::DestIn), + "destination-out" => Ok(CompositionStyle::DestOut), + "destination-over" => Ok(CompositionStyle::DestOver), + "destination-atop" => Ok(CompositionStyle::DestAtop), + "copy" => Ok(CompositionStyle::Copy), + "lighter" => Ok(CompositionStyle::Lighter), + "xor" => Ok(CompositionStyle::Xor), + _ => Err(()) + } + } +} + +impl CompositionStyle { + pub fn to_str(&self) -> &str { + match *self { + CompositionStyle::SrcIn => "source-in", + CompositionStyle::SrcOut => "source-out", + CompositionStyle::SrcOver => "source-over", + CompositionStyle::SrcAtop => "source-atop", + CompositionStyle::DestIn => "destination-in", + CompositionStyle::DestOut => "destination-out", + CompositionStyle::DestOver => "destination-over", + CompositionStyle::DestAtop => "destination-atop", + CompositionStyle::Copy => "copy", + CompositionStyle::Lighter => "lighter", + CompositionStyle::Xor => "xor", + } + } +} + +#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)] +pub enum BlendingStyle { + Multiply, + Screen, + Overlay, + Darken, + Lighten, + ColorDodge, + ColorBurn, + HardLight, + SoftLight, + Difference, + Exclusion, + Hue, + Saturation, + Color, + Luminosity, +} + +impl FromStr for BlendingStyle { + type Err = (); + + fn from_str(string: &str) -> Result<BlendingStyle, ()> { + match string { + "multiply" => Ok(BlendingStyle::Multiply), + "screen" => Ok(BlendingStyle::Screen), + "overlay" => Ok(BlendingStyle::Overlay), + "darken" => Ok(BlendingStyle::Darken), + "lighten" => Ok(BlendingStyle::Lighten), + "color-dodge" => Ok(BlendingStyle::ColorDodge), + "color-burn" => Ok(BlendingStyle::ColorBurn), + "hard-light" => Ok(BlendingStyle::HardLight), + "soft-light" => Ok(BlendingStyle::SoftLight), + "difference" => Ok(BlendingStyle::Difference), + "exclusion" => Ok(BlendingStyle::Exclusion), + "hue" => Ok(BlendingStyle::Hue), + "saturation" => Ok(BlendingStyle::Saturation), + "color" => Ok(BlendingStyle::Color), + "luminosity" => Ok(BlendingStyle::Luminosity), + _ => Err(()) + } + } +} + +impl BlendingStyle { + pub fn to_str(&self) -> &str { + match *self { + BlendingStyle::Multiply => "multiply", + BlendingStyle::Screen => "screen", + BlendingStyle::Overlay => "overlay", + BlendingStyle::Darken => "darken", + BlendingStyle::Lighten => "lighten", + BlendingStyle::ColorDodge => "color-dodge", + BlendingStyle::ColorBurn => "color-burn", + BlendingStyle::HardLight => "hard-light", + BlendingStyle::SoftLight => "soft-light", + BlendingStyle::Difference => "difference", + BlendingStyle::Exclusion => "exclusion", + BlendingStyle::Hue => "hue", + BlendingStyle::Saturation => "saturation", + BlendingStyle::Color => "color", + BlendingStyle::Luminosity => "luminosity", + } + } +} + +#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)] +pub enum CompositionOrBlending { + Composition(CompositionStyle), + Blending(BlendingStyle), +} + +impl Default for CompositionOrBlending { + fn default() -> CompositionOrBlending { + CompositionOrBlending::Composition(CompositionStyle::SrcOver) + } +} + +impl FromStr for CompositionOrBlending { + type Err = (); + + fn from_str(string: &str) -> Result<CompositionOrBlending, ()> { + if let Ok(op) = CompositionStyle::from_str(string) { + return Ok(CompositionOrBlending::Composition(op)); + } + + if let Ok(op) = BlendingStyle::from_str(string) { + return Ok(CompositionOrBlending::Blending(op)); + } + + Err(()) + } +} + +// TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this. +pub fn byte_swap(data: &mut [u8]) { + let length = data.len(); + // FIXME(rust #27741): Range::step_by is not stable yet as of this writing. + let mut i = 0; + while i < length { + let r = data[i + 2]; + data[i + 2] = data[i + 0]; + data[i + 0] = r; + i += 4; + } +} + +pub fn multiply_u8_pixel(a: u8, b: u8) -> u8 { + return (a as u32 * b as u32 / 255) as u8; +} + +pub fn byte_swap_and_premultiply(data: &mut [u8]) { + let length = data.len(); + + let mut i = 0; + while i < length { + let r = data[i + 2]; + let g = data[i + 1]; + let b = data[i + 0]; + let a = data[i + 3]; + + data[i + 0] = multiply_u8_pixel(r, a); + data[i + 1] = multiply_u8_pixel(g, a); + data[i + 2] = multiply_u8_pixel(b, a); + + i += 4; + } +} diff --git a/components/canvas_traits/webgl.rs b/components/canvas_traits/webgl.rs deleted file mode 100644 index 1bd6eb0649b..00000000000 --- a/components/canvas_traits/webgl.rs +++ /dev/null @@ -1,506 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use core::nonzero::NonZero; -use euclid::Size2D; -use offscreen_gl_context::{GLContextAttributes, GLLimits}; -use std::fmt; -use webrender_api; - -/// Sender type used in WebGLCommands. -pub use ::webgl_channel::WebGLSender; -/// Receiver type used in WebGLCommands. -pub use ::webgl_channel::WebGLReceiver; -/// Result type for send()/recv() calls in in WebGLCommands. -pub use ::webgl_channel::WebGLSendResult; -/// Helper function that creates a WebGL channel (WebGLSender, WebGLReceiver) to be used in WebGLCommands. -pub use ::webgl_channel::webgl_channel; -/// Entry point type used in a Script Pipeline to get the WebGLChan to be used in that thread. -pub use ::webgl_channel::WebGLPipeline; -/// Entry point channel type used for sending WebGLMsg messages to the WebGL renderer. -pub use ::webgl_channel::WebGLChan; - -/// WebGL Message API -#[derive(Clone, Deserialize, Serialize)] -pub enum WebGLMsg { - /// Creates a new WebGLContext. - CreateContext(Size2D<i32>, GLContextAttributes, WebGLSender<Result<(WebGLCreateContextResult), String>>), - /// Resizes a WebGLContext. - ResizeContext(WebGLContextId, Size2D<i32>, WebGLSender<Result<(), String>>), - /// Drops a WebGLContext. - RemoveContext(WebGLContextId), - /// Runs a WebGLCommand in a specific WebGLContext. - WebGLCommand(WebGLContextId, WebGLCommand), - /// Runs a WebVRCommand in a specific WebGLContext. - WebVRCommand(WebGLContextId, WebVRCommand), - /// Locks a specific WebGLContext. Lock messages are used for a correct synchronization - /// with WebRender external image API. - /// WR locks a external texture when it wants to use the shared texture contents. - /// The WR client should not change the shared texture content until the Unlock call. - /// Currently OpenGL Sync Objects are used to implement the synchronization mechanism. - Lock(WebGLContextId, WebGLSender<(u32, Size2D<i32>)>), - /// Unlocks a specific WebGLContext. Unlock messages are used for a correct synchronization - /// with WebRender external image API. - /// The WR unlocks a context when it finished reading the shared texture contents. - /// 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>), - /// Frees all resources and closes the thread. - Exit, -} - -/// Contains the WebGLCommand sender and information about a WebGLContext -#[derive(Clone, Deserialize, Serialize)] -pub struct WebGLCreateContextResult { - /// Sender instance to send commands to the specific WebGLContext - pub sender: WebGLMsgSender, - /// Information about the internal GL Context. - pub limits: GLLimits, - /// How the WebGLContext is shared with WebRender. - pub share_mode: WebGLContextShareMode, -} - -#[derive(Clone, Copy, Deserialize, HeapSizeOf, Serialize)] -pub enum WebGLContextShareMode { - /// Fast: a shared texture_id is used in WebRender. - SharedTexture, - /// Slow: glReadPixels is used to send pixels to WebRender each frame. - Readback, -} - -/// Helper struct to send WebGLCommands to a specific WebGLContext. -#[derive(Clone, Deserialize, HeapSizeOf, Serialize)] -pub struct WebGLMsgSender { - ctx_id: WebGLContextId, - #[ignore_heap_size_of = "channels are hard"] - sender: WebGLChan, -} - -impl WebGLMsgSender { - pub fn new(id: WebGLContextId, sender: WebGLChan) -> Self { - WebGLMsgSender { - ctx_id: id, - sender: sender, - } - } - - /// Send a WebGLCommand message - #[inline] - pub fn send(&self, command: WebGLCommand) -> WebGLSendResult { - self.sender.send(WebGLMsg::WebGLCommand(self.ctx_id, command)) - } - - /// Send a WebVRCommand message - #[inline] - pub fn send_vr(&self, command: WebVRCommand) -> WebGLSendResult { - self.sender.send(WebGLMsg::WebVRCommand(self.ctx_id, command)) - } - - /// Send a resize message - #[inline] - pub fn send_resize(&self, - size: Size2D<i32>, - sender: WebGLSender<Result<(), String>>) - -> WebGLSendResult { - self.sender.send(WebGLMsg::ResizeContext(self.ctx_id, size, sender)) - } - - #[inline] - pub fn send_remove(&self) -> WebGLSendResult { - self.sender.send(WebGLMsg::RemoveContext(self.ctx_id)) - } - - #[inline] - pub fn send_update_wr_image(&self, sender: WebGLSender<webrender_api::ImageKey>) -> WebGLSendResult { - self.sender.send(WebGLMsg::UpdateWebRenderImage(self.ctx_id, sender)) - } -} - -/// WebGL Commands for a specific WebGLContext -#[derive(Clone, Deserialize, Serialize)] -pub enum WebGLCommand { - GetContextAttributes(WebGLSender<GLContextAttributes>), - ActiveTexture(u32), - BlendColor(f32, f32, f32, f32), - BlendEquation(u32), - BlendEquationSeparate(u32, u32), - BlendFunc(u32, u32), - BlendFuncSeparate(u32, u32, u32, u32), - AttachShader(WebGLProgramId, WebGLShaderId), - DetachShader(WebGLProgramId, WebGLShaderId), - BindAttribLocation(WebGLProgramId, u32, String), - BufferData(u32, Vec<u8>, u32), - BufferSubData(u32, isize, Vec<u8>), - Clear(u32), - ClearColor(f32, f32, f32, f32), - ClearDepth(f64), - ClearStencil(i32), - ColorMask(bool, bool, bool, bool), - CullFace(u32), - FrontFace(u32), - DepthFunc(u32), - DepthMask(bool), - DepthRange(f64, f64), - Enable(u32), - Disable(u32), - CompileShader(WebGLShaderId, String), - CopyTexImage2D(u32, i32, u32, i32, i32, i32, i32, i32), - CopyTexSubImage2D(u32, i32, i32, i32, i32, i32, i32, i32), - CreateBuffer(WebGLSender<Option<WebGLBufferId>>), - CreateFramebuffer(WebGLSender<Option<WebGLFramebufferId>>), - CreateRenderbuffer(WebGLSender<Option<WebGLRenderbufferId>>), - CreateTexture(WebGLSender<Option<WebGLTextureId>>), - CreateProgram(WebGLSender<Option<WebGLProgramId>>), - CreateShader(u32, WebGLSender<Option<WebGLShaderId>>), - DeleteBuffer(WebGLBufferId), - DeleteFramebuffer(WebGLFramebufferId), - DeleteRenderbuffer(WebGLRenderbufferId), - DeleteTexture(WebGLTextureId), - DeleteProgram(WebGLProgramId), - DeleteShader(WebGLShaderId), - BindBuffer(u32, Option<WebGLBufferId>), - BindFramebuffer(u32, WebGLFramebufferBindingRequest), - BindRenderbuffer(u32, Option<WebGLRenderbufferId>), - BindTexture(u32, Option<WebGLTextureId>), - DisableVertexAttribArray(u32), - DrawArrays(u32, i32, i32), - DrawElements(u32, i32, u32, i64), - EnableVertexAttribArray(u32), - FramebufferRenderbuffer(u32, u32, u32, Option<WebGLRenderbufferId>), - FramebufferTexture2D(u32, u32, u32, Option<WebGLTextureId>, i32), - GetBufferParameter(u32, u32, WebGLSender<WebGLResult<WebGLParameter>>), - GetExtensions(WebGLSender<String>), - GetParameter(u32, WebGLSender<WebGLResult<WebGLParameter>>), - GetProgramParameter(WebGLProgramId, u32, WebGLSender<WebGLResult<WebGLParameter>>), - GetShaderParameter(WebGLShaderId, u32, WebGLSender<WebGLResult<WebGLParameter>>), - GetShaderPrecisionFormat(u32, u32, WebGLSender<WebGLResult<(i32, i32, i32)>>), - GetActiveAttrib(WebGLProgramId, u32, WebGLSender<WebGLResult<(i32, u32, String)>>), - GetActiveUniform(WebGLProgramId, u32, WebGLSender<WebGLResult<(i32, u32, String)>>), - GetAttribLocation(WebGLProgramId, String, WebGLSender<Option<i32>>), - GetUniformLocation(WebGLProgramId, String, WebGLSender<Option<i32>>), - GetVertexAttrib(u32, u32, WebGLSender<WebGLResult<WebGLParameter>>), - GetVertexAttribOffset(u32, u32, WebGLSender<WebGLResult<isize>>), - GetShaderInfoLog(WebGLShaderId, WebGLSender<String>), - GetProgramInfoLog(WebGLProgramId, WebGLSender<String>), - PolygonOffset(f32, f32), - RenderbufferStorage(u32, u32, i32, i32), - ReadPixels(i32, i32, i32, i32, u32, u32, WebGLSender<Vec<u8>>), - SampleCoverage(f32, bool), - Scissor(i32, i32, i32, i32), - StencilFunc(u32, i32, u32), - StencilFuncSeparate(u32, u32, i32, u32), - StencilMask(u32), - StencilMaskSeparate(u32, u32), - StencilOp(u32, u32, u32), - StencilOpSeparate(u32, u32, u32, u32), - Hint(u32, u32), - IsEnabled(u32, WebGLSender<bool>), - LineWidth(f32), - PixelStorei(u32, i32), - LinkProgram(WebGLProgramId), - Uniform1f(i32, f32), - Uniform1fv(i32, Vec<f32>), - Uniform1i(i32, i32), - Uniform1iv(i32, Vec<i32>), - Uniform2f(i32, f32, f32), - Uniform2fv(i32, Vec<f32>), - Uniform2i(i32, i32, i32), - Uniform2iv(i32, Vec<i32>), - Uniform3f(i32, f32, f32, f32), - Uniform3fv(i32, Vec<f32>), - Uniform3i(i32, i32, i32, i32), - Uniform3iv(i32, Vec<i32>), - Uniform4f(i32, f32, f32, f32, f32), - Uniform4fv(i32, Vec<f32>), - Uniform4i(i32, i32, i32, i32, i32), - Uniform4iv(i32, Vec<i32>), - UniformMatrix2fv(i32, bool, Vec<f32>), - UniformMatrix3fv(i32, bool, Vec<f32>), - UniformMatrix4fv(i32, bool, Vec<f32>), - UseProgram(WebGLProgramId), - ValidateProgram(WebGLProgramId), - VertexAttrib(u32, f32, f32, f32, f32), - VertexAttribPointer(u32, i32, u32, bool, i32, u32), - VertexAttribPointer2f(u32, i32, bool, i32, u32), - Viewport(i32, i32, i32, i32), - TexImage2D(u32, i32, i32, i32, i32, u32, u32, Vec<u8>), - TexParameteri(u32, u32, i32), - TexParameterf(u32, u32, f32), - TexSubImage2D(u32, i32, i32, i32, i32, i32, u32, u32, Vec<u8>), - DrawingBufferWidth(WebGLSender<i32>), - DrawingBufferHeight(WebGLSender<i32>), - Finish(WebGLSender<()>), - Flush, - GenerateMipmap(u32), - CreateVertexArray(WebGLSender<Option<WebGLVertexArrayId>>), - DeleteVertexArray(WebGLVertexArrayId), - BindVertexArray(Option<WebGLVertexArrayId>), -} - -macro_rules! define_resource_id_struct { - ($name:ident) => { - #[derive(Clone, Copy, Eq, Hash, PartialEq)] - pub struct $name(NonZero<u32>); - - impl $name { - #[allow(unsafe_code)] - #[inline] - pub unsafe fn new(id: u32) -> Self { - $name(NonZero::new_unchecked(id)) - } - - #[inline] - pub fn get(self) -> u32 { - self.0.get() - } - } - - }; -} - -macro_rules! define_resource_id { - ($name:ident) => { - define_resource_id_struct!($name); - - #[allow(unsafe_code)] - impl<'de> ::serde::Deserialize<'de> for $name { - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where D: ::serde::Deserializer<'de> - { - let id = try!(u32::deserialize(deserializer)); - if id == 0 { - Err(::serde::de::Error::custom("expected a non-zero value")) - } else { - Ok(unsafe { $name::new(id) }) - } - } - } - - impl ::serde::Serialize for $name { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where S: ::serde::Serializer - { - self.get().serialize(serializer) - } - } - - impl ::std::fmt::Debug for $name { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) - -> Result<(), ::std::fmt::Error> { - fmt.debug_tuple(stringify!($name)) - .field(&self.get()) - .finish() - } - } - - impl ::std::fmt::Display for $name { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) - -> Result<(), ::std::fmt::Error> { - write!(fmt, "{}", self.get()) - } - } - - impl ::heapsize::HeapSizeOf for $name { - fn heap_size_of_children(&self) -> usize { 0 } - } - } -} - -define_resource_id!(WebGLBufferId); -define_resource_id!(WebGLFramebufferId); -define_resource_id!(WebGLRenderbufferId); -define_resource_id!(WebGLTextureId); -define_resource_id!(WebGLProgramId); -define_resource_id!(WebGLShaderId); -define_resource_id!(WebGLVertexArrayId); - -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] -pub struct WebGLContextId(pub usize); - -impl ::heapsize::HeapSizeOf for WebGLContextId { - fn heap_size_of_children(&self) -> usize { 0 } -} - -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] -pub enum WebGLError { - InvalidEnum, - InvalidFramebufferOperation, - InvalidOperation, - InvalidValue, - OutOfMemory, - ContextLost, -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub enum WebGLFramebufferBindingRequest { - Explicit(WebGLFramebufferId), - Default, -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub enum WebGLParameter { - Int(i32), - Bool(bool), - String(String), - Float(f32), - FloatArray(Vec<f32>), - Invalid, -} - -pub type WebGLResult<T> = Result<T, WebGLError>; - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub enum WebGLShaderParameter { - Int(i32), - Bool(bool), - Invalid, -} - -pub type WebVRDeviceId = u32; - -// WebVR commands that must be called in the WebGL render thread. -#[derive(Clone, Deserialize, Serialize)] -pub enum WebVRCommand { - /// Start presenting to a VR device. - Create(WebVRDeviceId), - /// Synchronize the pose information to be used in the frame. - SyncPoses(WebVRDeviceId, f64, f64, WebGLSender<Result<Vec<u8>, ()>>), - /// Submit the frame to a VR device using the specified texture coordinates. - SubmitFrame(WebVRDeviceId, [f32; 4], [f32; 4]), - /// Stop presenting to a VR device - Release(WebVRDeviceId) -} - -// Trait object that handles WebVR commands. -// Receives the texture id and size associated to the WebGLContext. -pub trait WebVRRenderHandler: Send { - fn handle(&mut self, command: WebVRCommand, texture: Option<(u32, Size2D<i32>)>); -} - -impl fmt::Debug for WebGLCommand { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::WebGLCommand::*; - let name = match *self { - GetContextAttributes(..) => "GetContextAttributes", - ActiveTexture(..) => "ActiveTexture", - BlendColor(..) => "BlendColor", - BlendEquation(..) => "BlendEquation", - BlendEquationSeparate(..) => "BlendEquationSeparate", - BlendFunc(..) => "BlendFunc", - BlendFuncSeparate(..) => "BlendFuncSeparate", - AttachShader(..) => "AttachShader", - DetachShader(..) => "DetachShader", - BindAttribLocation(..) => "BindAttribLocation", - BufferData(..) => "BufferData", - BufferSubData(..) => "BufferSubData", - Clear(..) => "Clear", - ClearColor(..) => "ClearColor", - ClearDepth(..) => "ClearDepth", - ClearStencil(..) => "ClearStencil", - ColorMask(..) => "ColorMask", - CopyTexImage2D(..) => "CopyTexImage2D", - CopyTexSubImage2D(..) => "CopyTexSubImage2D", - CullFace(..) => "CullFace", - FrontFace(..) => "FrontFace", - DepthFunc(..) => "DepthFunc", - DepthMask(..) => "DepthMask", - DepthRange(..) => "DepthRange", - Enable(..) => "Enable", - Disable(..) => "Disable", - CompileShader(..) => "CompileShader", - CreateBuffer(..) => "CreateBuffer", - CreateFramebuffer(..) => "CreateFramebuffer", - CreateRenderbuffer(..) => "CreateRenderbuffer", - CreateTexture(..) => "CreateTexture", - CreateProgram(..) => "CreateProgram", - CreateShader(..) => "CreateShader", - DeleteBuffer(..) => "DeleteBuffer", - DeleteFramebuffer(..) => "DeleteFramebuffer", - DeleteRenderbuffer(..) => "DeleteRenderBuffer", - DeleteTexture(..) => "DeleteTexture", - DeleteProgram(..) => "DeleteProgram", - DeleteShader(..) => "DeleteShader", - BindBuffer(..) => "BindBuffer", - BindFramebuffer(..) => "BindFramebuffer", - BindRenderbuffer(..) => "BindRenderbuffer", - BindTexture(..) => "BindTexture", - DisableVertexAttribArray(..) => "DisableVertexAttribArray", - DrawArrays(..) => "DrawArrays", - DrawElements(..) => "DrawElements", - EnableVertexAttribArray(..) => "EnableVertexAttribArray", - FramebufferRenderbuffer(..) => "FramebufferRenderbuffer", - FramebufferTexture2D(..) => "FramebufferTexture2D", - GetBufferParameter(..) => "GetBufferParameter", - GetExtensions(..) => "GetExtensions", - GetParameter(..) => "GetParameter", - GetProgramParameter(..) => "GetProgramParameter", - GetShaderParameter(..) => "GetShaderParameter", - GetShaderPrecisionFormat(..) => "GetShaderPrecisionFormat", - GetActiveAttrib(..) => "GetActiveAttrib", - GetActiveUniform(..) => "GetActiveUniform", - GetAttribLocation(..) => "GetAttribLocation", - GetUniformLocation(..) => "GetUniformLocation", - GetShaderInfoLog(..) => "GetShaderInfoLog", - GetProgramInfoLog(..) => "GetProgramInfoLog", - GetVertexAttrib(..) => "GetVertexAttrib", - GetVertexAttribOffset(..) => "GetVertexAttribOffset", - PolygonOffset(..) => "PolygonOffset", - ReadPixels(..) => "ReadPixels", - RenderbufferStorage(..) => "RenderbufferStorage", - SampleCoverage(..) => "SampleCoverage", - Scissor(..) => "Scissor", - StencilFunc(..) => "StencilFunc", - StencilFuncSeparate(..) => "StencilFuncSeparate", - StencilMask(..) => "StencilMask", - StencilMaskSeparate(..) => "StencilMaskSeparate", - StencilOp(..) => "StencilOp", - StencilOpSeparate(..) => "StencilOpSeparate", - Hint(..) => "Hint", - IsEnabled(..) => "IsEnabled", - LineWidth(..) => "LineWidth", - PixelStorei(..) => "PixelStorei", - LinkProgram(..) => "LinkProgram", - Uniform1f(..) => "Uniform1f", - Uniform1fv(..) => "Uniform1fv", - Uniform1i(..) => "Uniform1i", - Uniform1iv(..) => "Uniform1iv", - Uniform2f(..) => "Uniform2f", - Uniform2fv(..) => "Uniform2fv", - Uniform2i(..) => "Uniform2i", - Uniform2iv(..) => "Uniform2iv", - Uniform3f(..) => "Uniform3f", - Uniform3fv(..) => "Uniform3fv", - Uniform3i(..) => "Uniform3i", - Uniform3iv(..) => "Uniform3iv", - Uniform4f(..) => "Uniform4f", - Uniform4fv(..) => "Uniform4fv", - Uniform4i(..) => "Uniform4i", - Uniform4iv(..) => "Uniform4iv", - UniformMatrix2fv(..) => "UniformMatrix2fv", - UniformMatrix3fv(..) => "UniformMatrix3fv", - UniformMatrix4fv(..) => "UniformMatrix4fv", - UseProgram(..) => "UseProgram", - ValidateProgram(..) => "ValidateProgram", - VertexAttrib(..) => "VertexAttrib", - VertexAttribPointer2f(..) => "VertexAttribPointer2f", - VertexAttribPointer(..) => "VertexAttribPointer", - Viewport(..) => "Viewport", - TexImage2D(..) => "TexImage2D", - TexParameteri(..) => "TexParameteri", - TexParameterf(..) => "TexParameterf", - TexSubImage2D(..) => "TexSubImage2D", - DrawingBufferWidth(..) => "DrawingBufferWidth", - DrawingBufferHeight(..) => "DrawingBufferHeight", - Finish(..) => "Finish", - Flush => "Flush", - GenerateMipmap(..) => "GenerateMipmap", - CreateVertexArray(..) => "CreateVertexArray", - DeleteVertexArray(..) => "DeleteVertexArray", - BindVertexArray(..) => "BindVertexArray" - }; - - write!(f, "CanvasWebGLMsg::{}(..)", name) - } -} diff --git a/components/canvas_traits/webgl_channel/ipc.rs b/components/canvas_traits/webgl_channel/ipc.rs deleted file mode 100644 index ac3020bbc7a..00000000000 --- a/components/canvas_traits/webgl_channel/ipc.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use ipc_channel; -use serde::{Deserialize, Serialize}; -use std::io; - -pub type WebGLSender<T> = ipc_channel::ipc::IpcSender<T>; -pub type WebGLReceiver<T> = ipc_channel::ipc::IpcReceiver<T>; - -pub fn webgl_channel<T: Serialize + for<'de> Deserialize<'de>>() - -> Result<(WebGLSender<T>, WebGLReceiver<T>), io::Error> { - ipc_channel::ipc::channel() -} diff --git a/components/canvas_traits/webgl_channel/mod.rs b/components/canvas_traits/webgl_channel/mod.rs deleted file mode 100644 index 1ac4ce15cb1..00000000000 --- a/components/canvas_traits/webgl_channel/mod.rs +++ /dev/null @@ -1,87 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Enum wrappers to be able to select different channel implementations at runtime. - -mod ipc; -mod mpsc; - -use ::webgl::WebGLMsg; -use serde::{Deserialize, Serialize}; -use servo_config::opts; - -lazy_static! { - static ref IS_MULTIPROCESS: bool = { - opts::multiprocess() - }; -} - -#[derive(Clone, Deserialize, Serialize)] -pub enum WebGLSender<T: Serialize> { - Ipc(ipc::WebGLSender<T>), - Mpsc(mpsc::WebGLSender<T>), -} - -impl<T: Serialize> WebGLSender<T> { - #[inline] - pub fn send(&self, msg: T) -> WebGLSendResult { - match *self { - WebGLSender::Ipc(ref sender) => { - sender.send(msg).map_err(|_| ()) - }, - WebGLSender::Mpsc(ref sender) => { - sender.send(msg).map_err(|_| ()) - } - } - } -} - -pub type WebGLSendResult = Result<(), ()>; - -pub enum WebGLReceiver<T> where T: for<'de> Deserialize<'de> + Serialize { - Ipc(ipc::WebGLReceiver<T>), - Mpsc(mpsc::WebGLReceiver<T>), -} - -impl<T> WebGLReceiver<T> where T: for<'de> Deserialize<'de> + Serialize { - pub fn recv(&self) -> Result<T, ()> { - match *self { - WebGLReceiver::Ipc(ref receiver) => { - receiver.recv().map_err(|_| ()) - }, - WebGLReceiver::Mpsc(ref receiver) => { - receiver.recv().map_err(|_| ()) - } - } - } -} - -pub fn webgl_channel<T>() -> Result<(WebGLSender<T>, WebGLReceiver<T>), ()> - where T: for<'de> Deserialize<'de> + Serialize { - if *IS_MULTIPROCESS { - ipc::webgl_channel().map(|(tx, rx)| (WebGLSender::Ipc(tx), WebGLReceiver::Ipc(rx))) - .map_err(|_| ()) - } else { - mpsc::webgl_channel().map(|(tx, rx)| (WebGLSender::Mpsc(tx), WebGLReceiver::Mpsc(rx))) - } -} - -#[derive(Clone, Deserialize, Serialize)] -pub struct WebGLChan(pub WebGLSender<WebGLMsg>); - -impl WebGLChan { - #[inline] - pub fn send(&self, msg: WebGLMsg) -> WebGLSendResult { - self.0.send(msg) - } -} - -#[derive(Clone, Deserialize, Serialize)] -pub struct WebGLPipeline(pub WebGLChan); - -impl WebGLPipeline { - pub fn channel(&self) -> WebGLChan { - self.0.clone() - } -} diff --git a/components/canvas_traits/webgl_channel/mpsc.rs b/components/canvas_traits/webgl_channel/mpsc.rs deleted file mode 100644 index b0fe29241f3..00000000000 --- a/components/canvas_traits/webgl_channel/mpsc.rs +++ /dev/null @@ -1,51 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use serde::{Deserialize, Serialize}; -use serde::{Deserializer, Serializer}; -use std::sync::mpsc; - -#[macro_use] -macro_rules! unreachable_serializable { - ($name:ident) => { - impl<T> Serialize for $name<T> { - fn serialize<S: Serializer>(&self, _: S) -> Result<S::Ok, S::Error> { - unreachable!(); - } - } - - impl<'a, T> Deserialize<'a> for $name<T> { - fn deserialize<D>(_: D) -> Result<$name<T>, D::Error> - where D: Deserializer<'a> { - unreachable!(); - } - } - }; -} - -#[derive(Clone)] -pub struct WebGLSender<T>(mpsc::Sender<T>); -pub struct WebGLReceiver<T>(mpsc::Receiver<T>); - -impl<T> WebGLSender<T> { - #[inline] - pub fn send(&self, data: T) -> Result<(), mpsc::SendError<T>> { - self.0.send(data) - } -} - -impl<T> WebGLReceiver<T> { - #[inline] - pub fn recv(&self) -> Result<T, mpsc::RecvError> { - self.0.recv() - } -} - -pub fn webgl_channel<T>() -> Result<(WebGLSender<T>, WebGLReceiver<T>), ()> { - let (sender, receiver) = mpsc::channel(); - Ok((WebGLSender(sender), WebGLReceiver(receiver))) -} - -unreachable_serializable!(WebGLReceiver); -unreachable_serializable!(WebGLSender); diff --git a/components/constellation/Cargo.toml b/components/constellation/Cargo.toml index f2ab08dc190..ff6bd2700f0 100644 --- a/components/constellation/Cargo.toml +++ b/components/constellation/Cargo.toml @@ -30,6 +30,7 @@ metrics = {path = "../metrics"} msg = {path = "../msg"} net = {path = "../net"} net_traits = {path = "../net_traits"} +offscreen_gl_context = { version = "0.11", features = ["serde"] } profile_traits = {path = "../profile_traits"} script_traits = {path = "../script_traits"} serde = "1.0" diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 3e9b0cc80be..1685a32d8d2 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -70,8 +70,8 @@ use bluetooth_traits::BluetoothRequest; use browsingcontext::{BrowsingContext, SessionHistoryChange, SessionHistoryEntry}; use browsingcontext::{FullyActiveBrowsingContextsIterator, AllBrowsingContextsIterator}; use canvas::canvas_paint_thread::CanvasPaintThread; -use canvas::webgl_thread::WebGLThreads; -use canvas_traits::canvas::CanvasMsg; +use canvas::webgl_paint_thread::WebGLPaintThread; +use canvas_traits::CanvasMsg; use clipboard::{ClipboardContext, ClipboardProvider}; use compositing::SendableFrameTree; use compositing::compositor_thread::CompositorProxy; @@ -96,6 +96,7 @@ use net_traits::pub_domains::reg_host; use net_traits::request::RequestInit; use net_traits::storage_thread::{StorageThreadMsg, StorageType}; use network_listener::NetworkListener; +use offscreen_gl_context::{GLContextAttributes, GLLimits}; use pipeline::{InitialPipelineState, Pipeline}; use profile_traits::mem; use profile_traits::time; @@ -297,11 +298,8 @@ pub struct Constellation<Message, LTF, STF> { /// Phantom data that keeps the Rust type system happy. phantom: PhantomData<(Message, LTF, STF)>, - /// Entry point to create and get channels to a WebGLThread. - webgl_threads: WebGLThreads, - /// A channel through which messages can be sent to the webvr thread. - webvr_chan: Option<IpcSender<WebVRMsg>>, + webvr_thread: Option<IpcSender<WebVRMsg>>, } /// State needed to construct a constellation. @@ -339,12 +337,6 @@ pub struct InitialConstellationState { /// Webrender API. pub webrender_api_sender: webrender_api::RenderApiSender, - /// Entry point to create and get channels to a WebGLThread. - pub webgl_threads: WebGLThreads, - - /// A channel to the webgl thread. - pub webvr_chan: Option<IpcSender<WebVRMsg>>, - /// Whether the constellation supports the clipboard. /// TODO: this field is not used, remove it? pub supports_clipboard: bool, @@ -589,8 +581,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> info!("Using seed {} for random pipeline closure.", seed); (rng, prob) }), - webgl_threads: state.webgl_threads, - webvr_chan: state.webvr_chan, + webvr_thread: None }; constellation.run(); @@ -709,8 +700,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> webrender_api_sender: self.webrender_api_sender.clone(), webrender_document: self.webrender_document, is_private, - webgl_chan: self.webgl_threads.pipeline(), - webvr_chan: self.webvr_chan.clone() + webvr_thread: self.webvr_thread.clone() }); let pipeline = match result { @@ -1004,6 +994,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> FromCompositorMsg::LogEntry(top_level_browsing_context_id, thread_name, entry) => { self.handle_log_entry(top_level_browsing_context_id, thread_name, entry); } + FromCompositorMsg::SetWebVRThread(webvr_thread) => { + assert!(self.webvr_thread.is_none()); + self.webvr_thread = Some(webvr_thread) + } FromCompositorMsg::WebVREvents(pipeline_ids, events) => { debug!("constellation got {:?} WebVR events", events.len()); self.handle_webvr_events(pipeline_ids, events); @@ -1160,6 +1154,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> debug!("constellation got create-canvas-paint-thread message"); self.handle_create_canvas_paint_thread_msg(&size, sender) } + FromScriptMsg::CreateWebGLPaintThread(size, attributes, sender) => { + debug!("constellation got create-WebGL-paint-thread message"); + self.handle_create_webgl_paint_thread_msg(&size, attributes, sender) + } FromScriptMsg::NodeStatus(message) => { debug!("constellation got NodeStatus message"); self.compositor_proxy.send(ToCompositorMsg::Status(source_top_ctx_id, message)); @@ -1369,12 +1367,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> } } - debug!("Exiting WebGL thread."); - if let Err(e) = self.webgl_threads.exit() { - warn!("Exit WebGL Thread failed ({})", e); - } - - if let Some(chan) = self.webvr_chan.as_ref() { + if let Some(chan) = self.webvr_thread.as_ref() { debug!("Exiting WebVR thread."); if let Err(e) = chan.send(WebVRMsg::Exit) { warn!("Exit WebVR thread failed ({})", e); @@ -2142,6 +2135,19 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> } } + fn handle_create_webgl_paint_thread_msg( + &mut self, + size: &Size2D<i32>, + attributes: GLContextAttributes, + response_sender: IpcSender<Result<(IpcSender<CanvasMsg>, GLLimits), String>>) { + let webrender_api = self.webrender_api_sender.clone(); + let response = WebGLPaintThread::start(*size, attributes, webrender_api); + + if let Err(e) = response_sender.send(response) { + warn!("Create WebGL paint thread response failed ({})", e); + } + } + fn handle_webdriver_msg(&mut self, msg: WebDriverCommandMsg) { // Find the script channel for the given parent pipeline, // and pass the event to that script thread. diff --git a/components/constellation/lib.rs b/components/constellation/lib.rs index 1c444ff6603..d2ac0f00dea 100644 --- a/components/constellation/lib.rs +++ b/components/constellation/lib.rs @@ -30,6 +30,7 @@ extern crate metrics; extern crate msg; extern crate net; extern crate net_traits; +extern crate offscreen_gl_context; extern crate profile_traits; extern crate script_traits; #[macro_use] extern crate serde; diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs index 74ce33ff564..92a5fb041ef 100644 --- a/components/constellation/pipeline.rs +++ b/components/constellation/pipeline.rs @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use bluetooth_traits::BluetoothRequest; -use canvas_traits::webgl::WebGLPipeline; use compositing::CompositionPipeline; use compositing::CompositorProxy; use compositing::compositor_thread::Msg as CompositorMsg; @@ -172,12 +171,8 @@ pub struct InitialPipelineState { /// Whether this pipeline is considered private. pub is_private: bool, - - /// A channel to the webgl thread. - pub webgl_chan: WebGLPipeline, - /// A channel to the webvr thread. - pub webvr_chan: Option<IpcSender<WebVRMsg>>, + pub webvr_thread: Option<IpcSender<WebVRMsg>>, } impl Pipeline { @@ -275,8 +270,7 @@ impl Pipeline { script_content_process_shutdown_port: script_content_process_shutdown_port, webrender_api_sender: state.webrender_api_sender, webrender_document: state.webrender_document, - webgl_chan: state.webgl_chan, - webvr_chan: state.webvr_chan, + webvr_thread: state.webvr_thread, }; // Spawn the child process. @@ -476,8 +470,7 @@ pub struct UnprivilegedPipelineContent { script_content_process_shutdown_port: IpcReceiver<()>, webrender_api_sender: webrender_api::RenderApiSender, webrender_document: webrender_api::DocumentId, - webgl_chan: WebGLPipeline, - webvr_chan: Option<IpcSender<WebVRMsg>>, + webvr_thread: Option<IpcSender<WebVRMsg>>, } impl UnprivilegedPipelineContent { @@ -506,8 +499,7 @@ impl UnprivilegedPipelineContent { window_size: self.window_size, pipeline_namespace_id: self.pipeline_namespace_id, content_process_shutdown_chan: self.script_content_process_shutdown_chan, - webgl_chan: self.webgl_chan, - webvr_chan: self.webvr_chan, + webvr_thread: self.webvr_thread, }, self.load_data.clone()); LTF::create(self.id, diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 98ece855d25..2d1b7c593dc 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -34,7 +34,7 @@ use style_traits::cursor::Cursor; use text::TextRun; use text::glyph::ByteIndex; use webrender_api::{self, ClipAndScrollInfo, ClipId, ColorF, GradientStop, LocalClip}; -use webrender_api::{MixBlendMode, ScrollPolicy, ScrollSensitivity, TransformStyle}; +use webrender_api::{MixBlendMode, ScrollPolicy, ScrollSensitivity, TransformStyle, WebGLContextId}; pub use style::dom::OpaqueNode; @@ -598,6 +598,7 @@ pub enum DisplayItem { SolidColor(Box<SolidColorDisplayItem>), Text(Box<TextDisplayItem>), Image(Box<ImageDisplayItem>), + WebGL(Box<WebGLDisplayItem>), Border(Box<BorderDisplayItem>), Gradient(Box<GradientDisplayItem>), RadialGradient(Box<RadialGradientDisplayItem>), @@ -927,6 +928,14 @@ pub struct ImageDisplayItem { /// 5.3. pub image_rendering: image_rendering::T, } + +#[derive(Clone, HeapSizeOf, Deserialize, Serialize)] +pub struct WebGLDisplayItem { + pub base: BaseDisplayItem, + pub context_id: WebGLContextId, +} + + /// Paints an iframe. #[derive(Clone, HeapSizeOf, Deserialize, Serialize)] pub struct IframeDisplayItem { @@ -1240,6 +1249,7 @@ impl DisplayItem { DisplayItem::SolidColor(ref solid_color) => &solid_color.base, DisplayItem::Text(ref text) => &text.base, DisplayItem::Image(ref image_item) => &image_item.base, + DisplayItem::WebGL(ref webgl_item) => &webgl_item.base, DisplayItem::Border(ref border) => &border.base, DisplayItem::Gradient(ref gradient) => &gradient.base, DisplayItem::RadialGradient(ref gradient) => &gradient.base, @@ -1365,6 +1375,7 @@ impl fmt::Debug for DisplayItem { text.range.begin().0 as usize..(text.range.begin().0 + text.range.length().0) as usize]) } DisplayItem::Image(_) => "Image".to_owned(), + DisplayItem::WebGL(_) => "WebGL".to_owned(), DisplayItem::Border(_) => "Border".to_owned(), DisplayItem::Gradient(_) => "Gradient".to_owned(), DisplayItem::RadialGradient(_) => "RadialGradient".to_owned(), diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 75e288e4826..3fc63df7c49 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -12,13 +12,13 @@ use app_units::{AU_PER_PX, Au}; use block::{BlockFlow, BlockStackingContextType}; -use canvas_traits::canvas::{CanvasMsg, FromLayoutMsg}; +use canvas_traits::{CanvasData, CanvasMsg, FromLayoutMsg}; use context::LayoutContext; use euclid::{Transform3D, Point2D, Vector2D, Rect, SideOffsets2D, Size2D, TypedSize2D}; use flex::FlexFlow; use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED}; use flow_ref::FlowRef; -use fragment::{CanvasFragmentSource, CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo}; +use fragment::{CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo}; use fragment::{SpecificFragmentInfo, TruncatedFragmentInfo}; use gfx::display_list; use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDetails, BorderDisplayItem}; @@ -28,7 +28,7 @@ use gfx::display_list::{GradientDisplayItem, IframeDisplayItem, ImageBorder, Ima use gfx::display_list::{LineDisplayItem, NormalBorder, OpaqueNode, PushTextShadowDisplayItem}; use gfx::display_list::{PopTextShadowDisplayItem, RadialGradientDisplayItem, ScrollRoot}; use gfx::display_list::{ScrollRootType, SolidColorDisplayItem, StackingContext, StackingContextType}; -use gfx::display_list::{TextDisplayItem, TextOrientation, WebRenderImageInfo}; +use gfx::display_list::{TextDisplayItem, TextOrientation, WebGLDisplayItem, WebRenderImageInfo}; use gfx_traits::{combine_id_with_fragment_type, FragmentType, StackingContextId}; use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT}; use ipc_channel::ipc; @@ -1978,22 +1978,15 @@ impl FragmentDisplayListBuilding for Fragment { let computed_width = canvas_fragment_info.dom_width.to_px(); let computed_height = canvas_fragment_info.dom_height.to_px(); - let (image_key, format) = match canvas_fragment_info.source { - CanvasFragmentSource::WebGL(image_key) => { - (image_key, PixelFormat::BGRA8) + let canvas_data = match canvas_fragment_info.ipc_renderer { + Some(ref ipc_renderer) => { + let ipc_renderer = ipc_renderer.lock().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); + ipc_renderer.send(CanvasMsg::FromLayout( + FromLayoutMsg::SendData(sender))).unwrap(); + receiver.recv().unwrap() }, - CanvasFragmentSource::Image(ref ipc_renderer) => { - match *ipc_renderer { - Some(ref ipc_renderer) => { - let ipc_renderer = ipc_renderer.lock().unwrap(); - let (sender, receiver) = ipc::channel().unwrap(); - ipc_renderer.send(CanvasMsg::FromLayout( - FromLayoutMsg::SendData(sender))).unwrap(); - (receiver.recv().unwrap().image_key, PixelFormat::BGRA8) - }, - None => return, - } - } + None => return, }; let base = state.create_base_display_item( @@ -2002,19 +1995,29 @@ impl FragmentDisplayListBuilding for Fragment { self.node, self.style.get_cursor(Cursor::Default), DisplayListSection::Content); - let display_item = DisplayItem::Image(box ImageDisplayItem { - base: base, - webrender_image: WebRenderImageInfo { - width: computed_width as u32, - height: computed_height as u32, - format: format, - key: Some(image_key), - }, - image_data: None, - stretch_size: stacking_relative_content_box.size, - tile_spacing: Size2D::zero(), - image_rendering: image_rendering::T::auto, - }); + let display_item = match canvas_data { + CanvasData::Image(canvas_data) => { + DisplayItem::Image(box ImageDisplayItem { + base: base, + webrender_image: WebRenderImageInfo { + width: computed_width as u32, + height: computed_height as u32, + format: PixelFormat::BGRA8, + key: Some(canvas_data.image_key), + }, + image_data: None, + stretch_size: stacking_relative_content_box.size, + tile_spacing: Size2D::zero(), + image_rendering: image_rendering::T::auto, + }) + } + CanvasData::WebGL(context_id) => { + DisplayItem::WebGL(box WebGLDisplayItem { + base: base, + context_id: context_id, + }) + } + }; state.add_display_item(display_item); } diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index f4928262e99..2510b185d1c 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -8,7 +8,7 @@ use ServoArc; use app_units::Au; -use canvas_traits::canvas::CanvasMsg; +use canvas_traits::CanvasMsg; use context::{LayoutContext, with_thread_local_font_context}; use euclid::{Transform3D, Point2D, Vector2D, Radians, Rect, Size2D}; use floats::ClearType; @@ -30,7 +30,7 @@ use msg::constellation_msg::{BrowsingContextId, PipelineId}; use net_traits::image::base::{Image, ImageMetadata}; use net_traits::image_cache::{ImageOrMetadataAvailable, UsePlaceholder}; use range::*; -use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource}; +use script_layout_interface::HTMLCanvasData; use script_layout_interface::SVGSVGData; use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutElement, ThreadSafeLayoutNode}; use serde::ser::{Serialize, SerializeStruct, Serializer}; @@ -53,7 +53,6 @@ use style::values::{self, Either, Auto}; use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto}; use text; use text::TextRunScanner; -use webrender_api; use wrapper::ThreadSafeLayoutNodeHelpers; // From gfxFontConstants.h in Firefox. @@ -323,31 +322,17 @@ impl InlineAbsoluteFragmentInfo { } #[derive(Clone)] -pub enum CanvasFragmentSource { - WebGL(webrender_api::ImageKey), - Image(Option<Arc<Mutex<IpcSender<CanvasMsg>>>>) -} - -#[derive(Clone)] pub struct CanvasFragmentInfo { - pub source: CanvasFragmentSource, + pub ipc_renderer: Option<Arc<Mutex<IpcSender<CanvasMsg>>>>, pub dom_width: Au, pub dom_height: Au, } impl CanvasFragmentInfo { pub fn new(data: HTMLCanvasData) -> CanvasFragmentInfo { - let source = match data.source { - HTMLCanvasDataSource::WebGL(texture_id) => { - CanvasFragmentSource::WebGL(texture_id) - }, - HTMLCanvasDataSource::Image(ipc_sender) => { - CanvasFragmentSource::Image(ipc_sender.map(|renderer| Arc::new(Mutex::new(renderer)))) - } - }; - CanvasFragmentInfo { - source: source, + ipc_renderer: data.ipc_renderer + .map(|renderer| Arc::new(Mutex::new(renderer))), dom_width: Au::from_px(data.width as i32), dom_height: Au::from_px(data.height as i32), } diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index 6e5a774e283..6b8b334d52d 100644 --- a/components/layout/webrender_helpers.rs +++ b/components/layout/webrender_helpers.rs @@ -305,6 +305,11 @@ impl WebRenderDisplayItemConverter for DisplayItem { } } } + DisplayItem::WebGL(ref item) => { + builder.push_webgl_canvas(item.base.bounds.to_rectf(), + Some(item.base.local_clip), + item.context_id); + } DisplayItem::Border(ref item) => { let rect = item.base.bounds.to_rectf(); let widths = item.border_widths.to_border_widths(); diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 4168fb4effa..81017cd344e 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -30,11 +30,8 @@ //! `JSTraceable` to a datatype. use app_units::Au; -use canvas_traits::canvas::{CanvasGradientStop, LinearGradientStyle, RadialGradientStyle}; -use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle}; -use canvas_traits::webgl::{WebGLBufferId, WebGLFramebufferId, WebGLProgramId, WebGLRenderbufferId}; -use canvas_traits::webgl::{WebGLChan, WebGLContextShareMode, WebGLError, WebGLPipeline, WebGLMsgSender}; -use canvas_traits::webgl::{WebGLReceiver, WebGLSender, WebGLShaderId, WebGLTextureId, WebGLVertexArrayId}; +use canvas_traits::{CanvasGradientStop, LinearGradientStyle, RadialGradientStyle}; +use canvas_traits::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle}; use cssparser::RGBA; use devtools_traits::{CSSError, TimelineMarkerType, WorkerId}; use dom::abstractworker::SharedRt; @@ -108,7 +105,8 @@ use style::stylesheets::keyframes_rule::Keyframe; use style::values::specified::Length; use time::Duration; use uuid::Uuid; -use webrender_api::ImageKey; +use webrender_api::{WebGLBufferId, WebGLError, WebGLFramebufferId, WebGLProgramId}; +use webrender_api::{WebGLRenderbufferId, WebGLShaderId, WebGLTextureId, WebGLVertexArrayId}; use webvr_traits::WebVRGamepadHand; /// A trait to allow tracing (only) DOM objects. @@ -393,13 +391,8 @@ unsafe_no_jsmanaged_fields!(OpaqueStyleAndLayoutData); unsafe_no_jsmanaged_fields!(PathBuf); unsafe_no_jsmanaged_fields!(CSSErrorReporter); unsafe_no_jsmanaged_fields!(DrawAPaintImageResult); -unsafe_no_jsmanaged_fields!(ImageKey); unsafe_no_jsmanaged_fields!(WebGLBufferId); -unsafe_no_jsmanaged_fields!(WebGLChan); -unsafe_no_jsmanaged_fields!(WebGLContextShareMode); unsafe_no_jsmanaged_fields!(WebGLFramebufferId); -unsafe_no_jsmanaged_fields!(WebGLMsgSender); -unsafe_no_jsmanaged_fields!(WebGLPipeline); unsafe_no_jsmanaged_fields!(WebGLProgramId); unsafe_no_jsmanaged_fields!(WebGLRenderbufferId); unsafe_no_jsmanaged_fields!(WebGLShaderId); @@ -473,20 +466,6 @@ unsafe impl<T: Send> JSTraceable for Sender<T> { } } -unsafe impl<T: Send> JSTraceable for WebGLReceiver<T> where T: for<'de> Deserialize<'de> + Serialize { - #[inline] - unsafe fn trace(&self, _: *mut JSTracer) { - // Do nothing - } -} - -unsafe impl<T: Send> JSTraceable for WebGLSender<T> where T: for<'de> Deserialize<'de> + Serialize { - #[inline] - unsafe fn trace(&self, _: *mut JSTracer) { - // Do nothing - } -} - unsafe impl JSTraceable for Transform2D<f32> { #[inline] unsafe fn trace(&self, _trc: *mut JSTracer) { diff --git a/components/script/dom/canvasgradient.rs b/components/script/dom/canvasgradient.rs index 3a0707ab5eb..64df591f760 100644 --- a/components/script/dom/canvasgradient.rs +++ b/components/script/dom/canvasgradient.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::canvas::{CanvasGradientStop, FillOrStrokeStyle, LinearGradientStyle, RadialGradientStyle}; +use canvas_traits::{CanvasGradientStop, FillOrStrokeStyle, LinearGradientStyle, RadialGradientStyle}; use cssparser::{Parser, ParserInput, RGBA}; use cssparser::Color as CSSColor; use dom::bindings::cell::DOMRefCell; diff --git a/components/script/dom/canvaspattern.rs b/components/script/dom/canvaspattern.rs index 46bcbedcef0..5d9dd5cb767 100644 --- a/components/script/dom/canvaspattern.rs +++ b/components/script/dom/canvaspattern.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::canvas::{FillOrStrokeStyle, RepetitionStyle, SurfaceStyle}; +use canvas_traits::{FillOrStrokeStyle, RepetitionStyle, SurfaceStyle}; use dom::bindings::codegen::Bindings::CanvasPatternBinding; use dom::bindings::js::Root; use dom::bindings::reflector::{Reflector, reflect_dom_object}; diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index d4fcfae4ab8..55d2ef3ceb4 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -2,10 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg}; -use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; -use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; -use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; +use canvas_traits::{Canvas2dMsg, CanvasCommonMsg, CanvasMsg}; +use canvas_traits::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; +use canvas_traits::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; +use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; use cssparser::{Parser, ParserInput, RGBA}; use cssparser::Color as CSSColor; use dom::bindings::cell::DOMRefCell; @@ -163,7 +163,7 @@ impl CanvasRenderingContext2D { pub fn set_bitmap_dimensions(&self, size: Size2D<i32>) { self.reset_to_initial_state(); self.ipc_renderer - .send(CanvasMsg::Recreate(size)) + .send(CanvasMsg::Common(CanvasCommonMsg::Recreate(size))) .unwrap(); } @@ -173,6 +173,10 @@ impl CanvasRenderingContext2D { *self.state.borrow_mut() = CanvasContextState::new(); } + pub fn ipc_renderer(&self) -> IpcSender<CanvasMsg> { + self.ipc_renderer.clone() + } + fn mark_as_dirty(&self) { if let Some(ref canvas) = self.canvas { canvas.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); @@ -1388,7 +1392,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { impl Drop for CanvasRenderingContext2D { fn drop(&mut self) { - if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close) { + if let Err(err) = self.ipc_renderer.send(CanvasMsg::Common(CanvasCommonMsg::Close)) { warn!("Could not close canvas: {}", err) } } diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 3d89c08b230..a95ff766171 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use base64; -use canvas_traits::canvas::{CanvasMsg, FromScriptMsg}; +use canvas_traits::{CanvasMsg, FromScriptMsg}; use dom::attr::Attr; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; @@ -30,11 +30,11 @@ use euclid::Size2D; use html5ever::{LocalName, Prefix}; use image::ColorType; use image::png::PNGEncoder; -use ipc_channel::ipc; +use ipc_channel::ipc::{self, IpcSender}; use js::error::throw_type_error; use js::jsapi::{HandleValue, JSContext}; use offscreen_gl_context::GLContextAttributes; -use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource}; +use script_layout_interface::HTMLCanvasData; use std::iter::repeat; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; @@ -106,22 +106,21 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { fn data(&self) -> HTMLCanvasData { unsafe { let canvas = &*self.unsafe_get(); - let source = match canvas.context.borrow_for_layout().as_ref() { - Some(&CanvasContext::Context2d(ref context)) => { - HTMLCanvasDataSource::Image(Some(context.to_layout().get_ipc_renderer())) - }, - Some(&CanvasContext::WebGL(ref context)) => { - context.to_layout().canvas_data_source() - }, - None => { - HTMLCanvasDataSource::Image(None) + let ipc_renderer = canvas.context.borrow_for_layout().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => { + context.to_layout().get_ipc_renderer() + }, + CanvasContext::WebGL(ref context) => { + context.to_layout().get_ipc_renderer() + }, } - }; + }); let width_attr = canvas.upcast::<Element>().get_attr_for_layout(&ns!(), &local_name!("width")); let height_attr = canvas.upcast::<Element>().get_attr_for_layout(&ns!(), &local_name!("height")); HTMLCanvasData { - source: source, + ipc_renderer: ipc_renderer, width: width_attr.map_or(DEFAULT_WIDTH, |val| val.as_uint()), height: height_attr.map_or(DEFAULT_HEIGHT, |val| val.as_uint()), } @@ -151,6 +150,15 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { impl HTMLCanvasElement { + pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { + self.context.borrow().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => context.ipc_renderer(), + CanvasContext::WebGL(ref context) => context.ipc_renderer(), + } + }) + } + pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> { if self.context.borrow().is_none() { let window = window_from_node(self); @@ -213,26 +221,22 @@ impl HTMLCanvasElement { return None } - let data = match self.context.borrow().as_ref() { - Some(&CanvasContext::Context2d(ref context)) => { - let (sender, receiver) = ipc::channel().unwrap(); - let msg = CanvasMsg::FromScript(FromScriptMsg::SendPixels(sender)); - context.get_ipc_renderer().send(msg).unwrap(); + let data = if let Some(renderer) = self.ipc_renderer() { + let (sender, receiver) = ipc::channel().unwrap(); + let msg = CanvasMsg::FromScript(FromScriptMsg::SendPixels(sender)); + renderer.send(msg).unwrap(); - match receiver.recv().unwrap() { - Some(pixels) => pixels, - None => { - return None; - } + match receiver.recv().unwrap() { + Some(pixels) => pixels, + None => { + // TODO(emilio, #14109): Not sure if WebGL canvas is + // required for 2d spec, but I think it's not, if so, make + // this return a readback from the GL context. + return None; } - }, - Some(&CanvasContext::WebGL(_)) => { - // TODO: add a method in WebGLRenderingContext to get the pixels. - return None; - }, - None => { - repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect() } + } else { + repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect() }; Some((data, size)) diff --git a/components/script/dom/paintrenderingcontext2d.rs b/components/script/dom/paintrenderingcontext2d.rs index c6b62b50e15..c3aa9e4c98b 100644 --- a/components/script/dom/paintrenderingcontext2d.rs +++ b/components/script/dom/paintrenderingcontext2d.rs @@ -2,9 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::canvas::CanvasImageData; -use canvas_traits::canvas::CanvasMsg; -use canvas_traits::canvas::FromLayoutMsg; +use canvas_traits::CanvasData; +use canvas_traits::CanvasMsg; +use canvas_traits::FromLayoutMsg; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineCap; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineJoin; @@ -58,9 +58,9 @@ impl PaintRenderingContext2D { PaintRenderingContext2DBinding::Wrap) } - pub fn send_data(&self, sender: IpcSender<CanvasImageData>) { + pub fn send_data(&self, sender: IpcSender<CanvasData>) { let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender)); - let _ = self.context.get_ipc_renderer().send(msg); + let _ = self.context.ipc_renderer().send(msg); } pub fn take_missing_image_urls(&self) -> Vec<ServoUrl> { diff --git a/components/script/dom/paintworkletglobalscope.rs b/components/script/dom/paintworkletglobalscope.rs index 607c432c78a..b0a43cbf25d 100644 --- a/components/script/dom/paintworkletglobalscope.rs +++ b/components/script/dom/paintworkletglobalscope.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use canvas_traits::CanvasData; use dom::bindings::callback::CallbackContainer; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::PaintWorkletGlobalScopeBinding; @@ -297,7 +298,7 @@ impl PaintWorkletGlobalScope { let (sender, receiver) = ipc::channel().expect("IPC channel creation."); rendering_context.send_data(sender); let image_key = match receiver.recv() { - Ok(data) => Some(data.image_key), + Ok(CanvasData::Image(data)) => Some(data.image_key), _ => None, }; diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs index a36bd27ad29..54f06fb928f 100644 --- a/components/script/dom/vrdisplay.rs +++ b/components/script/dom/vrdisplay.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::webgl::{webgl_channel, WebGLReceiver, WebVRCommand}; +use canvas_traits::CanvasMsg; use core::ops::Deref; use dom::bindings::callback::ExceptionHandling; use dom::bindings::cell::DOMRefCell; @@ -32,7 +32,8 @@ use dom::vrpose::VRPose; use dom::vrstageparameters::VRStageParameters; use dom::webglrenderingcontext::WebGLRenderingContext; use dom_struct::dom_struct; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc; +use ipc_channel::ipc::{IpcSender, IpcReceiver}; use js::jsapi::JSContext; use script_runtime::CommonScriptMsg; use script_runtime::ScriptThreadEventCategory::WebVREvent; @@ -42,6 +43,7 @@ use std::mem; use std::rc::Rc; use std::sync::mpsc; use std::thread; +use webrender_api::VRCompositorCommand; use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVRFrameData, WebVRLayer, WebVRMsg}; #[dom_struct] @@ -69,7 +71,7 @@ pub struct VRDisplay { // Compositor VRFrameData synchonization frame_data_status: Cell<VRFrameDataStatus>, #[ignore_heap_size_of = "channels are hard"] - frame_data_receiver: DOMRefCell<Option<WebGLReceiver<Result<Vec<u8>, ()>>>>, + frame_data_receiver: DOMRefCell<Option<IpcReceiver<Result<Vec<u8>, ()>>>>, running_display_raf: Cell<bool>, paused: Cell<bool>, stopped_on_pause: Cell<bool>, @@ -384,10 +386,11 @@ impl VRDisplayMethods for VRDisplay { return; } - let display_id = self.display.borrow().display_id; + let api_sender = self.layer_ctx.get().unwrap().ipc_renderer(); + let display_id = self.display.borrow().display_id as u64; let layer = self.layer.borrow(); - let msg = WebVRCommand::SubmitFrame(display_id, layer.left_bounds, layer.right_bounds); - self.layer_ctx.get().unwrap().send_vr_command(msg); + let msg = VRCompositorCommand::SubmitFrame(display_id, layer.left_bounds, layer.right_bounds); + api_sender.send(CanvasMsg::WebVR(msg)).unwrap(); } // https://w3c.github.io/webvr/spec/1.1/#dom-vrdisplay-getlayers @@ -486,11 +489,11 @@ impl VRDisplay { fn init_present(&self) { self.presenting.set(true); - let (sync_sender, sync_receiver) = webgl_channel().unwrap(); + let (sync_sender, sync_receiver) = ipc::channel().unwrap(); *self.frame_data_receiver.borrow_mut() = Some(sync_receiver); - let display_id = self.display.borrow().display_id; - let api_sender = self.layer_ctx.get().unwrap().webgl_sender(); + let display_id = self.display.borrow().display_id as u64; + let api_sender = self.layer_ctx.get().unwrap().ipc_renderer(); let js_sender = self.global().script_chan(); let address = Trusted::new(&*self); let near_init = self.depth_near.get(); @@ -508,7 +511,7 @@ impl VRDisplay { let mut far = far_init; // Initialize compositor - api_sender.send_vr(WebVRCommand::Create(display_id)).unwrap(); + api_sender.send(CanvasMsg::WebVR(VRCompositorCommand::Create(display_id))).unwrap(); loop { // Run RAF callbacks on JavaScript thread let msg = box NotifyDisplayRAF { @@ -518,8 +521,8 @@ impl VRDisplay { js_sender.send(CommonScriptMsg::RunnableMsg(WebVREvent, msg)).unwrap(); // Run Sync Poses in parallell on Render thread - let msg = WebVRCommand::SyncPoses(display_id, near, far, sync_sender.clone()); - api_sender.send_vr(msg).unwrap(); + let msg = VRCompositorCommand::SyncPoses(display_id, near, far, sync_sender.clone()); + api_sender.send(CanvasMsg::WebVR(msg)).unwrap(); // Wait until both SyncPoses & RAF ends if let Ok(depth) = raf_receiver.recv().unwrap() { @@ -538,9 +541,10 @@ impl VRDisplay { self.presenting.set(false); *self.frame_data_receiver.borrow_mut() = None; - let api_sender = self.layer_ctx.get().unwrap().webgl_sender(); - let display_id = self.display.borrow().display_id; - api_sender.send_vr(WebVRCommand::Release(display_id)).unwrap(); + let api_sender = self.layer_ctx.get().unwrap().ipc_renderer(); + let display_id = self.display.borrow().display_id as u64; + let msg = VRCompositorCommand::Release(display_id); + api_sender.send(CanvasMsg::WebVR(msg)).unwrap(); } // Only called when the JSContext is destroyed while presenting. @@ -623,7 +627,7 @@ impl Runnable for NotifyDisplayRAF { } -// WebVR Spec: If the number of values in the leftBounds/rightBounds arrays +// WebVR Spect: If the number of values in the leftBounds/rightBounds arrays // is not 0 or 4 for any of the passed layers the promise is rejected fn parse_bounds(src: &Option<Vec<Finite<f32>>>, dst: &mut [f32; 4]) -> Result<(), &'static str> { match *src { diff --git a/components/script/dom/webgl_extensions/ext/oesvertexarrayobject.rs b/components/script/dom/webgl_extensions/ext/oesvertexarrayobject.rs index 48385a3d50f..097742f5441 100644 --- a/components/script/dom/webgl_extensions/ext/oesvertexarrayobject.rs +++ b/components/script/dom/webgl_extensions/ext/oesvertexarrayobject.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLError}; +use canvas_traits::CanvasMsg; use dom::bindings::codegen::Bindings::OESVertexArrayObjectBinding::{self, OESVertexArrayObjectMethods}; use dom::bindings::codegen::Bindings::OESVertexArrayObjectBinding::OESVertexArrayObjectConstants; use dom::bindings::js::{JS, MutNullableJS, Root}; @@ -15,6 +15,7 @@ use js::jsapi::JSContext; use js::jsval::{JSVal, NullValue}; use std::iter; use super::{WebGLExtension, WebGLExtensions}; +use webrender_api::{self, WebGLCommand, WebGLError}; #[dom_struct] pub struct OESVertexArrayObject { @@ -47,8 +48,8 @@ impl OESVertexArrayObject { impl OESVertexArrayObjectMethods for OESVertexArrayObject { // https://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/ fn CreateVertexArrayOES(&self) -> Option<Root<WebGLVertexArrayObjectOES>> { - let (sender, receiver) = webgl_channel().unwrap(); - self.ctx.send_command(WebGLCommand::CreateVertexArray(sender)); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.ctx.send_renderer_message(CanvasMsg::WebGL(WebGLCommand::CreateVertexArray(sender))); let result = receiver.recv().unwrap(); result.map(|vao_id| WebGLVertexArrayObjectOES::new(&self.global(), vao_id)) @@ -65,7 +66,7 @@ impl OESVertexArrayObjectMethods for OESVertexArrayObject { if let Some(bound_vao) = self.bound_vao.get() { if bound_vao.id() == vao.id() { self.bound_vao.set(None); - self.ctx.send_command(WebGLCommand::BindVertexArray(None)); + self.ctx.send_renderer_message(CanvasMsg::WebGL(WebGLCommand::BindVertexArray(None))); } } @@ -79,7 +80,7 @@ impl OESVertexArrayObjectMethods for OESVertexArrayObject { } // Delete the vao - self.ctx.send_command(WebGLCommand::DeleteVertexArray(vao.id())); + self.ctx.send_renderer_message(CanvasMsg::WebGL(WebGLCommand::DeleteVertexArray(vao.id()))); vao.set_deleted(); } } @@ -113,7 +114,7 @@ impl OESVertexArrayObjectMethods for OESVertexArrayObject { return; } - self.ctx.send_command(WebGLCommand::BindVertexArray(Some(vao.id()))); + self.ctx.send_renderer_message(CanvasMsg::WebGL(WebGLCommand::BindVertexArray(Some(vao.id())))); vao.set_ever_bound(); self.bound_vao.set(Some(&vao)); @@ -123,7 +124,7 @@ impl OESVertexArrayObjectMethods for OESVertexArrayObject { let element_array = vao.bound_buffer_element_array(); self.ctx.set_bound_buffer_element_array(element_array.as_ref().map(|buffer| &**buffer)); } else { - self.ctx.send_command(WebGLCommand::BindVertexArray(None)); + self.ctx.send_renderer_message(CanvasMsg::WebGL(WebGLCommand::BindVertexArray(None))); self.bound_vao.set(None); self.ctx.set_bound_attrib_buffers(iter::empty()); } diff --git a/components/script/dom/webgl_extensions/ext/webglvertexarrayobjectoes.rs b/components/script/dom/webgl_extensions/ext/webglvertexarrayobjectoes.rs index 2fe109cafa6..e44b7c9bc42 100644 --- a/components/script/dom/webgl_extensions/ext/webglvertexarrayobjectoes.rs +++ b/components/script/dom/webgl_extensions/ext/webglvertexarrayobjectoes.rs @@ -2,7 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::webgl::WebGLVertexArrayId; use core::cell::Ref; use core::iter::FromIterator; use dom::bindings::cell::DOMRefCell; @@ -16,6 +15,7 @@ use dom::webglobject::WebGLObject; use dom_struct::dom_struct; use std::cell::Cell; use std::collections::HashMap; +use webrender_api::WebGLVertexArrayId; #[dom_struct] pub struct WebGLVertexArrayObjectOES { diff --git a/components/script/dom/webgl_extensions/extensions.rs b/components/script/dom/webgl_extensions/extensions.rs index 2a780b129ff..28c32dede64 100644 --- a/components/script/dom/webgl_extensions/extensions.rs +++ b/components/script/dom/webgl_extensions/extensions.rs @@ -2,7 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::webgl::WebGLError; use core::iter::FromIterator; use core::nonzero::NonZero; use dom::bindings::cell::DOMRefCell; @@ -20,6 +19,7 @@ use std::cell::Ref; use std::collections::{HashMap, HashSet}; use super::{ext, WebGLExtension}; use super::wrapper::{WebGLExtensionWrapper, TypedWebGLExtensionWrapper}; +use webrender_api::WebGLError; // Data types that are implemented for texImage2D and texSubImage2D in WebGLRenderingContext // but must trigger a InvalidValue error until the related WebGL Extensions are enabled. diff --git a/components/script/dom/webgl_validations/tex_image_2d.rs b/components/script/dom/webgl_validations/tex_image_2d.rs index cd5320453c7..41b2795bc14 100644 --- a/components/script/dom/webgl_validations/tex_image_2d.rs +++ b/components/script/dom/webgl_validations/tex_image_2d.rs @@ -2,13 +2,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::webgl::WebGLError::*; use dom::bindings::js::Root; use dom::webglrenderingcontext::WebGLRenderingContext; use dom::webgltexture::WebGLTexture; use std::{self, fmt}; use super::WebGLValidator; use super::types::{TexImageTarget, TexDataType, TexFormat}; +use webrender_api::WebGLError::*; /// The errors that the texImage* family of functions can generate. #[derive(Debug)] diff --git a/components/script/dom/webglbuffer.rs b/components/script/dom/webglbuffer.rs index 96db4466d56..448956a9b90 100644 --- a/components/script/dom/webglbuffer.rs +++ b/components/script/dom/webglbuffer.rs @@ -3,8 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl -use canvas_traits::webgl::{WebGLBufferId, WebGLCommand, WebGLError, WebGLMsgSender, WebGLResult, WebGLVertexArrayId}; -use canvas_traits::webgl::webgl_channel; +use canvas_traits::CanvasMsg; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::WebGLBufferBinding; use dom::bindings::js::Root; @@ -12,9 +11,11 @@ use dom::bindings::reflector::reflect_dom_object; use dom::webglobject::WebGLObject; use dom::window::Window; use dom_struct::dom_struct; +use ipc_channel::ipc::IpcSender; use std::cell::Cell; use std::collections::HashSet; - +use webrender_api; +use webrender_api::{WebGLBufferId, WebGLCommand, WebGLError, WebGLResult, WebGLVertexArrayId}; #[dom_struct] pub struct WebGLBuffer { @@ -28,11 +29,11 @@ pub struct WebGLBuffer { vao_references: DOMRefCell<Option<HashSet<WebGLVertexArrayId>>>, pending_delete: Cell<bool>, #[ignore_heap_size_of = "Defined in ipc-channel"] - renderer: WebGLMsgSender, + renderer: IpcSender<CanvasMsg>, } impl WebGLBuffer { - fn new_inherited(renderer: WebGLMsgSender, + fn new_inherited(renderer: IpcSender<CanvasMsg>, id: WebGLBufferId) -> WebGLBuffer { WebGLBuffer { @@ -47,17 +48,17 @@ impl WebGLBuffer { } } - pub fn maybe_new(window: &Window, renderer: WebGLMsgSender) + pub fn maybe_new(window: &Window, renderer: IpcSender<CanvasMsg>) -> Option<Root<WebGLBuffer>> { - let (sender, receiver) = webgl_channel().unwrap(); - renderer.send(WebGLCommand::CreateBuffer(sender)).unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateBuffer(sender))).unwrap(); let result = receiver.recv().unwrap(); result.map(|buffer_id| WebGLBuffer::new(window, renderer, buffer_id)) } pub fn new(window: &Window, - renderer: WebGLMsgSender, + renderer: IpcSender<CanvasMsg>, id: WebGLBufferId) -> Root<WebGLBuffer> { reflect_dom_object(box WebGLBuffer::new_inherited(renderer, id), @@ -80,7 +81,7 @@ impl WebGLBuffer { } else { self.target.set(Some(target)); } - let msg = WebGLCommand::BindBuffer(target, Some(self.id)); + let msg = CanvasMsg::WebGL(WebGLCommand::BindBuffer(target, Some(self.id))); self.renderer.send(msg).unwrap(); Ok(()) @@ -93,7 +94,9 @@ impl WebGLBuffer { } } self.capacity.set(data.len()); - self.renderer.send(WebGLCommand::BufferData(target, data.to_vec(), usage)).unwrap(); + self.renderer + .send(CanvasMsg::WebGL(WebGLCommand::BufferData(target, data.to_vec(), usage))) + .unwrap(); Ok(()) } @@ -105,7 +108,7 @@ impl WebGLBuffer { pub fn delete(&self) { if !self.is_deleted.get() { self.is_deleted.set(true); - let _ = self.renderer.send(WebGLCommand::DeleteBuffer(self.id)); + let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteBuffer(self.id))); } } @@ -141,7 +144,7 @@ impl WebGLBuffer { if let Some(ref mut vao_refs) = *self.vao_references.borrow_mut() { if vao_refs.take(&id).is_some() && self.pending_delete.get() { // WebGL spec: The deleted buffers should no longer be valid when the VAOs are deleted - let _ = self.renderer.send(WebGLCommand::DeleteBuffer(self.id)); + let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteBuffer(self.id))); self.is_deleted.set(true); } } diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index 7a6b1090064..bb486c80c38 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -3,9 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl -use canvas_traits::webgl::{WebGLCommand, WebGLFramebufferBindingRequest, WebGLFramebufferId}; -use canvas_traits::webgl::{WebGLMsgSender, WebGLResult, WebGLError}; -use canvas_traits::webgl::webgl_channel; +use canvas_traits::CanvasMsg; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::WebGLFramebufferBinding; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; @@ -16,7 +14,10 @@ use dom::webglrenderbuffer::WebGLRenderbuffer; use dom::webgltexture::WebGLTexture; use dom::window::Window; use dom_struct::dom_struct; +use ipc_channel::ipc::IpcSender; use std::cell::Cell; +use webrender_api; +use webrender_api::{WebGLCommand, WebGLFramebufferBindingRequest, WebGLFramebufferId, WebGLResult, WebGLError}; #[must_root] #[derive(JSTraceable, Clone, HeapSizeOf)] @@ -35,7 +36,7 @@ pub struct WebGLFramebuffer { size: Cell<Option<(i32, i32)>>, status: Cell<u32>, #[ignore_heap_size_of = "Defined in ipc-channel"] - renderer: WebGLMsgSender, + renderer: IpcSender<CanvasMsg>, // The attachment points for textures and renderbuffers on this // FBO. @@ -46,7 +47,7 @@ pub struct WebGLFramebuffer { } impl WebGLFramebuffer { - fn new_inherited(renderer: WebGLMsgSender, + fn new_inherited(renderer: IpcSender<CanvasMsg>, id: WebGLFramebufferId) -> WebGLFramebuffer { WebGLFramebuffer { @@ -64,17 +65,17 @@ impl WebGLFramebuffer { } } - pub fn maybe_new(window: &Window, renderer: WebGLMsgSender) + pub fn maybe_new(window: &Window, renderer: IpcSender<CanvasMsg>) -> Option<Root<WebGLFramebuffer>> { - let (sender, receiver) = webgl_channel().unwrap(); - renderer.send(WebGLCommand::CreateFramebuffer(sender)).unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateFramebuffer(sender))).unwrap(); let result = receiver.recv().unwrap(); result.map(|fb_id| WebGLFramebuffer::new(window, renderer, fb_id)) } pub fn new(window: &Window, - renderer: WebGLMsgSender, + renderer: IpcSender<CanvasMsg>, id: WebGLFramebufferId) -> Root<WebGLFramebuffer> { reflect_dom_object(box WebGLFramebuffer::new_inherited(renderer, id), @@ -97,13 +98,13 @@ impl WebGLFramebuffer { self.target.set(Some(target)); let cmd = WebGLCommand::BindFramebuffer(target, WebGLFramebufferBindingRequest::Explicit(self.id)); - self.renderer.send(cmd).unwrap(); + self.renderer.send(CanvasMsg::WebGL(cmd)).unwrap(); } pub fn delete(&self) { if !self.is_deleted.get() { self.is_deleted.set(true); - let _ = self.renderer.send(WebGLCommand::DeleteFramebuffer(self.id)); + let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteFramebuffer(self.id))); } } @@ -204,10 +205,10 @@ impl WebGLFramebuffer { } }; - self.renderer.send(WebGLCommand::FramebufferRenderbuffer(constants::FRAMEBUFFER, - attachment, - constants::RENDERBUFFER, - rb_id)).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::FramebufferRenderbuffer(constants::FRAMEBUFFER, + attachment, + constants::RENDERBUFFER, + rb_id))).unwrap(); self.update_status(); Ok(()) @@ -280,11 +281,11 @@ impl WebGLFramebuffer { } }; - self.renderer.send(WebGLCommand::FramebufferTexture2D(constants::FRAMEBUFFER, - attachment, - textarget, - tex_id, - level)).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::FramebufferTexture2D(constants::FRAMEBUFFER, + attachment, + textarget, + tex_id, + level))).unwrap(); self.update_status(); Ok(()) diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs index 6c298bb83fb..c76a2f3da18 100644 --- a/components/script/dom/webglprogram.rs +++ b/components/script/dom/webglprogram.rs @@ -3,8 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl -use canvas_traits::webgl::{WebGLCommand, WebGLError, WebGLMsgSender, WebGLParameter, WebGLProgramId, WebGLResult}; -use canvas_traits::webgl::webgl_channel; +use canvas_traits::CanvasMsg; use dom::bindings::codegen::Bindings::WebGLProgramBinding; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; use dom::bindings::js::{MutNullableJS, Root}; @@ -16,7 +15,10 @@ use dom::webglrenderingcontext::MAX_UNIFORM_AND_ATTRIBUTE_LEN; use dom::webglshader::WebGLShader; use dom::window::Window; use dom_struct::dom_struct; +use ipc_channel::ipc::IpcSender; use std::cell::Cell; +use webrender_api; +use webrender_api::{WebGLCommand, WebGLError, WebGLParameter, WebGLProgramId, WebGLResult}; #[dom_struct] pub struct WebGLProgram { @@ -28,11 +30,11 @@ pub struct WebGLProgram { fragment_shader: MutNullableJS<WebGLShader>, vertex_shader: MutNullableJS<WebGLShader>, #[ignore_heap_size_of = "Defined in ipc-channel"] - renderer: WebGLMsgSender, + renderer: IpcSender<CanvasMsg>, } impl WebGLProgram { - fn new_inherited(renderer: WebGLMsgSender, + fn new_inherited(renderer: IpcSender<CanvasMsg>, id: WebGLProgramId) -> WebGLProgram { WebGLProgram { @@ -47,17 +49,17 @@ impl WebGLProgram { } } - pub fn maybe_new(window: &Window, renderer: WebGLMsgSender) + pub fn maybe_new(window: &Window, renderer: IpcSender<CanvasMsg>) -> Option<Root<WebGLProgram>> { - let (sender, receiver) = webgl_channel().unwrap(); - renderer.send(WebGLCommand::CreateProgram(sender)).unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateProgram(sender))).unwrap(); let result = receiver.recv().unwrap(); result.map(|program_id| WebGLProgram::new(window, renderer, program_id)) } pub fn new(window: &Window, - renderer: WebGLMsgSender, + renderer: IpcSender<CanvasMsg>, id: WebGLProgramId) -> Root<WebGLProgram> { reflect_dom_object(box WebGLProgram::new_inherited(renderer, id), @@ -76,7 +78,7 @@ impl WebGLProgram { pub fn delete(&self) { if !self.is_deleted.get() { self.is_deleted.set(true); - let _ = self.renderer.send(WebGLCommand::DeleteProgram(self.id)); + let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteProgram(self.id))); if let Some(shader) = self.fragment_shader.get() { shader.decrement_attached_counter(); @@ -115,7 +117,7 @@ impl WebGLProgram { } self.linked.set(true); - self.renderer.send(WebGLCommand::LinkProgram(self.id)).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::LinkProgram(self.id))).unwrap(); Ok(()) } @@ -128,7 +130,7 @@ impl WebGLProgram { return Err(WebGLError::InvalidOperation); } - self.renderer.send(WebGLCommand::UseProgram(self.id)).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::UseProgram(self.id))).unwrap(); Ok(()) } @@ -137,7 +139,7 @@ impl WebGLProgram { if self.is_deleted() { return Err(WebGLError::InvalidOperation); } - self.renderer.send(WebGLCommand::ValidateProgram(self.id)).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::ValidateProgram(self.id))).unwrap(); Ok(()) } @@ -164,7 +166,7 @@ impl WebGLProgram { shader_slot.set(Some(shader)); shader.increment_attached_counter(); - self.renderer.send(WebGLCommand::AttachShader(self.id, shader.id())).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::AttachShader(self.id, shader.id()))).unwrap(); Ok(()) } @@ -194,7 +196,7 @@ impl WebGLProgram { shader_slot.set(None); shader.decrement_attached_counter(); - self.renderer.send(WebGLCommand::DetachShader(self.id, shader.id())).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DetachShader(self.id, shader.id()))).unwrap(); Ok(()) } @@ -214,7 +216,7 @@ impl WebGLProgram { } self.renderer - .send(WebGLCommand::BindAttribLocation(self.id, index, String::from(name))) + .send(CanvasMsg::WebGL(WebGLCommand::BindAttribLocation(self.id, index, String::from(name)))) .unwrap(); Ok(()) } @@ -223,9 +225,9 @@ impl WebGLProgram { if self.is_deleted() { return Err(WebGLError::InvalidValue); } - let (sender, receiver) = webgl_channel().unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); self.renderer - .send(WebGLCommand::GetActiveUniform(self.id, index, sender)) + .send(CanvasMsg::WebGL(WebGLCommand::GetActiveUniform(self.id, index, sender))) .unwrap(); receiver.recv().unwrap().map(|(size, ty, name)| @@ -237,9 +239,9 @@ impl WebGLProgram { if self.is_deleted() { return Err(WebGLError::InvalidValue); } - let (sender, receiver) = webgl_channel().unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); self.renderer - .send(WebGLCommand::GetActiveAttrib(self.id, index, sender)) + .send(CanvasMsg::WebGL(WebGLCommand::GetActiveAttrib(self.id, index, sender))) .unwrap(); receiver.recv().unwrap().map(|(size, ty, name)| @@ -264,9 +266,9 @@ impl WebGLProgram { return Ok(None); } - let (sender, receiver) = webgl_channel().unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); self.renderer - .send(WebGLCommand::GetAttribLocation(self.id, String::from(name), sender)) + .send(CanvasMsg::WebGL(WebGLCommand::GetAttribLocation(self.id, String::from(name), sender))) .unwrap(); Ok(receiver.recv().unwrap()) } @@ -285,9 +287,9 @@ impl WebGLProgram { return Ok(None); } - let (sender, receiver) = webgl_channel().unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); self.renderer - .send(WebGLCommand::GetUniformLocation(self.id, String::from(name), sender)) + .send(CanvasMsg::WebGL(WebGLCommand::GetUniformLocation(self.id, String::from(name), sender))) .unwrap(); Ok(receiver.recv().unwrap()) } @@ -306,15 +308,15 @@ impl WebGLProgram { return Ok("One or more shaders failed to compile".to_string()); } } - let (sender, receiver) = webgl_channel().unwrap(); - self.renderer.send(WebGLCommand::GetProgramInfoLog(self.id, sender)).unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::GetProgramInfoLog(self.id, sender))).unwrap(); Ok(receiver.recv().unwrap()) } /// glGetProgramParameter pub fn parameter(&self, param_id: u32) -> WebGLResult<WebGLParameter> { - let (sender, receiver) = webgl_channel().unwrap(); - self.renderer.send(WebGLCommand::GetProgramParameter(self.id, param_id, sender)).unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::GetProgramParameter(self.id, param_id, sender))).unwrap(); receiver.recv().unwrap() } } diff --git a/components/script/dom/webglrenderbuffer.rs b/components/script/dom/webglrenderbuffer.rs index 9a855651cc9..03589365c43 100644 --- a/components/script/dom/webglrenderbuffer.rs +++ b/components/script/dom/webglrenderbuffer.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl -use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLError, WebGLMsgSender, WebGLRenderbufferId, WebGLResult}; +use canvas_traits::CanvasMsg; use dom::bindings::codegen::Bindings::WebGLRenderbufferBinding; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; use dom::bindings::js::Root; @@ -11,7 +11,10 @@ use dom::bindings::reflector::reflect_dom_object; use dom::webglobject::WebGLObject; use dom::window::Window; use dom_struct::dom_struct; +use ipc_channel::ipc::IpcSender; use std::cell::Cell; +use webrender_api; +use webrender_api::{WebGLCommand, WebGLRenderbufferId, WebGLResult, WebGLError}; #[dom_struct] pub struct WebGLRenderbuffer { @@ -22,11 +25,11 @@ pub struct WebGLRenderbuffer { size: Cell<Option<(i32, i32)>>, internal_format: Cell<Option<u32>>, #[ignore_heap_size_of = "Defined in ipc-channel"] - renderer: WebGLMsgSender, + renderer: IpcSender<CanvasMsg>, } impl WebGLRenderbuffer { - fn new_inherited(renderer: WebGLMsgSender, + fn new_inherited(renderer: IpcSender<CanvasMsg>, id: WebGLRenderbufferId) -> WebGLRenderbuffer { WebGLRenderbuffer { @@ -40,17 +43,17 @@ impl WebGLRenderbuffer { } } - pub fn maybe_new(window: &Window, renderer: WebGLMsgSender) + pub fn maybe_new(window: &Window, renderer: IpcSender<CanvasMsg>) -> Option<Root<WebGLRenderbuffer>> { - let (sender, receiver) = webgl_channel().unwrap(); - renderer.send(WebGLCommand::CreateRenderbuffer(sender)).unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateRenderbuffer(sender))).unwrap(); let result = receiver.recv().unwrap(); result.map(|renderbuffer_id| WebGLRenderbuffer::new(window, renderer, renderbuffer_id)) } pub fn new(window: &Window, - renderer: WebGLMsgSender, + renderer: IpcSender<CanvasMsg>, id: WebGLRenderbufferId) -> Root<WebGLRenderbuffer> { reflect_dom_object(box WebGLRenderbuffer::new_inherited(renderer, id), @@ -71,14 +74,14 @@ impl WebGLRenderbuffer { pub fn bind(&self, target: u32) { self.ever_bound.set(true); - let msg = WebGLCommand::BindRenderbuffer(target, Some(self.id)); + let msg = CanvasMsg::WebGL(WebGLCommand::BindRenderbuffer(target, Some(self.id))); self.renderer.send(msg).unwrap(); } pub fn delete(&self) { if !self.is_deleted.get() { self.is_deleted.set(true); - let _ = self.renderer.send(WebGLCommand::DeleteRenderbuffer(self.id)); + let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteRenderbuffer(self.id))); } } @@ -107,7 +110,8 @@ impl WebGLRenderbuffer { // FIXME: Invalidate completeness after the call - let msg = WebGLCommand::RenderbufferStorage(constants::RENDERBUFFER, internal_format, width, height); + let msg = CanvasMsg::WebGL(WebGLCommand::RenderbufferStorage(constants::RENDERBUFFER, + internal_format, width, height)); self.renderer.send(msg).unwrap(); self.size.set(Some((width, height))); diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index c45362b4fe2..20fe133e02c 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -3,11 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 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::WebGLError::*; -use canvas_traits::webgl::webgl_channel; +use canvas_traits::{CanvasCommonMsg, CanvasMsg, byte_swap, multiply_u8_pixel}; use core::cell::Ref; use core::iter::FromIterator; use core::nonzero::NonZero; @@ -23,6 +19,7 @@ use dom::bindings::js::{JS, LayoutJS, MutNullableJS, Root}; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::event::{Event, EventBubbles, EventCancelable}; +use dom::globalscope::GlobalScope; use dom::htmlcanvaselement::HTMLCanvasElement; use dom::htmlcanvaselement::utils as canvas_utils; use dom::node::{Node, NodeDamage, window_from_node}; @@ -45,6 +42,7 @@ use dom::window::Window; use dom_struct::dom_struct; use euclid::Size2D; use half::f16; +use ipc_channel::ipc::{self, IpcSender}; use js::conversions::ConversionBehavior; use js::jsapi::{JSContext, JSObject, Type, Rooted}; use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UndefinedValue}; @@ -52,11 +50,13 @@ use js::typedarray::{TypedArray, TypedArrayElement, Float32, Int32}; use net_traits::image::base::PixelFormat; use net_traits::image_cache::ImageResponse; use offscreen_gl_context::{GLContextAttributes, GLLimits}; -use script_layout_interface::HTMLCanvasDataSource; +use script_traits::ScriptMsg; use servo_config::prefs::PREFS; use std::cell::Cell; use std::collections::HashMap; use webrender_api; +use webrender_api::{WebGLCommand, WebGLError, WebGLFramebufferBindingRequest, WebGLParameter}; +use webrender_api::WebGLError::*; type ImagePixelResult = Result<(Vec<u8>, Size2D<i32>, bool), ()>; pub const MAX_UNIFORM_AND_ATTRIBUTE_LEN: usize = 256; @@ -92,7 +92,9 @@ macro_rules! handle_object_deletion { } if let Some(command) = $unbind_command { - $self_.send_command(command); + $self_.ipc_renderer + .send(CanvasMsg::WebGL(command)) + .unwrap(); } } }; @@ -133,15 +135,12 @@ bitflags! { #[dom_struct] pub struct WebGLRenderingContext { reflector_: Reflector, - #[ignore_heap_size_of = "Channels are hard"] - webgl_sender: WebGLMsgSender, - #[ignore_heap_size_of = "Defined in webrender"] - webrender_image: Cell<Option<webrender_api::ImageKey>>, - share_mode: WebGLContextShareMode, + #[ignore_heap_size_of = "Defined in ipc-channel"] + ipc_renderer: IpcSender<CanvasMsg>, #[ignore_heap_size_of = "Defined in offscreen_gl_context"] limits: GLLimits, canvas: JS<HTMLCanvasElement>, - #[ignore_heap_size_of = "Defined in canvas_traits"] + #[ignore_heap_size_of = "Defined in webrender_api"] last_error: Cell<Option<WebGLError>>, texture_unpacking_settings: Cell<TextureUnpacking>, texture_unpacking_alignment: Cell<u32>, @@ -159,7 +158,7 @@ pub struct WebGLRenderingContext { current_scissor: Cell<(i32, i32, i32, i32)>, #[ignore_heap_size_of = "Because it's small"] current_clear_color: Cell<(f32, f32, f32, f32)>, - extension_manager: WebGLExtensions, + extension_manager: WebGLExtensions } impl WebGLRenderingContext { @@ -172,19 +171,17 @@ impl WebGLRenderingContext { return Err("WebGL context creation error forced by pref `webgl.testing.context_creation_error`".into()); } - let (sender, receiver) = webgl_channel().unwrap(); - let webgl_chan = window.webgl_chan(); - webgl_chan.send(WebGLMsg::CreateContext(size, attrs, sender)) - .unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); + let script_to_constellation_chan = window.upcast::<GlobalScope>().script_to_constellation_chan(); + script_to_constellation_chan.send(ScriptMsg::CreateWebGLPaintThread(size, attrs, sender)) + .unwrap(); let result = receiver.recv().unwrap(); - result.map(|ctx_data| { + result.map(|(ipc_renderer, context_limits)| { WebGLRenderingContext { reflector_: Reflector::new(), - webgl_sender: ctx_data.sender, - webrender_image: Cell::new(None), - share_mode: ctx_data.share_mode, - limits: ctx_data.limits, + ipc_renderer: ipc_renderer, + limits: context_limits, canvas: JS::from_ref(canvas), last_error: Cell::new(None), texture_unpacking_settings: Cell::new(CONVERT_COLORSPACE), @@ -256,43 +253,31 @@ impl WebGLRenderingContext { } pub fn recreate(&self, size: Size2D<i32>) { - let (sender, receiver) = webgl_channel().unwrap(); - self.webgl_sender.send_resize(size, sender).unwrap(); - - if let Err(msg) = receiver.recv().unwrap() { - error!("Error resizing WebGLContext: {}", msg); - return; - }; - - // Reset webrender_image because resize creates a new image_key. - // The new image key is set in the next handle_layout() method. - self.webrender_image.set(None); + self.ipc_renderer.send(CanvasMsg::Common(CanvasCommonMsg::Recreate(size))).unwrap(); // ClearColor needs to be restored because after a resize the GLContext is recreated // and the framebuffer is cleared using the default black transparent color. let color = self.current_clear_color.get(); - self.send_command(WebGLCommand::ClearColor(color.0, color.1, color.2, color.3)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::ClearColor(color.0, color.1, color.2, color.3))) + .unwrap(); // WebGL Spec: Scissor rect must not change if the canvas is resized. // See: webgl/conformance-1.0.3/conformance/rendering/gl-scissor-canvas-dimensions.html // NativeContext handling library changes the scissor after a resize, so we need to reset the // default scissor when the canvas was created or the last scissor that the user set. let rect = self.current_scissor.get(); - self.send_command(WebGLCommand::Scissor(rect.0, rect.1, rect.2, rect.3)); - } - - pub fn webgl_sender(&self) -> WebGLMsgSender { - self.webgl_sender.clone() + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Scissor(rect.0, rect.1, rect.2, rect.3))) + .unwrap() } - #[inline] - pub fn send_command(&self, command: WebGLCommand) { - self.webgl_sender.send(command).unwrap(); + pub fn ipc_renderer(&self) -> IpcSender<CanvasMsg> { + self.ipc_renderer.clone() } - #[inline] - pub fn send_vr_command(&self, command: WebVRCommand) { - self.webgl_sender.send_vr(command).unwrap(); + pub fn send_renderer_message(&self, msg: CanvasMsg) { + self.ipc_renderer.send(msg).unwrap(); } pub fn get_extension_manager<'a>(&'a self) -> &'a WebGLExtensions { @@ -385,7 +370,9 @@ impl WebGLRenderingContext { self.current_vertex_attrib_0.set((x, y, z, w)) } - self.send_command(WebGLCommand::VertexAttrib(indx, x, y, z, w)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::VertexAttrib(indx, x, y, z, w))) + .unwrap(); } fn get_current_framebuffer_size(&self) -> Option<(i32, i32)> { @@ -718,8 +705,8 @@ impl WebGLRenderingContext { // WebGLContext (probably via GetPixels()). ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLCanvasElement(canvas) => { if let Some((mut data, size)) = canvas.fetch_all_data() { - // Pixels got from Canvas have already alpha premultiplied byte_swap(&mut data); + // Pixels got from Canvas have already alpha premultiplied (data, size, true) } else { return Err(()); @@ -958,7 +945,9 @@ impl WebGLRenderingContext { // GL_UNPACK_ALIGNMENT, while for textures from images or // canvas (produced by rgba8_image_to_tex_image_data()), it // will be 1. - self.send_command(WebGLCommand::PixelStorei(constants::UNPACK_ALIGNMENT, unpacking_alignment as i32)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::PixelStorei(constants::UNPACK_ALIGNMENT, unpacking_alignment as i32))) + .unwrap(); let format = internal_format.as_gl_constant(); let data_type = data_type.as_gl_constant(); @@ -972,7 +961,9 @@ impl WebGLRenderingContext { data_type, pixels); - self.send_command(msg); + self.ipc_renderer + .send(CanvasMsg::WebGL(msg)) + .unwrap(); if let Some(fb) = self.bound_framebuffer.get() { fb.invalidate_texture(&*texture); @@ -1014,7 +1005,9 @@ impl WebGLRenderingContext { // GL_UNPACK_ALIGNMENT, while for textures from images or // canvas (produced by rgba8_image_to_tex_image_data()), it // will be 1. - self.send_command(WebGLCommand::PixelStorei(constants::UNPACK_ALIGNMENT, unpacking_alignment as i32)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::PixelStorei(constants::UNPACK_ALIGNMENT, unpacking_alignment as i32))) + .unwrap(); // TODO(emilio): convert colorspace if requested let msg = WebGLCommand::TexSubImage2D(target.as_gl_constant(), @@ -1023,7 +1016,9 @@ impl WebGLRenderingContext { format.as_gl_constant(), data_type.as_gl_constant(), pixels); - self.send_command(msg); + self.ipc_renderer + .send(CanvasMsg::WebGL(msg)) + .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14 @@ -1040,38 +1035,17 @@ impl WebGLRenderingContext { } fn get_gl_extensions(&self) -> String { - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::GetExtensions(sender)); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::GetExtensions(sender))) + .unwrap(); receiver.recv().unwrap() } - - 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() - } - } - } } impl Drop for WebGLRenderingContext { fn drop(&mut self) { - self.webgl_sender.send_remove().unwrap(); + self.ipc_renderer.send(CanvasMsg::Common(CanvasCommonMsg::Close)).unwrap(); } } @@ -1127,36 +1101,45 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11 fn Flush(&self) { - self.send_command(WebGLCommand::Flush); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Flush)) + .unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11 fn Finish(&self) { - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::Finish(sender)); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Finish(sender))) + .unwrap(); receiver.recv().unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1 fn DrawingBufferWidth(&self) -> i32 { - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::DrawingBufferWidth(sender)); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::DrawingBufferWidth(sender))) + .unwrap(); receiver.recv().unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1 fn DrawingBufferHeight(&self) -> i32 { - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::DrawingBufferHeight(sender)); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::DrawingBufferHeight(sender))) + .unwrap(); receiver.recv().unwrap() } #[allow(unsafe_code)] // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 unsafe fn GetBufferParameter(&self, _cx: *mut JSContext, target: u32, parameter: u32) -> JSVal { - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::GetBufferParameter(target, parameter, sender)); - + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::GetBufferParameter(target, parameter, sender))) + .unwrap(); match handle_potential_webgl_error!(self, receiver.recv().unwrap(), WebGLParameter::Invalid) { WebGLParameter::Int(val) => Int32Value(val), WebGLParameter::Bool(_) => panic!("Buffer parameter should not be bool"), @@ -1222,9 +1205,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } } - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::GetParameter(parameter, sender)); - + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::GetParameter(parameter, sender))) + .unwrap(); match handle_potential_webgl_error!(self, receiver.recv().unwrap(), WebGLParameter::Invalid) { WebGLParameter::Int(val) => Int32Value(val), WebGLParameter::Bool(val) => BooleanValue(val), @@ -1259,13 +1243,13 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.2 fn GetContextAttributes(&self) -> Option<WebGLContextAttributes> { - let (sender, receiver) = webgl_channel().unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); // If the send does not succeed, assume context lost - if self.webgl_sender.send(WebGLCommand::GetContextAttributes(sender)).is_err() { + if let Err(_) = self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::GetContextAttributes(sender))) { return None; } - let attrs = receiver.recv().unwrap(); Some(WebGLContextAttributes { @@ -1301,12 +1285,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn ActiveTexture(&self, texture: u32) { - self.send_command(WebGLCommand::ActiveTexture(texture)); + self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::ActiveTexture(texture))).unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn BlendColor(&self, r: f32, g: f32, b: f32, a: f32) { - self.send_command(WebGLCommand::BlendColor(r, g, b, a)); + self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::BlendColor(r, g, b, a))).unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 @@ -1315,7 +1299,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidEnum); } - self.send_command(WebGLCommand::BlendEquation(mode)); + self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::BlendEquation(mode))).unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 @@ -1324,7 +1308,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidEnum); } - self.send_command(WebGLCommand::BlendEquationSeparate(mode_rgb, mode_alpha)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::BlendEquationSeparate(mode_rgb, mode_alpha))) + .unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 @@ -1341,7 +1327,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidOperation); } - self.send_command(WebGLCommand::BlendFunc(src_factor, dest_factor)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::BlendFunc(src_factor, dest_factor))) + .unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 @@ -1358,7 +1346,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidOperation); } - self.send_command(WebGLCommand::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha)); + self.ipc_renderer.send( + CanvasMsg::WebGL(WebGLCommand::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha))).unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 @@ -1404,7 +1393,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } else { slot.set(None); // Unbind the current buffer - self.send_command(WebGLCommand::BindBuffer(target, None)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::BindBuffer(target, None))) + .unwrap() } } @@ -1429,7 +1420,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } else { // Bind the default framebuffer let cmd = WebGLCommand::BindFramebuffer(target, WebGLFramebufferBindingRequest::Default); - self.send_command(cmd); + self.ipc_renderer.send(CanvasMsg::WebGL(cmd)).unwrap(); self.bound_framebuffer.set(framebuffer); } } @@ -1451,7 +1442,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { _ => { self.bound_renderbuffer.set(None); // Unbind the currently bound renderbuffer - self.send_command(WebGLCommand::BindRenderbuffer(target, None)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::BindRenderbuffer(target, None))) + .unwrap() } } } @@ -1472,7 +1465,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } else { slot.set(None); // Unbind the currently bound texture - self.send_command(WebGLCommand::BindTexture(target, None)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::BindTexture(target, None))) + .unwrap() } } @@ -1590,7 +1585,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if (offset as usize) + data_vec.len() > bound_buffer.capacity() { return Ok(self.webgl_error(InvalidValue)); } - self.send_command(WebGLCommand::BufferSubData(target, offset as isize, data_vec)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::BufferSubData(target, offset as isize, data_vec))) + .unwrap(); Ok(()) } @@ -1673,7 +1670,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { width as i32, height as i32, border as i32); - self.send_command(msg); + self.ipc_renderer.send(CanvasMsg::WebGL(msg)).unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 @@ -1717,7 +1714,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { x, y, width as i32, height as i32); - self.send_command(msg); + self.ipc_renderer.send(CanvasMsg::WebGL(msg)).unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11 @@ -1726,36 +1723,46 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return; } - self.send_command(WebGLCommand::Clear(mask)); + self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::Clear(mask))).unwrap(); self.mark_as_dirty(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn ClearColor(&self, red: f32, green: f32, blue: f32, alpha: f32) { self.current_clear_color.set((red, green, blue, alpha)); - self.send_command(WebGLCommand::ClearColor(red, green, blue, alpha)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::ClearColor(red, green, blue, alpha))) + .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn ClearDepth(&self, depth: f32) { - self.send_command(WebGLCommand::ClearDepth(depth as f64)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::ClearDepth(depth as f64))) + .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn ClearStencil(&self, stencil: i32) { - self.send_command(WebGLCommand::ClearStencil(stencil)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::ClearStencil(stencil))) + .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn ColorMask(&self, r: bool, g: bool, b: bool, a: bool) { - self.send_command(WebGLCommand::ColorMask(r, g, b, a)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::ColorMask(r, g, b, a))) + .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn CullFace(&self, mode: u32) { match mode { constants::FRONT | constants::BACK | constants::FRONT_AND_BACK => - self.send_command(WebGLCommand::CullFace(mode)), + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::CullFace(mode))) + .unwrap(), _ => self.webgl_error(InvalidEnum), } } @@ -1764,7 +1771,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { fn FrontFace(&self, mode: u32) { match mode { constants::CW | constants::CCW => - self.send_command(WebGLCommand::FrontFace(mode)), + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::FrontFace(mode))) + .unwrap(), _ => self.webgl_error(InvalidEnum), } } @@ -1775,14 +1784,18 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { constants::EQUAL | constants::LEQUAL | constants::GREATER | constants::NOTEQUAL | constants::GEQUAL | constants::ALWAYS => - self.send_command(WebGLCommand::DepthFunc(func)), + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::DepthFunc(func))) + .unwrap(), _ => self.webgl_error(InvalidEnum), } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn DepthMask(&self, flag: bool) { - self.send_command(WebGLCommand::DepthMask(flag)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::DepthMask(flag))) + .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 @@ -1796,20 +1809,26 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidOperation); } - self.send_command(WebGLCommand::DepthRange(near as f64, far as f64)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::DepthRange(near as f64, far as f64))) + .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn Enable(&self, cap: u32) { if self.validate_feature_enum(cap) { - self.send_command(WebGLCommand::Enable(cap)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Enable(cap))) + .unwrap(); } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn Disable(&self, cap: u32) { if self.validate_feature_enum(cap) { - self.send_command(WebGLCommand::Disable(cap)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Disable(cap))) + .unwrap() } } @@ -1824,27 +1843,27 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // generated objects, either here or in the webgl thread // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 fn CreateBuffer(&self) -> Option<Root<WebGLBuffer>> { - WebGLBuffer::maybe_new(self.global().as_window(), self.webgl_sender.clone()) + WebGLBuffer::maybe_new(self.global().as_window(), self.ipc_renderer.clone()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 fn CreateFramebuffer(&self) -> Option<Root<WebGLFramebuffer>> { - WebGLFramebuffer::maybe_new(self.global().as_window(), self.webgl_sender.clone()) + WebGLFramebuffer::maybe_new(self.global().as_window(), self.ipc_renderer.clone()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7 fn CreateRenderbuffer(&self) -> Option<Root<WebGLRenderbuffer>> { - WebGLRenderbuffer::maybe_new(self.global().as_window(), self.webgl_sender.clone()) + WebGLRenderbuffer::maybe_new(self.global().as_window(), self.ipc_renderer.clone()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 fn CreateTexture(&self) -> Option<Root<WebGLTexture>> { - WebGLTexture::maybe_new(self.global().as_window(), self.webgl_sender.clone()) + WebGLTexture::maybe_new(self.global().as_window(), self.ipc_renderer.clone()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn CreateProgram(&self) -> Option<Root<WebGLProgram>> { - WebGLProgram::maybe_new(self.global().as_window(), self.webgl_sender.clone()) + WebGLProgram::maybe_new(self.global().as_window(), self.ipc_renderer.clone()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 @@ -1856,7 +1875,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return None; } } - WebGLShader::maybe_new(self.global().as_window(), self.webgl_sender.clone(), shader_type) + WebGLShader::maybe_new(self.global().as_window(), self.ipc_renderer.clone(), shader_type) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 @@ -1980,7 +1999,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return; } - self.send_command(WebGLCommand::DrawArrays(mode, first, count)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::DrawArrays(mode, first, count))) + .unwrap(); self.mark_as_dirty(); }, _ => self.webgl_error(InvalidEnum), @@ -2044,7 +2065,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { constants::LINE_LOOP | constants::LINES | constants::TRIANGLE_STRIP | constants::TRIANGLE_FAN | constants::TRIANGLES => { - self.send_command(WebGLCommand::DrawElements(mode, count, type_, offset)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::DrawElements(mode, count, type_, offset))) + .unwrap(); self.mark_as_dirty(); }, _ => self.webgl_error(InvalidEnum), @@ -2057,7 +2080,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidValue); } - self.send_command(WebGLCommand::EnableVertexAttribArray(attrib_id)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::EnableVertexAttribArray(attrib_id))) + .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 @@ -2066,7 +2091,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidValue); } - self.send_command(WebGLCommand::DisableVertexAttribArray(attrib_id)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::DisableVertexAttribArray(attrib_id))) + .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 @@ -2196,11 +2223,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { shader_type: u32, precision_type: u32) -> Option<Root<WebGLShaderPrecisionFormat>> { - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::GetShaderPrecisionFormat(shader_type, - precision_type, - sender)); - + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::GetShaderPrecisionFormat(shader_type, + precision_type, + sender))) + .unwrap(); match receiver.recv().unwrap() { Ok((range_min, range_max, precision)) => { Some(WebGLShaderPrecisionFormat::new(self.global().as_window(), range_min, range_max, precision)) @@ -2241,8 +2268,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return jsval.get(); } - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::GetVertexAttrib(index, pname, sender)); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::GetVertexAttrib(index, pname, sender))).unwrap(); match handle_potential_webgl_error!(self, receiver.recv().unwrap(), WebGLParameter::Invalid) { WebGLParameter::Int(val) => Int32Value(val), @@ -2260,8 +2287,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn GetVertexAttribOffset(&self, index: u32, pname: u32) -> i64 { - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::GetVertexAttribOffset(index, pname, sender)); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::GetVertexAttribOffset(index, pname, sender))).unwrap(); handle_potential_webgl_error!(self, receiver.recv().unwrap(), 0) as i64 } @@ -2280,7 +2307,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { _ => return self.webgl_error(InvalidEnum), } - self.send_command(WebGLCommand::Hint(target, mode)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Hint(target, mode))) + .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 @@ -2292,8 +2321,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn IsEnabled(&self, cap: u32) -> bool { if self.validate_feature_enum(cap) { - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::IsEnabled(cap, sender)); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::IsEnabled(cap, sender))) + .unwrap(); return receiver.recv().unwrap(); } @@ -2331,7 +2362,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidValue); } - self.send_command(WebGLCommand::LineWidth(width)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::LineWidth(width))) + .unwrap() } // NOTE: Usage of this function could affect rendering while we keep using @@ -2387,7 +2420,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn PolygonOffset(&self, factor: f32, units: f32) { - self.send_command(WebGLCommand::PolygonOffset(factor, units)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::PolygonOffset(factor, units))) + .unwrap() } #[allow(unsafe_code)] @@ -2487,8 +2522,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { _ => return Ok(self.webgl_error(InvalidOperation)), }; - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::ReadPixels(x, y, width, height, format, pixel_type, sender)); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::ReadPixels(x, y, width, height, format, pixel_type, sender))) + .unwrap(); let result = receiver.recv().unwrap(); @@ -2504,7 +2541,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn SampleCoverage(&self, value: f32, invert: bool) { - self.send_command(WebGLCommand::SampleCoverage(value, invert)); + self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::SampleCoverage(value, invert))).unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4 @@ -2514,7 +2551,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } self.current_scissor.set((x, y, width, height)); - self.send_command(WebGLCommand::Scissor(x, y, width, height)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Scissor(x, y, width, height))) + .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 @@ -2522,7 +2561,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { match func { constants::NEVER | constants::LESS | constants::EQUAL | constants::LEQUAL | constants::GREATER | constants::NOTEQUAL | constants::GEQUAL | constants::ALWAYS => - self.send_command(WebGLCommand::StencilFunc(func, ref_, mask)), + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::StencilFunc(func, ref_, mask))) + .unwrap(), _ => self.webgl_error(InvalidEnum), } } @@ -2537,21 +2578,27 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { match func { constants::NEVER | constants::LESS | constants::EQUAL | constants::LEQUAL | constants::GREATER | constants::NOTEQUAL | constants::GEQUAL | constants::ALWAYS => - self.send_command(WebGLCommand::StencilFuncSeparate(face, func, ref_, mask)), + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::StencilFuncSeparate(face, func, ref_, mask))) + .unwrap(), _ => self.webgl_error(InvalidEnum), } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn StencilMask(&self, mask: u32) { - self.send_command(WebGLCommand::StencilMask(mask)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::StencilMask(mask))) + .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn StencilMaskSeparate(&self, face: u32, mask: u32) { match face { constants::FRONT | constants::BACK | constants::FRONT_AND_BACK => - self.send_command(WebGLCommand::StencilMaskSeparate(face, mask)), + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::StencilMaskSeparate(face, mask))) + .unwrap(), _ => return self.webgl_error(InvalidEnum), } } @@ -2560,7 +2607,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { fn StencilOp(&self, fail: u32, zfail: u32, zpass: u32) { if self.validate_stencil_actions(fail) && self.validate_stencil_actions(zfail) && self.validate_stencil_actions(zpass) { - self.send_command(WebGLCommand::StencilOp(fail, zfail, zpass)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::StencilOp(fail, zfail, zpass))) + .unwrap() } else { self.webgl_error(InvalidEnum) } @@ -2575,7 +2624,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_stencil_actions(fail) && self.validate_stencil_actions(zfail) && self.validate_stencil_actions(zpass) { - self.send_command(WebGLCommand::StencilOpSeparate(face, fail, zfail, zpass)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::StencilOpSeparate(face, fail, zfail, zpass))) + .unwrap() } else { self.webgl_error(InvalidEnum) } @@ -2607,7 +2658,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { uniform: Option<&WebGLUniformLocation>, val: f32) { if self.validate_uniform_parameters(uniform, UniformSetterType::Float, &[val]) { - self.send_command(WebGLCommand::Uniform1f(uniform.unwrap().id(), val)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform1f(uniform.unwrap().id(), val))) + .unwrap() } } @@ -2616,7 +2669,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { uniform: Option<&WebGLUniformLocation>, val: i32) { if self.validate_uniform_parameters(uniform, UniformSetterType::Int, &[val]) { - self.send_command(WebGLCommand::Uniform1i(uniform.unwrap().id(), val)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform1i(uniform.unwrap().id(), val))) + .unwrap() } } @@ -2630,7 +2685,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { let data_vec = typed_array_or_sequence_to_vec::<Int32>(cx, data, ConversionBehavior::Default)?; if self.validate_uniform_parameters(uniform, UniformSetterType::Int, &data_vec) { - self.send_command(WebGLCommand::Uniform1iv(uniform.unwrap().id(), data_vec)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform1iv(uniform.unwrap().id(), data_vec))) + .unwrap() } Ok(()) @@ -2646,7 +2703,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { let data_vec = typed_array_or_sequence_to_vec::<Float32>(cx, data, ())?; if self.validate_uniform_parameters(uniform, UniformSetterType::Float, &data_vec) { - self.send_command(WebGLCommand::Uniform1fv(uniform.unwrap().id(), data_vec)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform1fv(uniform.unwrap().id(), data_vec))) + .unwrap() } Ok(()) @@ -2657,7 +2716,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { uniform: Option<&WebGLUniformLocation>, x: f32, y: f32) { if self.validate_uniform_parameters(uniform, UniformSetterType::FloatVec2, &[x, y]) { - self.send_command(WebGLCommand::Uniform2f(uniform.unwrap().id(), x, y)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform2f(uniform.unwrap().id(), x, y))) + .unwrap() } } @@ -2673,7 +2734,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::FloatVec2, &data_vec) { - self.send_command(WebGLCommand::Uniform2fv(uniform.unwrap().id(), data_vec)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform2fv(uniform.unwrap().id(), data_vec))) + .unwrap() } Ok(()) @@ -2686,7 +2749,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::IntVec2, &[x, y]) { - self.send_command(WebGLCommand::Uniform2i(uniform.unwrap().id(), x, y)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform2i(uniform.unwrap().id(), x, y))) + .unwrap() } } @@ -2702,7 +2767,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::IntVec2, &data_vec) { - self.send_command(WebGLCommand::Uniform2iv(uniform.unwrap().id(), data_vec)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform2iv(uniform.unwrap().id(), data_vec))) + .unwrap() } Ok(()) @@ -2715,7 +2782,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::FloatVec3, &[x, y, z]) { - self.send_command(WebGLCommand::Uniform3f(uniform.unwrap().id(), x, y, z)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform3f(uniform.unwrap().id(), x, y, z))) + .unwrap() } } @@ -2731,7 +2800,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::FloatVec3, &data_vec) { - self.send_command(WebGLCommand::Uniform3fv(uniform.unwrap().id(), data_vec)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform3fv(uniform.unwrap().id(), data_vec))) + .unwrap() } Ok(()) @@ -2744,7 +2815,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::IntVec3, &[x, y, z]) { - self.send_command(WebGLCommand::Uniform3i(uniform.unwrap().id(), x, y, z)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform3i(uniform.unwrap().id(), x, y, z))) + .unwrap() } } @@ -2760,7 +2833,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::IntVec3, &data_vec) { - self.send_command(WebGLCommand::Uniform3iv(uniform.unwrap().id(), data_vec)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform3iv(uniform.unwrap().id(), data_vec))) + .unwrap() } Ok(()) @@ -2773,7 +2848,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::IntVec4, &[x, y, z, w]) { - self.send_command(WebGLCommand::Uniform4i(uniform.unwrap().id(), x, y, z, w)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform4i(uniform.unwrap().id(), x, y, z, w))) + .unwrap() } } @@ -2790,7 +2867,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::IntVec4, &data_vec) { - self.send_command(WebGLCommand::Uniform4iv(uniform.unwrap().id(), data_vec)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform4iv(uniform.unwrap().id(), data_vec))) + .unwrap() } Ok(()) @@ -2803,7 +2882,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::FloatVec4, &[x, y, z, w]) { - self.send_command(WebGLCommand::Uniform4f(uniform.unwrap().id(), x, y, z, w)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform4f(uniform.unwrap().id(), x, y, z, w))) + .unwrap() } } @@ -2819,7 +2900,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::FloatVec4, &data_vec) { - self.send_command(WebGLCommand::Uniform4fv(uniform.unwrap().id(), data_vec)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Uniform4fv(uniform.unwrap().id(), data_vec))) + .unwrap() } Ok(()) @@ -2837,7 +2920,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::FloatMat2, &data_vec) { - self.send_command(WebGLCommand::UniformMatrix2fv(uniform.unwrap().id(), transpose, data_vec)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::UniformMatrix2fv(uniform.unwrap().id(), transpose, data_vec))) + .unwrap() } Ok(()) @@ -2855,7 +2940,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::FloatMat3, &data_vec) { - self.send_command(WebGLCommand::UniformMatrix3fv(uniform.unwrap().id(), transpose, data_vec)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::UniformMatrix3fv(uniform.unwrap().id(), transpose, data_vec))) + .unwrap() } Ok(()) @@ -2873,7 +2960,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if self.validate_uniform_parameters(uniform, UniformSetterType::FloatMat4, &data_vec) { - self.send_command(WebGLCommand::UniformMatrix4fv(uniform.unwrap().id(), transpose, data_vec)); + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::UniformMatrix4fv(uniform.unwrap().id(), transpose, data_vec))) + .unwrap() } Ok(()) @@ -3009,8 +3098,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { self.bound_attrib_buffers.borrow_mut().insert(attrib_id, JS::from_ref(&*buffer_array)); - let msg = WebGLCommand::VertexAttribPointer(attrib_id, size, data_type, normalized, stride, offset as u32); - self.send_command(msg); + let msg = CanvasMsg::WebGL( + WebGLCommand::VertexAttribPointer(attrib_id, size, data_type, normalized, stride, offset as u32)); + self.ipc_renderer.send(msg).unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4 @@ -3019,7 +3109,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidValue) } - self.send_command(WebGLCommand::Viewport(x, y, width, height)) + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::Viewport(x, y, width, height))) + .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 @@ -3364,13 +3456,13 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { pub trait LayoutCanvasWebGLRenderingContextHelpers { #[allow(unsafe_code)] - unsafe fn canvas_data_source(&self) -> HTMLCanvasDataSource; + unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg>; } impl LayoutCanvasWebGLRenderingContextHelpers for LayoutJS<WebGLRenderingContext> { #[allow(unsafe_code)] - unsafe fn canvas_data_source(&self) -> HTMLCanvasDataSource { - HTMLCanvasDataSource::WebGL((*self.unsafe_get()).layout_handle()) + unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> { + (*self.unsafe_get()).ipc_renderer.clone() } } diff --git a/components/script/dom/webglshader.rs b/components/script/dom/webglshader.rs index cf6fc55072d..edd9cf7bdb3 100644 --- a/components/script/dom/webglshader.rs +++ b/components/script/dom/webglshader.rs @@ -4,7 +4,7 @@ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl use angle::hl::{BuiltInResources, Output, ShaderValidator}; -use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLMsgSender, WebGLParameter, WebGLResult, WebGLShaderId}; +use canvas_traits::CanvasMsg; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::WebGLShaderBinding; use dom::bindings::js::Root; @@ -13,8 +13,11 @@ use dom::bindings::str::DOMString; use dom::webglobject::WebGLObject; use dom::window::Window; use dom_struct::dom_struct; +use ipc_channel::ipc::IpcSender; use std::cell::Cell; use std::sync::{ONCE_INIT, Once}; +use webrender_api; +use webrender_api::{WebGLCommand, WebGLParameter, WebGLResult, WebGLShaderId}; #[derive(Clone, Copy, PartialEq, Debug, JSTraceable, HeapSizeOf)] pub enum ShaderCompilationStatus { @@ -34,7 +37,7 @@ pub struct WebGLShader { attached_counter: Cell<u32>, compilation_status: Cell<ShaderCompilationStatus>, #[ignore_heap_size_of = "Defined in ipc-channel"] - renderer: WebGLMsgSender, + renderer: IpcSender<CanvasMsg>, } #[cfg(not(target_os = "android"))] @@ -46,7 +49,7 @@ const SHADER_OUTPUT_FORMAT: Output = Output::Essl; static GLSLANG_INITIALIZATION: Once = ONCE_INIT; impl WebGLShader { - fn new_inherited(renderer: WebGLMsgSender, + fn new_inherited(renderer: IpcSender<CanvasMsg>, id: WebGLShaderId, shader_type: u32) -> WebGLShader { @@ -65,18 +68,18 @@ impl WebGLShader { } pub fn maybe_new(window: &Window, - renderer: WebGLMsgSender, + renderer: IpcSender<CanvasMsg>, shader_type: u32) -> Option<Root<WebGLShader>> { - let (sender, receiver) = webgl_channel().unwrap(); - renderer.send(WebGLCommand::CreateShader(shader_type, sender)).unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateShader(shader_type, sender))).unwrap(); let result = receiver.recv().unwrap(); result.map(|shader_id| WebGLShader::new(window, renderer, shader_id, shader_type)) } pub fn new(window: &Window, - renderer: WebGLMsgSender, + renderer: IpcSender<CanvasMsg>, id: WebGLShaderId, shader_type: u32) -> Root<WebGLShader> { @@ -115,7 +118,7 @@ impl WebGLShader { // will succeed. // It could be interesting to retrieve the info log from the paint thread though let msg = WebGLCommand::CompileShader(self.id, translated_source); - self.renderer.send(msg).unwrap(); + self.renderer.send(CanvasMsg::WebGL(msg)).unwrap(); self.compilation_status.set(ShaderCompilationStatus::Succeeded); }, Err(error) => { @@ -139,7 +142,7 @@ impl WebGLShader { pub fn delete(&self) { if !self.is_deleted.get() { self.is_deleted.set(true); - let _ = self.renderer.send(WebGLCommand::DeleteShader(self.id)); + let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteShader(self.id))); } } @@ -167,8 +170,8 @@ impl WebGLShader { /// glGetParameter pub fn parameter(&self, param_id: u32) -> WebGLResult<WebGLParameter> { - let (sender, receiver) = webgl_channel().unwrap(); - self.renderer.send(WebGLCommand::GetShaderParameter(self.id, param_id, sender)).unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::GetShaderParameter(self.id, param_id, sender))).unwrap(); receiver.recv().unwrap() } diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs index 048af5d10e0..88d5faaf5c8 100644 --- a/components/script/dom/webgltexture.rs +++ b/components/script/dom/webgltexture.rs @@ -3,8 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // 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::CanvasMsg; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; use dom::bindings::codegen::Bindings::WebGLTextureBinding; @@ -14,8 +13,11 @@ use dom::webgl_validations::types::{TexImageTarget, TexFormat, TexDataType}; use dom::webglobject::WebGLObject; use dom::window::Window; use dom_struct::dom_struct; +use ipc_channel::ipc::IpcSender; use std::cell::Cell; use std::cmp; +use webrender_api; +use webrender_api::{WebGLCommand, WebGLError, WebGLResult, WebGLTextureId}; pub enum TexParameterValue { Float(f32), @@ -44,11 +46,11 @@ pub struct WebGLTexture { min_filter: Cell<Option<u32>>, mag_filter: Cell<Option<u32>>, #[ignore_heap_size_of = "Defined in ipc-channel"] - renderer: WebGLMsgSender, + renderer: IpcSender<CanvasMsg>, } impl WebGLTexture { - fn new_inherited(renderer: WebGLMsgSender, + fn new_inherited(renderer: IpcSender<CanvasMsg>, id: WebGLTextureId) -> WebGLTexture { WebGLTexture { @@ -65,17 +67,17 @@ impl WebGLTexture { } } - pub fn maybe_new(window: &Window, renderer: WebGLMsgSender) + pub fn maybe_new(window: &Window, renderer: IpcSender<CanvasMsg>) -> Option<Root<WebGLTexture>> { - let (sender, receiver) = webgl_channel().unwrap(); - renderer.send(WebGLCommand::CreateTexture(sender)).unwrap(); + let (sender, receiver) = webrender_api::channel::msg_channel().unwrap(); + renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateTexture(sender))).unwrap(); let result = receiver.recv().unwrap(); result.map(|texture_id| WebGLTexture::new(window, renderer, texture_id)) } pub fn new(window: &Window, - renderer: WebGLMsgSender, + renderer: IpcSender<CanvasMsg>, id: WebGLTextureId) -> Root<WebGLTexture> { reflect_dom_object(box WebGLTexture::new_inherited(renderer, id), @@ -111,7 +113,7 @@ impl WebGLTexture { self.target.set(Some(target)); } - let msg = WebGLCommand::BindTexture(target, Some(self.id)); + let msg = CanvasMsg::WebGL(WebGLCommand::BindTexture(target, Some(self.id))); self.renderer.send(msg).unwrap(); Ok(()) @@ -166,7 +168,7 @@ impl WebGLTexture { return Err(WebGLError::InvalidOperation); } - self.renderer.send(WebGLCommand::GenerateMipmap(target)).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::GenerateMipmap(target))).unwrap(); if self.base_mipmap_level + base_image_info.get_max_mimap_levels() == 0 { return Err(WebGLError::InvalidOperation); @@ -179,7 +181,7 @@ impl WebGLTexture { pub fn delete(&self) { if !self.is_deleted.get() { self.is_deleted.set(true); - let _ = self.renderer.send(WebGLCommand::DeleteTexture(self.id)); + let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteTexture(self.id))); } } @@ -214,7 +216,7 @@ impl WebGLTexture { constants::LINEAR_MIPMAP_LINEAR => { self.min_filter.set(Some(int_value as u32)); self.renderer - .send(WebGLCommand::TexParameteri(target, name, int_value)) + .send(CanvasMsg::WebGL(WebGLCommand::TexParameteri(target, name, int_value))) .unwrap(); Ok(()) }, @@ -228,7 +230,7 @@ impl WebGLTexture { constants::LINEAR => { self.mag_filter.set(Some(int_value as u32)); self.renderer - .send(WebGLCommand::TexParameteri(target, name, int_value)) + .send(CanvasMsg::WebGL(WebGLCommand::TexParameteri(target, name, int_value))) .unwrap(); Ok(()) }, @@ -243,7 +245,7 @@ impl WebGLTexture { constants::MIRRORED_REPEAT | constants::REPEAT => { self.renderer - .send(WebGLCommand::TexParameteri(target, name, int_value)) + .send(CanvasMsg::WebGL(WebGLCommand::TexParameteri(target, name, int_value))) .unwrap(); Ok(()) }, diff --git a/components/script/dom/webgluniformlocation.rs b/components/script/dom/webgluniformlocation.rs index 47292adeb18..228808303c4 100644 --- a/components/script/dom/webgluniformlocation.rs +++ b/components/script/dom/webgluniformlocation.rs @@ -3,12 +3,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl -use canvas_traits::webgl::WebGLProgramId; use dom::bindings::codegen::Bindings::WebGLUniformLocationBinding; use dom::bindings::js::Root; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::window::Window; use dom_struct::dom_struct; +use webrender_api::WebGLProgramId; #[dom_struct] pub struct WebGLUniformLocation { diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 2da650ee1ee..90693a2ccbf 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -5,7 +5,6 @@ use app_units::Au; use base64; use bluetooth_traits::BluetoothRequest; -use canvas_traits::webgl::WebGLChan; use cssparser::{Parser, ParserInput}; use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType}; use dom::bindings::cell::DOMRefCell; @@ -265,11 +264,7 @@ pub struct Window { /// A handle for communicating messages to the webvr thread, if available. #[ignore_heap_size_of = "channels are hard"] - webgl_chan: WebGLChan, - - /// A handle for communicating messages to the webvr thread, if available. - #[ignore_heap_size_of = "channels are hard"] - webvr_chan: Option<IpcSender<WebVRMsg>>, + webvr_thread: Option<IpcSender<WebVRMsg>>, /// A map for storing the previous permission state read results. permission_state_invocation_results: DOMRefCell<HashMap<String, PermissionState>>, @@ -385,12 +380,8 @@ impl Window { self.current_viewport.clone().get() } - pub fn webgl_chan(&self) -> WebGLChan { - self.webgl_chan.clone() - } - pub fn webvr_thread(&self) -> Option<IpcSender<WebVRMsg>> { - self.webvr_chan.clone() + self.webvr_thread.clone() } fn new_paint_worklet(&self) -> Root<Worklet> { @@ -1809,8 +1800,7 @@ impl Window { origin: MutableOrigin, navigation_start: u64, navigation_start_precise: f64, - webgl_chan: WebGLChan, - webvr_chan: Option<IpcSender<WebVRMsg>>) + webvr_thread: Option<IpcSender<WebVRMsg>>) -> Root<Window> { let layout_rpc: Box<LayoutRPC + Send> = { let (rpc_send, rpc_recv) = channel(); @@ -1876,8 +1866,7 @@ impl Window { scroll_offsets: DOMRefCell::new(HashMap::new()), media_query_lists: WeakMediaQueryListVec::new(), test_runner: Default::default(), - webgl_chan: webgl_chan, - webvr_chan: webvr_chan, + webvr_thread: webvr_thread, permission_state_invocation_results: DOMRefCell::new(HashMap::new()), pending_layout_images: DOMRefCell::new(HashMap::new()), unminified_js_dir: DOMRefCell::new(None), diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 4a05002637a..ea8038897ac 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -18,7 +18,6 @@ //! loop. use bluetooth_traits::BluetoothRequest; -use canvas_traits::webgl::WebGLPipeline; use devtools; use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo}; use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId}; @@ -509,11 +508,8 @@ pub struct ScriptThread { /// The unit of related similar-origin browsing contexts' list of MutationObserver objects mutation_observers: DOMRefCell<Vec<JS<MutationObserver>>>, - /// A handle to the webgl thread - webgl_chan: WebGLPipeline, - /// A handle to the webvr thread, if available - webvr_chan: Option<IpcSender<WebVRMsg>>, + webvr_thread: Option<IpcSender<WebVRMsg>>, /// The worklet thread pool worklet_thread_pool: DOMRefCell<Option<Rc<WorkletThreadPool>>>, @@ -885,8 +881,7 @@ impl ScriptThread { layout_to_constellation_chan: state.layout_to_constellation_chan, - webgl_chan: state.webgl_chan, - webvr_chan: state.webvr_chan, + webvr_thread: state.webvr_thread, worklet_thread_pool: Default::default(), @@ -2033,8 +2028,7 @@ impl ScriptThread { origin, incomplete.navigation_start, incomplete.navigation_start_precise, - self.webgl_chan.channel(), - self.webvr_chan.clone()); + self.webvr_thread.clone()); // Initialize the browsing context for the window. let window_proxy = self.local_window_proxy(&window, diff --git a/components/script_layout_interface/lib.rs b/components/script_layout_interface/lib.rs index 7c0f97ef917..e3e956096bb 100644 --- a/components/script_layout_interface/lib.rs +++ b/components/script_layout_interface/lib.rs @@ -43,7 +43,7 @@ pub mod rpc; pub mod wrapper_traits; use atomic_refcell::AtomicRefCell; -use canvas_traits::canvas::CanvasMsg; +use canvas_traits::CanvasMsg; use core::nonzero::NonZero; use ipc_channel::ipc::IpcSender; use libc::c_void; @@ -124,13 +124,8 @@ pub enum LayoutElementType { SVGSVGElement, } -pub enum HTMLCanvasDataSource { - WebGL(webrender_api::ImageKey), - Image(Option<IpcSender<CanvasMsg>>) -} - pub struct HTMLCanvasData { - pub source: HTMLCanvasDataSource, + pub ipc_renderer: Option<IpcSender<CanvasMsg>>, pub width: u32, pub height: u32, } diff --git a/components/script_traits/Cargo.toml b/components/script_traits/Cargo.toml index 2c083b2773c..70fcdbb3f33 100644 --- a/components/script_traits/Cargo.toml +++ b/components/script_traits/Cargo.toml @@ -25,6 +25,7 @@ libc = "0.2" metrics = {path = "../metrics"} msg = {path = "../msg"} net_traits = {path = "../net_traits"} +offscreen_gl_context = { version = "0.11", features = ["serde"] } profile_traits = {path = "../profile_traits"} rustc-serialize = "0.3.4" serde = "1.0" diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 4a197e759ff..85122d35c3c 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -24,6 +24,7 @@ extern crate ipc_channel; extern crate libc; extern crate msg; extern crate net_traits; +extern crate offscreen_gl_context; extern crate profile_traits; extern crate rustc_serialize; #[macro_use] extern crate serde; @@ -38,7 +39,6 @@ mod script_msg; pub mod webdriver_msg; use bluetooth_traits::BluetoothRequest; -use canvas_traits::webgl::WebGLPipeline; use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId}; use euclid::{Size2D, Length, Point2D, Vector2D, Rect, ScaleFactor, TypedSize2D}; use gfx_traits::Epoch; @@ -524,10 +524,8 @@ pub struct InitialScriptState { pub pipeline_namespace_id: PipelineNamespaceId, /// A ping will be sent on this channel once the script thread shuts down. pub content_process_shutdown_chan: IpcSender<()>, - /// 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_thread: Option<IpcSender<WebVRMsg>> } /// This trait allows creating a `ScriptThread` without depending on the `script` @@ -761,6 +759,8 @@ pub enum ConstellationMsg { Reload(TopLevelBrowsingContextId), /// A log entry, with the top-level browsing context id and thread name LogEntry(Option<TopLevelBrowsingContextId>, Option<String>, LogEntry), + /// Set the WebVR thread channel. + SetWebVRThread(IpcSender<WebVRMsg>), /// Dispatch WebVR events to the subscribed script threads. WebVREvents(Vec<PipelineId>, Vec<WebVREvent>), /// Create a new top level browsing context. diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs index 156f85a2be7..4fd8fca5c7f 100644 --- a/components/script_traits/script_msg.rs +++ b/components/script_traits/script_msg.rs @@ -12,7 +12,7 @@ use LoadData; use MozBrowserEvent; use WorkerGlobalScopeInit; use WorkerScriptLoadOrigin; -use canvas_traits::canvas::CanvasMsg; +use canvas_traits::CanvasMsg; use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId}; use euclid::{Point2D, Size2D, TypedSize2D}; use ipc_channel::ipc::IpcSender; @@ -21,6 +21,7 @@ use msg::constellation_msg::{Key, KeyModifiers, KeyState}; use net_traits::CoreResourceMsg; use net_traits::request::RequestInit; use net_traits::storage_thread::StorageType; +use offscreen_gl_context::{GLContextAttributes, GLLimits}; use servo_url::ImmutableOrigin; use servo_url::ServoUrl; use style_traits::CSSPixel; @@ -77,6 +78,11 @@ pub enum ScriptMsg { /// Requests that a new 2D canvas thread be created. (This is done in the constellation because /// 2D canvases may use the GPU and we don't want to give untrusted content access to the GPU.) CreateCanvasPaintThread(Size2D<i32>, IpcSender<IpcSender<CanvasMsg>>), + /// Requests that a new WebGL thread be created. (This is done in the constellation because + /// WebGL uses the GPU and we don't want to give untrusted content access to the GPU.) + CreateWebGLPaintThread(Size2D<i32>, + GLContextAttributes, + IpcSender<Result<(IpcSender<CanvasMsg>, GLLimits), String>>), /// Notifies the constellation that this frame has received focus. Focus, /// Forward an event that was sent to the parent window. diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 93e6d4cf454..07212a2b2d1 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -68,8 +68,6 @@ fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) { } use bluetooth::BluetoothThreadFactory; use bluetooth_traits::BluetoothRequest; -use canvas::gl_context::GLContextFactory; -use canvas::webgl_thread::WebGLThreads; use compositing::IOCompositor; use compositing::compositor_thread::{self, CompositorProxy, CompositorReceiver, InitialCompositorState}; use compositing::windowing::WindowEvent; @@ -151,7 +149,7 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static { let mut resource_path = resources_dir_path().unwrap(); resource_path.push("shaders"); - let (mut webrender, webrender_api_sender) = { + let (webrender, webrender_api_sender) = { // TODO(gw): Duplicates device_pixels_per_screen_px from compositor. Tidy up! let scale_factor = window.hidpi_factor().get(); let device_pixel_ratio = match opts.device_pixels_per_px { @@ -213,7 +211,7 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static { debugger_chan, devtools_chan, supports_clipboard, - &mut webrender, + &webrender, webrender_document, webrender_api_sender); @@ -290,7 +288,7 @@ fn create_constellation(user_agent: Cow<'static, str>, debugger_chan: Option<debugger::Sender>, devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>, supports_clipboard: bool, - webrender: &mut webrender::Renderer, + webrender: &webrender::Renderer, webrender_document: webrender_api::DocumentId, webrender_api_sender: webrender_api::RenderApiSender) -> (Sender<ConstellationMsg>, SWManagerSenders) { @@ -306,30 +304,6 @@ fn create_constellation(user_agent: Cow<'static, str>, let resource_sender = public_resource_threads.sender(); - let (webvr_chan, webvr_constellation_sender, webvr_compositor) = if PREFS.is_webvr_enabled() { - // WebVR initialization - let (mut handler, sender) = WebVRCompositorHandler::new(); - let (webvr_thread, constellation_sender) = WebVRThread::spawn(sender); - handler.set_webvr_thread_sender(webvr_thread.clone()); - (Some(webvr_thread), Some(constellation_sender), Some(handler)) - } else { - (None, None, None) - }; - - // GLContext factory used to create WebGL Contexts - let gl_factory = if opts::get().should_use_osmesa() { - GLContextFactory::current_osmesa_handle().unwrap() - } else { - GLContextFactory::current_native_handle(&compositor_proxy).unwrap() - }; - - // Initialize WebGL Thread entry point. - let (webgl_threads, image_handler) = WebGLThreads::new(gl_factory, - 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); - let initial_state = InitialConstellationState { compositor_proxy, debugger_chan, @@ -343,17 +317,20 @@ fn create_constellation(user_agent: Cow<'static, str>, supports_clipboard, webrender_document, webrender_api_sender, - webgl_threads, - webvr_chan, }; let (constellation_chan, from_swmanager_sender) = Constellation::<script_layout_interface::message::Msg, layout_thread::LayoutThread, script::script_thread::ScriptThread>::start(initial_state); - if let Some(webvr_constellation_sender) = webvr_constellation_sender { - // Set constellation channel used by WebVR thread to broadcast events - webvr_constellation_sender.send(constellation_chan.clone()).unwrap(); + if PREFS.is_webvr_enabled() { + // WebVR initialization + let (mut handler, sender) = WebVRCompositorHandler::new(); + let webvr_thread = WebVRThread::spawn(constellation_chan.clone(), sender); + handler.set_webvr_thread_sender(webvr_thread.clone()); + + webrender.set_vr_compositor_handler(handler); + constellation_chan.send(ConstellationMsg::SetWebVRThread(webvr_thread)).unwrap(); } // channels to communicate with Service Worker Manager diff --git a/components/webvr/Cargo.toml b/components/webvr/Cargo.toml index f6a7427a709..f7edd95d6d8 100644 --- a/components/webvr/Cargo.toml +++ b/components/webvr/Cargo.toml @@ -10,11 +10,10 @@ name = "webvr" path = "lib.rs" [dependencies] -canvas_traits = {path = "../canvas_traits"} -euclid = "0.15" ipc-channel = "0.8" log = "0.3" msg = {path = "../msg"} script_traits = {path = "../script_traits"} servo_config = {path = "../config"} webvr_traits = {path = "../webvr_traits" } +webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} diff --git a/components/webvr/lib.rs b/components/webvr/lib.rs index 0ad9722b21e..62f3e992fdc 100644 --- a/components/webvr/lib.rs +++ b/components/webvr/lib.rs @@ -4,14 +4,13 @@ #![deny(unsafe_code)] -extern crate canvas_traits; -extern crate euclid; extern crate ipc_channel; #[macro_use] extern crate log; extern crate msg; extern crate script_traits; extern crate servo_config; +extern crate webrender_api; extern crate webvr_traits; mod webvr_thread; diff --git a/components/webvr/webvr_thread.rs b/components/webvr/webvr_thread.rs index 77f42a6b39e..ec550153870 100644 --- a/components/webvr/webvr_thread.rs +++ b/components/webvr/webvr_thread.rs @@ -2,8 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::webgl; -use euclid::Size2D; use ipc_channel::ipc; use ipc_channel::ipc::{IpcReceiver, IpcSender}; use msg::constellation_msg::PipelineId; @@ -13,6 +11,8 @@ use std::{thread, time}; use std::collections::{HashMap, HashSet}; use std::sync::mpsc; use std::sync::mpsc::{Receiver, Sender}; +use webrender_api; +use webrender_api::DeviceIntSize; use webvr_traits::{WebVRMsg, WebVRResult}; use webvr_traits::webvr::*; @@ -34,7 +34,7 @@ use webvr_traits::webvr::*; /// ids using the WebVR APIs. These ids are used to implement privacy guidelines defined in the WebVR Spec. /// * When a JavaScript thread gains access to present to a headset, WebVRThread is not used as a intermediary in /// the VRDisplay.requestAnimationFrame loop in order to minimize latency. A direct communication with WebRender -/// is used instead. See WebVRCompositorHandler and the WebVRCommands for more details. +/// is used instead. See WebVRCompositorHandler and the VRCompositorCommanda for more details. pub struct WebVRThread { receiver: IpcReceiver<WebVRMsg>, sender: IpcSender<WebVRMsg>, @@ -66,17 +66,15 @@ impl WebVRThread { } } - pub fn spawn(vr_compositor_chan: WebVRCompositorSender) - -> (IpcSender<WebVRMsg>, Sender<Sender<ConstellationMsg>>) { + pub fn spawn(constellation_chan: Sender<ConstellationMsg>, + vr_compositor_chan: WebVRCompositorSender) + -> IpcSender<WebVRMsg> { let (sender, receiver) = ipc::channel().unwrap(); - let (constellation_sender, constellation_receiver) = mpsc::channel(); let sender_clone = sender.clone(); thread::Builder::new().name("WebVRThread".into()).spawn(move || { - let constellation_chan = constellation_receiver.recv().unwrap(); WebVRThread::new(receiver, sender_clone, constellation_chan, vr_compositor_chan).start(); }).expect("Thread spawning failed"); - - (sender, constellation_sender) + sender } fn start(&mut self) { @@ -307,7 +305,7 @@ impl WebVRThread { pub struct WebVRCompositor(*mut VRDisplay); pub struct WebVRCompositorHandler { - compositors: HashMap<webgl::WebVRDeviceId, WebVRCompositor>, + compositors: HashMap<webrender_api::VRCompositorId, WebVRCompositor>, webvr_thread_receiver: Receiver<Option<WebVRCompositor>>, webvr_thread_sender: Option<IpcSender<WebVRMsg>> } @@ -330,14 +328,14 @@ impl WebVRCompositorHandler { } } -impl webgl::WebVRRenderHandler for WebVRCompositorHandler { +impl webrender_api::VRCompositorHandler for WebVRCompositorHandler { #[allow(unsafe_code)] - fn handle(&mut self, cmd: webgl::WebVRCommand, texture: Option<(u32, Size2D<i32>)>) { + fn handle(&mut self, cmd: webrender_api::VRCompositorCommand, texture: Option<(u32, DeviceIntSize)>) { match cmd { - webgl::WebVRCommand::Create(compositor_id) => { + webrender_api::VRCompositorCommand::Create(compositor_id) => { self.create_compositor(compositor_id); } - webgl::WebVRCommand::SyncPoses(compositor_id, near, far, sender) => { + webrender_api::VRCompositorCommand::SyncPoses(compositor_id, near, far, sender) => { if let Some(compositor) = self.compositors.get(&compositor_id) { let pose = unsafe { (*compositor.0).sync_poses(); @@ -348,7 +346,7 @@ impl webgl::WebVRRenderHandler for WebVRCompositorHandler { let _ = sender.send(Err(())); } } - webgl::WebVRCommand::SubmitFrame(compositor_id, left_bounds, right_bounds) => { + webrender_api::VRCompositorCommand::SubmitFrame(compositor_id, left_bounds, right_bounds) => { if let Some(compositor) = self.compositors.get(&compositor_id) { if let Some((texture_id, size)) = texture { let layer = VRLayer { @@ -363,7 +361,7 @@ impl webgl::WebVRRenderHandler for WebVRCompositorHandler { } } } - webgl::WebVRCommand::Release(compositor_id) => { + webrender_api::VRCompositorCommand::Release(compositor_id) => { self.compositors.remove(&compositor_id); } } @@ -372,7 +370,7 @@ impl webgl::WebVRRenderHandler for WebVRCompositorHandler { impl WebVRCompositorHandler { #[allow(unsafe_code)] - fn create_compositor(&mut self, display_id: webgl::WebVRDeviceId) { + fn create_compositor(&mut self, display_id: webrender_api::VRCompositorId) { let sender = match self.webvr_thread_sender { Some(ref s) => s, None => return, |