mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Kick off WebGL 2.0 implementation
This commit is contained in:
parent
fd4843a40e
commit
ddd6c86e99
14 changed files with 1665 additions and 68 deletions
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue