diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-10-27 05:56:12 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-27 05:56:12 -0500 |
commit | d21657a9e5cfdb858c1a99a246001ceac05bb982 (patch) | |
tree | 7e830c65fda5668d6f92e6b196588b3bd12746dc /components/script/dom/htmlcanvaselement.rs | |
parent | 8f171058f8d4ee1009134ea574ba771a3be5d6f1 (diff) | |
parent | ddd6c86e992a45d6490b8ec6eb2bf7b3ecce9a03 (diff) | |
download | servo-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.rs | 107 |
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 } |