mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Add Support for WebGL Transormfeedback
Reference: https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.15
This commit is contained in:
parent
a33d493a4f
commit
4f112b1705
17 changed files with 588 additions and 17 deletions
|
@ -11,8 +11,8 @@ use crate::dom::bindings::codegen::UnionTypes::ArrayBufferViewOrArrayBuffer;
|
|||
use crate::dom::bindings::codegen::UnionTypes::Float32ArrayOrUnrestrictedFloatSequence;
|
||||
use crate::dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
|
||||
use crate::dom::bindings::codegen::UnionTypes::Int32ArrayOrLongSequence;
|
||||
use crate::dom::bindings::conversions::ToJSValConvertible;
|
||||
use crate::dom::bindings::error::{ErrorResult, Fallible};
|
||||
use crate::dom::bindings::reflector::DomObject;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom};
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
|
@ -32,8 +32,10 @@ use crate::dom::webglshader::WebGLShader;
|
|||
use crate::dom::webglshaderprecisionformat::WebGLShaderPrecisionFormat;
|
||||
use crate::dom::webglsync::WebGLSync;
|
||||
use crate::dom::webgltexture::WebGLTexture;
|
||||
use crate::dom::webgltransformfeedback::WebGLTransformFeedback;
|
||||
use crate::dom::webgluniformlocation::WebGLUniformLocation;
|
||||
use crate::dom::window::Window;
|
||||
use crate::js::conversions::ToJSValConvertible;
|
||||
use crate::script_runtime::JSContext;
|
||||
use canvas_traits::webgl::WebGLError::*;
|
||||
use canvas_traits::webgl::{
|
||||
|
@ -62,6 +64,7 @@ pub struct WebGL2RenderingContext {
|
|||
bound_pixel_unpack_buffer: MutNullableDom<WebGLBuffer>,
|
||||
bound_transform_feedback_buffer: MutNullableDom<WebGLBuffer>,
|
||||
bound_uniform_buffer: MutNullableDom<WebGLBuffer>,
|
||||
current_transform_feedback: MutNullableDom<WebGLTransformFeedback>,
|
||||
}
|
||||
|
||||
fn typedarray_elem_size(typeid: Type) -> usize {
|
||||
|
@ -100,6 +103,7 @@ impl WebGL2RenderingContext {
|
|||
bound_pixel_unpack_buffer: MutNullableDom::new(None),
|
||||
bound_transform_feedback_buffer: MutNullableDom::new(None),
|
||||
bound_uniform_buffer: MutNullableDom::new(None),
|
||||
current_transform_feedback: MutNullableDom::new(None),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -210,6 +214,9 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
|
|||
constants::UNIFORM_BUFFER_BINDING => unsafe {
|
||||
optional_root_object_to_js_or_null!(*cx, &self.bound_uniform_buffer.get())
|
||||
},
|
||||
constants::TRANSFORM_FEEDBACK_BINDING => unsafe {
|
||||
optional_root_object_to_js_or_null!(*cx, self.current_transform_feedback.get())
|
||||
},
|
||||
_ => self.base.GetParameter(cx, parameter),
|
||||
}
|
||||
}
|
||||
|
@ -824,7 +831,24 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
|
|||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
|
||||
fn GetProgramParameter(&self, cx: JSContext, program: &WebGLProgram, param_id: u32) -> JSVal {
|
||||
self.base.GetProgramParameter(cx, program, param_id)
|
||||
handle_potential_webgl_error!(
|
||||
self.base,
|
||||
self.base.validate_ownership(program),
|
||||
return NullValue()
|
||||
);
|
||||
if program.is_deleted() {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return NullValue();
|
||||
}
|
||||
match param_id {
|
||||
constants::TRANSFORM_FEEDBACK_VARYINGS => {
|
||||
Int32Value(program.transform_feedback_varyings_length())
|
||||
},
|
||||
constants::TRANSFORM_FEEDBACK_BUFFER_MODE => {
|
||||
Int32Value(program.transform_feedback_buffer_mode())
|
||||
},
|
||||
_ => self.base.GetProgramParameter(cx, program, param_id),
|
||||
}
|
||||
}
|
||||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
|
||||
|
@ -1721,6 +1745,212 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.15
|
||||
fn CreateTransformFeedback(&self) -> Option<DomRoot<WebGLTransformFeedback>> {
|
||||
Some(WebGLTransformFeedback::new(&self.base))
|
||||
}
|
||||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.15
|
||||
fn DeleteTransformFeedback(&self, tf: Option<&WebGLTransformFeedback>) {
|
||||
if let Some(tf) = tf {
|
||||
handle_potential_webgl_error!(self.base, self.base.validate_ownership(tf), return);
|
||||
if tf.is_active() {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return;
|
||||
}
|
||||
tf.delete(false);
|
||||
self.current_transform_feedback.set(None);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.15
|
||||
fn IsTransformFeedback(&self, tf: Option<&WebGLTransformFeedback>) -> bool {
|
||||
match tf {
|
||||
Some(tf) => {
|
||||
if !tf.is_valid() {
|
||||
return false;
|
||||
}
|
||||
handle_potential_webgl_error!(
|
||||
self.base,
|
||||
self.base.validate_ownership(tf),
|
||||
return false
|
||||
);
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
self.base
|
||||
.send_command(WebGLCommand::IsTransformFeedback(tf.id(), sender));
|
||||
receiver.recv().unwrap()
|
||||
},
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.15
|
||||
fn BindTransformFeedback(&self, target: u32, tf: Option<&WebGLTransformFeedback>) {
|
||||
if target != constants::TRANSFORM_FEEDBACK {
|
||||
self.base.webgl_error(InvalidEnum);
|
||||
return;
|
||||
}
|
||||
match tf {
|
||||
Some(transform_feedback) => {
|
||||
handle_potential_webgl_error!(
|
||||
self.base,
|
||||
self.base.validate_ownership(transform_feedback),
|
||||
return
|
||||
);
|
||||
if !transform_feedback.is_valid() {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return;
|
||||
}
|
||||
if let Some(current_tf) = self.current_transform_feedback.get() {
|
||||
if current_tf.is_active() && !current_tf.is_paused() {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
transform_feedback.bind(&self.base, target);
|
||||
self.current_transform_feedback
|
||||
.set(Some(transform_feedback));
|
||||
},
|
||||
None => self
|
||||
.base
|
||||
.send_command(WebGLCommand::BindTransformFeedback(target, 0)),
|
||||
}
|
||||
}
|
||||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.15
|
||||
fn BeginTransformFeedback(&self, primitiveMode: u32) {
|
||||
match primitiveMode {
|
||||
constants::POINTS | constants::LINES | constants::TRIANGLES => {},
|
||||
_ => {
|
||||
self.base.webgl_error(InvalidEnum);
|
||||
return;
|
||||
},
|
||||
};
|
||||
let current_tf = match self.current_transform_feedback.get() {
|
||||
Some(current_tf) => current_tf,
|
||||
None => {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return;
|
||||
},
|
||||
};
|
||||
if current_tf.is_active() {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return;
|
||||
};
|
||||
let program = match self.base.current_program() {
|
||||
Some(program) => program,
|
||||
None => {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return;
|
||||
},
|
||||
};
|
||||
if !program.is_linked() || program.transform_feedback_varyings_length() != 0 {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return;
|
||||
};
|
||||
current_tf.begin(&self.base, primitiveMode);
|
||||
}
|
||||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.15
|
||||
fn EndTransformFeedback(&self) {
|
||||
if let Some(current_tf) = self.current_transform_feedback.get() {
|
||||
if !current_tf.is_active() {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return;
|
||||
}
|
||||
current_tf.end(&self.base);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.15
|
||||
fn ResumeTransformFeedback(&self) {
|
||||
if let Some(current_tf) = self.current_transform_feedback.get() {
|
||||
if !current_tf.is_active() || !current_tf.is_paused() {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return;
|
||||
}
|
||||
current_tf.resume(&self.base);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.15
|
||||
fn PauseTransformFeedback(&self) {
|
||||
if let Some(current_tf) = self.current_transform_feedback.get() {
|
||||
if !current_tf.is_active() || current_tf.is_paused() {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return;
|
||||
}
|
||||
current_tf.pause(&self.base);
|
||||
}
|
||||
}
|
||||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.15
|
||||
fn TransformFeedbackVaryings(
|
||||
&self,
|
||||
program: &WebGLProgram,
|
||||
varyings: Vec<DOMString>,
|
||||
bufferMode: u32,
|
||||
) {
|
||||
handle_potential_webgl_error!(self.base, program.validate(), return);
|
||||
let strs = varyings
|
||||
.iter()
|
||||
.map(|name| String::from(name.to_owned()))
|
||||
.collect::<Vec<String>>();
|
||||
match bufferMode {
|
||||
constants::INTERLEAVED_ATTRIBS => {
|
||||
self.base
|
||||
.send_command(WebGLCommand::TransformFeedbackVaryings(
|
||||
program.id(),
|
||||
strs,
|
||||
bufferMode,
|
||||
));
|
||||
},
|
||||
constants::SEPARATE_ATTRIBS => {
|
||||
let max_tf_sp_att =
|
||||
self.base.limits().max_transform_feedback_separate_attribs as usize;
|
||||
if strs.len() >= max_tf_sp_att {
|
||||
self.base.webgl_error(InvalidValue);
|
||||
return;
|
||||
}
|
||||
self.base
|
||||
.send_command(WebGLCommand::TransformFeedbackVaryings(
|
||||
program.id(),
|
||||
strs,
|
||||
bufferMode,
|
||||
));
|
||||
},
|
||||
_ => self.base.webgl_error(InvalidEnum),
|
||||
}
|
||||
}
|
||||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.15
|
||||
fn GetTransformFeedbackVarying(
|
||||
&self,
|
||||
program: &WebGLProgram,
|
||||
index: u32,
|
||||
) -> Option<DomRoot<WebGLActiveInfo>> {
|
||||
handle_potential_webgl_error!(self.base, program.validate(), return None);
|
||||
if index >= program.transform_feedback_varyings_length() as u32 {
|
||||
self.base.webgl_error(InvalidValue);
|
||||
return None;
|
||||
}
|
||||
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
self.base
|
||||
.send_command(WebGLCommand::GetTransformFeedbackVarying(
|
||||
program.id(),
|
||||
index,
|
||||
sender,
|
||||
));
|
||||
let (size, ty, name) = receiver.recv().unwrap();
|
||||
Some(WebGLActiveInfo::new(
|
||||
self.base.global().as_window(),
|
||||
size,
|
||||
ty,
|
||||
DOMString::from(name),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl LayoutCanvasWebGLRenderingContextHelpers for LayoutDom<WebGL2RenderingContext> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue