mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
Auto merge of #21184 - servo:webgl, r=jdm
Use active uniforms data to implement gl.uniform* checks <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21184) <!-- Reviewable:end -->
This commit is contained in:
commit
3003e6f897
15 changed files with 592 additions and 418 deletions
|
@ -646,8 +646,9 @@ impl WebGLImpl {
|
||||||
ctx.gl().attach_shader(program_id.get(), shader_id.get()),
|
ctx.gl().attach_shader(program_id.get(), shader_id.get()),
|
||||||
WebGLCommand::DetachShader(program_id, shader_id) =>
|
WebGLCommand::DetachShader(program_id, shader_id) =>
|
||||||
ctx.gl().detach_shader(program_id.get(), shader_id.get()),
|
ctx.gl().detach_shader(program_id.get(), shader_id.get()),
|
||||||
WebGLCommand::BindAttribLocation(program_id, index, ref name) =>
|
WebGLCommand::BindAttribLocation(program_id, index, ref name) => {
|
||||||
ctx.gl().bind_attrib_location(program_id.get(), index, name),
|
ctx.gl().bind_attrib_location(program_id.get(), index, &to_name_in_compiled_shader(name))
|
||||||
|
}
|
||||||
WebGLCommand::BlendColor(r, g, b, a) =>
|
WebGLCommand::BlendColor(r, g, b, a) =>
|
||||||
ctx.gl().blend_color(r, g, b, a),
|
ctx.gl().blend_color(r, g, b, a),
|
||||||
WebGLCommand::BlendEquation(mode) =>
|
WebGLCommand::BlendEquation(mode) =>
|
||||||
|
@ -736,10 +737,6 @@ impl WebGLImpl {
|
||||||
ctx.gl().stencil_op(fail, zfail, zpass),
|
ctx.gl().stencil_op(fail, zfail, zpass),
|
||||||
WebGLCommand::StencilOpSeparate(face, fail, zfail, zpass) =>
|
WebGLCommand::StencilOpSeparate(face, fail, zfail, zpass) =>
|
||||||
ctx.gl().stencil_op_separate(face, fail, zfail, zpass),
|
ctx.gl().stencil_op_separate(face, fail, zfail, zpass),
|
||||||
WebGLCommand::GetActiveAttrib(program_id, index, ref chan) =>
|
|
||||||
Self::active_attrib(ctx.gl(), program_id, index, chan),
|
|
||||||
WebGLCommand::GetActiveUniform(program_id, index, ref chan) =>
|
|
||||||
Self::active_uniform(ctx.gl(), program_id, index, chan),
|
|
||||||
WebGLCommand::GetRenderbufferParameter(target, pname, ref chan) =>
|
WebGLCommand::GetRenderbufferParameter(target, pname, ref chan) =>
|
||||||
Self::get_renderbuffer_parameter(ctx.gl(), target, pname, chan),
|
Self::get_renderbuffer_parameter(ctx.gl(), target, pname, chan),
|
||||||
WebGLCommand::GetFramebufferAttachmentParameter(target, attachment, pname, ref chan) =>
|
WebGLCommand::GetFramebufferAttachmentParameter(target, attachment, pname, ref chan) =>
|
||||||
|
@ -820,12 +817,15 @@ impl WebGLImpl {
|
||||||
ctx.gl().uniform_4i(uniform_id, x, y, z, w),
|
ctx.gl().uniform_4i(uniform_id, x, y, z, w),
|
||||||
WebGLCommand::Uniform4iv(uniform_id, ref v) =>
|
WebGLCommand::Uniform4iv(uniform_id, ref v) =>
|
||||||
ctx.gl().uniform_4iv(uniform_id, v),
|
ctx.gl().uniform_4iv(uniform_id, v),
|
||||||
WebGLCommand::UniformMatrix2fv(uniform_id, transpose, ref v) =>
|
WebGLCommand::UniformMatrix2fv(uniform_id, ref v) => {
|
||||||
ctx.gl().uniform_matrix_2fv(uniform_id, transpose, v),
|
ctx.gl().uniform_matrix_2fv(uniform_id, false, v)
|
||||||
WebGLCommand::UniformMatrix3fv(uniform_id, transpose, ref v) =>
|
}
|
||||||
ctx.gl().uniform_matrix_3fv(uniform_id, transpose, v),
|
WebGLCommand::UniformMatrix3fv(uniform_id, ref v) => {
|
||||||
WebGLCommand::UniformMatrix4fv(uniform_id, transpose, ref v) =>
|
ctx.gl().uniform_matrix_3fv(uniform_id, false, v)
|
||||||
ctx.gl().uniform_matrix_4fv(uniform_id, transpose, v),
|
}
|
||||||
|
WebGLCommand::UniformMatrix4fv(uniform_id, ref v) => {
|
||||||
|
ctx.gl().uniform_matrix_4fv(uniform_id, false, v)
|
||||||
|
}
|
||||||
WebGLCommand::ValidateProgram(program_id) =>
|
WebGLCommand::ValidateProgram(program_id) =>
|
||||||
ctx.gl().validate_program(program_id.get()),
|
ctx.gl().validate_program(program_id.get()),
|
||||||
WebGLCommand::VertexAttrib(attrib_id, x, y, z, w) =>
|
WebGLCommand::VertexAttrib(attrib_id, x, y, z, w) =>
|
||||||
|
@ -1003,6 +1003,7 @@ impl WebGLImpl {
|
||||||
return ProgramLinkInfo {
|
return ProgramLinkInfo {
|
||||||
linked: false,
|
linked: false,
|
||||||
active_attribs: vec![].into(),
|
active_attribs: vec![].into(),
|
||||||
|
active_uniforms: vec![].into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1011,6 +1012,8 @@ impl WebGLImpl {
|
||||||
gl.get_program_iv(program.get(), gl::ACTIVE_ATTRIBUTES, &mut num_active_attribs);
|
gl.get_program_iv(program.get(), gl::ACTIVE_ATTRIBUTES, &mut num_active_attribs);
|
||||||
}
|
}
|
||||||
let active_attribs = (0..num_active_attribs[0] as u32).map(|i| {
|
let active_attribs = (0..num_active_attribs[0] as u32).map(|i| {
|
||||||
|
// FIXME(nox): This allocates strings sometimes for nothing
|
||||||
|
// and the gleam method keeps getting ACTIVE_ATTRIBUTE_MAX_LENGTH.
|
||||||
let (size, type_, name) = gl.get_active_attrib(program.get(), i);
|
let (size, type_, name) = gl.get_active_attrib(program.get(), i);
|
||||||
let location = if name.starts_with("gl_") {
|
let location = if name.starts_with("gl_") {
|
||||||
-1
|
-1
|
||||||
|
@ -1025,9 +1028,31 @@ impl WebGLImpl {
|
||||||
}
|
}
|
||||||
}).collect::<Vec<_>>().into();
|
}).collect::<Vec<_>>().into();
|
||||||
|
|
||||||
|
let mut num_active_uniforms = [0];
|
||||||
|
unsafe {
|
||||||
|
gl.get_program_iv(program.get(), gl::ACTIVE_UNIFORMS, &mut num_active_uniforms);
|
||||||
|
}
|
||||||
|
let active_uniforms = (0..num_active_uniforms[0] as u32).map(|i| {
|
||||||
|
// FIXME(nox): This allocates strings sometimes for nothing
|
||||||
|
// and the gleam method keeps getting ACTIVE_UNIFORM_MAX_LENGTH.
|
||||||
|
let (size, type_, mut name) = gl.get_active_uniform(program.get(), i);
|
||||||
|
let is_array = name.ends_with("[0]");
|
||||||
|
if is_array {
|
||||||
|
// FIXME(nox): NLL
|
||||||
|
let len = name.len();
|
||||||
|
name.truncate(len - 3);
|
||||||
|
}
|
||||||
|
ActiveUniformInfo {
|
||||||
|
base_name: from_name_in_compiled_shader(&name).into(),
|
||||||
|
size: if is_array { Some(size) } else { None },
|
||||||
|
type_,
|
||||||
|
}
|
||||||
|
}).collect::<Vec<_>>().into();
|
||||||
|
|
||||||
ProgramLinkInfo {
|
ProgramLinkInfo {
|
||||||
linked: true,
|
linked: true,
|
||||||
active_attribs,
|
active_attribs,
|
||||||
|
active_uniforms,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1045,42 +1070,6 @@ impl WebGLImpl {
|
||||||
chan.send(result.into()).unwrap()
|
chan.send(result.into()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
fn active_attrib(
|
|
||||||
gl: &gl::Gl,
|
|
||||||
program_id: WebGLProgramId,
|
|
||||||
index: u32,
|
|
||||||
chan: &WebGLSender<WebGLResult<(i32, u32, String)>>,
|
|
||||||
) {
|
|
||||||
let mut max = [0];
|
|
||||||
unsafe {
|
|
||||||
gl.get_program_iv(program_id.get(), gl::ACTIVE_ATTRIBUTES, &mut max);
|
|
||||||
}
|
|
||||||
let result = if index >= max[0] as u32 {
|
|
||||||
Err(WebGLError::InvalidValue)
|
|
||||||
} else {
|
|
||||||
Ok(gl.get_active_attrib(program_id.get(), index))
|
|
||||||
};
|
|
||||||
chan.send(result).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
fn active_uniform(gl: &gl::Gl,
|
|
||||||
program_id: WebGLProgramId,
|
|
||||||
index: u32,
|
|
||||||
chan: &WebGLSender<WebGLResult<(i32, u32, String)>>) {
|
|
||||||
let mut max = [0];
|
|
||||||
unsafe {
|
|
||||||
gl.get_program_iv(program_id.get(), gl::ACTIVE_UNIFORMS, &mut max);
|
|
||||||
}
|
|
||||||
let result = if index >= max[0] as u32 {
|
|
||||||
Err(WebGLError::InvalidValue)
|
|
||||||
} else {
|
|
||||||
Ok(gl.get_active_uniform(program_id.get(), index))
|
|
||||||
};
|
|
||||||
chan.send(result).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn finish(gl: &gl::Gl, chan: &WebGLSender<()>) {
|
fn finish(gl: &gl::Gl, chan: &WebGLSender<()>) {
|
||||||
gl.finish();
|
gl.finish();
|
||||||
chan.send(()).unwrap();
|
chan.send(()).unwrap();
|
||||||
|
@ -1121,17 +1110,14 @@ impl WebGLImpl {
|
||||||
chan.send(parameter).unwrap();
|
chan.send(parameter).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn uniform_location(gl: &gl::Gl,
|
fn uniform_location(
|
||||||
program_id: WebGLProgramId,
|
gl: &gl::Gl,
|
||||||
name: &str,
|
program_id: WebGLProgramId,
|
||||||
chan: &WebGLSender<Option<i32>>) {
|
name: &str,
|
||||||
let location = gl.get_uniform_location(program_id.get(), name);
|
chan: &WebGLSender<i32>,
|
||||||
let location = if location == -1 {
|
) {
|
||||||
None
|
let location = gl.get_uniform_location(program_id.get(), &to_name_in_compiled_shader(name));
|
||||||
} else {
|
assert!(location >= 0);
|
||||||
Some(location)
|
|
||||||
};
|
|
||||||
|
|
||||||
chan.send(location).unwrap();
|
chan.send(location).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1244,3 +1230,39 @@ impl WebGLImpl {
|
||||||
gl.compile_shader(shader_id.get());
|
gl.compile_shader(shader_id.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ANGLE adds a `_u` prefix to variable names:
|
||||||
|
///
|
||||||
|
/// https://chromium.googlesource.com/angle/angle/+/855d964bd0d05f6b2cb303f625506cf53d37e94f
|
||||||
|
///
|
||||||
|
/// To avoid hard-coding this we would need to use the `sh::GetAttributes` and `sh::GetUniforms`
|
||||||
|
/// API to look up the `x.name` and `x.mappedName` members.
|
||||||
|
const ANGLE_NAME_PREFIX: &'static str = "_u";
|
||||||
|
|
||||||
|
fn to_name_in_compiled_shader(s: &str) -> String {
|
||||||
|
map_dot_separated(s, |s, mapped| {
|
||||||
|
mapped.push_str(ANGLE_NAME_PREFIX);
|
||||||
|
mapped.push_str(s);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_name_in_compiled_shader(s: &str) -> String {
|
||||||
|
map_dot_separated(s, |s, mapped| {
|
||||||
|
mapped.push_str(if s.starts_with(ANGLE_NAME_PREFIX) {
|
||||||
|
&s[ANGLE_NAME_PREFIX.len()..]
|
||||||
|
} else {
|
||||||
|
s
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_dot_separated<F: Fn(&str, &mut String)>(s: &str, f: F) -> String {
|
||||||
|
let mut iter = s.split('.');
|
||||||
|
let mut mapped = String::new();
|
||||||
|
f(iter.next().unwrap(), &mut mapped);
|
||||||
|
for s in iter {
|
||||||
|
mapped.push('.');
|
||||||
|
f(s, &mut mapped);
|
||||||
|
}
|
||||||
|
mapped
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use euclid::Size2D;
|
||||||
use gleam::gl;
|
use gleam::gl;
|
||||||
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
||||||
use serde_bytes::ByteBuf;
|
use serde_bytes::ByteBuf;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
use webrender_api::{DocumentId, ImageKey, PipelineId};
|
use webrender_api::{DocumentId, ImageKey, PipelineId};
|
||||||
|
|
||||||
|
@ -207,9 +208,7 @@ pub enum WebGLCommand {
|
||||||
FramebufferTexture2D(u32, u32, u32, Option<WebGLTextureId>, i32),
|
FramebufferTexture2D(u32, u32, u32, Option<WebGLTextureId>, i32),
|
||||||
GetExtensions(WebGLSender<String>),
|
GetExtensions(WebGLSender<String>),
|
||||||
GetShaderPrecisionFormat(u32, u32, WebGLSender<(i32, i32, i32)>),
|
GetShaderPrecisionFormat(u32, u32, WebGLSender<(i32, i32, i32)>),
|
||||||
GetActiveAttrib(WebGLProgramId, u32, WebGLSender<WebGLResult<(i32, u32, String)>>),
|
GetUniformLocation(WebGLProgramId, String, WebGLSender<i32>),
|
||||||
GetActiveUniform(WebGLProgramId, u32, WebGLSender<WebGLResult<(i32, u32, String)>>),
|
|
||||||
GetUniformLocation(WebGLProgramId, String, WebGLSender<Option<i32>>),
|
|
||||||
GetShaderInfoLog(WebGLShaderId, WebGLSender<String>),
|
GetShaderInfoLog(WebGLShaderId, WebGLSender<String>),
|
||||||
GetProgramInfoLog(WebGLProgramId, WebGLSender<String>),
|
GetProgramInfoLog(WebGLProgramId, WebGLSender<String>),
|
||||||
GetFramebufferAttachmentParameter(u32, u32, u32, WebGLSender<i32>),
|
GetFramebufferAttachmentParameter(u32, u32, u32, WebGLSender<i32>),
|
||||||
|
@ -246,9 +245,9 @@ pub enum WebGLCommand {
|
||||||
Uniform4fv(i32, Vec<f32>),
|
Uniform4fv(i32, Vec<f32>),
|
||||||
Uniform4i(i32, i32, i32, i32, i32),
|
Uniform4i(i32, i32, i32, i32, i32),
|
||||||
Uniform4iv(i32, Vec<i32>),
|
Uniform4iv(i32, Vec<i32>),
|
||||||
UniformMatrix2fv(i32, bool, Vec<f32>),
|
UniformMatrix2fv(i32, Vec<f32>),
|
||||||
UniformMatrix3fv(i32, bool, Vec<f32>),
|
UniformMatrix3fv(i32, Vec<f32>),
|
||||||
UniformMatrix4fv(i32, bool, Vec<f32>),
|
UniformMatrix4fv(i32, Vec<f32>),
|
||||||
UseProgram(Option<WebGLProgramId>),
|
UseProgram(Option<WebGLProgramId>),
|
||||||
ValidateProgram(WebGLProgramId),
|
ValidateProgram(WebGLProgramId),
|
||||||
VertexAttrib(u32, f32, f32, f32, f32),
|
VertexAttrib(u32, f32, f32, f32, f32),
|
||||||
|
@ -425,6 +424,8 @@ pub struct ProgramLinkInfo {
|
||||||
pub linked: bool,
|
pub linked: bool,
|
||||||
/// The list of active attributes.
|
/// The list of active attributes.
|
||||||
pub active_attribs: Box<[ActiveAttribInfo]>,
|
pub active_attribs: Box<[ActiveAttribInfo]>,
|
||||||
|
/// The list of active uniforms.
|
||||||
|
pub active_uniforms: Box<[ActiveUniformInfo]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Description of a single active attribute.
|
/// Description of a single active attribute.
|
||||||
|
@ -440,6 +441,29 @@ pub struct ActiveAttribInfo {
|
||||||
pub location: i32,
|
pub location: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Description of a single active uniform.
|
||||||
|
#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
|
||||||
|
pub struct ActiveUniformInfo {
|
||||||
|
/// The base name of the uniform.
|
||||||
|
pub base_name: Box<str>,
|
||||||
|
/// The size of the uniform, if it is an array.
|
||||||
|
pub size: Option<i32>,
|
||||||
|
/// The type of the uniform.
|
||||||
|
pub type_: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveUniformInfo {
|
||||||
|
pub fn name(&self) -> Cow<str> {
|
||||||
|
if self.size.is_some() {
|
||||||
|
let mut name = String::from(&*self.base_name);
|
||||||
|
name.push_str("[0]");
|
||||||
|
Cow::Owned(name)
|
||||||
|
} else {
|
||||||
|
Cow::Borrowed(&self.base_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! parameters {
|
macro_rules! parameters {
|
||||||
($name:ident { $(
|
($name:ident { $(
|
||||||
$variant:ident($kind:ident { $(
|
$variant:ident($kind:ident { $(
|
||||||
|
@ -578,39 +602,3 @@ parameters! {
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ANGLE adds a `_u` prefix to variable names:
|
|
||||||
///
|
|
||||||
/// https://chromium.googlesource.com/angle/angle/+/855d964bd0d05f6b2cb303f625506cf53d37e94f
|
|
||||||
///
|
|
||||||
/// To avoid hard-coding this we would need to use the `sh::GetAttributes` and `sh::GetUniforms`
|
|
||||||
/// API to look up the `x.name` and `x.mappedName` members.
|
|
||||||
const ANGLE_NAME_PREFIX: &'static str = "_u";
|
|
||||||
|
|
||||||
pub fn to_name_in_compiled_shader(s: &str) -> String {
|
|
||||||
map_dot_separated(s, |s, mapped| {
|
|
||||||
mapped.push_str(ANGLE_NAME_PREFIX);
|
|
||||||
mapped.push_str(s);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_name_in_compiled_shader(s: &str) -> String {
|
|
||||||
map_dot_separated(s, |s, mapped| {
|
|
||||||
mapped.push_str(if s.starts_with(ANGLE_NAME_PREFIX) {
|
|
||||||
&s[ANGLE_NAME_PREFIX.len()..]
|
|
||||||
} else {
|
|
||||||
s
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn map_dot_separated<F: Fn(&str, &mut String)>(s: &str, f: F) -> String {
|
|
||||||
let mut iter = s.split('.');
|
|
||||||
let mut mapped = String::new();
|
|
||||||
f(iter.next().unwrap(), &mut mapped);
|
|
||||||
for s in iter {
|
|
||||||
mapped.push('.');
|
|
||||||
f(s, &mut mapped);
|
|
||||||
}
|
|
||||||
mapped
|
|
||||||
}
|
|
||||||
|
|
|
@ -32,10 +32,11 @@
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use canvas_traits::canvas::{CanvasGradientStop, CanvasId, LinearGradientStyle, RadialGradientStyle};
|
use canvas_traits::canvas::{CanvasGradientStop, CanvasId, LinearGradientStyle, RadialGradientStyle};
|
||||||
use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle};
|
use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle};
|
||||||
use canvas_traits::webgl::{ActiveAttribInfo, WebGLBufferId, WebGLFramebufferId, WebGLProgramId, WebGLRenderbufferId};
|
use canvas_traits::webgl::{ActiveAttribInfo, ActiveUniformInfo, WebGLBufferId, WebGLChan};
|
||||||
use canvas_traits::webgl::{WebGLChan, WebGLContextShareMode, WebGLError, WebGLPipeline, WebGLMsgSender};
|
use canvas_traits::webgl::{WebGLContextShareMode, WebGLError, WebGLFramebufferId, WebGLMsgSender};
|
||||||
use canvas_traits::webgl::{WebGLReceiver, WebGLSender, WebGLShaderId, WebGLTextureId, WebGLVertexArrayId};
|
use canvas_traits::webgl::{WebGLPipeline, WebGLProgramId, WebGLReceiver, WebGLRenderbufferId};
|
||||||
use canvas_traits::webgl::{WebGLSLVersion, WebGLVersion};
|
use canvas_traits::webgl::{WebGLSLVersion, WebGLSender, WebGLShaderId, WebGLTextureId};
|
||||||
|
use canvas_traits::webgl::{WebGLVersion, WebGLVertexArrayId};
|
||||||
use cssparser::RGBA;
|
use cssparser::RGBA;
|
||||||
use devtools_traits::{CSSError, TimelineMarkerType, WorkerId};
|
use devtools_traits::{CSSError, TimelineMarkerType, WorkerId};
|
||||||
use dom::abstractworker::SharedRt;
|
use dom::abstractworker::SharedRt;
|
||||||
|
@ -343,6 +344,7 @@ unsafe impl<A: JSTraceable, B: JSTraceable, C: JSTraceable> JSTraceable for (A,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_no_jsmanaged_fields!(ActiveAttribInfo);
|
unsafe_no_jsmanaged_fields!(ActiveAttribInfo);
|
||||||
|
unsafe_no_jsmanaged_fields!(ActiveUniformInfo);
|
||||||
unsafe_no_jsmanaged_fields!(bool, f32, f64, String, AtomicBool, AtomicUsize, Uuid, char);
|
unsafe_no_jsmanaged_fields!(bool, f32, f64, String, AtomicBool, AtomicUsize, Uuid, char);
|
||||||
unsafe_no_jsmanaged_fields!(usize, u8, u16, u32, u64);
|
unsafe_no_jsmanaged_fields!(usize, u8, u16, u32, u64);
|
||||||
unsafe_no_jsmanaged_fields!(isize, i8, i16, i32, i64);
|
unsafe_no_jsmanaged_fields!(isize, i8, i16, i32, i64);
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
|
||||||
use canvas_traits::webgl::{ActiveAttribInfo, WebGLCommand, WebGLError, WebGLMsgSender};
|
use canvas_traits::webgl::{ActiveAttribInfo, ActiveUniformInfo, WebGLCommand, WebGLError};
|
||||||
use canvas_traits::webgl::{WebGLProgramId, WebGLResult, from_name_in_compiled_shader};
|
use canvas_traits::webgl::{WebGLMsgSender, WebGLProgramId, WebGLResult, webgl_channel};
|
||||||
use canvas_traits::webgl::{to_name_in_compiled_shader, webgl_channel};
|
|
||||||
use dom::bindings::cell::DomRefCell;
|
use dom::bindings::cell::DomRefCell;
|
||||||
use dom::bindings::codegen::Bindings::WebGLProgramBinding;
|
use dom::bindings::codegen::Bindings::WebGLProgramBinding;
|
||||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||||
|
@ -16,6 +15,7 @@ use dom::webglactiveinfo::WebGLActiveInfo;
|
||||||
use dom::webglobject::WebGLObject;
|
use dom::webglobject::WebGLObject;
|
||||||
use dom::webglrenderingcontext::MAX_UNIFORM_AND_ATTRIBUTE_LEN;
|
use dom::webglrenderingcontext::MAX_UNIFORM_AND_ATTRIBUTE_LEN;
|
||||||
use dom::webglshader::WebGLShader;
|
use dom::webglshader::WebGLShader;
|
||||||
|
use dom::webgluniformlocation::WebGLUniformLocation;
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use fnv::FnvHashSet;
|
use fnv::FnvHashSet;
|
||||||
|
@ -33,6 +33,7 @@ pub struct WebGLProgram {
|
||||||
#[ignore_malloc_size_of = "Defined in ipc-channel"]
|
#[ignore_malloc_size_of = "Defined in ipc-channel"]
|
||||||
renderer: WebGLMsgSender,
|
renderer: WebGLMsgSender,
|
||||||
active_attribs: DomRefCell<Box<[ActiveAttribInfo]>>,
|
active_attribs: DomRefCell<Box<[ActiveAttribInfo]>>,
|
||||||
|
active_uniforms: DomRefCell<Box<[ActiveUniformInfo]>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebGLProgram {
|
impl WebGLProgram {
|
||||||
|
@ -49,6 +50,7 @@ impl WebGLProgram {
|
||||||
vertex_shader: Default::default(),
|
vertex_shader: Default::default(),
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
active_attribs: DomRefCell::new(vec![].into()),
|
active_attribs: DomRefCell::new(vec![].into()),
|
||||||
|
active_uniforms: DomRefCell::new(vec![].into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,20 +125,30 @@ impl WebGLProgram {
|
||||||
self.renderer.send(WebGLCommand::LinkProgram(self.id, sender)).unwrap();
|
self.renderer.send(WebGLCommand::LinkProgram(self.id, sender)).unwrap();
|
||||||
let link_info = receiver.recv().unwrap();
|
let link_info = receiver.recv().unwrap();
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.31
|
{
|
||||||
let mut used_locs = FnvHashSet::default();
|
let mut used_locs = FnvHashSet::default();
|
||||||
for active_attrib in &*link_info.active_attribs {
|
let mut used_names = FnvHashSet::default();
|
||||||
if active_attrib.location == -1 {
|
for active_attrib in &*link_info.active_attribs {
|
||||||
continue;
|
if active_attrib.location == -1 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let columns = match active_attrib.type_ {
|
||||||
|
constants::FLOAT_MAT2 => 2,
|
||||||
|
constants::FLOAT_MAT3 => 3,
|
||||||
|
constants::FLOAT_MAT4 => 4,
|
||||||
|
_ => 1,
|
||||||
|
};
|
||||||
|
assert!(used_names.insert(&*active_attrib.name));
|
||||||
|
for column in 0..columns {
|
||||||
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.31
|
||||||
|
if !used_locs.insert(active_attrib.location as u32 + column) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let columns = match active_attrib.type_ {
|
for active_uniform in &*link_info.active_uniforms {
|
||||||
constants::FLOAT_MAT2 => 2,
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.41
|
||||||
constants::FLOAT_MAT3 => 3,
|
if !used_names.insert(&*active_uniform.base_name) {
|
||||||
constants::FLOAT_MAT4 => 4,
|
|
||||||
_ => 1,
|
|
||||||
};
|
|
||||||
for column in 0..columns {
|
|
||||||
if !used_locs.insert(active_attrib.location as u32 + column) {
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,6 +156,7 @@ impl WebGLProgram {
|
||||||
|
|
||||||
self.linked.set(link_info.linked);
|
self.linked.set(link_info.linked);
|
||||||
*self.active_attribs.borrow_mut() = link_info.active_attribs;
|
*self.active_attribs.borrow_mut() = link_info.active_attribs;
|
||||||
|
*self.active_uniforms.borrow_mut() = link_info.active_uniforms;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,6 +164,10 @@ impl WebGLProgram {
|
||||||
Ref::map(self.active_attribs.borrow(), |attribs| &**attribs)
|
Ref::map(self.active_attribs.borrow(), |attribs| &**attribs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn active_uniforms(&self) -> Ref<[ActiveUniformInfo]> {
|
||||||
|
Ref::map(self.active_uniforms.borrow(), |uniforms| &**uniforms)
|
||||||
|
}
|
||||||
|
|
||||||
/// glValidateProgram
|
/// glValidateProgram
|
||||||
pub fn validate(&self) -> WebGLResult<()> {
|
pub fn validate(&self) -> WebGLResult<()> {
|
||||||
if self.is_deleted() {
|
if self.is_deleted() {
|
||||||
|
@ -232,10 +249,8 @@ impl WebGLProgram {
|
||||||
return Err(WebGLError::InvalidOperation);
|
return Err(WebGLError::InvalidOperation);
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = to_name_in_compiled_shader(&name);
|
|
||||||
|
|
||||||
self.renderer
|
self.renderer
|
||||||
.send(WebGLCommand::BindAttribLocation(self.id, index, name))
|
.send(WebGLCommand::BindAttribLocation(self.id, index, name.into()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -244,15 +259,14 @@ impl WebGLProgram {
|
||||||
if self.is_deleted() {
|
if self.is_deleted() {
|
||||||
return Err(WebGLError::InvalidValue);
|
return Err(WebGLError::InvalidValue);
|
||||||
}
|
}
|
||||||
let (sender, receiver) = webgl_channel().unwrap();
|
let uniforms = self.active_uniforms.borrow();
|
||||||
self.renderer
|
let data = uniforms.get(index as usize).ok_or(WebGLError::InvalidValue)?;
|
||||||
.send(WebGLCommand::GetActiveUniform(self.id, index, sender))
|
Ok(WebGLActiveInfo::new(
|
||||||
.unwrap();
|
self.global().as_window(),
|
||||||
|
data.size.unwrap_or(1),
|
||||||
receiver.recv().unwrap().map(|(size, ty, name)| {
|
data.type_,
|
||||||
let name = DOMString::from(from_name_in_compiled_shader(&name));
|
data.name().into(),
|
||||||
WebGLActiveInfo::new(self.global().as_window(), size, ty, name)
|
))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// glGetActiveAttrib
|
/// glGetActiveAttrib
|
||||||
|
@ -298,7 +312,10 @@ impl WebGLProgram {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// glGetUniformLocation
|
/// glGetUniformLocation
|
||||||
pub fn get_uniform_location(&self, name: DOMString) -> WebGLResult<Option<i32>> {
|
pub fn get_uniform_location(
|
||||||
|
&self,
|
||||||
|
name: DOMString,
|
||||||
|
) -> WebGLResult<Option<DomRoot<WebGLUniformLocation>>> {
|
||||||
if !self.is_linked() || self.is_deleted() {
|
if !self.is_linked() || self.is_deleted() {
|
||||||
return Err(WebGLError::InvalidOperation);
|
return Err(WebGLError::InvalidOperation);
|
||||||
}
|
}
|
||||||
|
@ -307,17 +324,37 @@ impl WebGLProgram {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the name is reserved
|
// Check if the name is reserved
|
||||||
if name.starts_with("webgl") || name.starts_with("_webgl_") {
|
if name.starts_with("gl_") {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = to_name_in_compiled_shader(&name);
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#GLSL_CONSTRUCTS
|
||||||
|
if name.starts_with("webgl_") || name.starts_with("_webgl_") {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (size, type_) = {
|
||||||
|
let (base_name, array_index) = match parse_uniform_name(&name) {
|
||||||
|
Some((name, index)) if index.map_or(true, |i| i >= 0) => (name, index),
|
||||||
|
_ => return Ok(None),
|
||||||
|
};
|
||||||
|
|
||||||
|
let uniforms = self.active_uniforms.borrow();
|
||||||
|
match uniforms.iter().find(|attrib| &*attrib.base_name == base_name) {
|
||||||
|
Some(uniform) if array_index.is_none() || array_index < uniform.size => {
|
||||||
|
(uniform.size.map(|size| size - array_index.unwrap_or_default()), uniform.type_)
|
||||||
|
},
|
||||||
|
_ => return Ok(None),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let (sender, receiver) = webgl_channel().unwrap();
|
let (sender, receiver) = webgl_channel().unwrap();
|
||||||
self.renderer
|
self.renderer
|
||||||
.send(WebGLCommand::GetUniformLocation(self.id, name, sender))
|
.send(WebGLCommand::GetUniformLocation(self.id, name.into(), sender))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Ok(receiver.recv().unwrap())
|
let location = receiver.recv().unwrap();
|
||||||
|
|
||||||
|
Ok(Some(WebGLUniformLocation::new(self.global().as_window(), location, self.id, size, type_)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// glGetProgramInfoLog
|
/// glGetProgramInfoLog
|
||||||
|
@ -358,3 +395,13 @@ impl Drop for WebGLProgram {
|
||||||
self.delete();
|
self.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn parse_uniform_name(name: &str) -> Option<(&str, Option<i32>)> {
|
||||||
|
if !name.ends_with(']') {
|
||||||
|
return Some((name, None));
|
||||||
|
}
|
||||||
|
let bracket_pos = name[..name.len() - 1].rfind('[')?;
|
||||||
|
let index = name[(bracket_pos + 1)..(name.len() - 1)].parse::<i32>().ok()?;
|
||||||
|
Some((&name[..bracket_pos], Some(index)))
|
||||||
|
}
|
||||||
|
|
|
@ -425,6 +425,21 @@ impl WebGLRenderingContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_location<F>(&self, location: Option<&WebGLUniformLocation>, f: F)
|
||||||
|
where
|
||||||
|
F: FnOnce(&WebGLUniformLocation) -> WebGLResult<()>,
|
||||||
|
{
|
||||||
|
let location = match location {
|
||||||
|
Some(loc) => loc,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
match self.current_program.get() {
|
||||||
|
Some(ref program) if program.id() == location.program_id() => {}
|
||||||
|
_ => return self.webgl_error(InvalidOperation),
|
||||||
|
}
|
||||||
|
handle_potential_webgl_error!(self, f(location));
|
||||||
|
}
|
||||||
|
|
||||||
fn tex_parameter(&self, target: u32, name: u32, value: TexParameterValue) {
|
fn tex_parameter(&self, target: u32, name: u32, value: TexParameterValue) {
|
||||||
let texture = match target {
|
let texture = match target {
|
||||||
constants::TEXTURE_2D |
|
constants::TEXTURE_2D |
|
||||||
|
@ -528,38 +543,6 @@ impl WebGLRenderingContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
|
||||||
// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml
|
|
||||||
// https://www.khronos.org/registry/gles/specs/2.0/es_full_spec_2.0.25.pdf#nameddest=section-2.10.4
|
|
||||||
fn validate_uniform_parameters<T>(&self,
|
|
||||||
uniform: Option<&WebGLUniformLocation>,
|
|
||||||
uniform_type: UniformSetterType,
|
|
||||||
data: &[T]) -> bool {
|
|
||||||
let uniform = match uniform {
|
|
||||||
Some(uniform) => uniform,
|
|
||||||
None => return false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let program = self.current_program.get();
|
|
||||||
match program {
|
|
||||||
Some(ref program) if program.id() == uniform.program_id() => {},
|
|
||||||
_ => {
|
|
||||||
self.webgl_error(InvalidOperation);
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO(emilio): Get more complex uniform info from ANGLE, and use it to
|
|
||||||
// properly validate that the uniform setter type is compatible with the
|
|
||||||
// uniform type, and that the uniform size matches.
|
|
||||||
if data.len() % uniform_type.element_count() != 0 {
|
|
||||||
self.webgl_error(InvalidOperation);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://en.wikipedia.org/wiki/Relative_luminance
|
// https://en.wikipedia.org/wiki/Relative_luminance
|
||||||
#[inline]
|
#[inline]
|
||||||
fn luminance(r: u8, g: u8, b: u8) -> u8 {
|
fn luminance(r: u8, g: u8, b: u8) -> u8 {
|
||||||
|
@ -2693,12 +2676,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
Int32Value(program.attached_shaders().map(|shaders| shaders.len() as i32).unwrap_or(0))
|
Int32Value(program.attached_shaders().map(|shaders| shaders.len() as i32).unwrap_or(0))
|
||||||
}
|
}
|
||||||
constants::ACTIVE_ATTRIBUTES => Int32Value(program.active_attribs().len() as i32),
|
constants::ACTIVE_ATTRIBUTES => Int32Value(program.active_attribs().len() as i32),
|
||||||
constants::ACTIVE_UNIFORMS => {
|
constants::ACTIVE_UNIFORMS => Int32Value(program.active_uniforms().len() as i32),
|
||||||
// FIXME(nox): We'll need to cache that on the DOM side at some point.
|
|
||||||
let (sender, receiver) = webgl_channel().unwrap();
|
|
||||||
self.send_command(WebGLCommand::GetProgramActiveUniforms(program.id(), sender));
|
|
||||||
Int32Value(receiver.recv().unwrap())
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
self.webgl_error(InvalidEnum);
|
self.webgl_error(InvalidEnum);
|
||||||
NullValue()
|
NullValue()
|
||||||
|
@ -2767,9 +2745,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
program: &WebGLProgram,
|
program: &WebGLProgram,
|
||||||
name: DOMString,
|
name: DOMString,
|
||||||
) -> Option<DomRoot<WebGLUniformLocation>> {
|
) -> Option<DomRoot<WebGLUniformLocation>> {
|
||||||
handle_potential_webgl_error!(self, program.get_uniform_location(name), None).map(|location| {
|
handle_potential_webgl_error!(self, program.get_uniform_location(name), None)
|
||||||
WebGLUniformLocation::new(self.global().as_window(), location, program.id())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
@ -3171,75 +3147,145 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn Uniform1f(&self,
|
fn Uniform1f(
|
||||||
location: Option<&WebGLUniformLocation>,
|
&self,
|
||||||
val: f32) {
|
location: Option<&WebGLUniformLocation>,
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::Float, &[val]) {
|
val: f32,
|
||||||
self.send_command(WebGLCommand::Uniform1f(location.unwrap().id(), val))
|
) {
|
||||||
}
|
self.with_location(location, |location| {
|
||||||
|
match location.type_() {
|
||||||
|
constants::BOOL | constants::FLOAT => {}
|
||||||
|
_ => return Err(InvalidOperation),
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform1f(location.id(), val));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn Uniform1i(&self,
|
fn Uniform1i(
|
||||||
location: Option<&WebGLUniformLocation>,
|
&self,
|
||||||
val: i32) {
|
location: Option<&WebGLUniformLocation>,
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::Int, &[val]) {
|
val: i32,
|
||||||
self.send_command(WebGLCommand::Uniform1i(location.unwrap().id(), val))
|
) {
|
||||||
}
|
self.with_location(location, |location| {
|
||||||
|
match location.type_() {
|
||||||
|
constants::BOOL | constants::INT => {}
|
||||||
|
constants::SAMPLER_2D | constants::SAMPLER_CUBE => {
|
||||||
|
if val < 0 || val as u32 >= self.limits.max_combined_texture_image_units {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Err(InvalidOperation),
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform1i(location.id(), val));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn Uniform1iv(
|
fn Uniform1iv(
|
||||||
&self,
|
&self,
|
||||||
location: Option<&WebGLUniformLocation>,
|
location: Option<&WebGLUniformLocation>,
|
||||||
v: Int32ArrayOrLongSequence,
|
val: Int32ArrayOrLongSequence,
|
||||||
) {
|
) {
|
||||||
let v = match v {
|
self.with_location(location, |location| {
|
||||||
Int32ArrayOrLongSequence::Int32Array(v) => v.to_vec(),
|
match location.type_() {
|
||||||
Int32ArrayOrLongSequence::LongSequence(v) => v,
|
constants::BOOL | constants::INT | constants::SAMPLER_2D | constants::SAMPLER_CUBE => {}
|
||||||
};
|
_ => return Err(InvalidOperation),
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::Int, &v) {
|
}
|
||||||
self.send_command(WebGLCommand::Uniform1iv(location.unwrap().id(), v))
|
let val = match val {
|
||||||
}
|
Int32ArrayOrLongSequence::Int32Array(v) => v.to_vec(),
|
||||||
|
Int32ArrayOrLongSequence::LongSequence(v) => v,
|
||||||
|
};
|
||||||
|
if val.is_empty() {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if location.size().is_none() && val.len() != 1 {
|
||||||
|
return Err(InvalidOperation);
|
||||||
|
}
|
||||||
|
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 < 0 || v as u32 >= self.limits.max_combined_texture_image_units {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform1iv(location.id(), val));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn Uniform1fv(
|
fn Uniform1fv(
|
||||||
&self,
|
&self,
|
||||||
location: Option<&WebGLUniformLocation>,
|
location: Option<&WebGLUniformLocation>,
|
||||||
v: Float32ArrayOrUnrestrictedFloatSequence,
|
val: Float32ArrayOrUnrestrictedFloatSequence,
|
||||||
) {
|
) {
|
||||||
let v = match v {
|
self.with_location(location, |location| {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
match location.type_() {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
constants::BOOL | constants::FLOAT => {}
|
||||||
};
|
_ => return Err(InvalidOperation),
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::Float, &v) {
|
}
|
||||||
self.send_command(WebGLCommand::Uniform1fv(location.unwrap().id(), v));
|
let val = match val {
|
||||||
}
|
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
||||||
|
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
||||||
|
};
|
||||||
|
if val.is_empty() {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if location.size().is_none() && val.len() != 1 {
|
||||||
|
return Err(InvalidOperation);
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform1fv(location.id(), val));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn Uniform2f(&self,
|
fn Uniform2f(
|
||||||
location: Option<&WebGLUniformLocation>,
|
&self,
|
||||||
x: f32, y: f32) {
|
location: Option<&WebGLUniformLocation>,
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::FloatVec2, &[x, y]) {
|
x: f32,
|
||||||
self.send_command(WebGLCommand::Uniform2f(location.unwrap().id(), x, y));
|
y: f32,
|
||||||
}
|
) {
|
||||||
|
self.with_location(location, |location| {
|
||||||
|
match location.type_() {
|
||||||
|
constants::BOOL_VEC2 | constants::FLOAT_VEC2 => {}
|
||||||
|
_ => return Err(InvalidOperation),
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform2f(location.id(), x, y));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn Uniform2fv(
|
fn Uniform2fv(
|
||||||
&self,
|
&self,
|
||||||
location: Option<&WebGLUniformLocation>,
|
location: Option<&WebGLUniformLocation>,
|
||||||
v: Float32ArrayOrUnrestrictedFloatSequence,
|
val: Float32ArrayOrUnrestrictedFloatSequence,
|
||||||
) {
|
) {
|
||||||
let v = match v {
|
self.with_location(location, |location| {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
match location.type_() {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
constants::BOOL_VEC2 | constants::FLOAT_VEC2 => {}
|
||||||
};
|
_ => return Err(InvalidOperation),
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::FloatVec2, &v) {
|
}
|
||||||
self.send_command(WebGLCommand::Uniform2fv(location.unwrap().id(), v));
|
let val = match val {
|
||||||
}
|
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
||||||
|
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
||||||
|
};
|
||||||
|
if val.len() < 2 || val.len() % 2 != 0 {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if location.size().is_none() && val.len() != 2 {
|
||||||
|
return Err(InvalidOperation);
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform2fv(location.id(), val));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
|
@ -3249,26 +3295,40 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
) {
|
) {
|
||||||
if self.validate_uniform_parameters(location,
|
self.with_location(location, |location| {
|
||||||
UniformSetterType::IntVec2,
|
match location.type_() {
|
||||||
&[x, y]) {
|
constants::BOOL_VEC2 | constants::INT_VEC2 => {}
|
||||||
self.send_command(WebGLCommand::Uniform2i(location.unwrap().id(), x, y));
|
_ => return Err(InvalidOperation),
|
||||||
}
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform2i(location.id(), x, y));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn Uniform2iv(
|
fn Uniform2iv(
|
||||||
&self,
|
&self,
|
||||||
location: Option<&WebGLUniformLocation>,
|
location: Option<&WebGLUniformLocation>,
|
||||||
v: Int32ArrayOrLongSequence,
|
val: Int32ArrayOrLongSequence,
|
||||||
) {
|
) {
|
||||||
let v = match v {
|
self.with_location(location, |location| {
|
||||||
Int32ArrayOrLongSequence::Int32Array(v) => v.to_vec(),
|
match location.type_() {
|
||||||
Int32ArrayOrLongSequence::LongSequence(v) => v,
|
constants::BOOL_VEC2 | constants::INT_VEC2 => {}
|
||||||
};
|
_ => return Err(InvalidOperation),
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::IntVec2, &v) {
|
}
|
||||||
self.send_command(WebGLCommand::Uniform2iv(location.unwrap().id(), v));
|
let val = match val {
|
||||||
}
|
Int32ArrayOrLongSequence::Int32Array(v) => v.to_vec(),
|
||||||
|
Int32ArrayOrLongSequence::LongSequence(v) => v,
|
||||||
|
};
|
||||||
|
if val.len() < 2 || val.len() % 2 != 0 {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if location.size().is_none() && val.len() != 2 {
|
||||||
|
return Err(InvalidOperation);
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform2iv(location.id(), val));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
|
@ -3279,52 +3339,84 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
y: f32,
|
y: f32,
|
||||||
z: f32,
|
z: f32,
|
||||||
) {
|
) {
|
||||||
if self.validate_uniform_parameters(location,
|
self.with_location(location, |location| {
|
||||||
UniformSetterType::FloatVec3,
|
match location.type_() {
|
||||||
&[x, y, z]) {
|
constants::BOOL_VEC3 | constants::FLOAT_VEC3 => {}
|
||||||
self.send_command(WebGLCommand::Uniform3f(location.unwrap().id(), x, y, z));
|
_ => return Err(InvalidOperation),
|
||||||
}
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform3f(location.id(), x, y, z));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn Uniform3fv(
|
fn Uniform3fv(
|
||||||
&self,
|
&self,
|
||||||
location: Option<&WebGLUniformLocation>,
|
location: Option<&WebGLUniformLocation>,
|
||||||
v: Float32ArrayOrUnrestrictedFloatSequence,
|
val: Float32ArrayOrUnrestrictedFloatSequence,
|
||||||
) {
|
) {
|
||||||
let v = match v {
|
self.with_location(location, |location| {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
match location.type_() {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
constants::BOOL_VEC3 | constants::FLOAT_VEC3 => {}
|
||||||
};
|
_ => return Err(InvalidOperation),
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::FloatVec3, &v) {
|
}
|
||||||
self.send_command(WebGLCommand::Uniform3fv(location.unwrap().id(), v))
|
let val = match val {
|
||||||
}
|
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
||||||
|
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
||||||
|
};
|
||||||
|
if val.len() < 3 || val.len() % 3 != 0 {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if location.size().is_none() && val.len() != 3 {
|
||||||
|
return Err(InvalidOperation);
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform3fv(location.id(), val));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn Uniform3i(&self,
|
fn Uniform3i(
|
||||||
location: Option<&WebGLUniformLocation>,
|
&self,
|
||||||
x: i32, y: i32, z: i32) {
|
location: Option<&WebGLUniformLocation>,
|
||||||
if self.validate_uniform_parameters(location,
|
x: i32,
|
||||||
UniformSetterType::IntVec3,
|
y: i32,
|
||||||
&[x, y, z]) {
|
z: i32,
|
||||||
self.send_command(WebGLCommand::Uniform3i(location.unwrap().id(), x, y, z))
|
) {
|
||||||
}
|
self.with_location(location, |location| {
|
||||||
|
match location.type_() {
|
||||||
|
constants::BOOL_VEC3 | constants::INT_VEC3 => {}
|
||||||
|
_ => return Err(InvalidOperation),
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform3i(location.id(), x, y, z));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn Uniform3iv(
|
fn Uniform3iv(
|
||||||
&self,
|
&self,
|
||||||
location: Option<&WebGLUniformLocation>,
|
location: Option<&WebGLUniformLocation>,
|
||||||
v: Int32ArrayOrLongSequence,
|
val: Int32ArrayOrLongSequence,
|
||||||
) {
|
) {
|
||||||
let v = match v {
|
self.with_location(location, |location| {
|
||||||
Int32ArrayOrLongSequence::Int32Array(v) => v.to_vec(),
|
match location.type_() {
|
||||||
Int32ArrayOrLongSequence::LongSequence(v) => v,
|
constants::BOOL_VEC3 | constants::INT_VEC3 => {}
|
||||||
};
|
_ => return Err(InvalidOperation),
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::IntVec3, &v) {
|
}
|
||||||
self.send_command(WebGLCommand::Uniform3iv(location.unwrap().id(), v))
|
let val = match val {
|
||||||
}
|
Int32ArrayOrLongSequence::Int32Array(v) => v.to_vec(),
|
||||||
|
Int32ArrayOrLongSequence::LongSequence(v) => v,
|
||||||
|
};
|
||||||
|
if val.len() < 3 || val.len() % 3 != 0 {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if location.size().is_none() && val.len() != 3 {
|
||||||
|
return Err(InvalidOperation);
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform3iv(location.id(), val));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
|
@ -3336,11 +3428,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
z: i32,
|
z: i32,
|
||||||
w: i32,
|
w: i32,
|
||||||
) {
|
) {
|
||||||
if self.validate_uniform_parameters(location,
|
self.with_location(location, |location| {
|
||||||
UniformSetterType::IntVec4,
|
match location.type_() {
|
||||||
&[x, y, z, w]) {
|
constants::BOOL_VEC4 | constants::INT_VEC4 => {}
|
||||||
self.send_command(WebGLCommand::Uniform4i(location.unwrap().id(), x, y, z, w))
|
_ => return Err(InvalidOperation),
|
||||||
}
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform4i(location.id(), x, y, z, w));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3348,15 +3443,26 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
fn Uniform4iv(
|
fn Uniform4iv(
|
||||||
&self,
|
&self,
|
||||||
location: Option<&WebGLUniformLocation>,
|
location: Option<&WebGLUniformLocation>,
|
||||||
v: Int32ArrayOrLongSequence,
|
val: Int32ArrayOrLongSequence,
|
||||||
) {
|
) {
|
||||||
let v = match v {
|
self.with_location(location, |location| {
|
||||||
Int32ArrayOrLongSequence::Int32Array(v) => v.to_vec(),
|
match location.type_() {
|
||||||
Int32ArrayOrLongSequence::LongSequence(v) => v,
|
constants::BOOL_VEC4 | constants::INT_VEC4 => {}
|
||||||
};
|
_ => return Err(InvalidOperation),
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::IntVec4, &v) {
|
}
|
||||||
self.send_command(WebGLCommand::Uniform4iv(location.unwrap().id(), v))
|
let val = match val {
|
||||||
}
|
Int32ArrayOrLongSequence::Int32Array(v) => v.to_vec(),
|
||||||
|
Int32ArrayOrLongSequence::LongSequence(v) => v,
|
||||||
|
};
|
||||||
|
if val.len() < 4 || val.len() % 4 != 0 {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if location.size().is_none() && val.len() != 4 {
|
||||||
|
return Err(InvalidOperation);
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform4iv(location.id(), val));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
|
@ -3368,26 +3474,40 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
z: f32,
|
z: f32,
|
||||||
w: f32,
|
w: f32,
|
||||||
) {
|
) {
|
||||||
if self.validate_uniform_parameters(location,
|
self.with_location(location, |location| {
|
||||||
UniformSetterType::FloatVec4,
|
match location.type_() {
|
||||||
&[x, y, z, w]) {
|
constants::BOOL_VEC4 | constants::FLOAT_VEC4 => {}
|
||||||
self.send_command(WebGLCommand::Uniform4f(location.unwrap().id(), x, y, z, w))
|
_ => return Err(InvalidOperation),
|
||||||
}
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform4f(location.id(), x, y, z, w));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn Uniform4fv(
|
fn Uniform4fv(
|
||||||
&self,
|
&self,
|
||||||
location: Option<&WebGLUniformLocation>,
|
location: Option<&WebGLUniformLocation>,
|
||||||
v: Float32ArrayOrUnrestrictedFloatSequence,
|
val: Float32ArrayOrUnrestrictedFloatSequence,
|
||||||
) {
|
) {
|
||||||
let v = match v {
|
self.with_location(location, |location| {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
match location.type_() {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
constants::BOOL_VEC4 | constants::FLOAT_VEC4 => {}
|
||||||
};
|
_ => return Err(InvalidOperation),
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::FloatVec4, &v) {
|
}
|
||||||
self.send_command(WebGLCommand::Uniform4fv(location.unwrap().id(), v))
|
let val = match val {
|
||||||
}
|
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
||||||
|
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
||||||
|
};
|
||||||
|
if val.len() < 4 || val.len() % 4 != 0 {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if location.size().is_none() && val.len() != 4 {
|
||||||
|
return Err(InvalidOperation);
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::Uniform4fv(location.id(), val));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
|
@ -3395,15 +3515,29 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
&self,
|
&self,
|
||||||
location: Option<&WebGLUniformLocation>,
|
location: Option<&WebGLUniformLocation>,
|
||||||
transpose: bool,
|
transpose: bool,
|
||||||
v: Float32ArrayOrUnrestrictedFloatSequence,
|
val: Float32ArrayOrUnrestrictedFloatSequence,
|
||||||
) {
|
) {
|
||||||
let v = match v {
|
self.with_location(location, |location| {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
match location.type_() {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
constants::FLOAT_MAT2 => {}
|
||||||
};
|
_ => return Err(InvalidOperation),
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::FloatMat2, &v) {
|
}
|
||||||
self.send_command(WebGLCommand::UniformMatrix2fv(location.unwrap().id(), transpose, v));
|
let val = match val {
|
||||||
}
|
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
||||||
|
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
||||||
|
};
|
||||||
|
if transpose {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if val.len() < 4 || val.len() % 4 != 0 {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if location.size().is_none() && val.len() != 4 {
|
||||||
|
return Err(InvalidOperation);
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::UniformMatrix2fv(location.id(), val));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
|
@ -3411,15 +3545,29 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
&self,
|
&self,
|
||||||
location: Option<&WebGLUniformLocation>,
|
location: Option<&WebGLUniformLocation>,
|
||||||
transpose: bool,
|
transpose: bool,
|
||||||
v: Float32ArrayOrUnrestrictedFloatSequence,
|
val: Float32ArrayOrUnrestrictedFloatSequence,
|
||||||
) {
|
) {
|
||||||
let v = match v {
|
self.with_location(location, |location| {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
match location.type_() {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
constants::FLOAT_MAT3 => {}
|
||||||
};
|
_ => return Err(InvalidOperation),
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::FloatMat3, &v) {
|
}
|
||||||
self.send_command(WebGLCommand::UniformMatrix3fv(location.unwrap().id(), transpose, v));
|
let val = match val {
|
||||||
}
|
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
||||||
|
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
||||||
|
};
|
||||||
|
if transpose {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if val.len() < 9 || val.len() % 9 != 0 {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if location.size().is_none() && val.len() != 9 {
|
||||||
|
return Err(InvalidOperation);
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::UniformMatrix3fv(location.id(), val));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
|
@ -3427,15 +3575,29 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
&self,
|
&self,
|
||||||
location: Option<&WebGLUniformLocation>,
|
location: Option<&WebGLUniformLocation>,
|
||||||
transpose: bool,
|
transpose: bool,
|
||||||
v: Float32ArrayOrUnrestrictedFloatSequence,
|
val: Float32ArrayOrUnrestrictedFloatSequence,
|
||||||
) {
|
) {
|
||||||
let v = match v {
|
self.with_location(location, |location| {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
match location.type_() {
|
||||||
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
constants::FLOAT_MAT4 => {}
|
||||||
};
|
_ => return Err(InvalidOperation),
|
||||||
if self.validate_uniform_parameters(location, UniformSetterType::FloatMat4, &v) {
|
}
|
||||||
self.send_command(WebGLCommand::UniformMatrix4fv(location.unwrap().id(), transpose, v));
|
let val = match val {
|
||||||
}
|
Float32ArrayOrUnrestrictedFloatSequence::Float32Array(v) => v.to_vec(),
|
||||||
|
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
|
||||||
|
};
|
||||||
|
if transpose {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if val.len() < 16 || val.len() % 16 != 0 {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if location.size().is_none() && val.len() != 16 {
|
||||||
|
return Err(InvalidOperation);
|
||||||
|
}
|
||||||
|
self.send_command(WebGLCommand::UniformMatrix4fv(location.id(), val));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
|
||||||
|
@ -3937,39 +4099,6 @@ impl LayoutCanvasWebGLRenderingContextHelpers for LayoutDom<WebGLRenderingContex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum UniformSetterType {
|
|
||||||
Int,
|
|
||||||
IntVec2,
|
|
||||||
IntVec3,
|
|
||||||
IntVec4,
|
|
||||||
Float,
|
|
||||||
FloatVec2,
|
|
||||||
FloatVec3,
|
|
||||||
FloatVec4,
|
|
||||||
FloatMat2,
|
|
||||||
FloatMat3,
|
|
||||||
FloatMat4,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UniformSetterType {
|
|
||||||
pub fn element_count(&self) -> usize {
|
|
||||||
match *self {
|
|
||||||
UniformSetterType::Int => 1,
|
|
||||||
UniformSetterType::IntVec2 => 2,
|
|
||||||
UniformSetterType::IntVec3 => 3,
|
|
||||||
UniformSetterType::IntVec4 => 4,
|
|
||||||
UniformSetterType::Float => 1,
|
|
||||||
UniformSetterType::FloatVec2 => 2,
|
|
||||||
UniformSetterType::FloatVec3 => 3,
|
|
||||||
UniformSetterType::FloatVec4 => 4,
|
|
||||||
UniformSetterType::FloatMat2 => 4,
|
|
||||||
UniformSetterType::FloatMat3 => 9,
|
|
||||||
UniformSetterType::FloatMat4 => 16,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(JSTraceable, MallocSizeOf)]
|
#[derive(JSTraceable, MallocSizeOf)]
|
||||||
#[must_root]
|
#[must_root]
|
||||||
pub struct VertexAttribs {
|
pub struct VertexAttribs {
|
||||||
|
|
|
@ -15,26 +15,38 @@ pub struct WebGLUniformLocation {
|
||||||
reflector_: Reflector,
|
reflector_: Reflector,
|
||||||
id: i32,
|
id: i32,
|
||||||
program_id: WebGLProgramId,
|
program_id: WebGLProgramId,
|
||||||
|
size: Option<i32>,
|
||||||
|
type_: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebGLUniformLocation {
|
impl WebGLUniformLocation {
|
||||||
fn new_inherited(id: i32,
|
fn new_inherited(
|
||||||
program_id: WebGLProgramId)
|
id: i32,
|
||||||
-> WebGLUniformLocation {
|
program_id: WebGLProgramId,
|
||||||
WebGLUniformLocation {
|
size: Option<i32>,
|
||||||
|
type_: u32,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
id: id,
|
id,
|
||||||
program_id: program_id,
|
program_id,
|
||||||
|
size,
|
||||||
|
type_,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(window: &Window,
|
pub fn new(
|
||||||
id: i32,
|
window: &Window,
|
||||||
program_id: WebGLProgramId)
|
id: i32,
|
||||||
-> DomRoot<WebGLUniformLocation> {
|
program_id: WebGLProgramId,
|
||||||
reflect_dom_object(Box::new(WebGLUniformLocation::new_inherited(id, program_id)),
|
size: Option<i32>,
|
||||||
window,
|
type_: u32,
|
||||||
WebGLUniformLocationBinding::Wrap)
|
) -> DomRoot<Self> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(Self::new_inherited(id, program_id, size, type_)),
|
||||||
|
window,
|
||||||
|
WebGLUniformLocationBinding::Wrap,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id(&self) -> i32 {
|
pub fn id(&self) -> i32 {
|
||||||
|
@ -44,4 +56,12 @@ impl WebGLUniformLocation {
|
||||||
pub fn program_id(&self) -> WebGLProgramId {
|
pub fn program_id(&self) -> WebGLProgramId {
|
||||||
self.program_id
|
self.program_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> Option<i32> {
|
||||||
|
self.size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_(&self) -> u32 {
|
||||||
|
self.type_
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,20 @@
|
||||||
[type-conversion-test.html]
|
[type-conversion-test.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: CRASH
|
[WebGL test #340: context.bufferData(context.ARRAY_BUFFER, argument, context.STATIC_DRAW) should be undefined. Threw exception TypeError: Not an ArrayBufferView]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #407: context.bufferData(context.ARRAY_BUFFER, argument, context.STATIC_DRAW) should be undefined. Threw exception TypeError: Not an ArrayBufferView]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #474: context.bufferData(context.ARRAY_BUFFER, argument, context.STATIC_DRAW) should be undefined. Threw exception TypeError: Not an ArrayBufferView]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #541: context.bufferData(context.ARRAY_BUFFER, argument, context.STATIC_DRAW) should be undefined. Threw exception TypeError: Not an ArrayBufferView]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #608: context.bufferData(context.ARRAY_BUFFER, argument, context.STATIC_DRAW) should be undefined. Threw exception TypeError: Not an ArrayBufferView]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WebGL test #675: context.bufferData(context.ARRAY_BUFFER, argument, context.STATIC_DRAW) should be undefined. Threw exception TypeError: Not an ArrayBufferView]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
[uniformMatrixBadArgs.html]
|
[uniformMatrixBadArgs.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: CRASH
|
[WebGL test #0: testUniformf]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[uniformfBadArgs.html]
|
|
||||||
type: testharness
|
|
||||||
expected: CRASH
|
|
||||||
[WebGL test #0: testUniformf]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[uniformiBadArgs.html]
|
|
||||||
type: testharness
|
|
||||||
expected: CRASH
|
|
||||||
[WebGL test #0: testUniformf]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
[gl-uniform-arrays.html]
|
[gl-uniform-arrays.html]
|
||||||
type: testharness
|
expected: ERROR
|
||||||
disabled: flaky
|
[Overall test]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
[gl-uniformmatrix4fv.html]
|
|
||||||
type: testharness
|
|
||||||
[WebGL test #0: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL uniformMatrix Conformance Tests]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #0: getError expected: INVALID_VALUE. Was INVALID_OPERATION : should fail with insufficient array size for uniformMatrix2fv]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #2: getError expected: INVALID_VALUE. Was INVALID_OPERATION : should fail with more than 1 array size for uniformMatrix2fv]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #4: getError expected: INVALID_VALUE. Was NO_ERROR : uniformMatrix2fv should return INVALID_VALUE with transpose = true]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #5: getError expected: INVALID_VALUE. Was INVALID_OPERATION : should fail with insufficient array size for uniformMatrix3fv]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #7: getError expected: INVALID_VALUE. Was INVALID_OPERATION : should fail with more than 1 array size for uniformMatrix3fv]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #9: getError expected: INVALID_VALUE. Was NO_ERROR : uniformMatrix3fv should return INVALID_VALUE with transpose = true]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #10: getError expected: INVALID_VALUE. Was INVALID_OPERATION : should fail with insufficient array size for uniformMatrix4fv]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #12: getError expected: INVALID_VALUE. Was INVALID_OPERATION : should fail with more than 1 array size for uniformMatrix4fv]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[WebGL test #14: getError expected: INVALID_VALUE. Was NO_ERROR : uniformMatrix4fv should return INVALID_VALUE with transpose = true]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
[uniform-default-values.html]
|
[uniform-default-values.html]
|
||||||
type: testharness
|
|
||||||
expected: ERROR
|
expected: ERROR
|
||||||
[WebGL uniform default values]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Overall test]
|
[Overall test]
|
||||||
expected: NOTRUN
|
expected: NOTRUN
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
[uniform-location.html]
|
[uniform-location.html]
|
||||||
type: testharness
|
|
||||||
[WebGL test #9: contextA.getUniform(programS, locationSx) should be 333. Threw exception TypeError: contextA.getUniform is not a function]
|
[WebGL test #9: contextA.getUniform(programS, locationSx) should be 333. Threw exception TypeError: contextA.getUniform is not a function]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[uniform-samplers-test.html]
|
|
||||||
type: testharness
|
|
||||||
disabled: flaky
|
|
Loading…
Add table
Add a link
Reference in a new issue