From f2e2b3d34b5ed1afa2b937eedee4908cd5d07a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1ty=C3=A1s=20Mustoha?= Date: Mon, 9 Sep 2019 11:21:46 +0200 Subject: 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 --- components/script/dom/webglquery.rs | 194 ++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 components/script/dom/webglquery.rs (limited to 'components/script/dom/webglquery.rs') diff --git a/components/script/dom/webglquery.rs b/components/script/dom/webglquery.rs new file mode 100644 index 00000000000..c3cd4e9e08c --- /dev/null +++ b/components/script/dom/webglquery.rs @@ -0,0 +1,194 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants; +use crate::dom::bindings::codegen::Bindings::WebGLQueryBinding; +use crate::dom::bindings::inheritance::Castable; +use crate::dom::bindings::refcounted::Trusted; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::webglobject::WebGLObject; +use crate::dom::webglrenderingcontext::WebGLRenderingContext; +use crate::task_source::TaskSource; +use canvas_traits::webgl::WebGLError::*; +use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLQueryId}; +use dom_struct::dom_struct; +use std::cell::Cell; + +#[dom_struct] +pub struct WebGLQuery { + webgl_object: WebGLObject, + gl_id: WebGLQueryId, + gl_target: Cell>, + marked_for_deletion: Cell, + query_result_available: Cell>, + query_result: Cell, +} + +impl WebGLQuery { + fn new_inherited(context: &WebGLRenderingContext, id: WebGLQueryId) -> Self { + Self { + webgl_object: WebGLObject::new_inherited(context), + gl_id: id, + gl_target: Cell::new(None), + marked_for_deletion: Cell::new(false), + query_result_available: Cell::new(None), + query_result: Cell::new(0), + } + } + + pub fn new(context: &WebGLRenderingContext) -> DomRoot { + let (sender, receiver) = webgl_channel().unwrap(); + context.send_command(WebGLCommand::GenerateQuery(sender)); + let id = receiver.recv().unwrap(); + + reflect_dom_object( + Box::new(Self::new_inherited(context, id)), + &*context.global(), + WebGLQueryBinding::Wrap, + ) + } + + pub fn begin( + &self, + context: &WebGLRenderingContext, + target: u32, + ) -> Result<(), canvas_traits::webgl::WebGLError> { + if self.marked_for_deletion.get() { + return Err(InvalidOperation); + } + if let Some(current_target) = self.gl_target.get() { + if current_target != target { + return Err(InvalidOperation); + } + } + match target { + constants::ANY_SAMPLES_PASSED | + constants::ANY_SAMPLES_PASSED_CONSERVATIVE | + constants::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN => (), + _ => return Err(InvalidEnum), + } + self.gl_target.set(Some(target)); + + context.send_command(WebGLCommand::BeginQuery(target, self.gl_id)); + Ok(()) + } + + pub fn end( + &self, + context: &WebGLRenderingContext, + target: u32, + ) -> Result<(), canvas_traits::webgl::WebGLError> { + if self.marked_for_deletion.get() { + return Err(InvalidOperation); + } + if let Some(current_target) = self.gl_target.get() { + if current_target != target { + return Err(InvalidOperation); + } + } + match target { + constants::ANY_SAMPLES_PASSED | + constants::ANY_SAMPLES_PASSED_CONSERVATIVE | + constants::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN => (), + _ => return Err(InvalidEnum), + } + context.send_command(WebGLCommand::EndQuery(target)); + Ok(()) + } + + pub fn delete(&self, fallible: bool) { + if !self.marked_for_deletion.get() { + self.marked_for_deletion.set(true); + + let context = self.upcast::().context(); + let command = WebGLCommand::DeleteQuery(self.gl_id); + if fallible { + context.send_command_ignored(command); + } else { + context.send_command(command); + } + } + } + + pub fn is_valid(&self) -> bool { + !self.marked_for_deletion.get() && self.target().is_some() + } + + pub fn target(&self) -> Option { + self.gl_target.get() + } + + fn update_results(&self, context: &WebGLRenderingContext) { + let (sender, receiver) = webgl_channel().unwrap(); + context.send_command(WebGLCommand::GetQueryState( + sender, + self.gl_id, + constants::QUERY_RESULT_AVAILABLE, + )); + let is_available = receiver.recv().unwrap(); + if is_available == 0 { + self.query_result_available.set(None); + return; + } + + let (sender, receiver) = webgl_channel().unwrap(); + context.send_command(WebGLCommand::GetQueryState( + sender, + self.gl_id, + constants::QUERY_RESULT, + )); + + self.query_result.set(receiver.recv().unwrap()); + self.query_result_available.set(Some(is_available)); + } + + #[cfg_attr(rustfmt, rustfmt_skip)] + pub fn get_parameter( + &self, + context: &WebGLRenderingContext, + pname: u32, + ) -> Result { + if !self.is_valid() { + return Err(InvalidOperation); + } + match pname { + constants::QUERY_RESULT | + constants::QUERY_RESULT_AVAILABLE => {}, + _ => return Err(InvalidEnum), + } + + if self.query_result_available.get().is_none() { + self.query_result_available.set(Some(0)); + + let this = Trusted::new(self); + let context = Trusted::new(context); + let task = task!(request_query_state: move || { + let this = this.root(); + let context = context.root(); + this.update_results(&context); + }); + + let global = self.global(); + global + .as_window() + .task_manager() + .dom_manipulation_task_source() + .queue(task, global.upcast()) + .unwrap(); + } + + match pname { + constants::QUERY_RESULT => Ok(self.query_result.get()), + constants::QUERY_RESULT_AVAILABLE => Ok(self.query_result_available.get().unwrap()), + _ => unreachable!(), + } + } +} + +impl Drop for WebGLQuery { + fn drop(&mut self) { + self.delete(true); + } +} -- cgit v1.2.3 From 3ea6d87bcc37167464e856949a4b9b77d0e9318a Mon Sep 17 00:00:00 2001 From: YUAN LYU Date: Fri, 20 Mar 2020 22:14:18 -0400 Subject: Add trait DomObjectWrap to provide WRAP function --- components/script/dom/webglquery.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'components/script/dom/webglquery.rs') diff --git a/components/script/dom/webglquery.rs b/components/script/dom/webglquery.rs index c3cd4e9e08c..d7418471936 100644 --- a/components/script/dom/webglquery.rs +++ b/components/script/dom/webglquery.rs @@ -3,7 +3,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants; -use crate::dom::bindings::codegen::Bindings::WebGLQueryBinding; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; @@ -46,7 +45,6 @@ impl WebGLQuery { reflect_dom_object( Box::new(Self::new_inherited(context, id)), &*context.global(), - WebGLQueryBinding::Wrap, ) } -- cgit v1.2.3 From 9c343fcc9600a1a2b768a4632793d0856d55ddce Mon Sep 17 00:00:00 2001 From: Tobias Tschinkowitz Date: Thu, 23 Apr 2020 18:23:01 +0200 Subject: Replaced failible boolean with an enum --- components/script/dom/webglquery.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'components/script/dom/webglquery.rs') diff --git a/components/script/dom/webglquery.rs b/components/script/dom/webglquery.rs index d7418471936..454fe72954e 100644 --- a/components/script/dom/webglquery.rs +++ b/components/script/dom/webglquery.rs @@ -8,7 +8,7 @@ use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; use crate::dom::bindings::root::DomRoot; use crate::dom::webglobject::WebGLObject; -use crate::dom::webglrenderingcontext::WebGLRenderingContext; +use crate::dom::webglrenderingcontext::{Operation, WebGLRenderingContext}; use crate::task_source::TaskSource; use canvas_traits::webgl::WebGLError::*; use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLQueryId}; @@ -96,16 +96,15 @@ impl WebGLQuery { Ok(()) } - pub fn delete(&self, fallible: bool) { + pub fn delete(&self, operation_fallibility: Operation) { if !self.marked_for_deletion.get() { self.marked_for_deletion.set(true); let context = self.upcast::().context(); let command = WebGLCommand::DeleteQuery(self.gl_id); - if fallible { - context.send_command_ignored(command); - } else { - context.send_command(command); + match operation_fallibility { + Operation::Fallible => context.send_command_ignored(command), + Operation::Infallible => context.send_command(command), } } } @@ -187,6 +186,6 @@ impl WebGLQuery { impl Drop for WebGLQuery { fn drop(&mut self) { - self.delete(true); + self.delete(Operation::Fallible); } } -- cgit v1.2.3