diff options
-rw-r--r-- | components/canvas/Cargo.toml | 16 | ||||
-rw-r--r-- | components/canvas/lib.rs | 6 | ||||
-rw-r--r-- | components/canvas/webgl_paint_task.rs | 105 | ||||
-rw-r--r-- | components/script/dom/htmlcanvaselement.rs | 53 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 24 | ||||
-rw-r--r-- | components/script/dom/webidls/HTMLCanvasElement.webidl | 2 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 28 | ||||
-rw-r--r-- | ports/cef/Cargo.lock | 15 | ||||
-rw-r--r-- | ports/gonk/Cargo.lock | 15 | ||||
m--------- | support/android-rs-glue | 0 |
10 files changed, 171 insertions, 93 deletions
diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml index df07dbd1de0..b3f0198396e 100644 --- a/components/canvas/Cargo.toml +++ b/components/canvas/Cargo.toml @@ -19,16 +19,16 @@ git = "https://github.com/servo/rust-geom" [dependencies.gleam] git = "https://github.com/servo/gleam" -[dependencies.glutin] -git = "https://github.com/servo/glutin" -branch = "servo" -features = ["headless"] - -[dependencies.msg] -path = "../msg" - [dependencies.util] path = "../util" [dependencies.gfx] path = "../gfx" + +[dependencies.glutin] +git = "https://github.com/servo/glutin" +branch = "servo" +features = ["headless"] + +[dependencies.offscreen_gl_context] +git = "https://github.com/ecoal95/rust-offscreen-rendering-context" diff --git a/components/canvas/lib.rs b/components/canvas/lib.rs index 5feab435394..17a5bcd0197 100644 --- a/components/canvas/lib.rs +++ b/components/canvas/lib.rs @@ -5,6 +5,7 @@ #![feature(collections)] #![feature(core)] #![feature(std_misc)] +#![feature(rustc_private)] extern crate azure; extern crate cssparser; @@ -12,9 +13,12 @@ extern crate geom; extern crate gfx; extern crate util; extern crate gleam; -extern crate msg; +extern crate offscreen_gl_context; extern crate glutin; +#[macro_use] +extern crate log; + pub mod canvas_paint_task; pub mod webgl_paint_task; pub mod canvas_msg; diff --git a/components/canvas/webgl_paint_task.rs b/components/canvas/webgl_paint_task.rs index eaa224c22b3..97e711b6718 100644 --- a/components/canvas/webgl_paint_task.rs +++ b/components/canvas/webgl_paint_task.rs @@ -2,36 +2,73 @@ * 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_msg::{CanvasWebGLMsg, CanvasCommonMsg, CanvasMsg}; +use canvas_msg::{CanvasMsg, CanvasWebGLMsg, CanvasCommonMsg}; use geom::size::Size2D; use gleam::gl; -use gleam::gl::types::{GLint, GLsizei}; +use gleam::gl::types::{GLsizei}; use util::task::spawn_named; use std::borrow::ToOwned; use std::sync::mpsc::{channel, Sender}; use util::vec::byte_swap; +use offscreen_gl_context::{GLContext, GLContextAttributes}; -use glutin::{HeadlessRendererBuilder}; +use glutin::{HeadlessRendererBuilder, HeadlessContext}; + +// FIXME(ecoal95): We use glutin as a fallback until GLContext support improves. +enum PlatformIndependentContext { + GLContext(GLContext), + GlutinContext(HeadlessContext), +} + +impl PlatformIndependentContext { + fn make_current(&self) { + match *self { + PlatformIndependentContext::GLContext(ref ctx) => ctx.make_current().unwrap(), + PlatformIndependentContext::GlutinContext(ref ctx) => unsafe { ctx.make_current() } + } + } +} + +fn create_offscreen_context(size: Size2D<i32>, attrs: GLContextAttributes) -> Result<PlatformIndependentContext, &'static str> { + match GLContext::create_offscreen(size, attrs) { + Ok(ctx) => Ok(PlatformIndependentContext::GLContext(ctx)), + Err(msg) => { + debug!("GLContext creation error: {}", msg); + match HeadlessRendererBuilder::new(size.width as u32, size.height as u32).build() { + Ok(ctx) => Ok(PlatformIndependentContext::GlutinContext(ctx)), + Err(_) => Err("Glutin headless context creation failed") + } + } + } +} pub struct WebGLPaintTask { size: Size2D<i32>, + original_context_size: Size2D<i32>, + gl_context: PlatformIndependentContext, } +// This allows trying to create the PaintTask +// before creating the thread +unsafe impl Send for WebGLPaintTask {} + impl WebGLPaintTask { - fn new(size: Size2D<i32>) -> WebGLPaintTask { - WebGLPaintTask::create(size); - WebGLPaintTask { + fn new(size: Size2D<i32>) -> Result<WebGLPaintTask, &'static str> { + let context = try!(create_offscreen_context(size, GLContextAttributes::default())); + Ok(WebGLPaintTask { size: size, - } + original_context_size: size, + gl_context: context + }) } - pub fn start(size: Size2D<i32>) -> Sender<CanvasMsg> { + pub fn start(size: Size2D<i32>) -> Result<Sender<CanvasMsg>, &'static str> { let (chan, port) = channel::<CanvasMsg>(); + let mut painter = try!(WebGLPaintTask::new(size)); spawn_named("WebGLTask".to_owned(), move || { - let mut painter = WebGLPaintTask::new(size); painter.init(); loop { match port.recv().unwrap() { @@ -52,35 +89,8 @@ impl WebGLPaintTask { } } }); - chan - } - fn create(size: Size2D<i32>) { - // It creates OpenGL context - let context = HeadlessRendererBuilder::new(size.width as u32, size.height as u32).build().unwrap(); - unsafe { - context.make_current(); - } - } - - fn init(&self) { - let framebuffer_ids = gl::gen_framebuffers(1); - gl::bind_framebuffer(gl::FRAMEBUFFER, framebuffer_ids[0]); - - let texture_ids = gl::gen_textures(1); - gl::bind_texture(gl::TEXTURE_2D, texture_ids[0]); - - gl::tex_image_2d(gl::TEXTURE_2D, 0, gl::RGB as GLint, self.size.width as GLsizei, - self.size.height as GLsizei, 0, gl::RGB, gl::UNSIGNED_BYTE, None); - gl::tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint); - gl::tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint); - - gl::framebuffer_texture_2d(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, - texture_ids[0], 0); - gl::bind_texture(gl::TEXTURE_2D, 0); - - gl::viewport(0 as GLint, 0 as GLint, - self.size.width as GLsizei, self.size.height as GLsizei); + Ok(chan) } fn clear(&self, mask: u32) { @@ -95,9 +105,9 @@ impl WebGLPaintTask { // FIXME(#5652, dmarcos) Instead of a readback strategy we have // to layerize the canvas let mut pixels = gl::read_pixels(0, 0, - self.size.width as gl::GLsizei, - self.size.height as gl::GLsizei, - gl::RGBA, gl::UNSIGNED_BYTE); + self.size.width as gl::GLsizei, + self.size.height as gl::GLsizei, + gl::RGBA, gl::UNSIGNED_BYTE); // rgba -> bgra byte_swap(&mut pixels); @@ -105,8 +115,19 @@ impl WebGLPaintTask { } fn recreate(&mut self, size: Size2D<i32>) { - self.size = size; - self.init(); + // TODO(ecoal95): GLContext should support a resize() method + if size.width > self.original_context_size.width || + size.height > self.original_context_size.height { + panic!("Can't grow a GLContext (yet)"); + } else { + // Right now we just crop the viewport, it will do the job + self.size = size; + gl::viewport(0, 0, size.width, size.height); + unsafe { gl::Scissor(0, 0, size.width, size.height); } + } } + fn init(&mut self) { + self.gl_context.make_current(); + } } diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index c75b3c5ec3f..efeb61386e0 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -169,24 +169,37 @@ impl<'a> HTMLCanvasElementMethods for JSRef<'a, HTMLCanvasElement> { fn GetContext(self, id: DOMString) -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> { match &*id { - "2d" => { - let context_2d = self.context_2d.or_init(|| { - let window = window_from_node(self).root(); - let size = self.get_size(); - CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size) - }); - Some(CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D(Unrooted::from_temporary(context_2d))) - } - "webgl" | "experimental-webgl" => { - let context_webgl = self.context_webgl.or_init(|| { - let window = window_from_node(self).root(); - let size = self.get_size(); - WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size) - }); - Some(CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext(Unrooted::from_temporary(context_webgl))) - } - _ => return None - } + "2d" => { + if self.context_webgl.get().is_some() { + debug!("Trying to get a 2d context for a canvas with an already initialized WebGL context"); + return None; + } + + let context_2d = self.context_2d.or_init(|| { + let window = window_from_node(self).root(); + let size = self.get_size(); + CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size) + }); + Some(CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D(Unrooted::from_temporary(context_2d))) + } + "webgl" | "experimental-webgl" => { + if self.context_2d.get().is_some() { + debug!("Trying to get a WebGL context for a canvas with an already initialized 2d context"); + return None; + } + + if !self.context_webgl.get().is_some() { + let window = window_from_node(self).root(); + let size = self.get_size(); + + self.context_webgl.assign(WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size)) + } + + self.context_webgl.get().map( |ctx| + CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext(Unrooted::from_temporary(ctx))) + } + _ => None + } } } @@ -226,11 +239,11 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLCanvasElement> { let value = attr.value(); let recreate = match attr.local_name() { &atom!("width") => { - self.width.set(parse_unsigned_integer(value.chars()).unwrap_or(DEFAULT_WIDTH)); + self.width.set(parse_unsigned_integer(value.as_slice().chars()).unwrap_or(DEFAULT_WIDTH)); true } &atom!("height") => { - self.height.set(parse_unsigned_integer(value.chars()).unwrap_or(DEFAULT_HEIGHT)); + self.height.set(parse_unsigned_integer(value.as_slice().chars()).unwrap_or(DEFAULT_HEIGHT)); true } _ => false, diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 07c47970476..a521f469d1d 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -23,25 +23,32 @@ pub struct WebGLRenderingContext { impl WebGLRenderingContext { fn new_inherited(global: GlobalRef, canvas: JSRef<HTMLCanvasElement>, size: Size2D<i32>) - -> WebGLRenderingContext { - WebGLRenderingContext { + -> Result<WebGLRenderingContext, &'static str> { + let chan = try!(WebGLPaintTask::start(size)); + + Ok(WebGLRenderingContext { reflector_: Reflector::new(), global: GlobalField::from_rooted(&global), - renderer: WebGLPaintTask::start(size), + renderer: chan, canvas: JS::from_rooted(canvas), - } + }) } pub fn new(global: GlobalRef, canvas: JSRef<HTMLCanvasElement>, size: Size2D<i32>) - -> Temporary<WebGLRenderingContext> { - reflect_dom_object(box WebGLRenderingContext::new_inherited(global, canvas, size), - global, WebGLRenderingContextBinding::Wrap) + -> Option<Temporary<WebGLRenderingContext>> { + match WebGLRenderingContext::new_inherited(global, canvas, size) { + Ok(ctx) => Some(reflect_dom_object(box ctx, global, + WebGLRenderingContextBinding::Wrap)), + Err(msg) => { + error!("Couldn't create WebGLRenderingContext: {}", msg); + None + } + } } pub fn recreate(&self, size: Size2D<i32>) { self.renderer.send(CanvasMsg::Common(CanvasCommonMsg::Recreate(size))).unwrap(); } - } #[unsafe_destructor] @@ -72,4 +79,3 @@ impl LayoutCanvasWebGLRenderingContextHelpers for LayoutJS<WebGLRenderingContext (*self.unsafe_get()).renderer.clone() } } - diff --git a/components/script/dom/webidls/HTMLCanvasElement.webidl b/components/script/dom/webidls/HTMLCanvasElement.webidl index 2458ce41a1f..882e3f031c7 100644 --- a/components/script/dom/webidls/HTMLCanvasElement.webidl +++ b/components/script/dom/webidls/HTMLCanvasElement.webidl @@ -3,7 +3,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/. */ -// https://www.whatwg.org/html/#htmlcanvaselement +// https://www.whatwg.org/html/#htmlcanvaselement typedef (CanvasRenderingContext2D or WebGLRenderingContext) RenderingContext; interface HTMLCanvasElement : HTMLElement { diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index b383fe6e733..2874d1ef4de 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -34,7 +34,7 @@ version = "0.0.1" [[package]] name = "android_glue" version = "0.0.1" -source = "git+https://github.com/tomaka/android-rs-glue#5a68056599fb498b0cf3715fd359894825e3b856" +source = "git+https://github.com/tomaka/android-rs-glue#fa1eaa1d1857e0fa93832c5c8db5dc8bbcbc1eba" [[package]] name = "azure" @@ -67,7 +67,7 @@ dependencies = [ "gfx 0.0.1", "gleam 0.0.1 (git+https://github.com/servo/gleam)", "glutin 0.0.7 (git+https://github.com/servo/glutin?branch=servo)", - "msg 0.0.1", + "offscreen_gl_context 0.0.1 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)", "util 0.0.1", ] @@ -318,7 +318,7 @@ name = "gdi32-sys" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -517,7 +517,7 @@ name = "kernel32-sys" version = "0.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -710,6 +710,19 @@ dependencies = [ ] [[package]] +name = "offscreen_gl_context" +version = "0.0.1" +source = "git+https://github.com/ecoal95/rust-offscreen-rendering-context#9547d416019b15e0e59dc5176f5b1a14e14b44ca" +dependencies = [ + "cgl 0.0.1 (git+https://github.com/servo/rust-cgl)", + "geom 0.1.0 (git+https://github.com/servo/rust-geom)", + "gleam 0.0.1 (git+https://github.com/servo/gleam)", + "glx 0.0.1 (git+https://github.com/servo/rust-glx)", + "libc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "xlib 0.1.0 (git+https://github.com/servo/rust-xlib)", +] + +[[package]] name = "openssl" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1000,7 +1013,7 @@ name = "user32-sys" version = "0.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1084,11 +1097,6 @@ dependencies = [ [[package]] name = "winapi" -version = "0.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 152b6359aed..eca0ca7f0b3 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -65,7 +65,7 @@ dependencies = [ "gfx 0.0.1", "gleam 0.0.1 (git+https://github.com/servo/gleam)", "glutin 0.0.7 (git+https://github.com/servo/glutin?branch=servo)", - "msg 0.0.1", + "offscreen_gl_context 0.0.1 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)", "util 0.0.1", ] @@ -688,6 +688,19 @@ dependencies = [ ] [[package]] +name = "offscreen_gl_context" +version = "0.0.1" +source = "git+https://github.com/ecoal95/rust-offscreen-rendering-context#9547d416019b15e0e59dc5176f5b1a14e14b44ca" +dependencies = [ + "cgl 0.0.1 (git+https://github.com/servo/rust-cgl)", + "geom 0.1.0 (git+https://github.com/servo/rust-geom)", + "gleam 0.0.1 (git+https://github.com/servo/gleam)", + "glx 0.0.1 (git+https://github.com/servo/rust-glx)", + "libc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "xlib 0.1.0 (git+https://github.com/servo/rust-xlib)", +] + +[[package]] name = "openssl" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index 492a3b92ce6..f2bb8c7c3c0 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -59,7 +59,7 @@ dependencies = [ "gfx 0.0.1", "gleam 0.0.1 (git+https://github.com/servo/gleam)", "glutin 0.0.7 (git+https://github.com/servo/glutin?branch=servo)", - "msg 0.0.1", + "offscreen_gl_context 0.0.1 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)", "util 0.0.1", ] @@ -680,6 +680,19 @@ dependencies = [ ] [[package]] +name = "offscreen_gl_context" +version = "0.0.1" +source = "git+https://github.com/ecoal95/rust-offscreen-rendering-context#9547d416019b15e0e59dc5176f5b1a14e14b44ca" +dependencies = [ + "cgl 0.0.1 (git+https://github.com/servo/rust-cgl)", + "geom 0.1.0 (git+https://github.com/servo/rust-geom)", + "gleam 0.0.1 (git+https://github.com/servo/gleam)", + "glx 0.0.1 (git+https://github.com/servo/rust-glx)", + "libc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "xlib 0.1.0 (git+https://github.com/servo/rust-xlib)", +] + +[[package]] name = "openssl" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/support/android-rs-glue b/support/android-rs-glue -Subproject 5a68056599fb498b0cf3715fd359894825e3b85 +Subproject 34f588aace4d05ce42f4ca605d5470df8fdd236 |