aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnthony Ramine <n.oxyde@gmail.com>2017-08-16 23:23:18 +0200
committerAnthony Ramine <n.oxyde@gmail.com>2017-08-16 23:23:18 +0200
commit676f2c8acf6fec8ad77d4daa51bef5bdcae101c5 (patch)
treed212209744e3b10a315dc79da754a70d7543e428
parent4d10d39e8fe841c5fe2ac58da2daaa13c10c140e (diff)
downloadservo-676f2c8acf6fec8ad77d4daa51bef5bdcae101c5.tar.gz
servo-676f2c8acf6fec8ad77d4daa51bef5bdcae101c5.zip
Revert "Auto merge of #18114 - emilio:revert-webgl-refactor, r=nox"
This reverts commit 4d10d39e8fe841c5fe2ac58da2daaa13c10c140e, reversing changes made to ee94e2b7c0bd327abe8f9545b2a1f792f67a2bdd.
-rw-r--r--Cargo.lock11
-rw-r--r--components/canvas/Cargo.toml3
-rw-r--r--components/canvas/canvas_paint_thread.rs16
-rw-r--r--components/canvas/gl_context.rs203
-rw-r--r--components/canvas/lib.rs10
-rw-r--r--components/canvas/webgl_mode/inprocess.rs95
-rw-r--r--components/canvas/webgl_mode/mod.rs6
-rw-r--r--components/canvas/webgl_paint_thread.rs379
-rw-r--r--components/canvas/webgl_thread.rs1204
-rw-r--r--components/canvas_traits/Cargo.toml3
-rw-r--r--components/canvas_traits/canvas.rs409
-rw-r--r--components/canvas_traits/lib.rs426
-rw-r--r--components/canvas_traits/webgl.rs506
-rw-r--r--components/canvas_traits/webgl_channel/ipc.rs15
-rw-r--r--components/canvas_traits/webgl_channel/mod.rs87
-rw-r--r--components/canvas_traits/webgl_channel/mpsc.rs51
-rw-r--r--components/constellation/Cargo.toml1
-rw-r--r--components/constellation/constellation.rs50
-rw-r--r--components/constellation/lib.rs1
-rw-r--r--components/constellation/pipeline.rs16
-rw-r--r--components/gfx/display_list/mod.rs13
-rw-r--r--components/layout/display_list_builder.rs65
-rw-r--r--components/layout/fragment.rs25
-rw-r--r--components/layout/webrender_helpers.rs5
-rw-r--r--components/script/dom/bindings/trace.rs29
-rw-r--r--components/script/dom/canvasgradient.rs2
-rw-r--r--components/script/dom/canvaspattern.rs2
-rw-r--r--components/script/dom/canvasrenderingcontext2d.rs16
-rw-r--r--components/script/dom/htmlcanvaselement.rs66
-rw-r--r--components/script/dom/paintrenderingcontext2d.rs10
-rw-r--r--components/script/dom/paintworkletglobalscope.rs3
-rw-r--r--components/script/dom/vrdisplay.rs36
-rw-r--r--components/script/dom/webgl_extensions/ext/oesvertexarrayobject.rs15
-rw-r--r--components/script/dom/webgl_extensions/ext/webglvertexarrayobjectoes.rs2
-rw-r--r--components/script/dom/webgl_extensions/extensions.rs2
-rw-r--r--components/script/dom/webgl_validations/tex_image_2d.rs2
-rw-r--r--components/script/dom/webglbuffer.rs29
-rw-r--r--components/script/dom/webglframebuffer.rs41
-rw-r--r--components/script/dom/webglprogram.rs56
-rw-r--r--components/script/dom/webglrenderbuffer.rs24
-rw-r--r--components/script/dom/webglrenderingcontext.rs448
-rw-r--r--components/script/dom/webglshader.rs25
-rw-r--r--components/script/dom/webgltexture.rs30
-rw-r--r--components/script/dom/webgluniformlocation.rs2
-rw-r--r--components/script/dom/window.rs19
-rw-r--r--components/script/script_thread.rs12
-rw-r--r--components/script_layout_interface/lib.rs9
-rw-r--r--components/script_traits/Cargo.toml1
-rw-r--r--components/script_traits/lib.rs8
-rw-r--r--components/script_traits/script_msg.rs8
-rw-r--r--components/servo/lib.rs45
-rw-r--r--components/webvr/Cargo.toml3
-rw-r--r--components/webvr/lib.rs3
-rw-r--r--components/webvr/webvr_thread.rs32
54 files changed, 3154 insertions, 1426 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 759122f23e5..4455b98c203 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -325,6 +325,7 @@ 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)",
@@ -332,7 +333,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)",
- "servo_config 0.0.1",
+ "webrender 0.48.0 (git+https://github.com/servo/webrender)",
"webrender_api 0.48.0 (git+https://github.com/servo/webrender)",
]
@@ -345,7 +346,10 @@ 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)",
]
@@ -526,7 +530,6 @@ 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)",
@@ -2596,7 +2599,6 @@ 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)",
@@ -3529,12 +3531,13 @@ 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 ad149daccb6..e8bf234a052 100644
--- a/components/canvas/Cargo.toml
+++ b/components/canvas/Cargo.toml
@@ -12,6 +12,7 @@ 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"
@@ -19,5 +20,5 @@ ipc-channel = "0.8"
log = "0.3.5"
num-traits = "0.1.32"
offscreen_gl_context = { version = "0.11", features = ["serde"] }
-servo_config = {path = "../config"}
+webrender = {git = "https://github.com/servo/webrender"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs
index b7e21777001..8fe05d1f6a9 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::*;
+use canvas_traits::canvas::*;
use cssparser::RGBA;
use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D};
use ipc_channel::ipc::{self, IpcSender};
@@ -193,12 +193,8 @@ impl<'a> CanvasPaintThread<'a> {
Canvas2dMsg::SetShadowColor(ref color) => painter.set_shadow_color(color.to_azure_style()),
}
},
- CanvasMsg::Common(message) => {
- match message {
- CanvasCommonMsg::Close => break,
- CanvasCommonMsg::Recreate(size) => painter.recreate(size),
- }
- },
+ CanvasMsg::Close => break,
+ CanvasMsg::Recreate(size) => painter.recreate(size),
CanvasMsg::FromScript(message) => {
match message {
FromScriptMsg::SendPixels(chan) => {
@@ -213,8 +209,6 @@ 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");
@@ -571,7 +565,7 @@ impl<'a> CanvasPaintThread<'a> {
})
}
- fn send_data(&mut self, chan: IpcSender<CanvasData>) {
+ fn send_data(&mut self, chan: IpcSender<CanvasImageData>) {
self.drawtarget.snapshot().get_data_surface().with_data(|element| {
let size = self.drawtarget.get_size();
@@ -614,7 +608,7 @@ impl<'a> CanvasPaintThread<'a> {
let data = CanvasImageData {
image_key: self.image_key.unwrap(),
};
- chan.send(CanvasData::Image(data)).unwrap();
+ chan.send(data).unwrap();
})
}
diff --git a/components/canvas/gl_context.rs b/components/canvas/gl_context.rs
new file mode 100644
index 00000000000..69a26c0e03c
--- /dev/null
+++ b/components/canvas/gl_context.rs
@@ -0,0 +1,203 @@
+/* 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 a3d90909637..b9f0823a07d 100644
--- a/components/canvas/lib.rs
+++ b/components/canvas/lib.rs
@@ -6,16 +6,18 @@
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 servo_config;
+extern crate webrender;
extern crate webrender_api;
pub mod canvas_paint_thread;
-pub mod webgl_paint_thread;
+pub mod gl_context;
+mod webgl_mode;
+pub mod webgl_thread;
diff --git a/components/canvas/webgl_mode/inprocess.rs b/components/canvas/webgl_mode/inprocess.rs
new file mode 100644
index 00000000000..257f1395545
--- /dev/null
+++ b/components/canvas/webgl_mode/inprocess.rs
@@ -0,0 +1,95 @@
+/* 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
new file mode 100644
index 00000000000..660818fb096
--- /dev/null
+++ b/components/canvas/webgl_mode/mod.rs
@@ -0,0 +1,6 @@
+/* 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
deleted file mode 100644
index 2b6819effba..00000000000
--- a/components/canvas/webgl_paint_thread.rs
+++ /dev/null
@@ -1,379 +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::{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
new file mode 100644
index 00000000000..907233a3b89
--- /dev/null
+++ b/components/canvas/webgl_thread.rs
@@ -0,0 +1,1204 @@
+/* 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 afc23f4a2e0..43cc74e60b1 100644
--- a/components/canvas_traits/Cargo.toml
+++ b/components/canvas_traits/Cargo.toml
@@ -15,5 +15,8 @@ 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
new file mode 100644
index 00000000000..92444d03799
--- /dev/null
+++ b/components/canvas_traits/canvas.rs
@@ -0,0 +1,409 @@
+/* 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 1f6d9eda087..7830d669e3e 100644
--- a/components/canvas_traits/lib.rs
+++ b/components/canvas_traits/lib.rs
@@ -4,432 +4,22 @@
#![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;
-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;
- }
-}
+pub mod canvas;
+pub mod webgl;
+mod webgl_channel;
diff --git a/components/canvas_traits/webgl.rs b/components/canvas_traits/webgl.rs
new file mode 100644
index 00000000000..1bd6eb0649b
--- /dev/null
+++ b/components/canvas_traits/webgl.rs
@@ -0,0 +1,506 @@
+/* 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
new file mode 100644
index 00000000000..ac3020bbc7a
--- /dev/null
+++ b/components/canvas_traits/webgl_channel/ipc.rs
@@ -0,0 +1,15 @@
+/* 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
new file mode 100644
index 00000000000..1ac4ce15cb1
--- /dev/null
+++ b/components/canvas_traits/webgl_channel/mod.rs
@@ -0,0 +1,87 @@
+/* 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
new file mode 100644
index 00000000000..b0fe29241f3
--- /dev/null
+++ b/components/canvas_traits/webgl_channel/mpsc.rs
@@ -0,0 +1,51 @@
+/* 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 ff6bd2700f0..f2ab08dc190 100644
--- a/components/constellation/Cargo.toml
+++ b/components/constellation/Cargo.toml
@@ -30,7 +30,6 @@ 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 1685a32d8d2..3e9b0cc80be 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_paint_thread::WebGLPaintThread;
-use canvas_traits::CanvasMsg;
+use canvas::webgl_thread::WebGLThreads;
+use canvas_traits::canvas::CanvasMsg;
use clipboard::{ClipboardContext, ClipboardProvider};
use compositing::SendableFrameTree;
use compositing::compositor_thread::CompositorProxy;
@@ -96,7 +96,6 @@ 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;
@@ -298,8 +297,11 @@ 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_thread: Option<IpcSender<WebVRMsg>>,
+ webvr_chan: Option<IpcSender<WebVRMsg>>,
}
/// State needed to construct a constellation.
@@ -337,6 +339,12 @@ 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,
@@ -581,7 +589,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
info!("Using seed {} for random pipeline closure.", seed);
(rng, prob)
}),
- webvr_thread: None
+ webgl_threads: state.webgl_threads,
+ webvr_chan: state.webvr_chan,
};
constellation.run();
@@ -700,7 +709,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
webrender_api_sender: self.webrender_api_sender.clone(),
webrender_document: self.webrender_document,
is_private,
- webvr_thread: self.webvr_thread.clone()
+ webgl_chan: self.webgl_threads.pipeline(),
+ webvr_chan: self.webvr_chan.clone()
});
let pipeline = match result {
@@ -994,10 +1004,6 @@ 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);
@@ -1154,10 +1160,6 @@ 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));
@@ -1367,7 +1369,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
}
- if let Some(chan) = self.webvr_thread.as_ref() {
+ 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() {
debug!("Exiting WebVR thread.");
if let Err(e) = chan.send(WebVRMsg::Exit) {
warn!("Exit WebVR thread failed ({})", e);
@@ -2135,19 +2142,6 @@ 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 d2ac0f00dea..1c444ff6603 100644
--- a/components/constellation/lib.rs
+++ b/components/constellation/lib.rs
@@ -30,7 +30,6 @@ 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 92a5fb041ef..74ce33ff564 100644
--- a/components/constellation/pipeline.rs
+++ b/components/constellation/pipeline.rs
@@ -3,6 +3,7 @@
* 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;
@@ -171,8 +172,12 @@ 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_thread: Option<IpcSender<WebVRMsg>>,
+ pub webvr_chan: Option<IpcSender<WebVRMsg>>,
}
impl Pipeline {
@@ -270,7 +275,8 @@ impl Pipeline {
script_content_process_shutdown_port: script_content_process_shutdown_port,
webrender_api_sender: state.webrender_api_sender,
webrender_document: state.webrender_document,
- webvr_thread: state.webvr_thread,
+ webgl_chan: state.webgl_chan,
+ webvr_chan: state.webvr_chan,
};
// Spawn the child process.
@@ -470,7 +476,8 @@ pub struct UnprivilegedPipelineContent {
script_content_process_shutdown_port: IpcReceiver<()>,
webrender_api_sender: webrender_api::RenderApiSender,
webrender_document: webrender_api::DocumentId,
- webvr_thread: Option<IpcSender<WebVRMsg>>,
+ webgl_chan: WebGLPipeline,
+ webvr_chan: Option<IpcSender<WebVRMsg>>,
}
impl UnprivilegedPipelineContent {
@@ -499,7 +506,8 @@ impl UnprivilegedPipelineContent {
window_size: self.window_size,
pipeline_namespace_id: self.pipeline_namespace_id,
content_process_shutdown_chan: self.script_content_process_shutdown_chan,
- webvr_thread: self.webvr_thread,
+ webgl_chan: self.webgl_chan,
+ webvr_chan: self.webvr_chan,
}, 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 2d1b7c593dc..98ece855d25 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, WebGLContextId};
+use webrender_api::{MixBlendMode, ScrollPolicy, ScrollSensitivity, TransformStyle};
pub use style::dom::OpaqueNode;
@@ -598,7 +598,6 @@ pub enum DisplayItem {
SolidColor(Box<SolidColorDisplayItem>),
Text(Box<TextDisplayItem>),
Image(Box<ImageDisplayItem>),
- WebGL(Box<WebGLDisplayItem>),
Border(Box<BorderDisplayItem>),
Gradient(Box<GradientDisplayItem>),
RadialGradient(Box<RadialGradientDisplayItem>),
@@ -928,14 +927,6 @@ 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 {
@@ -1249,7 +1240,6 @@ 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,
@@ -1375,7 +1365,6 @@ 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 3fc63df7c49..75e288e4826 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::{CanvasData, CanvasMsg, FromLayoutMsg};
+use canvas_traits::canvas::{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::{CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo};
+use fragment::{CanvasFragmentSource, 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, WebGLDisplayItem, WebRenderImageInfo};
+use gfx::display_list::{TextDisplayItem, TextOrientation, 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,15 +1978,22 @@ 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 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()
+ let (image_key, format) = match canvas_fragment_info.source {
+ CanvasFragmentSource::WebGL(image_key) => {
+ (image_key, PixelFormat::BGRA8)
},
- None => return,
+ 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,
+ }
+ }
};
let base = state.create_base_display_item(
@@ -1995,29 +2002,19 @@ impl FragmentDisplayListBuilding for Fragment {
self.node,
self.style.get_cursor(Cursor::Default),
DisplayListSection::Content);
- 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,
- })
- }
- };
+ 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,
+ });
state.add_display_item(display_item);
}
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 2510b185d1c..f4928262e99 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -8,7 +8,7 @@
use ServoArc;
use app_units::Au;
-use canvas_traits::CanvasMsg;
+use canvas_traits::canvas::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;
+use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource};
use script_layout_interface::SVGSVGData;
use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use serde::ser::{Serialize, SerializeStruct, Serializer};
@@ -53,6 +53,7 @@ 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.
@@ -322,17 +323,31 @@ impl InlineAbsoluteFragmentInfo {
}
#[derive(Clone)]
+pub enum CanvasFragmentSource {
+ WebGL(webrender_api::ImageKey),
+ Image(Option<Arc<Mutex<IpcSender<CanvasMsg>>>>)
+}
+
+#[derive(Clone)]
pub struct CanvasFragmentInfo {
- pub ipc_renderer: Option<Arc<Mutex<IpcSender<CanvasMsg>>>>,
+ pub source: CanvasFragmentSource,
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 {
- ipc_renderer: data.ipc_renderer
- .map(|renderer| Arc::new(Mutex::new(renderer))),
+ source: source,
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 6b8b334d52d..6e5a774e283 100644
--- a/components/layout/webrender_helpers.rs
+++ b/components/layout/webrender_helpers.rs
@@ -305,11 +305,6 @@ 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 81017cd344e..4168fb4effa 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -30,8 +30,11 @@
//! `JSTraceable` to a datatype.
use app_units::Au;
-use canvas_traits::{CanvasGradientStop, LinearGradientStyle, RadialGradientStyle};
-use canvas_traits::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle};
+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 cssparser::RGBA;
use devtools_traits::{CSSError, TimelineMarkerType, WorkerId};
use dom::abstractworker::SharedRt;
@@ -105,8 +108,7 @@ use style::stylesheets::keyframes_rule::Keyframe;
use style::values::specified::Length;
use time::Duration;
use uuid::Uuid;
-use webrender_api::{WebGLBufferId, WebGLError, WebGLFramebufferId, WebGLProgramId};
-use webrender_api::{WebGLRenderbufferId, WebGLShaderId, WebGLTextureId, WebGLVertexArrayId};
+use webrender_api::ImageKey;
use webvr_traits::WebVRGamepadHand;
/// A trait to allow tracing (only) DOM objects.
@@ -391,8 +393,13 @@ 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);
@@ -466,6 +473,20 @@ 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 64df591f760..3a0707ab5eb 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::{CanvasGradientStop, FillOrStrokeStyle, LinearGradientStyle, RadialGradientStyle};
+use canvas_traits::canvas::{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 5d9dd5cb767..46bcbedcef0 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::{FillOrStrokeStyle, RepetitionStyle, SurfaceStyle};
+use canvas_traits::canvas::{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 55d2ef3ceb4..d4fcfae4ab8 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::{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 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 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::Common(CanvasCommonMsg::Recreate(size)))
+ .send(CanvasMsg::Recreate(size))
.unwrap();
}
@@ -173,10 +173,6 @@ 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);
@@ -1392,7 +1388,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
impl Drop for CanvasRenderingContext2D {
fn drop(&mut self) {
- if let Err(err) = self.ipc_renderer.send(CanvasMsg::Common(CanvasCommonMsg::Close)) {
+ if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close) {
warn!("Could not close canvas: {}", err)
}
}
diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs
index a95ff766171..3d89c08b230 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::{CanvasMsg, FromScriptMsg};
+use canvas_traits::canvas::{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::{self, IpcSender};
+use ipc_channel::ipc;
use js::error::throw_type_error;
use js::jsapi::{HandleValue, JSContext};
use offscreen_gl_context::GLContextAttributes;
-use script_layout_interface::HTMLCanvasData;
+use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource};
use std::iter::repeat;
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
@@ -106,21 +106,22 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> {
fn data(&self) -> HTMLCanvasData {
unsafe {
let canvas = &*self.unsafe_get();
- 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 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 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 {
- ipc_renderer: ipc_renderer,
+ source: source,
width: width_attr.map_or(DEFAULT_WIDTH, |val| val.as_uint()),
height: height_attr.map_or(DEFAULT_HEIGHT, |val| val.as_uint()),
}
@@ -150,15 +151,6 @@ 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);
@@ -221,22 +213,26 @@ impl HTMLCanvasElement {
return None
}
- 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();
+ 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();
- 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;
+ match receiver.recv().unwrap() {
+ Some(pixels) => pixels,
+ None => {
+ 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 c3aa9e4c98b..c6b62b50e15 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::CanvasData;
-use canvas_traits::CanvasMsg;
-use canvas_traits::FromLayoutMsg;
+use canvas_traits::canvas::CanvasImageData;
+use canvas_traits::canvas::CanvasMsg;
+use canvas_traits::canvas::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<CanvasData>) {
+ pub fn send_data(&self, sender: IpcSender<CanvasImageData>) {
let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender));
- let _ = self.context.ipc_renderer().send(msg);
+ let _ = self.context.get_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 b0a43cbf25d..607c432c78a 100644
--- a/components/script/dom/paintworkletglobalscope.rs
+++ b/components/script/dom/paintworkletglobalscope.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::CanvasData;
use dom::bindings::callback::CallbackContainer;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::PaintWorkletGlobalScopeBinding;
@@ -298,7 +297,7 @@ impl PaintWorkletGlobalScope {
let (sender, receiver) = ipc::channel().expect("IPC channel creation.");
rendering_context.send_data(sender);
let image_key = match receiver.recv() {
- Ok(CanvasData::Image(data)) => Some(data.image_key),
+ Ok(data) => Some(data.image_key),
_ => None,
};
diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs
index 54f06fb928f..a36bd27ad29 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::CanvasMsg;
+use canvas_traits::webgl::{webgl_channel, WebGLReceiver, WebVRCommand};
use core::ops::Deref;
use dom::bindings::callback::ExceptionHandling;
use dom::bindings::cell::DOMRefCell;
@@ -32,8 +32,7 @@ use dom::vrpose::VRPose;
use dom::vrstageparameters::VRStageParameters;
use dom::webglrenderingcontext::WebGLRenderingContext;
use dom_struct::dom_struct;
-use ipc_channel::ipc;
-use ipc_channel::ipc::{IpcSender, IpcReceiver};
+use ipc_channel::ipc::{self, IpcSender};
use js::jsapi::JSContext;
use script_runtime::CommonScriptMsg;
use script_runtime::ScriptThreadEventCategory::WebVREvent;
@@ -43,7 +42,6 @@ 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]
@@ -71,7 +69,7 @@ pub struct VRDisplay {
// Compositor VRFrameData synchonization
frame_data_status: Cell<VRFrameDataStatus>,
#[ignore_heap_size_of = "channels are hard"]
- frame_data_receiver: DOMRefCell<Option<IpcReceiver<Result<Vec<u8>, ()>>>>,
+ frame_data_receiver: DOMRefCell<Option<WebGLReceiver<Result<Vec<u8>, ()>>>>,
running_display_raf: Cell<bool>,
paused: Cell<bool>,
stopped_on_pause: Cell<bool>,
@@ -386,11 +384,10 @@ impl VRDisplayMethods for VRDisplay {
return;
}
- let api_sender = self.layer_ctx.get().unwrap().ipc_renderer();
- let display_id = self.display.borrow().display_id as u64;
+ let display_id = self.display.borrow().display_id;
let layer = self.layer.borrow();
- let msg = VRCompositorCommand::SubmitFrame(display_id, layer.left_bounds, layer.right_bounds);
- api_sender.send(CanvasMsg::WebVR(msg)).unwrap();
+ let msg = WebVRCommand::SubmitFrame(display_id, layer.left_bounds, layer.right_bounds);
+ self.layer_ctx.get().unwrap().send_vr_command(msg);
}
// https://w3c.github.io/webvr/spec/1.1/#dom-vrdisplay-getlayers
@@ -489,11 +486,11 @@ impl VRDisplay {
fn init_present(&self) {
self.presenting.set(true);
- let (sync_sender, sync_receiver) = ipc::channel().unwrap();
+ let (sync_sender, sync_receiver) = webgl_channel().unwrap();
*self.frame_data_receiver.borrow_mut() = Some(sync_receiver);
- let display_id = self.display.borrow().display_id as u64;
- let api_sender = self.layer_ctx.get().unwrap().ipc_renderer();
+ let display_id = self.display.borrow().display_id;
+ let api_sender = self.layer_ctx.get().unwrap().webgl_sender();
let js_sender = self.global().script_chan();
let address = Trusted::new(&*self);
let near_init = self.depth_near.get();
@@ -511,7 +508,7 @@ impl VRDisplay {
let mut far = far_init;
// Initialize compositor
- api_sender.send(CanvasMsg::WebVR(VRCompositorCommand::Create(display_id))).unwrap();
+ api_sender.send_vr(WebVRCommand::Create(display_id)).unwrap();
loop {
// Run RAF callbacks on JavaScript thread
let msg = box NotifyDisplayRAF {
@@ -521,8 +518,8 @@ impl VRDisplay {
js_sender.send(CommonScriptMsg::RunnableMsg(WebVREvent, msg)).unwrap();
// Run Sync Poses in parallell on Render thread
- let msg = VRCompositorCommand::SyncPoses(display_id, near, far, sync_sender.clone());
- api_sender.send(CanvasMsg::WebVR(msg)).unwrap();
+ let msg = WebVRCommand::SyncPoses(display_id, near, far, sync_sender.clone());
+ api_sender.send_vr(msg).unwrap();
// Wait until both SyncPoses & RAF ends
if let Ok(depth) = raf_receiver.recv().unwrap() {
@@ -541,10 +538,9 @@ impl VRDisplay {
self.presenting.set(false);
*self.frame_data_receiver.borrow_mut() = None;
- 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();
+ 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();
}
// Only called when the JSContext is destroyed while presenting.
@@ -627,7 +623,7 @@ impl Runnable for NotifyDisplayRAF {
}
-// WebVR Spect: If the number of values in the leftBounds/rightBounds arrays
+// WebVR Spec: 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 097742f5441..48385a3d50f 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::CanvasMsg;
+use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLError};
use dom::bindings::codegen::Bindings::OESVertexArrayObjectBinding::{self, OESVertexArrayObjectMethods};
use dom::bindings::codegen::Bindings::OESVertexArrayObjectBinding::OESVertexArrayObjectConstants;
use dom::bindings::js::{JS, MutNullableJS, Root};
@@ -15,7 +15,6 @@ 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 {
@@ -48,8 +47,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) = webrender_api::channel::msg_channel().unwrap();
- self.ctx.send_renderer_message(CanvasMsg::WebGL(WebGLCommand::CreateVertexArray(sender)));
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.ctx.send_command(WebGLCommand::CreateVertexArray(sender));
let result = receiver.recv().unwrap();
result.map(|vao_id| WebGLVertexArrayObjectOES::new(&self.global(), vao_id))
@@ -66,7 +65,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_renderer_message(CanvasMsg::WebGL(WebGLCommand::BindVertexArray(None)));
+ self.ctx.send_command(WebGLCommand::BindVertexArray(None));
}
}
@@ -80,7 +79,7 @@ impl OESVertexArrayObjectMethods for OESVertexArrayObject {
}
// Delete the vao
- self.ctx.send_renderer_message(CanvasMsg::WebGL(WebGLCommand::DeleteVertexArray(vao.id())));
+ self.ctx.send_command(WebGLCommand::DeleteVertexArray(vao.id()));
vao.set_deleted();
}
}
@@ -114,7 +113,7 @@ impl OESVertexArrayObjectMethods for OESVertexArrayObject {
return;
}
- self.ctx.send_renderer_message(CanvasMsg::WebGL(WebGLCommand::BindVertexArray(Some(vao.id()))));
+ self.ctx.send_command(WebGLCommand::BindVertexArray(Some(vao.id())));
vao.set_ever_bound();
self.bound_vao.set(Some(&vao));
@@ -124,7 +123,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_renderer_message(CanvasMsg::WebGL(WebGLCommand::BindVertexArray(None)));
+ self.ctx.send_command(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 e44b7c9bc42..2fe109cafa6 100644
--- a/components/script/dom/webgl_extensions/ext/webglvertexarrayobjectoes.rs
+++ b/components/script/dom/webgl_extensions/ext/webglvertexarrayobjectoes.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::webgl::WebGLVertexArrayId;
use core::cell::Ref;
use core::iter::FromIterator;
use dom::bindings::cell::DOMRefCell;
@@ -15,7 +16,6 @@ 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 28c32dede64..2a780b129ff 100644
--- a/components/script/dom/webgl_extensions/extensions.rs
+++ b/components/script/dom/webgl_extensions/extensions.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::webgl::WebGLError;
use core::iter::FromIterator;
use core::nonzero::NonZero;
use dom::bindings::cell::DOMRefCell;
@@ -19,7 +20,6 @@ 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 41b2795bc14..cd5320453c7 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 448956a9b90..96db4466d56 100644
--- a/components/script/dom/webglbuffer.rs
+++ b/components/script/dom/webglbuffer.rs
@@ -3,7 +3,8 @@
* 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::CanvasMsg;
+use canvas_traits::webgl::{WebGLBufferId, WebGLCommand, WebGLError, WebGLMsgSender, WebGLResult, WebGLVertexArrayId};
+use canvas_traits::webgl::webgl_channel;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::WebGLBufferBinding;
use dom::bindings::js::Root;
@@ -11,11 +12,9 @@ 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 {
@@ -29,11 +28,11 @@ pub struct WebGLBuffer {
vao_references: DOMRefCell<Option<HashSet<WebGLVertexArrayId>>>,
pending_delete: Cell<bool>,
#[ignore_heap_size_of = "Defined in ipc-channel"]
- renderer: IpcSender<CanvasMsg>,
+ renderer: WebGLMsgSender,
}
impl WebGLBuffer {
- fn new_inherited(renderer: IpcSender<CanvasMsg>,
+ fn new_inherited(renderer: WebGLMsgSender,
id: WebGLBufferId)
-> WebGLBuffer {
WebGLBuffer {
@@ -48,17 +47,17 @@ impl WebGLBuffer {
}
}
- pub fn maybe_new(window: &Window, renderer: IpcSender<CanvasMsg>)
+ pub fn maybe_new(window: &Window, renderer: WebGLMsgSender)
-> Option<Root<WebGLBuffer>> {
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateBuffer(sender))).unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ renderer.send(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: IpcSender<CanvasMsg>,
+ renderer: WebGLMsgSender,
id: WebGLBufferId)
-> Root<WebGLBuffer> {
reflect_dom_object(box WebGLBuffer::new_inherited(renderer, id),
@@ -81,7 +80,7 @@ impl WebGLBuffer {
} else {
self.target.set(Some(target));
}
- let msg = CanvasMsg::WebGL(WebGLCommand::BindBuffer(target, Some(self.id)));
+ let msg = WebGLCommand::BindBuffer(target, Some(self.id));
self.renderer.send(msg).unwrap();
Ok(())
@@ -94,9 +93,7 @@ impl WebGLBuffer {
}
}
self.capacity.set(data.len());
- self.renderer
- .send(CanvasMsg::WebGL(WebGLCommand::BufferData(target, data.to_vec(), usage)))
- .unwrap();
+ self.renderer.send(WebGLCommand::BufferData(target, data.to_vec(), usage)).unwrap();
Ok(())
}
@@ -108,7 +105,7 @@ impl WebGLBuffer {
pub fn delete(&self) {
if !self.is_deleted.get() {
self.is_deleted.set(true);
- let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteBuffer(self.id)));
+ let _ = self.renderer.send(WebGLCommand::DeleteBuffer(self.id));
}
}
@@ -144,7 +141,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(CanvasMsg::WebGL(WebGLCommand::DeleteBuffer(self.id)));
+ let _ = self.renderer.send(WebGLCommand::DeleteBuffer(self.id));
self.is_deleted.set(true);
}
}
diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs
index bb486c80c38..7a6b1090064 100644
--- a/components/script/dom/webglframebuffer.rs
+++ b/components/script/dom/webglframebuffer.rs
@@ -3,7 +3,9 @@
* 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::CanvasMsg;
+use canvas_traits::webgl::{WebGLCommand, WebGLFramebufferBindingRequest, WebGLFramebufferId};
+use canvas_traits::webgl::{WebGLMsgSender, WebGLResult, WebGLError};
+use canvas_traits::webgl::webgl_channel;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::WebGLFramebufferBinding;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
@@ -14,10 +16,7 @@ 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)]
@@ -36,7 +35,7 @@ pub struct WebGLFramebuffer {
size: Cell<Option<(i32, i32)>>,
status: Cell<u32>,
#[ignore_heap_size_of = "Defined in ipc-channel"]
- renderer: IpcSender<CanvasMsg>,
+ renderer: WebGLMsgSender,
// The attachment points for textures and renderbuffers on this
// FBO.
@@ -47,7 +46,7 @@ pub struct WebGLFramebuffer {
}
impl WebGLFramebuffer {
- fn new_inherited(renderer: IpcSender<CanvasMsg>,
+ fn new_inherited(renderer: WebGLMsgSender,
id: WebGLFramebufferId)
-> WebGLFramebuffer {
WebGLFramebuffer {
@@ -65,17 +64,17 @@ impl WebGLFramebuffer {
}
}
- pub fn maybe_new(window: &Window, renderer: IpcSender<CanvasMsg>)
+ pub fn maybe_new(window: &Window, renderer: WebGLMsgSender)
-> Option<Root<WebGLFramebuffer>> {
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateFramebuffer(sender))).unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ renderer.send(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: IpcSender<CanvasMsg>,
+ renderer: WebGLMsgSender,
id: WebGLFramebufferId)
-> Root<WebGLFramebuffer> {
reflect_dom_object(box WebGLFramebuffer::new_inherited(renderer, id),
@@ -98,13 +97,13 @@ impl WebGLFramebuffer {
self.target.set(Some(target));
let cmd = WebGLCommand::BindFramebuffer(target, WebGLFramebufferBindingRequest::Explicit(self.id));
- self.renderer.send(CanvasMsg::WebGL(cmd)).unwrap();
+ self.renderer.send(cmd).unwrap();
}
pub fn delete(&self) {
if !self.is_deleted.get() {
self.is_deleted.set(true);
- let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteFramebuffer(self.id)));
+ let _ = self.renderer.send(WebGLCommand::DeleteFramebuffer(self.id));
}
}
@@ -205,10 +204,10 @@ impl WebGLFramebuffer {
}
};
- self.renderer.send(CanvasMsg::WebGL(WebGLCommand::FramebufferRenderbuffer(constants::FRAMEBUFFER,
- attachment,
- constants::RENDERBUFFER,
- rb_id))).unwrap();
+ self.renderer.send(WebGLCommand::FramebufferRenderbuffer(constants::FRAMEBUFFER,
+ attachment,
+ constants::RENDERBUFFER,
+ rb_id)).unwrap();
self.update_status();
Ok(())
@@ -281,11 +280,11 @@ impl WebGLFramebuffer {
}
};
- self.renderer.send(CanvasMsg::WebGL(WebGLCommand::FramebufferTexture2D(constants::FRAMEBUFFER,
- attachment,
- textarget,
- tex_id,
- level))).unwrap();
+ self.renderer.send(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 c76a2f3da18..6c298bb83fb 100644
--- a/components/script/dom/webglprogram.rs
+++ b/components/script/dom/webglprogram.rs
@@ -3,7 +3,8 @@
* 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::CanvasMsg;
+use canvas_traits::webgl::{WebGLCommand, WebGLError, WebGLMsgSender, WebGLParameter, WebGLProgramId, WebGLResult};
+use canvas_traits::webgl::webgl_channel;
use dom::bindings::codegen::Bindings::WebGLProgramBinding;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use dom::bindings::js::{MutNullableJS, Root};
@@ -15,10 +16,7 @@ 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 {
@@ -30,11 +28,11 @@ pub struct WebGLProgram {
fragment_shader: MutNullableJS<WebGLShader>,
vertex_shader: MutNullableJS<WebGLShader>,
#[ignore_heap_size_of = "Defined in ipc-channel"]
- renderer: IpcSender<CanvasMsg>,
+ renderer: WebGLMsgSender,
}
impl WebGLProgram {
- fn new_inherited(renderer: IpcSender<CanvasMsg>,
+ fn new_inherited(renderer: WebGLMsgSender,
id: WebGLProgramId)
-> WebGLProgram {
WebGLProgram {
@@ -49,17 +47,17 @@ impl WebGLProgram {
}
}
- pub fn maybe_new(window: &Window, renderer: IpcSender<CanvasMsg>)
+ pub fn maybe_new(window: &Window, renderer: WebGLMsgSender)
-> Option<Root<WebGLProgram>> {
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateProgram(sender))).unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ renderer.send(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: IpcSender<CanvasMsg>,
+ renderer: WebGLMsgSender,
id: WebGLProgramId)
-> Root<WebGLProgram> {
reflect_dom_object(box WebGLProgram::new_inherited(renderer, id),
@@ -78,7 +76,7 @@ impl WebGLProgram {
pub fn delete(&self) {
if !self.is_deleted.get() {
self.is_deleted.set(true);
- let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteProgram(self.id)));
+ let _ = self.renderer.send(WebGLCommand::DeleteProgram(self.id));
if let Some(shader) = self.fragment_shader.get() {
shader.decrement_attached_counter();
@@ -117,7 +115,7 @@ impl WebGLProgram {
}
self.linked.set(true);
- self.renderer.send(CanvasMsg::WebGL(WebGLCommand::LinkProgram(self.id))).unwrap();
+ self.renderer.send(WebGLCommand::LinkProgram(self.id)).unwrap();
Ok(())
}
@@ -130,7 +128,7 @@ impl WebGLProgram {
return Err(WebGLError::InvalidOperation);
}
- self.renderer.send(CanvasMsg::WebGL(WebGLCommand::UseProgram(self.id))).unwrap();
+ self.renderer.send(WebGLCommand::UseProgram(self.id)).unwrap();
Ok(())
}
@@ -139,7 +137,7 @@ impl WebGLProgram {
if self.is_deleted() {
return Err(WebGLError::InvalidOperation);
}
- self.renderer.send(CanvasMsg::WebGL(WebGLCommand::ValidateProgram(self.id))).unwrap();
+ self.renderer.send(WebGLCommand::ValidateProgram(self.id)).unwrap();
Ok(())
}
@@ -166,7 +164,7 @@ impl WebGLProgram {
shader_slot.set(Some(shader));
shader.increment_attached_counter();
- self.renderer.send(CanvasMsg::WebGL(WebGLCommand::AttachShader(self.id, shader.id()))).unwrap();
+ self.renderer.send(WebGLCommand::AttachShader(self.id, shader.id())).unwrap();
Ok(())
}
@@ -196,7 +194,7 @@ impl WebGLProgram {
shader_slot.set(None);
shader.decrement_attached_counter();
- self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DetachShader(self.id, shader.id()))).unwrap();
+ self.renderer.send(WebGLCommand::DetachShader(self.id, shader.id())).unwrap();
Ok(())
}
@@ -216,7 +214,7 @@ impl WebGLProgram {
}
self.renderer
- .send(CanvasMsg::WebGL(WebGLCommand::BindAttribLocation(self.id, index, String::from(name))))
+ .send(WebGLCommand::BindAttribLocation(self.id, index, String::from(name)))
.unwrap();
Ok(())
}
@@ -225,9 +223,9 @@ impl WebGLProgram {
if self.is_deleted() {
return Err(WebGLError::InvalidValue);
}
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
self.renderer
- .send(CanvasMsg::WebGL(WebGLCommand::GetActiveUniform(self.id, index, sender)))
+ .send(WebGLCommand::GetActiveUniform(self.id, index, sender))
.unwrap();
receiver.recv().unwrap().map(|(size, ty, name)|
@@ -239,9 +237,9 @@ impl WebGLProgram {
if self.is_deleted() {
return Err(WebGLError::InvalidValue);
}
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
self.renderer
- .send(CanvasMsg::WebGL(WebGLCommand::GetActiveAttrib(self.id, index, sender)))
+ .send(WebGLCommand::GetActiveAttrib(self.id, index, sender))
.unwrap();
receiver.recv().unwrap().map(|(size, ty, name)|
@@ -266,9 +264,9 @@ impl WebGLProgram {
return Ok(None);
}
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
self.renderer
- .send(CanvasMsg::WebGL(WebGLCommand::GetAttribLocation(self.id, String::from(name), sender)))
+ .send(WebGLCommand::GetAttribLocation(self.id, String::from(name), sender))
.unwrap();
Ok(receiver.recv().unwrap())
}
@@ -287,9 +285,9 @@ impl WebGLProgram {
return Ok(None);
}
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
self.renderer
- .send(CanvasMsg::WebGL(WebGLCommand::GetUniformLocation(self.id, String::from(name), sender)))
+ .send(WebGLCommand::GetUniformLocation(self.id, String::from(name), sender))
.unwrap();
Ok(receiver.recv().unwrap())
}
@@ -308,15 +306,15 @@ impl WebGLProgram {
return Ok("One or more shaders failed to compile".to_string());
}
}
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- self.renderer.send(CanvasMsg::WebGL(WebGLCommand::GetProgramInfoLog(self.id, sender))).unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.renderer.send(WebGLCommand::GetProgramInfoLog(self.id, sender)).unwrap();
Ok(receiver.recv().unwrap())
}
/// glGetProgramParameter
pub fn parameter(&self, param_id: u32) -> WebGLResult<WebGLParameter> {
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- self.renderer.send(CanvasMsg::WebGL(WebGLCommand::GetProgramParameter(self.id, param_id, sender))).unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.renderer.send(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 03589365c43..9a855651cc9 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::CanvasMsg;
+use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLError, WebGLMsgSender, WebGLRenderbufferId, WebGLResult};
use dom::bindings::codegen::Bindings::WebGLRenderbufferBinding;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use dom::bindings::js::Root;
@@ -11,10 +11,7 @@ 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 {
@@ -25,11 +22,11 @@ pub struct WebGLRenderbuffer {
size: Cell<Option<(i32, i32)>>,
internal_format: Cell<Option<u32>>,
#[ignore_heap_size_of = "Defined in ipc-channel"]
- renderer: IpcSender<CanvasMsg>,
+ renderer: WebGLMsgSender,
}
impl WebGLRenderbuffer {
- fn new_inherited(renderer: IpcSender<CanvasMsg>,
+ fn new_inherited(renderer: WebGLMsgSender,
id: WebGLRenderbufferId)
-> WebGLRenderbuffer {
WebGLRenderbuffer {
@@ -43,17 +40,17 @@ impl WebGLRenderbuffer {
}
}
- pub fn maybe_new(window: &Window, renderer: IpcSender<CanvasMsg>)
+ pub fn maybe_new(window: &Window, renderer: WebGLMsgSender)
-> Option<Root<WebGLRenderbuffer>> {
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateRenderbuffer(sender))).unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ renderer.send(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: IpcSender<CanvasMsg>,
+ renderer: WebGLMsgSender,
id: WebGLRenderbufferId)
-> Root<WebGLRenderbuffer> {
reflect_dom_object(box WebGLRenderbuffer::new_inherited(renderer, id),
@@ -74,14 +71,14 @@ impl WebGLRenderbuffer {
pub fn bind(&self, target: u32) {
self.ever_bound.set(true);
- let msg = CanvasMsg::WebGL(WebGLCommand::BindRenderbuffer(target, Some(self.id)));
+ let msg = 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(CanvasMsg::WebGL(WebGLCommand::DeleteRenderbuffer(self.id)));
+ let _ = self.renderer.send(WebGLCommand::DeleteRenderbuffer(self.id));
}
}
@@ -110,8 +107,7 @@ impl WebGLRenderbuffer {
// FIXME: Invalidate completeness after the call
- let msg = CanvasMsg::WebGL(WebGLCommand::RenderbufferStorage(constants::RENDERBUFFER,
- internal_format, width, height));
+ let msg = 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 20fe133e02c..c45362b4fe2 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -3,7 +3,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt};
-use canvas_traits::{CanvasCommonMsg, CanvasMsg, byte_swap, multiply_u8_pixel};
+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 core::cell::Ref;
use core::iter::FromIterator;
use core::nonzero::NonZero;
@@ -19,7 +23,6 @@ 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};
@@ -42,7 +45,6 @@ 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};
@@ -50,13 +52,11 @@ 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_traits::ScriptMsg;
+use script_layout_interface::HTMLCanvasDataSource;
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,9 +92,7 @@ macro_rules! handle_object_deletion {
}
if let Some(command) = $unbind_command {
- $self_.ipc_renderer
- .send(CanvasMsg::WebGL(command))
- .unwrap();
+ $self_.send_command(command);
}
}
};
@@ -135,12 +133,15 @@ bitflags! {
#[dom_struct]
pub struct WebGLRenderingContext {
reflector_: Reflector,
- #[ignore_heap_size_of = "Defined in ipc-channel"]
- ipc_renderer: IpcSender<CanvasMsg>,
+ #[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 offscreen_gl_context"]
limits: GLLimits,
canvas: JS<HTMLCanvasElement>,
- #[ignore_heap_size_of = "Defined in webrender_api"]
+ #[ignore_heap_size_of = "Defined in canvas_traits"]
last_error: Cell<Option<WebGLError>>,
texture_unpacking_settings: Cell<TextureUnpacking>,
texture_unpacking_alignment: Cell<u32>,
@@ -158,7 +159,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 {
@@ -171,17 +172,19 @@ impl WebGLRenderingContext {
return Err("WebGL context creation error forced by pref `webgl.testing.context_creation_error`".into());
}
- 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 (sender, receiver) = webgl_channel().unwrap();
+ let webgl_chan = window.webgl_chan();
+ webgl_chan.send(WebGLMsg::CreateContext(size, attrs, sender))
+ .unwrap();
let result = receiver.recv().unwrap();
- result.map(|(ipc_renderer, context_limits)| {
+ result.map(|ctx_data| {
WebGLRenderingContext {
reflector_: Reflector::new(),
- ipc_renderer: ipc_renderer,
- limits: context_limits,
+ webgl_sender: ctx_data.sender,
+ webrender_image: Cell::new(None),
+ share_mode: ctx_data.share_mode,
+ limits: ctx_data.limits,
canvas: JS::from_ref(canvas),
last_error: Cell::new(None),
texture_unpacking_settings: Cell::new(CONVERT_COLORSPACE),
@@ -253,31 +256,43 @@ impl WebGLRenderingContext {
}
pub fn recreate(&self, size: Size2D<i32>) {
- self.ipc_renderer.send(CanvasMsg::Common(CanvasCommonMsg::Recreate(size))).unwrap();
+ 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);
// 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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::ClearColor(color.0, color.1, color.2, color.3)))
- .unwrap();
+ self.send_command(WebGLCommand::ClearColor(color.0, color.1, color.2, color.3));
// 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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Scissor(rect.0, rect.1, rect.2, rect.3)))
- .unwrap()
+ self.send_command(WebGLCommand::Scissor(rect.0, rect.1, rect.2, rect.3));
+ }
+
+ pub fn webgl_sender(&self) -> WebGLMsgSender {
+ self.webgl_sender.clone()
}
- pub fn ipc_renderer(&self) -> IpcSender<CanvasMsg> {
- self.ipc_renderer.clone()
+ #[inline]
+ pub fn send_command(&self, command: WebGLCommand) {
+ self.webgl_sender.send(command).unwrap();
}
- pub fn send_renderer_message(&self, msg: CanvasMsg) {
- self.ipc_renderer.send(msg).unwrap();
+ #[inline]
+ pub fn send_vr_command(&self, command: WebVRCommand) {
+ self.webgl_sender.send_vr(command).unwrap();
}
pub fn get_extension_manager<'a>(&'a self) -> &'a WebGLExtensions {
@@ -370,9 +385,7 @@ impl WebGLRenderingContext {
self.current_vertex_attrib_0.set((x, y, z, w))
}
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::VertexAttrib(indx, x, y, z, w)))
- .unwrap();
+ self.send_command(WebGLCommand::VertexAttrib(indx, x, y, z, w));
}
fn get_current_framebuffer_size(&self) -> Option<(i32, i32)> {
@@ -705,8 +718,8 @@ impl WebGLRenderingContext {
// WebGLContext (probably via GetPixels()).
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLCanvasElement(canvas) => {
if let Some((mut data, size)) = canvas.fetch_all_data() {
- byte_swap(&mut data);
// Pixels got from Canvas have already alpha premultiplied
+ byte_swap(&mut data);
(data, size, true)
} else {
return Err(());
@@ -945,9 +958,7 @@ 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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::PixelStorei(constants::UNPACK_ALIGNMENT, unpacking_alignment as i32)))
- .unwrap();
+ self.send_command(WebGLCommand::PixelStorei(constants::UNPACK_ALIGNMENT, unpacking_alignment as i32));
let format = internal_format.as_gl_constant();
let data_type = data_type.as_gl_constant();
@@ -961,9 +972,7 @@ impl WebGLRenderingContext {
data_type,
pixels);
- self.ipc_renderer
- .send(CanvasMsg::WebGL(msg))
- .unwrap();
+ self.send_command(msg);
if let Some(fb) = self.bound_framebuffer.get() {
fb.invalidate_texture(&*texture);
@@ -1005,9 +1014,7 @@ 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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::PixelStorei(constants::UNPACK_ALIGNMENT, unpacking_alignment as i32)))
- .unwrap();
+ self.send_command(WebGLCommand::PixelStorei(constants::UNPACK_ALIGNMENT, unpacking_alignment as i32));
// TODO(emilio): convert colorspace if requested
let msg = WebGLCommand::TexSubImage2D(target.as_gl_constant(),
@@ -1016,9 +1023,7 @@ impl WebGLRenderingContext {
format.as_gl_constant(),
data_type.as_gl_constant(), pixels);
- self.ipc_renderer
- .send(CanvasMsg::WebGL(msg))
- .unwrap()
+ self.send_command(msg);
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14
@@ -1035,17 +1040,38 @@ impl WebGLRenderingContext {
}
fn get_gl_extensions(&self) -> String {
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::GetExtensions(sender)))
- .unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.send_command(WebGLCommand::GetExtensions(sender));
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.ipc_renderer.send(CanvasMsg::Common(CanvasCommonMsg::Close)).unwrap();
+ self.webgl_sender.send_remove().unwrap();
}
}
@@ -1101,45 +1127,36 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11
fn Flush(&self) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Flush))
- .unwrap();
+ self.send_command(WebGLCommand::Flush);
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11
fn Finish(&self) {
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Finish(sender)))
- .unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.send_command(WebGLCommand::Finish(sender));
receiver.recv().unwrap()
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1
fn DrawingBufferWidth(&self) -> i32 {
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::DrawingBufferWidth(sender)))
- .unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.send_command(WebGLCommand::DrawingBufferWidth(sender));
receiver.recv().unwrap()
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1
fn DrawingBufferHeight(&self) -> i32 {
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::DrawingBufferHeight(sender)))
- .unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.send_command(WebGLCommand::DrawingBufferHeight(sender));
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) = webrender_api::channel::msg_channel().unwrap();
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::GetBufferParameter(target, parameter, sender)))
- .unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.send_command(WebGLCommand::GetBufferParameter(target, parameter, sender));
+
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"),
@@ -1205,10 +1222,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
}
}
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::GetParameter(parameter, sender)))
- .unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.send_command(WebGLCommand::GetParameter(parameter, sender));
+
match handle_potential_webgl_error!(self, receiver.recv().unwrap(), WebGLParameter::Invalid) {
WebGLParameter::Int(val) => Int32Value(val),
WebGLParameter::Bool(val) => BooleanValue(val),
@@ -1243,13 +1259,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) = webrender_api::channel::msg_channel().unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
// If the send does not succeed, assume context lost
- if let Err(_) = self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::GetContextAttributes(sender))) {
+ if self.webgl_sender.send(WebGLCommand::GetContextAttributes(sender)).is_err() {
return None;
}
+
let attrs = receiver.recv().unwrap();
Some(WebGLContextAttributes {
@@ -1285,12 +1301,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
fn ActiveTexture(&self, texture: u32) {
- self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::ActiveTexture(texture))).unwrap();
+ self.send_command(WebGLCommand::ActiveTexture(texture));
}
// 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.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::BlendColor(r, g, b, a))).unwrap();
+ self.send_command(WebGLCommand::BlendColor(r, g, b, a));
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
@@ -1299,7 +1315,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidEnum);
}
- self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::BlendEquation(mode))).unwrap();
+ self.send_command(WebGLCommand::BlendEquation(mode));
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
@@ -1308,9 +1324,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidEnum);
}
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::BlendEquationSeparate(mode_rgb, mode_alpha)))
- .unwrap();
+ self.send_command(WebGLCommand::BlendEquationSeparate(mode_rgb, mode_alpha));
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
@@ -1327,9 +1341,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidOperation);
}
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::BlendFunc(src_factor, dest_factor)))
- .unwrap();
+ self.send_command(WebGLCommand::BlendFunc(src_factor, dest_factor));
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
@@ -1346,8 +1358,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidOperation);
}
- self.ipc_renderer.send(
- CanvasMsg::WebGL(WebGLCommand::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha))).unwrap();
+ self.send_command(WebGLCommand::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha));
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
@@ -1393,9 +1404,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
} else {
slot.set(None);
// Unbind the current buffer
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::BindBuffer(target, None)))
- .unwrap()
+ self.send_command(WebGLCommand::BindBuffer(target, None));
}
}
@@ -1420,7 +1429,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
} else {
// Bind the default framebuffer
let cmd = WebGLCommand::BindFramebuffer(target, WebGLFramebufferBindingRequest::Default);
- self.ipc_renderer.send(CanvasMsg::WebGL(cmd)).unwrap();
+ self.send_command(cmd);
self.bound_framebuffer.set(framebuffer);
}
}
@@ -1442,9 +1451,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
_ => {
self.bound_renderbuffer.set(None);
// Unbind the currently bound renderbuffer
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::BindRenderbuffer(target, None)))
- .unwrap()
+ self.send_command(WebGLCommand::BindRenderbuffer(target, None));
}
}
}
@@ -1465,9 +1472,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
} else {
slot.set(None);
// Unbind the currently bound texture
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::BindTexture(target, None)))
- .unwrap()
+ self.send_command(WebGLCommand::BindTexture(target, None));
}
}
@@ -1585,9 +1590,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if (offset as usize) + data_vec.len() > bound_buffer.capacity() {
return Ok(self.webgl_error(InvalidValue));
}
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::BufferSubData(target, offset as isize, data_vec)))
- .unwrap();
+ self.send_command(WebGLCommand::BufferSubData(target, offset as isize, data_vec));
Ok(())
}
@@ -1670,7 +1673,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
width as i32, height as i32,
border as i32);
- self.ipc_renderer.send(CanvasMsg::WebGL(msg)).unwrap()
+ self.send_command(msg);
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
@@ -1714,7 +1717,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
x, y,
width as i32, height as i32);
- self.ipc_renderer.send(CanvasMsg::WebGL(msg)).unwrap();
+ self.send_command(msg);
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11
@@ -1723,46 +1726,36 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return;
}
- self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::Clear(mask))).unwrap();
+ self.send_command(WebGLCommand::Clear(mask));
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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::ClearColor(red, green, blue, alpha)))
- .unwrap()
+ self.send_command(WebGLCommand::ClearColor(red, green, blue, alpha));
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
fn ClearDepth(&self, depth: f32) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::ClearDepth(depth as f64)))
- .unwrap()
+ self.send_command(WebGLCommand::ClearDepth(depth as f64))
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
fn ClearStencil(&self, stencil: i32) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::ClearStencil(stencil)))
- .unwrap()
+ self.send_command(WebGLCommand::ClearStencil(stencil))
}
// 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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::ColorMask(r, g, b, a)))
- .unwrap()
+ self.send_command(WebGLCommand::ColorMask(r, g, b, a))
}
// 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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::CullFace(mode)))
- .unwrap(),
+ self.send_command(WebGLCommand::CullFace(mode)),
_ => self.webgl_error(InvalidEnum),
}
}
@@ -1771,9 +1764,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
fn FrontFace(&self, mode: u32) {
match mode {
constants::CW | constants::CCW =>
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::FrontFace(mode)))
- .unwrap(),
+ self.send_command(WebGLCommand::FrontFace(mode)),
_ => self.webgl_error(InvalidEnum),
}
}
@@ -1784,18 +1775,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
constants::EQUAL | constants::LEQUAL |
constants::GREATER | constants::NOTEQUAL |
constants::GEQUAL | constants::ALWAYS =>
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::DepthFunc(func)))
- .unwrap(),
+ self.send_command(WebGLCommand::DepthFunc(func)),
_ => self.webgl_error(InvalidEnum),
}
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
fn DepthMask(&self, flag: bool) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::DepthMask(flag)))
- .unwrap()
+ self.send_command(WebGLCommand::DepthMask(flag))
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
@@ -1809,26 +1796,20 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidOperation);
}
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::DepthRange(near as f64, far as f64)))
- .unwrap()
+ self.send_command(WebGLCommand::DepthRange(near as f64, far as f64))
}
// 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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Enable(cap)))
- .unwrap();
+ self.send_command(WebGLCommand::Enable(cap));
}
}
// 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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Disable(cap)))
- .unwrap()
+ self.send_command(WebGLCommand::Disable(cap));
}
}
@@ -1843,27 +1824,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.ipc_renderer.clone())
+ WebGLBuffer::maybe_new(self.global().as_window(), self.webgl_sender.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.ipc_renderer.clone())
+ WebGLFramebuffer::maybe_new(self.global().as_window(), self.webgl_sender.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.ipc_renderer.clone())
+ WebGLRenderbuffer::maybe_new(self.global().as_window(), self.webgl_sender.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.ipc_renderer.clone())
+ WebGLTexture::maybe_new(self.global().as_window(), self.webgl_sender.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.ipc_renderer.clone())
+ WebGLProgram::maybe_new(self.global().as_window(), self.webgl_sender.clone())
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
@@ -1875,7 +1856,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return None;
}
}
- WebGLShader::maybe_new(self.global().as_window(), self.ipc_renderer.clone(), shader_type)
+ WebGLShader::maybe_new(self.global().as_window(), self.webgl_sender.clone(), shader_type)
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
@@ -1999,9 +1980,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return;
}
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::DrawArrays(mode, first, count)))
- .unwrap();
+ self.send_command(WebGLCommand::DrawArrays(mode, first, count));
self.mark_as_dirty();
},
_ => self.webgl_error(InvalidEnum),
@@ -2065,9 +2044,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
constants::LINE_LOOP | constants::LINES |
constants::TRIANGLE_STRIP | constants::TRIANGLE_FAN |
constants::TRIANGLES => {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::DrawElements(mode, count, type_, offset)))
- .unwrap();
+ self.send_command(WebGLCommand::DrawElements(mode, count, type_, offset));
self.mark_as_dirty();
},
_ => self.webgl_error(InvalidEnum),
@@ -2080,9 +2057,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidValue);
}
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::EnableVertexAttribArray(attrib_id)))
- .unwrap()
+ self.send_command(WebGLCommand::EnableVertexAttribArray(attrib_id));
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
@@ -2091,9 +2066,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidValue);
}
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::DisableVertexAttribArray(attrib_id)))
- .unwrap()
+ self.send_command(WebGLCommand::DisableVertexAttribArray(attrib_id));
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
@@ -2223,11 +2196,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
shader_type: u32,
precision_type: u32)
-> Option<Root<WebGLShaderPrecisionFormat>> {
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::GetShaderPrecisionFormat(shader_type,
- precision_type,
- sender)))
- .unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.send_command(WebGLCommand::GetShaderPrecisionFormat(shader_type,
+ precision_type,
+ sender));
+
match receiver.recv().unwrap() {
Ok((range_min, range_max, precision)) => {
Some(WebGLShaderPrecisionFormat::new(self.global().as_window(), range_min, range_max, precision))
@@ -2268,8 +2241,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return jsval.get();
}
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::GetVertexAttrib(index, pname, sender))).unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.send_command(WebGLCommand::GetVertexAttrib(index, pname, sender));
match handle_potential_webgl_error!(self, receiver.recv().unwrap(), WebGLParameter::Invalid) {
WebGLParameter::Int(val) => Int32Value(val),
@@ -2287,8 +2260,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) = webrender_api::channel::msg_channel().unwrap();
- self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::GetVertexAttribOffset(index, pname, sender))).unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.send_command(WebGLCommand::GetVertexAttribOffset(index, pname, sender));
handle_potential_webgl_error!(self, receiver.recv().unwrap(), 0) as i64
}
@@ -2307,9 +2280,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
_ => return self.webgl_error(InvalidEnum),
}
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Hint(target, mode)))
- .unwrap()
+ self.send_command(WebGLCommand::Hint(target, mode));
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
@@ -2321,10 +2292,8 @@ 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) = webrender_api::channel::msg_channel().unwrap();
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::IsEnabled(cap, sender)))
- .unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.send_command(WebGLCommand::IsEnabled(cap, sender));
return receiver.recv().unwrap();
}
@@ -2362,9 +2331,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidValue);
}
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::LineWidth(width)))
- .unwrap()
+ self.send_command(WebGLCommand::LineWidth(width))
}
// NOTE: Usage of this function could affect rendering while we keep using
@@ -2420,9 +2387,7 @@ 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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::PolygonOffset(factor, units)))
- .unwrap()
+ self.send_command(WebGLCommand::PolygonOffset(factor, units))
}
#[allow(unsafe_code)]
@@ -2522,10 +2487,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
_ => return Ok(self.webgl_error(InvalidOperation)),
};
- 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 (sender, receiver) = webgl_channel().unwrap();
+ self.send_command(WebGLCommand::ReadPixels(x, y, width, height, format, pixel_type, sender));
let result = receiver.recv().unwrap();
@@ -2541,7 +2504,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.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::SampleCoverage(value, invert))).unwrap();
+ self.send_command(WebGLCommand::SampleCoverage(value, invert));
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4
@@ -2551,9 +2514,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
}
self.current_scissor.set((x, y, width, height));
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Scissor(x, y, width, height)))
- .unwrap()
+ self.send_command(WebGLCommand::Scissor(x, y, width, height));
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
@@ -2561,9 +2522,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
match func {
constants::NEVER | constants::LESS | constants::EQUAL | constants::LEQUAL |
constants::GREATER | constants::NOTEQUAL | constants::GEQUAL | constants::ALWAYS =>
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::StencilFunc(func, ref_, mask)))
- .unwrap(),
+ self.send_command(WebGLCommand::StencilFunc(func, ref_, mask)),
_ => self.webgl_error(InvalidEnum),
}
}
@@ -2578,27 +2537,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
match func {
constants::NEVER | constants::LESS | constants::EQUAL | constants::LEQUAL |
constants::GREATER | constants::NOTEQUAL | constants::GEQUAL | constants::ALWAYS =>
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::StencilFuncSeparate(face, func, ref_, mask)))
- .unwrap(),
+ self.send_command(WebGLCommand::StencilFuncSeparate(face, func, ref_, mask)),
_ => self.webgl_error(InvalidEnum),
}
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
fn StencilMask(&self, mask: u32) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::StencilMask(mask)))
- .unwrap()
+ self.send_command(WebGLCommand::StencilMask(mask))
}
// 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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::StencilMaskSeparate(face, mask)))
- .unwrap(),
+ self.send_command(WebGLCommand::StencilMaskSeparate(face, mask)),
_ => return self.webgl_error(InvalidEnum),
}
}
@@ -2607,9 +2560,7 @@ 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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::StencilOp(fail, zfail, zpass)))
- .unwrap()
+ self.send_command(WebGLCommand::StencilOp(fail, zfail, zpass));
} else {
self.webgl_error(InvalidEnum)
}
@@ -2624,9 +2575,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_stencil_actions(fail) && self.validate_stencil_actions(zfail) &&
self.validate_stencil_actions(zpass) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::StencilOpSeparate(face, fail, zfail, zpass)))
- .unwrap()
+ self.send_command(WebGLCommand::StencilOpSeparate(face, fail, zfail, zpass))
} else {
self.webgl_error(InvalidEnum)
}
@@ -2658,9 +2607,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
uniform: Option<&WebGLUniformLocation>,
val: f32) {
if self.validate_uniform_parameters(uniform, UniformSetterType::Float, &[val]) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform1f(uniform.unwrap().id(), val)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform1f(uniform.unwrap().id(), val))
}
}
@@ -2669,9 +2616,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
uniform: Option<&WebGLUniformLocation>,
val: i32) {
if self.validate_uniform_parameters(uniform, UniformSetterType::Int, &[val]) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform1i(uniform.unwrap().id(), val)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform1i(uniform.unwrap().id(), val))
}
}
@@ -2685,9 +2630,7 @@ 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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform1iv(uniform.unwrap().id(), data_vec)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform1iv(uniform.unwrap().id(), data_vec))
}
Ok(())
@@ -2703,9 +2646,7 @@ 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.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform1fv(uniform.unwrap().id(), data_vec)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform1fv(uniform.unwrap().id(), data_vec));
}
Ok(())
@@ -2716,9 +2657,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
uniform: Option<&WebGLUniformLocation>,
x: f32, y: f32) {
if self.validate_uniform_parameters(uniform, UniformSetterType::FloatVec2, &[x, y]) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform2f(uniform.unwrap().id(), x, y)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform2f(uniform.unwrap().id(), x, y));
}
}
@@ -2734,9 +2673,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::FloatVec2,
&data_vec) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform2fv(uniform.unwrap().id(), data_vec)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform2fv(uniform.unwrap().id(), data_vec));
}
Ok(())
@@ -2749,9 +2686,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::IntVec2,
&[x, y]) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform2i(uniform.unwrap().id(), x, y)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform2i(uniform.unwrap().id(), x, y));
}
}
@@ -2767,9 +2702,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::IntVec2,
&data_vec) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform2iv(uniform.unwrap().id(), data_vec)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform2iv(uniform.unwrap().id(), data_vec));
}
Ok(())
@@ -2782,9 +2715,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::FloatVec3,
&[x, y, z]) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform3f(uniform.unwrap().id(), x, y, z)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform3f(uniform.unwrap().id(), x, y, z));
}
}
@@ -2800,9 +2731,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::FloatVec3,
&data_vec) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform3fv(uniform.unwrap().id(), data_vec)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform3fv(uniform.unwrap().id(), data_vec))
}
Ok(())
@@ -2815,9 +2744,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::IntVec3,
&[x, y, z]) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform3i(uniform.unwrap().id(), x, y, z)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform3i(uniform.unwrap().id(), x, y, z))
}
}
@@ -2833,9 +2760,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::IntVec3,
&data_vec) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform3iv(uniform.unwrap().id(), data_vec)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform3iv(uniform.unwrap().id(), data_vec))
}
Ok(())
@@ -2848,9 +2773,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::IntVec4,
&[x, y, z, w]) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform4i(uniform.unwrap().id(), x, y, z, w)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform4i(uniform.unwrap().id(), x, y, z, w))
}
}
@@ -2867,9 +2790,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::IntVec4,
&data_vec) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform4iv(uniform.unwrap().id(), data_vec)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform4iv(uniform.unwrap().id(), data_vec))
}
Ok(())
@@ -2882,9 +2803,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::FloatVec4,
&[x, y, z, w]) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform4f(uniform.unwrap().id(), x, y, z, w)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform4f(uniform.unwrap().id(), x, y, z, w))
}
}
@@ -2900,9 +2819,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::FloatVec4,
&data_vec) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Uniform4fv(uniform.unwrap().id(), data_vec)))
- .unwrap()
+ self.send_command(WebGLCommand::Uniform4fv(uniform.unwrap().id(), data_vec))
}
Ok(())
@@ -2920,9 +2837,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::FloatMat2,
&data_vec) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::UniformMatrix2fv(uniform.unwrap().id(), transpose, data_vec)))
- .unwrap()
+ self.send_command(WebGLCommand::UniformMatrix2fv(uniform.unwrap().id(), transpose, data_vec));
}
Ok(())
@@ -2940,9 +2855,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::FloatMat3,
&data_vec) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::UniformMatrix3fv(uniform.unwrap().id(), transpose, data_vec)))
- .unwrap()
+ self.send_command(WebGLCommand::UniformMatrix3fv(uniform.unwrap().id(), transpose, data_vec));
}
Ok(())
@@ -2960,9 +2873,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if self.validate_uniform_parameters(uniform,
UniformSetterType::FloatMat4,
&data_vec) {
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::UniformMatrix4fv(uniform.unwrap().id(), transpose, data_vec)))
- .unwrap()
+ self.send_command(WebGLCommand::UniformMatrix4fv(uniform.unwrap().id(), transpose, data_vec));
}
Ok(())
@@ -3098,9 +3009,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
self.bound_attrib_buffers.borrow_mut().insert(attrib_id, JS::from_ref(&*buffer_array));
- let msg = CanvasMsg::WebGL(
- WebGLCommand::VertexAttribPointer(attrib_id, size, data_type, normalized, stride, offset as u32));
- self.ipc_renderer.send(msg).unwrap()
+ let msg = WebGLCommand::VertexAttribPointer(attrib_id, size, data_type, normalized, stride, offset as u32);
+ self.send_command(msg);
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4
@@ -3109,9 +3019,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidValue)
}
- self.ipc_renderer
- .send(CanvasMsg::WebGL(WebGLCommand::Viewport(x, y, width, height)))
- .unwrap()
+ self.send_command(WebGLCommand::Viewport(x, y, width, height))
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
@@ -3456,13 +3364,13 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
pub trait LayoutCanvasWebGLRenderingContextHelpers {
#[allow(unsafe_code)]
- unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg>;
+ unsafe fn canvas_data_source(&self) -> HTMLCanvasDataSource;
}
impl LayoutCanvasWebGLRenderingContextHelpers for LayoutJS<WebGLRenderingContext> {
#[allow(unsafe_code)]
- unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> {
- (*self.unsafe_get()).ipc_renderer.clone()
+ unsafe fn canvas_data_source(&self) -> HTMLCanvasDataSource {
+ HTMLCanvasDataSource::WebGL((*self.unsafe_get()).layout_handle())
}
}
diff --git a/components/script/dom/webglshader.rs b/components/script/dom/webglshader.rs
index edd9cf7bdb3..cf6fc55072d 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::CanvasMsg;
+use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLMsgSender, WebGLParameter, WebGLResult, WebGLShaderId};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::WebGLShaderBinding;
use dom::bindings::js::Root;
@@ -13,11 +13,8 @@ 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 {
@@ -37,7 +34,7 @@ pub struct WebGLShader {
attached_counter: Cell<u32>,
compilation_status: Cell<ShaderCompilationStatus>,
#[ignore_heap_size_of = "Defined in ipc-channel"]
- renderer: IpcSender<CanvasMsg>,
+ renderer: WebGLMsgSender,
}
#[cfg(not(target_os = "android"))]
@@ -49,7 +46,7 @@ const SHADER_OUTPUT_FORMAT: Output = Output::Essl;
static GLSLANG_INITIALIZATION: Once = ONCE_INIT;
impl WebGLShader {
- fn new_inherited(renderer: IpcSender<CanvasMsg>,
+ fn new_inherited(renderer: WebGLMsgSender,
id: WebGLShaderId,
shader_type: u32)
-> WebGLShader {
@@ -68,18 +65,18 @@ impl WebGLShader {
}
pub fn maybe_new(window: &Window,
- renderer: IpcSender<CanvasMsg>,
+ renderer: WebGLMsgSender,
shader_type: u32)
-> Option<Root<WebGLShader>> {
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateShader(shader_type, sender))).unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ renderer.send(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: IpcSender<CanvasMsg>,
+ renderer: WebGLMsgSender,
id: WebGLShaderId,
shader_type: u32)
-> Root<WebGLShader> {
@@ -118,7 +115,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(CanvasMsg::WebGL(msg)).unwrap();
+ self.renderer.send(msg).unwrap();
self.compilation_status.set(ShaderCompilationStatus::Succeeded);
},
Err(error) => {
@@ -142,7 +139,7 @@ impl WebGLShader {
pub fn delete(&self) {
if !self.is_deleted.get() {
self.is_deleted.set(true);
- let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteShader(self.id)));
+ let _ = self.renderer.send(WebGLCommand::DeleteShader(self.id));
}
}
@@ -170,8 +167,8 @@ impl WebGLShader {
/// glGetParameter
pub fn parameter(&self, param_id: u32) -> WebGLResult<WebGLParameter> {
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- self.renderer.send(CanvasMsg::WebGL(WebGLCommand::GetShaderParameter(self.id, param_id, sender))).unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.renderer.send(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 88d5faaf5c8..048af5d10e0 100644
--- a/components/script/dom/webgltexture.rs
+++ b/components/script/dom/webgltexture.rs
@@ -3,7 +3,8 @@
* 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::CanvasMsg;
+
+use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLError, WebGLMsgSender, WebGLResult, WebGLTextureId};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use dom::bindings::codegen::Bindings::WebGLTextureBinding;
@@ -13,11 +14,8 @@ 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),
@@ -46,11 +44,11 @@ pub struct WebGLTexture {
min_filter: Cell<Option<u32>>,
mag_filter: Cell<Option<u32>>,
#[ignore_heap_size_of = "Defined in ipc-channel"]
- renderer: IpcSender<CanvasMsg>,
+ renderer: WebGLMsgSender,
}
impl WebGLTexture {
- fn new_inherited(renderer: IpcSender<CanvasMsg>,
+ fn new_inherited(renderer: WebGLMsgSender,
id: WebGLTextureId)
-> WebGLTexture {
WebGLTexture {
@@ -67,17 +65,17 @@ impl WebGLTexture {
}
}
- pub fn maybe_new(window: &Window, renderer: IpcSender<CanvasMsg>)
+ pub fn maybe_new(window: &Window, renderer: WebGLMsgSender)
-> Option<Root<WebGLTexture>> {
- let (sender, receiver) = webrender_api::channel::msg_channel().unwrap();
- renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateTexture(sender))).unwrap();
+ let (sender, receiver) = webgl_channel().unwrap();
+ renderer.send(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: IpcSender<CanvasMsg>,
+ renderer: WebGLMsgSender,
id: WebGLTextureId)
-> Root<WebGLTexture> {
reflect_dom_object(box WebGLTexture::new_inherited(renderer, id),
@@ -113,7 +111,7 @@ impl WebGLTexture {
self.target.set(Some(target));
}
- let msg = CanvasMsg::WebGL(WebGLCommand::BindTexture(target, Some(self.id)));
+ let msg = WebGLCommand::BindTexture(target, Some(self.id));
self.renderer.send(msg).unwrap();
Ok(())
@@ -168,7 +166,7 @@ impl WebGLTexture {
return Err(WebGLError::InvalidOperation);
}
- self.renderer.send(CanvasMsg::WebGL(WebGLCommand::GenerateMipmap(target))).unwrap();
+ self.renderer.send(WebGLCommand::GenerateMipmap(target)).unwrap();
if self.base_mipmap_level + base_image_info.get_max_mimap_levels() == 0 {
return Err(WebGLError::InvalidOperation);
@@ -181,7 +179,7 @@ impl WebGLTexture {
pub fn delete(&self) {
if !self.is_deleted.get() {
self.is_deleted.set(true);
- let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteTexture(self.id)));
+ let _ = self.renderer.send(WebGLCommand::DeleteTexture(self.id));
}
}
@@ -216,7 +214,7 @@ impl WebGLTexture {
constants::LINEAR_MIPMAP_LINEAR => {
self.min_filter.set(Some(int_value as u32));
self.renderer
- .send(CanvasMsg::WebGL(WebGLCommand::TexParameteri(target, name, int_value)))
+ .send(WebGLCommand::TexParameteri(target, name, int_value))
.unwrap();
Ok(())
},
@@ -230,7 +228,7 @@ impl WebGLTexture {
constants::LINEAR => {
self.mag_filter.set(Some(int_value as u32));
self.renderer
- .send(CanvasMsg::WebGL(WebGLCommand::TexParameteri(target, name, int_value)))
+ .send(WebGLCommand::TexParameteri(target, name, int_value))
.unwrap();
Ok(())
},
@@ -245,7 +243,7 @@ impl WebGLTexture {
constants::MIRRORED_REPEAT |
constants::REPEAT => {
self.renderer
- .send(CanvasMsg::WebGL(WebGLCommand::TexParameteri(target, name, int_value)))
+ .send(WebGLCommand::TexParameteri(target, name, int_value))
.unwrap();
Ok(())
},
diff --git a/components/script/dom/webgluniformlocation.rs b/components/script/dom/webgluniformlocation.rs
index 228808303c4..47292adeb18 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 90693a2ccbf..2da650ee1ee 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -5,6 +5,7 @@
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;
@@ -264,7 +265,11 @@ pub struct Window {
/// A handle for communicating messages to the webvr thread, if available.
#[ignore_heap_size_of = "channels are hard"]
- webvr_thread: Option<IpcSender<WebVRMsg>>,
+ 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>>,
/// A map for storing the previous permission state read results.
permission_state_invocation_results: DOMRefCell<HashMap<String, PermissionState>>,
@@ -380,8 +385,12 @@ 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_thread.clone()
+ self.webvr_chan.clone()
}
fn new_paint_worklet(&self) -> Root<Worklet> {
@@ -1800,7 +1809,8 @@ impl Window {
origin: MutableOrigin,
navigation_start: u64,
navigation_start_precise: f64,
- webvr_thread: Option<IpcSender<WebVRMsg>>)
+ webgl_chan: WebGLChan,
+ webvr_chan: Option<IpcSender<WebVRMsg>>)
-> Root<Window> {
let layout_rpc: Box<LayoutRPC + Send> = {
let (rpc_send, rpc_recv) = channel();
@@ -1866,7 +1876,8 @@ impl Window {
scroll_offsets: DOMRefCell::new(HashMap::new()),
media_query_lists: WeakMediaQueryListVec::new(),
test_runner: Default::default(),
- webvr_thread: webvr_thread,
+ webgl_chan: webgl_chan,
+ webvr_chan: webvr_chan,
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 ea8038897ac..4a05002637a 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -18,6 +18,7 @@
//! loop.
use bluetooth_traits::BluetoothRequest;
+use canvas_traits::webgl::WebGLPipeline;
use devtools;
use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo};
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
@@ -508,8 +509,11 @@ 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_thread: Option<IpcSender<WebVRMsg>>,
+ webvr_chan: Option<IpcSender<WebVRMsg>>,
/// The worklet thread pool
worklet_thread_pool: DOMRefCell<Option<Rc<WorkletThreadPool>>>,
@@ -881,7 +885,8 @@ impl ScriptThread {
layout_to_constellation_chan: state.layout_to_constellation_chan,
- webvr_thread: state.webvr_thread,
+ webgl_chan: state.webgl_chan,
+ webvr_chan: state.webvr_chan,
worklet_thread_pool: Default::default(),
@@ -2028,7 +2033,8 @@ impl ScriptThread {
origin,
incomplete.navigation_start,
incomplete.navigation_start_precise,
- self.webvr_thread.clone());
+ self.webgl_chan.channel(),
+ self.webvr_chan.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 e3e956096bb..7c0f97ef917 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::CanvasMsg;
+use canvas_traits::canvas::CanvasMsg;
use core::nonzero::NonZero;
use ipc_channel::ipc::IpcSender;
use libc::c_void;
@@ -124,8 +124,13 @@ pub enum LayoutElementType {
SVGSVGElement,
}
+pub enum HTMLCanvasDataSource {
+ WebGL(webrender_api::ImageKey),
+ Image(Option<IpcSender<CanvasMsg>>)
+}
+
pub struct HTMLCanvasData {
- pub ipc_renderer: Option<IpcSender<CanvasMsg>>,
+ pub source: HTMLCanvasDataSource,
pub width: u32,
pub height: u32,
}
diff --git a/components/script_traits/Cargo.toml b/components/script_traits/Cargo.toml
index 70fcdbb3f33..2c083b2773c 100644
--- a/components/script_traits/Cargo.toml
+++ b/components/script_traits/Cargo.toml
@@ -25,7 +25,6 @@ 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 85122d35c3c..4a197e759ff 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -24,7 +24,6 @@ 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;
@@ -39,6 +38,7 @@ 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,8 +524,10 @@ 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_thread: Option<IpcSender<WebVRMsg>>
+ pub webvr_chan: Option<IpcSender<WebVRMsg>>
}
/// This trait allows creating a `ScriptThread` without depending on the `script`
@@ -759,8 +761,6 @@ 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 4fd8fca5c7f..156f85a2be7 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::CanvasMsg;
+use canvas_traits::canvas::CanvasMsg;
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
use euclid::{Point2D, Size2D, TypedSize2D};
use ipc_channel::ipc::IpcSender;
@@ -21,7 +21,6 @@ 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;
@@ -78,11 +77,6 @@ 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 07212a2b2d1..93e6d4cf454 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -68,6 +68,8 @@ 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;
@@ -149,7 +151,7 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
let mut resource_path = resources_dir_path().unwrap();
resource_path.push("shaders");
- let (webrender, webrender_api_sender) = {
+ let (mut 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 {
@@ -211,7 +213,7 @@ impl<Window> Servo<Window> where Window: WindowMethods + 'static {
debugger_chan,
devtools_chan,
supports_clipboard,
- &webrender,
+ &mut webrender,
webrender_document,
webrender_api_sender);
@@ -288,7 +290,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: &webrender::Renderer,
+ webrender: &mut webrender::Renderer,
webrender_document: webrender_api::DocumentId,
webrender_api_sender: webrender_api::RenderApiSender)
-> (Sender<ConstellationMsg>, SWManagerSenders) {
@@ -304,6 +306,30 @@ 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,
@@ -317,20 +343,17 @@ 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 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();
+ 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();
}
// channels to communicate with Service Worker Manager
diff --git a/components/webvr/Cargo.toml b/components/webvr/Cargo.toml
index f7edd95d6d8..f6a7427a709 100644
--- a/components/webvr/Cargo.toml
+++ b/components/webvr/Cargo.toml
@@ -10,10 +10,11 @@ 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 62f3e992fdc..0ad9722b21e 100644
--- a/components/webvr/lib.rs
+++ b/components/webvr/lib.rs
@@ -4,13 +4,14 @@
#![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 ec550153870..77f42a6b39e 100644
--- a/components/webvr/webvr_thread.rs
+++ b/components/webvr/webvr_thread.rs
@@ -2,6 +2,8 @@
* 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;
@@ -11,8 +13,6 @@ 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 VRCompositorCommanda for more details.
+/// is used instead. See WebVRCompositorHandler and the WebVRCommands for more details.
pub struct WebVRThread {
receiver: IpcReceiver<WebVRMsg>,
sender: IpcSender<WebVRMsg>,
@@ -66,15 +66,17 @@ impl WebVRThread {
}
}
- pub fn spawn(constellation_chan: Sender<ConstellationMsg>,
- vr_compositor_chan: WebVRCompositorSender)
- -> IpcSender<WebVRMsg> {
+ pub fn spawn(vr_compositor_chan: WebVRCompositorSender)
+ -> (IpcSender<WebVRMsg>, Sender<Sender<ConstellationMsg>>) {
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
+
+ (sender, constellation_sender)
}
fn start(&mut self) {
@@ -305,7 +307,7 @@ impl WebVRThread {
pub struct WebVRCompositor(*mut VRDisplay);
pub struct WebVRCompositorHandler {
- compositors: HashMap<webrender_api::VRCompositorId, WebVRCompositor>,
+ compositors: HashMap<webgl::WebVRDeviceId, WebVRCompositor>,
webvr_thread_receiver: Receiver<Option<WebVRCompositor>>,
webvr_thread_sender: Option<IpcSender<WebVRMsg>>
}
@@ -328,14 +330,14 @@ impl WebVRCompositorHandler {
}
}
-impl webrender_api::VRCompositorHandler for WebVRCompositorHandler {
+impl webgl::WebVRRenderHandler for WebVRCompositorHandler {
#[allow(unsafe_code)]
- fn handle(&mut self, cmd: webrender_api::VRCompositorCommand, texture: Option<(u32, DeviceIntSize)>) {
+ fn handle(&mut self, cmd: webgl::WebVRCommand, texture: Option<(u32, Size2D<i32>)>) {
match cmd {
- webrender_api::VRCompositorCommand::Create(compositor_id) => {
+ webgl::WebVRCommand::Create(compositor_id) => {
self.create_compositor(compositor_id);
}
- webrender_api::VRCompositorCommand::SyncPoses(compositor_id, near, far, sender) => {
+ webgl::WebVRCommand::SyncPoses(compositor_id, near, far, sender) => {
if let Some(compositor) = self.compositors.get(&compositor_id) {
let pose = unsafe {
(*compositor.0).sync_poses();
@@ -346,7 +348,7 @@ impl webrender_api::VRCompositorHandler for WebVRCompositorHandler {
let _ = sender.send(Err(()));
}
}
- webrender_api::VRCompositorCommand::SubmitFrame(compositor_id, left_bounds, right_bounds) => {
+ webgl::WebVRCommand::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 {
@@ -361,7 +363,7 @@ impl webrender_api::VRCompositorHandler for WebVRCompositorHandler {
}
}
}
- webrender_api::VRCompositorCommand::Release(compositor_id) => {
+ webgl::WebVRCommand::Release(compositor_id) => {
self.compositors.remove(&compositor_id);
}
}
@@ -370,7 +372,7 @@ impl webrender_api::VRCompositorHandler for WebVRCompositorHandler {
impl WebVRCompositorHandler {
#[allow(unsafe_code)]
- fn create_compositor(&mut self, display_id: webrender_api::VRCompositorId) {
+ fn create_compositor(&mut self, display_id: webgl::WebVRDeviceId) {
let sender = match self.webvr_thread_sender {
Some(ref s) => s,
None => return,