diff options
author | Mátyás Mustoha <matyas.mustoha@h-lab.eu> | 2019-09-09 11:21:46 +0200 |
---|---|---|
committer | Mátyás Mustoha <matyas.mustoha@h-lab.eu> | 2019-10-01 12:30:24 +0200 |
commit | f2e2b3d34b5ed1afa2b937eedee4908cd5d07a05 (patch) | |
tree | 58c6677d4c3541ad5cb5e95d9b1d308c3cf2f6c1 /components/script/dom/webgl2renderingcontext.rs | |
parent | 402db83b2b19f33240b0db4cf07e0c9d056b1786 (diff) | |
download | servo-f2e2b3d34b5ed1afa2b937eedee4908cd5d07a05.tar.gz servo-f2e2b3d34b5ed1afa2b937eedee4908cd5d07a05.zip |
Initial implementation of WebGLQueries
This patch adds initial support for WeGLQueries. Most related WebGL
functions and objects are implemented [1]. What's still missing is
the `EXT_disjoint_timer_query_webgl2` support.
[1]: https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.12
Diffstat (limited to 'components/script/dom/webgl2renderingcontext.rs')
-rw-r--r-- | components/script/dom/webgl2renderingcontext.rs | 157 |
1 files changed, 155 insertions, 2 deletions
diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs index 26b81f8ad3a..f33b10f7931 100644 --- a/components/script/dom/webgl2renderingcontext.rs +++ b/components/script/dom/webgl2renderingcontext.rs @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding; +use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants; use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextMethods; use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods; @@ -12,7 +13,7 @@ use crate::dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTML use crate::dom::bindings::codegen::UnionTypes::Int32ArrayOrLongSequence; use crate::dom::bindings::error::{ErrorResult, Fallible}; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; -use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom}; +use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom}; use crate::dom::bindings::str::DOMString; use crate::dom::htmlcanvaselement::HTMLCanvasElement; use crate::dom::htmliframeelement::HTMLIFrameElement; @@ -20,6 +21,7 @@ use crate::dom::webglactiveinfo::WebGLActiveInfo; use crate::dom::webglbuffer::WebGLBuffer; use crate::dom::webglframebuffer::WebGLFramebuffer; use crate::dom::webglprogram::WebGLProgram; +use crate::dom::webglquery::WebGLQuery; use crate::dom::webglrenderbuffer::WebGLRenderbuffer; use crate::dom::webglrenderingcontext::{ LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext, @@ -31,11 +33,12 @@ use crate::dom::webgluniformlocation::WebGLUniformLocation; use crate::dom::window::Window; use crate::script_runtime::JSContext; /// https://www.khronos.org/registry/webgl/specs/latest/2.0/webgl.idl +use canvas_traits::webgl::WebGLError::*; use canvas_traits::webgl::{GLContextAttributes, WebGLVersion}; use dom_struct::dom_struct; use euclid::default::Size2D; use js::jsapi::JSObject; -use js::jsval::JSVal; +use js::jsval::{BooleanValue, JSVal, NullValue, UInt32Value}; use js::rust::CustomAutoRooterGuard; use js::typedarray::ArrayBufferView; use script_layout_interface::HTMLCanvasDataSource; @@ -45,6 +48,8 @@ use std::ptr::NonNull; pub struct WebGL2RenderingContext { reflector_: Reflector, base: Dom<WebGLRenderingContext>, + occlusion_query: MutNullableDom<WebGLQuery>, + primitives_query: MutNullableDom<WebGLQuery>, } impl WebGL2RenderingContext { @@ -58,6 +63,8 @@ impl WebGL2RenderingContext { Some(WebGL2RenderingContext { reflector_: Reflector::new(), base: Dom::from_ref(&*base), + occlusion_query: MutNullableDom::new(None), + primitives_query: MutNullableDom::new(None), }) } @@ -1044,6 +1051,152 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { fn VertexAttribDivisor(&self, index: u32, divisor: u32) { self.base.vertex_attrib_divisor(index, divisor); } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.12 + fn CreateQuery(&self) -> Option<DomRoot<WebGLQuery>> { + Some(WebGLQuery::new(&self.base)) + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.12 + #[cfg_attr(rustfmt, rustfmt_skip)] + fn DeleteQuery(&self, query: Option<&WebGLQuery>) { + if let Some(query) = query { + handle_potential_webgl_error!(self.base, self.base.validate_ownership(query), return); + + if let Some(query_target) = query.target() { + let slot = match query_target { + constants::ANY_SAMPLES_PASSED | + constants::ANY_SAMPLES_PASSED_CONSERVATIVE => { + &self.occlusion_query + }, + constants::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN => { + &self.primitives_query + }, + _ => unreachable!(), + }; + if let Some(stored_query) = slot.get() { + if stored_query.target() == query.target() { + slot.set(None); + } + } + } + + query.delete(false); + } + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.12 + fn IsQuery(&self, query: Option<&WebGLQuery>) -> bool { + match query { + Some(query) => self.base.validate_ownership(query).is_ok() && query.is_valid(), + None => false, + } + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.12 + #[cfg_attr(rustfmt, rustfmt_skip)] + fn BeginQuery(&self, target: u32, query: &WebGLQuery) { + handle_potential_webgl_error!(self.base, self.base.validate_ownership(query), return); + + let active_query = match target { + constants::ANY_SAMPLES_PASSED | + constants::ANY_SAMPLES_PASSED_CONSERVATIVE => { + &self.occlusion_query + }, + constants::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN => { + &self.primitives_query + }, + _ => { + self.base.webgl_error(InvalidEnum); + return; + }, + }; + if active_query.get().is_some() { + self.base.webgl_error(InvalidOperation); + return; + } + let result = query.begin(&self.base, target); + match result { + Ok(_) => active_query.set(Some(query)), + Err(error) => self.base.webgl_error(error), + } + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.12 + #[cfg_attr(rustfmt, rustfmt_skip)] + fn EndQuery(&self, target: u32) { + let active_query = match target { + constants::ANY_SAMPLES_PASSED | + constants::ANY_SAMPLES_PASSED_CONSERVATIVE => { + self.occlusion_query.take() + }, + constants::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN => { + self.primitives_query.take() + }, + _ => { + self.base.webgl_error(InvalidEnum); + return; + }, + }; + match active_query { + None => self.base.webgl_error(InvalidOperation), + Some(query) => { + let result = query.end(&self.base, target); + if let Err(error) = result { + self.base.webgl_error(error); + } + }, + } + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.12 + #[cfg_attr(rustfmt, rustfmt_skip)] + fn GetQuery(&self, target: u32, pname: u32) -> Option<DomRoot<WebGLQuery>> { + if pname != constants::CURRENT_QUERY { + self.base.webgl_error(InvalidEnum); + return None; + } + let active_query = match target { + constants::ANY_SAMPLES_PASSED | + constants::ANY_SAMPLES_PASSED_CONSERVATIVE => { + self.occlusion_query.get() + }, + constants::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN => { + self.primitives_query.get() + }, + _ => { + self.base.webgl_error(InvalidEnum); + None + }, + }; + if let Some(query) = active_query.as_ref() { + if query.target() != Some(target) { + return None; + } + } + active_query + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.12 + #[cfg_attr(rustfmt, rustfmt_skip)] + fn GetQueryParameter(&self, _cx: JSContext, query: &WebGLQuery, pname: u32) -> JSVal { + handle_potential_webgl_error!( + self.base, + self.base.validate_ownership(query), + return NullValue() + ); + match query.get_parameter(&self.base, pname) { + Ok(value) => match pname { + constants::QUERY_RESULT => UInt32Value(value), + constants::QUERY_RESULT_AVAILABLE => BooleanValue(value != 0), + _ => unreachable!(), + }, + Err(error) => { + self.base.webgl_error(error); + NullValue() + }, + } + } } impl LayoutCanvasWebGLRenderingContextHelpers for LayoutDom<WebGL2RenderingContext> { |