aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/htmlcanvaselement.rs
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-10-27 05:56:12 -0500
committerGitHub <noreply@github.com>2017-10-27 05:56:12 -0500
commitd21657a9e5cfdb858c1a99a246001ceac05bb982 (patch)
tree7e830c65fda5668d6f92e6b196588b3bd12746dc /components/script/dom/htmlcanvaselement.rs
parent8f171058f8d4ee1009134ea574ba771a3be5d6f1 (diff)
parentddd6c86e992a45d6490b8ec6eb2bf7b3ecce9a03 (diff)
downloadservo-d21657a9e5cfdb858c1a99a246001ceac05bb982.tar.gz
servo-d21657a9e5cfdb858c1a99a246001ceac05bb982.zip
Auto merge of #19028 - MortimerGoro:webgl2, r=emilio
Kick off WebGL 2.0 implementation <!-- Please describe your changes on the following line: --> This PR kicks off the WebGL 2.0 implementation: - Include WebGL2RenderingContext.webidl and comment unimplemented methods - Create WebGL2 struct hierarchy with WebGL 1.0 backwards compatibility - Add WebGL 2.0 entry points to canvas - Select the correct GL Version on GLContext backends (related PR https://github.com/emilio/rust-offscreen-rendering-context/pull/108) - Add WebGL version selection in shader compilations - Create a WebGL 2.0 preference I tried a complex three.js demo using canvas.getContext("webgl2") and the backwards compatibility worked great. Next steps: - I'll add WebGLVersion selection/filtering to WebGLExtensions and move some extensions to core in WebGL 2.0 (e.g. VAOs) - I'll add the WebGL 2.0 conformance WPT - I'll create a mega-issue with a the list of all TODO methods for a complete WebGL 2.0 implementation (as @emilio did with WebGL 1.0), so we can start start getting community involvement. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require tests because I will add the entire webgl 2.0 WPT in a different PR <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19028) <!-- Reviewable:end -->
Diffstat (limited to 'components/script/dom/htmlcanvaselement.rs')
-rw-r--r--components/script/dom/htmlcanvaselement.rs107
1 files changed, 79 insertions, 28 deletions
diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs
index a44c1fd1fa5..9496670238b 100644
--- a/components/script/dom/htmlcanvaselement.rs
+++ b/components/script/dom/htmlcanvaselement.rs
@@ -4,13 +4,13 @@
use base64;
use canvas_traits::canvas::{CanvasMsg, FromScriptMsg};
+use canvas_traits::webgl::WebGLVersion;
use dom::attr::Attr;
use dom::bindings::cell::DomRefCell;
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods;
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding;
-use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods;
+use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::{HTMLCanvasElementMethods, RenderingContext};
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes;
-use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext;
use dom::bindings::conversions::ConversionResult;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::inheritance::Castable;
@@ -24,6 +24,7 @@ use dom::globalscope::GlobalScope;
use dom::htmlelement::HTMLElement;
use dom::node::{Node, window_from_node};
use dom::virtualmethods::VirtualMethods;
+use dom::webgl2renderingcontext::WebGL2RenderingContext;
use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext};
use dom_struct::dom_struct;
use euclid::Size2D;
@@ -35,6 +36,7 @@ use js::error::throw_type_error;
use js::jsapi::{HandleValue, JSContext};
use offscreen_gl_context::GLContextAttributes;
use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource};
+use servo_config::prefs::PREFS;
use std::iter::repeat;
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
@@ -46,6 +48,7 @@ const DEFAULT_HEIGHT: u32 = 150;
pub enum CanvasContext {
Context2d(Dom<CanvasRenderingContext2D>),
WebGL(Dom<WebGLRenderingContext>),
+ WebGL2(Dom<WebGL2RenderingContext>),
}
#[dom_struct]
@@ -79,6 +82,7 @@ impl HTMLCanvasElement {
match *context {
CanvasContext::Context2d(ref context) => context.set_bitmap_dimensions(size),
CanvasContext::WebGL(ref context) => context.recreate(size),
+ CanvasContext::WebGL2(ref context) => context.recreate(size),
}
}
}
@@ -113,6 +117,9 @@ impl LayoutHTMLCanvasElementHelpers for LayoutDom<HTMLCanvasElement> {
Some(&CanvasContext::WebGL(ref context)) => {
context.to_layout().canvas_data_source()
},
+ Some(&CanvasContext::WebGL2(ref context)) => {
+ context.to_layout().canvas_data_source()
+ },
None => {
HTMLCanvasDataSource::Image(None)
}
@@ -165,32 +172,16 @@ impl HTMLCanvasElement {
}
}
- #[allow(unsafe_code)]
- pub fn get_or_init_webgl_context(&self,
- cx: *mut JSContext,
- attrs: Option<HandleValue>) -> Option<DomRoot<WebGLRenderingContext>> {
+ pub fn get_or_init_webgl_context(
+ &self,
+ cx: *mut JSContext,
+ attrs: Option<HandleValue>
+ ) -> Option<DomRoot<WebGLRenderingContext>> {
if self.context.borrow().is_none() {
let window = window_from_node(self);
let size = self.get_size();
-
- let attrs = if let Some(webgl_attributes) = attrs {
- match unsafe {
- WebGLContextAttributes::new(cx, webgl_attributes) } {
- Ok(ConversionResult::Success(ref attrs)) => From::from(attrs),
- Ok(ConversionResult::Failure(ref error)) => {
- unsafe { throw_type_error(cx, &error); }
- return None;
- }
- _ => {
- debug!("Unexpected error on conversion of WebGLContextAttributes");
- return None;
- }
- }
- } else {
- GLContextAttributes::default()
- };
-
- let maybe_ctx = WebGLRenderingContext::new(&window, self, size, attrs);
+ let attrs = Self::get_gl_attributes(cx, attrs)?;
+ let maybe_ctx = WebGLRenderingContext::new(&window, self, WebGLVersion::WebGL1, size, attrs);
*self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(Dom::from_ref(&*ctx)));
}
@@ -202,6 +193,58 @@ impl HTMLCanvasElement {
}
}
+ pub fn get_or_init_webgl2_context(
+ &self,
+ cx: *mut JSContext,
+ attrs: Option<HandleValue>
+ ) -> Option<DomRoot<WebGL2RenderingContext>> {
+ if !PREFS.is_webgl2_enabled() {
+ return None
+ }
+ if self.context.borrow().is_none() {
+ let window = window_from_node(self);
+ let size = self.get_size();
+ let attrs = Self::get_gl_attributes(cx, attrs)?;
+ let maybe_ctx = WebGL2RenderingContext::new(&window, self, size, attrs);
+
+ *self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL2(Dom::from_ref(&*ctx)));
+ }
+
+ if let Some(CanvasContext::WebGL2(ref context)) = *self.context.borrow() {
+ Some(DomRoot::from_ref(&*context))
+ } else {
+ None
+ }
+ }
+
+ /// Gets the base WebGLRenderingContext for WebGL or WebGL 2, if exists.
+ pub fn get_base_webgl_context(&self) -> Option<DomRoot<WebGLRenderingContext>> {
+ match *self.context.borrow() {
+ Some(CanvasContext::WebGL(ref context)) => Some(DomRoot::from_ref(&*context)),
+ Some(CanvasContext::WebGL2(ref context)) => Some(context.base_context()),
+ _ => None
+ }
+ }
+
+ #[allow(unsafe_code)]
+ fn get_gl_attributes(cx: *mut JSContext, attrs: Option<HandleValue>) -> Option<GLContextAttributes> {
+ let webgl_attributes = match attrs {
+ Some(attrs) => attrs,
+ None => return Some(GLContextAttributes::default()),
+ };
+ match unsafe { WebGLContextAttributes::new(cx, webgl_attributes) } {
+ Ok(ConversionResult::Success(ref attrs)) => Some(From::from(attrs)),
+ Ok(ConversionResult::Failure(ref error)) => {
+ unsafe { throw_type_error(cx, &error); }
+ None
+ }
+ _ => {
+ debug!("Unexpected error on conversion of WebGLContextAttributes");
+ None
+ }
+ }
+ }
+
pub fn is_valid(&self) -> bool {
self.Height() != 0 && self.Width() != 0
}
@@ -225,6 +268,10 @@ impl HTMLCanvasElement {
// TODO: add a method in WebGLRenderingContext to get the pixels.
return None;
},
+ Some(&CanvasContext::WebGL2(_)) => {
+ // TODO: add a method in WebGL2RenderingContext to get the pixels.
+ return None;
+ },
None => {
repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect()
}
@@ -253,15 +300,19 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
cx: *mut JSContext,
id: DOMString,
attributes: Vec<HandleValue>)
- -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> {
+ -> Option<RenderingContext> {
match &*id {
"2d" => {
self.get_or_init_2d_context()
- .map(CanvasRenderingContext2DOrWebGLRenderingContext::CanvasRenderingContext2D)
+ .map(RenderingContext::CanvasRenderingContext2D)
}
"webgl" | "experimental-webgl" => {
self.get_or_init_webgl_context(cx, attributes.get(0).cloned())
- .map(CanvasRenderingContext2DOrWebGLRenderingContext::WebGLRenderingContext)
+ .map(RenderingContext::WebGLRenderingContext)
+ }
+ "webgl2" | "experimental-webgl2" => {
+ self.get_or_init_webgl2_context(cx, attributes.get(0).cloned())
+ .map(RenderingContext::WebGL2RenderingContext)
}
_ => None
}