diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2020-01-15 10:45:07 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-15 10:45:07 -0500 |
commit | f9174a471733d82d1b4b1a9a22cb7adedffcf450 (patch) | |
tree | 79421120380dbf0d1a2f23def49ad15ef3fc48db /components/script/dom/webgl2renderingcontext.rs | |
parent | 2373769e766aa6794bd141cd2da137e71a580c86 (diff) | |
parent | bc914381a8951f10bf028c31d50ab08b03a32ecf (diff) | |
download | servo-f9174a471733d82d1b4b1a9a22cb7adedffcf450.tar.gz servo-f9174a471733d82d1b4b1a9a22cb7adedffcf450.zip |
Auto merge of #25519 - szeged:mmatyas__webgl_fns_uniforms, r=jdm
Add support for WebGL2 unsigned uniform operations
This adds support for the WebGL2 `uniform[1234]ui` and `uniform[1234]uiv` operations.
See: https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8
<!-- Please describe your changes on the following line: -->
cc @jdm @zakorgy @imiklos
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] There are tests for these changes
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Diffstat (limited to 'components/script/dom/webgl2renderingcontext.rs')
-rw-r--r-- | components/script/dom/webgl2renderingcontext.rs | 226 |
1 files changed, 222 insertions, 4 deletions
diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs index 2689448e0bc..86ca17c12d8 100644 --- a/components/script/dom/webgl2renderingcontext.rs +++ b/components/script/dom/webgl2renderingcontext.rs @@ -11,6 +11,7 @@ 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::codegen::UnionTypes::Uint32ArrayOrUnsignedLongSequence; use crate::dom::bindings::error::{ErrorResult, Fallible}; use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; @@ -25,7 +26,8 @@ use crate::dom::webglprogram::WebGLProgram; use crate::dom::webglquery::WebGLQuery; use crate::dom::webglrenderbuffer::WebGLRenderbuffer; use crate::dom::webglrenderingcontext::{ - LayoutCanvasWebGLRenderingContextHelpers, Size2DExt, WebGLRenderingContext, + uniform_get, uniform_typed, LayoutCanvasWebGLRenderingContextHelpers, Size2DExt, + WebGLRenderingContext, }; use crate::dom::webglsampler::{WebGLSampler, WebGLSamplerValue}; use crate::dom::webglshader::WebGLShader; @@ -48,7 +50,7 @@ use js::jsapi::{JSObject, Type}; use js::jsval::{BooleanValue, DoubleValue, Int32Value, UInt32Value}; use js::jsval::{JSVal, NullValue, ObjectValue, UndefinedValue}; use js::rust::CustomAutoRooterGuard; -use js::typedarray::{ArrayBufferView, CreateWith, Uint32Array}; +use js::typedarray::{ArrayBufferView, CreateWith, Uint32, Uint32Array}; use script_layout_interface::HTMLCanvasDataSource; use std::cell::Cell; use std::cmp; @@ -388,6 +390,49 @@ impl WebGL2RenderingContext { .copy_from_slice(&src[src_start..src_start + src_row_bytes as usize]); } } + + fn uniform_vec_section( + &self, + vec: Uint32ArrayOrUnsignedLongSequence, + offset: u32, + length: u32, + uniform_size: usize, + uniform_location: &WebGLUniformLocation, + ) -> WebGLResult<Vec<u32>> { + let vec = match vec { + Uint32ArrayOrUnsignedLongSequence::Uint32Array(v) => v.to_vec(), + Uint32ArrayOrUnsignedLongSequence::UnsignedLongSequence(v) => v, + }; + + let offset = offset as usize; + if offset > vec.len() { + return Err(InvalidValue); + } + + let length = if length > 0 { + length as usize + } else { + vec.len() - offset + }; + if offset + length > vec.len() { + return Err(InvalidValue); + } + + let vec = if offset == 0 && length == vec.len() { + vec + } else { + vec[offset..offset + length].to_vec() + }; + + if vec.len() < uniform_size || vec.len() % uniform_size != 0 { + return Err(InvalidValue); + } + if uniform_location.size().is_none() && vec.len() != uniform_size { + return Err(InvalidOperation); + } + + Ok(vec) + } } impl WebGL2RenderingContextMethods for WebGL2RenderingContext { @@ -1474,6 +1519,57 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { self.base.Uniform1iv(location, v) } + // https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + fn Uniform1ui(&self, location: Option<&WebGLUniformLocation>, val: u32) { + self.base.with_location(location, |location| { + match location.type_() { + constants::BOOL | constants::UNSIGNED_INT => (), + _ => return Err(InvalidOperation), + } + self.base + .send_command(WebGLCommand::Uniform1ui(location.id(), val)); + Ok(()) + }); + } + + // https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + fn Uniform1uiv( + &self, + location: Option<&WebGLUniformLocation>, + val: Uint32ArrayOrUnsignedLongSequence, + src_offset: u32, + src_length: u32, + ) { + self.base.with_location(location, |location| { + match location.type_() { + constants::BOOL | + constants::UNSIGNED_INT | + constants::SAMPLER_2D | + constants::SAMPLER_CUBE => {}, + _ => return Err(InvalidOperation), + } + + let val = self.uniform_vec_section(val, src_offset, src_length, 1, location)?; + + match location.type_() { + constants::SAMPLER_2D | constants::SAMPLER_CUBE => { + for &v in val + .iter() + .take(cmp::min(location.size().unwrap_or(1) as usize, val.len())) + { + if v >= self.base.limits().max_combined_texture_image_units { + return Err(InvalidValue); + } + } + }, + _ => {}, + } + self.base + .send_command(WebGLCommand::Uniform1uiv(location.id(), val)); + Ok(()) + }); + } + /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn Uniform1fv( &self, @@ -1507,6 +1603,39 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { self.base.Uniform2iv(location, v) } + // https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + fn Uniform2ui(&self, location: Option<&WebGLUniformLocation>, x: u32, y: u32) { + self.base.with_location(location, |location| { + match location.type_() { + constants::BOOL_VEC2 | constants::UNSIGNED_INT_VEC2 => {}, + _ => return Err(InvalidOperation), + } + self.base + .send_command(WebGLCommand::Uniform2ui(location.id(), x, y)); + Ok(()) + }); + } + + // https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + fn Uniform2uiv( + &self, + location: Option<&WebGLUniformLocation>, + val: Uint32ArrayOrUnsignedLongSequence, + src_offset: u32, + src_length: u32, + ) { + self.base.with_location(location, |location| { + match location.type_() { + constants::BOOL_VEC2 | constants::UNSIGNED_INT_VEC2 => {}, + _ => return Err(InvalidOperation), + } + let val = self.uniform_vec_section(val, src_offset, src_length, 2, location)?; + self.base + .send_command(WebGLCommand::Uniform2uiv(location.id(), val)); + Ok(()) + }); + } + /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn Uniform3f(&self, location: Option<&WebGLUniformLocation>, x: f32, y: f32, z: f32) { self.base.Uniform3f(location, x, y, z) @@ -1531,6 +1660,39 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { self.base.Uniform3iv(location, v) } + // https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + fn Uniform3ui(&self, location: Option<&WebGLUniformLocation>, x: u32, y: u32, z: u32) { + self.base.with_location(location, |location| { + match location.type_() { + constants::BOOL_VEC3 | constants::UNSIGNED_INT_VEC3 => {}, + _ => return Err(InvalidOperation), + } + self.base + .send_command(WebGLCommand::Uniform3ui(location.id(), x, y, z)); + Ok(()) + }); + } + + // https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + fn Uniform3uiv( + &self, + location: Option<&WebGLUniformLocation>, + val: Uint32ArrayOrUnsignedLongSequence, + src_offset: u32, + src_length: u32, + ) { + self.base.with_location(location, |location| { + match location.type_() { + constants::BOOL_VEC3 | constants::UNSIGNED_INT_VEC3 => {}, + _ => return Err(InvalidOperation), + } + let val = self.uniform_vec_section(val, src_offset, src_length, 3, location)?; + self.base + .send_command(WebGLCommand::Uniform3uiv(location.id(), val)); + Ok(()) + }); + } + /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn Uniform4i(&self, location: Option<&WebGLUniformLocation>, x: i32, y: i32, z: i32, w: i32) { self.base.Uniform4i(location, x, y, z, w) @@ -1541,6 +1703,39 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { self.base.Uniform4iv(location, v) } + // https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + fn Uniform4ui(&self, location: Option<&WebGLUniformLocation>, x: u32, y: u32, z: u32, w: u32) { + self.base.with_location(location, |location| { + match location.type_() { + constants::BOOL_VEC4 | constants::UNSIGNED_INT_VEC4 => {}, + _ => return Err(InvalidOperation), + } + self.base + .send_command(WebGLCommand::Uniform4ui(location.id(), x, y, z, w)); + Ok(()) + }); + } + + // https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + fn Uniform4uiv( + &self, + location: Option<&WebGLUniformLocation>, + val: Uint32ArrayOrUnsignedLongSequence, + src_offset: u32, + src_length: u32, + ) { + self.base.with_location(location, |location| { + match location.type_() { + constants::BOOL_VEC4 | constants::UNSIGNED_INT_VEC4 => {}, + _ => return Err(InvalidOperation), + } + let val = self.uniform_vec_section(val, src_offset, src_length, 4, location)?; + self.base + .send_command(WebGLCommand::Uniform4uiv(location.id(), val)); + Ok(()) + }); + } + /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn Uniform4f(&self, location: Option<&WebGLUniformLocation>, x: f32, y: f32, z: f32, w: f32) { self.base.Uniform4f(location, x, y, z, w) @@ -1585,14 +1780,37 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { self.base.UniformMatrix4fv(location, transpose, v) } - // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + #[allow(unsafe_code)] fn GetUniform( &self, cx: JSContext, program: &WebGLProgram, location: &WebGLUniformLocation, ) -> JSVal { - self.base.GetUniform(cx, program, location) + handle_potential_webgl_error!( + self.base, + self.base.uniform_check_program(program, location), + return NullValue() + ); + + let triple = (&*self.base, program.id(), location.id()); + + match location.type_() { + constants::UNSIGNED_INT => { + UInt32Value(uniform_get(triple, WebGLCommand::GetUniformUint)) + }, + constants::UNSIGNED_INT_VEC2 => unsafe { + uniform_typed::<Uint32>(*cx, &uniform_get(triple, WebGLCommand::GetUniformUint2)) + }, + constants::UNSIGNED_INT_VEC3 => unsafe { + uniform_typed::<Uint32>(*cx, &uniform_get(triple, WebGLCommand::GetUniformUint3)) + }, + constants::UNSIGNED_INT_VEC4 => unsafe { + uniform_typed::<Uint32>(*cx, &uniform_get(triple, WebGLCommand::GetUniformUint4)) + }, + _ => self.base.GetUniform(cx, program, location), + } } /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 |