aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/canvas/Cargo.toml16
-rw-r--r--components/canvas/lib.rs6
-rw-r--r--components/canvas/webgl_paint_task.rs105
-rw-r--r--components/script/dom/htmlcanvaselement.rs53
-rw-r--r--components/script/dom/webglrenderingcontext.rs24
-rw-r--r--components/script/dom/webidls/HTMLCanvasElement.webidl2
-rw-r--r--components/servo/Cargo.lock28
-rw-r--r--ports/cef/Cargo.lock15
-rw-r--r--ports/gonk/Cargo.lock15
m---------support/android-rs-glue0
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