mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00: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
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -4882,9 +4882,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sparkle"
|
||||
version = "0.1.8"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25e193f97790240fc9208b077001c8331f4ccc801daa4df56efcb90e513c0989"
|
||||
checksum = "84b935631ddcc08b257a331ac645cc6831e52a4ff55d4c430142575c6757a094"
|
||||
dependencies = [
|
||||
"gl_generator 0.13.1",
|
||||
]
|
||||
|
|
|
@ -20,6 +20,8 @@ impl GLLimitsDetect for GLLimits {
|
|||
let max_renderbuffer_size = gl.get_integer(gl::MAX_RENDERBUFFER_SIZE);
|
||||
let max_texture_image_units = gl.get_integer(gl::MAX_TEXTURE_IMAGE_UNITS);
|
||||
let max_vertex_texture_image_units = gl.get_integer(gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS);
|
||||
let max_transform_feedback_separate_attribs =
|
||||
gl.get_integer(gl::MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
|
||||
|
||||
// TODO: better value for this?
|
||||
let max_client_wait_timeout_webgl = std::time::Duration::new(1, 0);
|
||||
|
@ -67,6 +69,7 @@ impl GLLimitsDetect for GLLimits {
|
|||
max_vertex_texture_image_units,
|
||||
max_vertex_uniform_vectors,
|
||||
max_client_wait_timeout_webgl,
|
||||
max_transform_feedback_separate_attribs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1180,6 +1180,41 @@ impl WebGLImpl {
|
|||
WebGLCommand::GetRenderbufferParameter(target, pname, ref chan) => {
|
||||
Self::get_renderbuffer_parameter(gl, target, pname, chan)
|
||||
},
|
||||
WebGLCommand::CreateTransformFeedback(ref sender) => {
|
||||
let value = gl.gen_transform_feedbacks();
|
||||
sender.send(value).unwrap()
|
||||
},
|
||||
WebGLCommand::DeleteTransformFeedback(id) => {
|
||||
gl.delete_transform_feedbacks(id);
|
||||
},
|
||||
WebGLCommand::IsTransformFeedback(id, ref sender) => {
|
||||
let value = gl.is_transform_feedback(id);
|
||||
sender.send(value).unwrap()
|
||||
},
|
||||
WebGLCommand::BindTransformFeedback(target, id) => {
|
||||
gl.bind_transform_feedback(target, id);
|
||||
},
|
||||
WebGLCommand::BeginTransformFeedback(mode) => {
|
||||
gl.begin_transform_feedback(mode);
|
||||
},
|
||||
WebGLCommand::EndTransformFeedback() => {
|
||||
gl.end_transform_feedback();
|
||||
},
|
||||
WebGLCommand::PauseTransformFeedback() => {
|
||||
gl.pause_transform_feedback();
|
||||
},
|
||||
WebGLCommand::ResumeTransformFeedback() => {
|
||||
gl.resume_transform_feedback();
|
||||
},
|
||||
WebGLCommand::GetTransformFeedbackVarying(program, index, ref sender) => {
|
||||
let (size, ty, mut name) = gl.get_transform_feedback_varying(program.get(), index);
|
||||
// We need to split, because the name starts with '_u' prefix.
|
||||
name = name.split_off(2);
|
||||
sender.send((size, ty, name)).unwrap();
|
||||
},
|
||||
WebGLCommand::TransformFeedbackVaryings(program, ref varyings, buffer_mode) => {
|
||||
gl.transform_feedback_varyings(program.get(), varyings.as_slice(), buffer_mode);
|
||||
},
|
||||
WebGLCommand::GetFramebufferAttachmentParameter(
|
||||
target,
|
||||
attachment,
|
||||
|
@ -1814,9 +1849,10 @@ impl WebGLImpl {
|
|||
linked: false,
|
||||
active_attribs: vec![].into(),
|
||||
active_uniforms: vec![].into(),
|
||||
transform_feedback_length: Default::default(),
|
||||
transform_feedback_mode: Default::default(),
|
||||
};
|
||||
}
|
||||
|
||||
let mut num_active_attribs = [0];
|
||||
unsafe {
|
||||
gl.get_program_iv(
|
||||
|
@ -1868,11 +1904,28 @@ impl WebGLImpl {
|
|||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
|
||||
let mut transform_feedback_length = [0];
|
||||
unsafe {
|
||||
gl.get_program_iv(
|
||||
program.get(),
|
||||
gl::TRANSFORM_FEEDBACK_VARYINGS,
|
||||
&mut transform_feedback_length,
|
||||
);
|
||||
}
|
||||
let mut transform_feedback_mode = [0];
|
||||
unsafe {
|
||||
gl.get_program_iv(
|
||||
program.get(),
|
||||
gl::TRANSFORM_FEEDBACK_BUFFER_MODE,
|
||||
&mut transform_feedback_mode,
|
||||
);
|
||||
}
|
||||
ProgramLinkInfo {
|
||||
linked: true,
|
||||
active_attribs,
|
||||
active_uniforms,
|
||||
transform_feedback_length: transform_feedback_length[0],
|
||||
transform_feedback_mode: transform_feedback_mode[0],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -292,6 +292,16 @@ pub enum WebGLCommand {
|
|||
GetProgramInfoLog(WebGLProgramId, WebGLSender<String>),
|
||||
GetFramebufferAttachmentParameter(u32, u32, u32, WebGLSender<i32>),
|
||||
GetRenderbufferParameter(u32, u32, WebGLSender<i32>),
|
||||
CreateTransformFeedback(WebGLSender<u32>),
|
||||
DeleteTransformFeedback(u32),
|
||||
IsTransformFeedback(u32, WebGLSender<bool>),
|
||||
BindTransformFeedback(u32, u32),
|
||||
BeginTransformFeedback(u32),
|
||||
EndTransformFeedback(),
|
||||
PauseTransformFeedback(),
|
||||
ResumeTransformFeedback(),
|
||||
GetTransformFeedbackVarying(WebGLProgramId, u32, WebGLSender<(i32, u32, String)>),
|
||||
TransformFeedbackVaryings(WebGLProgramId, Vec<String>, u32),
|
||||
PolygonOffset(f32, f32),
|
||||
RenderbufferStorage(u32, u32, i32, i32),
|
||||
ReadPixels(Rect<u32>, u32, u32, IpcBytesSender),
|
||||
|
@ -660,6 +670,10 @@ pub struct ProgramLinkInfo {
|
|||
pub active_attribs: Box<[ActiveAttribInfo]>,
|
||||
/// The list of active uniforms.
|
||||
pub active_uniforms: Box<[ActiveUniformInfo]>,
|
||||
/// The number of varying variables
|
||||
pub transform_feedback_length: i32,
|
||||
/// The buffer mode used when transform feedback is active
|
||||
pub transform_feedback_mode: i32,
|
||||
}
|
||||
|
||||
/// Description of a single active attribute.
|
||||
|
@ -733,6 +747,8 @@ parameters! {
|
|||
Bool(ParameterBool {
|
||||
DepthWritemask = gl::DEPTH_WRITEMASK,
|
||||
SampleCoverageInvert = gl::SAMPLE_COVERAGE_INVERT,
|
||||
TransformFeedbackActive = gl::TRANSFORM_FEEDBACK_ACTIVE,
|
||||
TransformFeedbackPaused = gl::TRANSFORM_FEEDBACK_PAUSED,
|
||||
}),
|
||||
Bool4(ParameterBool4 {
|
||||
ColorWritemask = gl::COLOR_WRITEMASK,
|
||||
|
@ -774,6 +790,12 @@ parameters! {
|
|||
StencilValueMask = gl::STENCIL_VALUE_MASK,
|
||||
StencilWritemask = gl::STENCIL_WRITEMASK,
|
||||
SubpixelBits = gl::SUBPIXEL_BITS,
|
||||
TransformFeedbackBinding = gl::TRANSFORM_FEEDBACK_BINDING,
|
||||
MaxTransformFeedbackInterleavedComponents = gl::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
|
||||
MaxTransformFeedbackSeparateAttribs = gl::MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
|
||||
MaxTransformFeedbackSeparateComponents = gl::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
|
||||
TransformFeedbackBufferSize = gl::TRANSFORM_FEEDBACK_BUFFER_SIZE,
|
||||
TransformFeedbackBufferStart = gl::TRANSFORM_FEEDBACK_BUFFER_START,
|
||||
}),
|
||||
Int2(ParameterInt2 {
|
||||
MaxViewportDims = gl::MAX_VIEWPORT_DIMS,
|
||||
|
@ -968,4 +990,5 @@ pub struct GLLimits {
|
|||
pub max_vertex_texture_image_units: u32,
|
||||
pub max_vertex_uniform_vectors: u32,
|
||||
pub max_client_wait_timeout_webgl: std::time::Duration,
|
||||
pub max_transform_feedback_separate_attribs: u32,
|
||||
}
|
||||
|
|
|
@ -532,6 +532,7 @@ pub mod webglshader;
|
|||
pub mod webglshaderprecisionformat;
|
||||
pub mod webglsync;
|
||||
pub mod webgltexture;
|
||||
pub mod webgltransformfeedback;
|
||||
pub mod webgluniformlocation;
|
||||
pub mod webglvertexarrayobjectoes;
|
||||
pub mod websocket;
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -34,6 +34,8 @@ pub struct WebGLProgram {
|
|||
vertex_shader: MutNullableDom<WebGLShader>,
|
||||
active_attribs: DomRefCell<Box<[ActiveAttribInfo]>>,
|
||||
active_uniforms: DomRefCell<Box<[ActiveUniformInfo]>>,
|
||||
transform_feedback_varyings_length: Cell<i32>,
|
||||
transform_feedback_mode: Cell<i32>,
|
||||
}
|
||||
|
||||
impl WebGLProgram {
|
||||
|
@ -50,6 +52,8 @@ impl WebGLProgram {
|
|||
vertex_shader: Default::default(),
|
||||
active_attribs: DomRefCell::new(vec![].into()),
|
||||
active_uniforms: DomRefCell::new(vec![].into()),
|
||||
transform_feedback_varyings_length: Default::default(),
|
||||
transform_feedback_mode: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,6 +191,10 @@ impl WebGLProgram {
|
|||
|
||||
self.linked.set(link_info.linked);
|
||||
self.link_called.set(true);
|
||||
self.transform_feedback_varyings_length
|
||||
.set(link_info.transform_feedback_length);
|
||||
self.transform_feedback_mode
|
||||
.set(link_info.transform_feedback_mode);
|
||||
*self.active_attribs.borrow_mut() = link_info.active_attribs;
|
||||
*self.active_uniforms.borrow_mut() = link_info.active_uniforms;
|
||||
Ok(())
|
||||
|
@ -444,6 +452,14 @@ impl WebGLProgram {
|
|||
pub fn link_generation(&self) -> u64 {
|
||||
self.link_generation.get()
|
||||
}
|
||||
|
||||
pub fn transform_feedback_varyings_length(&self) -> i32 {
|
||||
self.transform_feedback_varyings_length.get()
|
||||
}
|
||||
|
||||
pub fn transform_feedback_buffer_mode(&self) -> i32 {
|
||||
self.transform_feedback_mode.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WebGLProgram {
|
||||
|
|
|
@ -1165,6 +1165,10 @@ impl WebGLRenderingContext {
|
|||
|
||||
slot.set(buffer);
|
||||
}
|
||||
|
||||
pub fn current_program(&self) -> Option<DomRoot<WebGLProgram>> {
|
||||
self.current_program.get()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "webgl_backtrace"))]
|
||||
|
|
133
components/script/dom/webgltransformfeedback.rs
Normal file
133
components/script/dom/webgltransformfeedback.rs
Normal file
|
@ -0,0 +1,133 @@
|
|||
/* 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::WebGLTransformFeedbackBinding;
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
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 canvas_traits::webgl::{webgl_channel, WebGLCommand};
|
||||
use dom_struct::dom_struct;
|
||||
use std::cell::Cell;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct WebGLTransformFeedback {
|
||||
webgl_object: WebGLObject,
|
||||
id: u32,
|
||||
marked_for_deletion: Cell<bool>,
|
||||
has_been_bound: Cell<bool>,
|
||||
is_active: Cell<bool>,
|
||||
is_paused: Cell<bool>,
|
||||
}
|
||||
|
||||
impl WebGLTransformFeedback {
|
||||
fn new_inherited(context: &WebGLRenderingContext, id: u32) -> Self {
|
||||
Self {
|
||||
webgl_object: WebGLObject::new_inherited(context),
|
||||
id,
|
||||
marked_for_deletion: Cell::new(false),
|
||||
has_been_bound: Cell::new(false),
|
||||
is_active: Cell::new(false),
|
||||
is_paused: Cell::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(context: &WebGLRenderingContext) -> DomRoot<Self> {
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
context.send_command(WebGLCommand::CreateTransformFeedback(sender));
|
||||
let id = receiver.recv().unwrap();
|
||||
|
||||
reflect_dom_object(
|
||||
Box::new(WebGLTransformFeedback::new_inherited(context, id)),
|
||||
&*context.global(),
|
||||
WebGLTransformFeedbackBinding::Wrap,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl WebGLTransformFeedback {
|
||||
pub fn bind(&self, context: &WebGLRenderingContext, target: u32) {
|
||||
context.send_command(WebGLCommand::BindTransformFeedback(target, self.id()));
|
||||
self.has_been_bound.set(true);
|
||||
}
|
||||
|
||||
pub fn begin(&self, context: &WebGLRenderingContext, primitive_mode: u32) {
|
||||
if self.has_been_bound.get() && !self.is_active() {
|
||||
context.send_command(WebGLCommand::BeginTransformFeedback(primitive_mode));
|
||||
self.set_active(true);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end(&self, context: &WebGLRenderingContext) {
|
||||
if self.has_been_bound.get() && self.is_active() {
|
||||
if self.is_paused() {
|
||||
context.send_command(WebGLCommand::ResumeTransformFeedback());
|
||||
}
|
||||
context.send_command(WebGLCommand::EndTransformFeedback());
|
||||
self.set_active(false);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resume(&self, context: &WebGLRenderingContext) {
|
||||
if self.is_active() && self.is_paused() {
|
||||
context.send_command(WebGLCommand::ResumeTransformFeedback());
|
||||
self.set_pause(false);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pause(&self, context: &WebGLRenderingContext) {
|
||||
if self.is_active() && !self.is_paused() {
|
||||
context.send_command(WebGLCommand::PauseTransformFeedback());
|
||||
self.set_pause(true);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id(&self) -> u32 {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn is_valid(&self) -> bool {
|
||||
!self.marked_for_deletion.get()
|
||||
}
|
||||
|
||||
pub fn is_active(&self) -> bool {
|
||||
self.is_active.get()
|
||||
}
|
||||
|
||||
pub fn is_paused(&self) -> bool {
|
||||
self.is_paused.get()
|
||||
}
|
||||
|
||||
pub fn delete(&self, fallible: bool) {
|
||||
if self.is_valid() && self.id() != 0 {
|
||||
self.marked_for_deletion.set(true);
|
||||
let context = self.upcast::<WebGLObject>().context();
|
||||
let cmd = WebGLCommand::DeleteTransformFeedback(self.id);
|
||||
if fallible {
|
||||
context.send_command_ignored(cmd);
|
||||
} else {
|
||||
context.send_command(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_active(&self, value: bool) {
|
||||
if self.is_valid() && self.has_been_bound.get() {
|
||||
self.is_active.set(value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_pause(&self, value: bool) {
|
||||
if self.is_valid() && self.is_active() {
|
||||
self.is_active.set(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WebGLTransformFeedback {
|
||||
fn drop(&mut self) {
|
||||
self.delete(true);
|
||||
}
|
||||
}
|
|
@ -12,9 +12,6 @@ typedef long long GLint64;
|
|||
typedef unsigned long long GLuint64;
|
||||
|
||||
|
||||
// interface WebGLTransformFeedback : WebGLObject {
|
||||
// };
|
||||
|
||||
// interface WebGLVertexArrayObject : WebGLObject {
|
||||
// };
|
||||
|
||||
|
@ -544,7 +541,7 @@ interface mixin WebGL2RenderingContextBase
|
|||
any getSyncParameter(WebGLSync sync, GLenum pname);
|
||||
|
||||
/* Transform Feedback */
|
||||
/*WebGLTransformFeedback? createTransformFeedback();
|
||||
WebGLTransformFeedback? createTransformFeedback();
|
||||
void deleteTransformFeedback(WebGLTransformFeedback? tf);
|
||||
[WebGLHandlesContextLoss] GLboolean isTransformFeedback(WebGLTransformFeedback? tf);
|
||||
void bindTransformFeedback (GLenum target, WebGLTransformFeedback? tf);
|
||||
|
@ -553,7 +550,7 @@ interface mixin WebGL2RenderingContextBase
|
|||
void transformFeedbackVaryings(WebGLProgram program, sequence<DOMString> varyings, GLenum bufferMode);
|
||||
WebGLActiveInfo? getTransformFeedbackVarying(WebGLProgram program, GLuint index);
|
||||
void pauseTransformFeedback();
|
||||
void resumeTransformFeedback();*/
|
||||
void resumeTransformFeedback();
|
||||
|
||||
/* Uniform Buffer Objects and Transform Feedback Buffers */
|
||||
// void bindBufferBase(GLenum target, GLuint index, WebGLBuffer? buffer);
|
||||
|
|
11
components/script/dom/webidls/WebGLTransformFeedback.webidl
Normal file
11
components/script/dom/webidls/WebGLTransformFeedback.webidl
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* 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/. */
|
||||
//
|
||||
// WebGL IDL definitions scraped from the Khronos specification:
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.15
|
||||
//
|
||||
|
||||
[Exposed=(Window), Pref="dom.webgl2.enabled"]
|
||||
interface WebGLTransformFeedback : WebGLObject {
|
||||
};
|
|
@ -1,2 +1,50 @@
|
|||
[get-buffer-sub-data-validity.html]
|
||||
expected: ERROR
|
||||
[WebGL test #9: areArraysEqual(dest, srcData) should be true. Was false.]
|
||||
expected: FAIL
|
||||
|
||||
[Overall test]
|
||||
expected: NOTRUN
|
||||
|
||||
[WebGL test #7: areArraysEqual(dest, srcData) should be true. Was false.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #6: getError expected: NO_ERROR. Was INVALID_VALUE : after evaluating: gl.getBufferSubData(gl.COPY_WRITE_BUFFER, 0, dest)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #2: getError expected: NO_ERROR. Was INVALID_VALUE : after evaluating: gl.getBufferSubData(gl.COPY_WRITE_BUFFER, 0, dest)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #12: getError expected: NO_ERROR. Was INVALID_VALUE : after evaluating: gl.getBufferSubData(gl.COPY_WRITE_BUFFER, 0, dest)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #10: getError expected: NO_ERROR. Was INVALID_VALUE : after evaluating: gl.getBufferSubData(gl.COPY_WRITE_BUFFER, 0, dest)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #14: getError expected: NO_ERROR. Was INVALID_VALUE : after evaluating: gl.getBufferSubData(gl.COPY_WRITE_BUFFER, 0, dest)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #4: getError expected: NO_ERROR. Was INVALID_VALUE : after evaluating: gl.getBufferSubData(gl.COPY_WRITE_BUFFER, 0, dest)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #13: areArraysEqual(dest, srcData) should be true. Was false.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #15: areArraysEqual(dest, srcData) should be true. Was false.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #8: getError expected: NO_ERROR. Was INVALID_VALUE : after evaluating: gl.getBufferSubData(gl.COPY_WRITE_BUFFER, 0, dest)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #5: areArraysEqual(dest, srcData) should be true. Was false.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #0: getError expected: NO_ERROR. Was INVALID_ENUM : linking transform feedback shader should not set an error]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #3: areArraysEqual(dest, srcData) should be true. Was false.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #11: areArraysEqual(dest, srcData) should be true. Was false.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -191,3 +191,42 @@
|
|||
[WebGL test #42: Property either does not exist or is not a function: deleteTransformFeedback]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #41: Property either does not exist or is not a function: bindBufferBase]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #51: Property either does not exist or is not a function: deleteVertexArray]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #50: Property either does not exist or is not a function: createVertexArray]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #42: Property either does not exist or is not a function: bindBufferRange]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #53: Property either does not exist or is not a function: bindVertexArray]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #48: Property either does not exist or is not a function: getActiveUniformBlockName]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #52: Property either does not exist or is not a function: isVertexArray]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #46: Property either does not exist or is not a function: getUniformBlockIndex]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #49: Property either does not exist or is not a function: uniformBlockBinding]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #44: Property either does not exist or is not a function: getUniformIndices]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #47: Property either does not exist or is not a function: getActiveUniformBlockParameter]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #43: Property either does not exist or is not a function: getIndexedParameter]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #45: Property either does not exist or is not a function: getActiveUniforms]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -3,3 +3,6 @@
|
|||
[WebGL test #5: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #10: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -105,6 +105,18 @@
|
|||
[WebGL test #106: getFramebufferAttachmentParameter did not generate INVALID_ENUM for invalid attachment enum: NO_ERROR]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #121: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||
[WebGL test #131: gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_DEPTH_SIZE) should be non-zero. Was 0]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #128: gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH) should be 2. Was 0.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #129: gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT) should be 2. Was 0.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #123: gl.getProgramParameter(uniformBlockProgram, gl.ACTIVE_UNIFORM_BLOCKS) should be 1 (of type number). Was null (of type object).]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #138: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
[non-existent-varying.html]
|
||||
expected: ERROR
|
||||
[WebGL test #0: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||
expected: FAIL
|
||||
|
|
@ -9,3 +9,6 @@
|
|||
[WebGL test #1: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #2: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||
expected: FAIL
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue