Skip to content

Commit

Permalink
Add initial support for VertexAttribI4*, VertexAttribIPointer
Browse files Browse the repository at this point in the history
Adds initial support for the WebGL2 `VertexAttribI4i`, `VertexAttribI4iv`, `VertexAttribI4ui`, `VertexAttribI4uiv` and `VertexAttribIPointer` calls.
  • Loading branch information
Istvan authored and jdm committed Apr 7, 2020
1 parent 5a26190 commit 62f00df
Show file tree
Hide file tree
Showing 17 changed files with 290 additions and 53 deletions.
7 changes: 6 additions & 1 deletion components/canvas/webgl_thread.rs
Expand Up @@ -1297,7 +1297,6 @@ impl WebGLImpl {
WebGLCommand::GetFragDataLocation(program_id, ref name, ref sender) => {
let location =
gl.get_frag_data_location(program_id.get(), &to_name_in_compiled_shader(name));
assert!(location >= 0);
sender.send(location).unwrap();
},
WebGLCommand::GetUniformLocation(program_id, ref name, ref chan) => {
Expand Down Expand Up @@ -1402,6 +1401,12 @@ impl WebGLImpl {
WebGLCommand::VertexAttrib(attrib_id, x, y, z, w) => {
gl.vertex_attrib_4f(attrib_id, x, y, z, w)
},
WebGLCommand::VertexAttribI(attrib_id, x, y, z, w) => {
gl.vertex_attrib_4i(attrib_id, x, y, z, w)
},
WebGLCommand::VertexAttribU(attrib_id, x, y, z, w) => {
gl.vertex_attrib_4ui(attrib_id, x, y, z, w)
},
WebGLCommand::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset) => {
gl.vertex_attrib_pointer_f32(attrib_id, size, normalized, stride, offset)
},
Expand Down
2 changes: 2 additions & 0 deletions components/canvas_traits/webgl.rs
Expand Up @@ -387,6 +387,8 @@ pub enum WebGLCommand {
UseProgram(Option<WebGLProgramId>),
ValidateProgram(WebGLProgramId),
VertexAttrib(u32, f32, f32, f32, f32),
VertexAttribI(u32, i32, i32, i32, i32),
VertexAttribU(u32, u32, u32, u32, u32),
VertexAttribPointer(u32, i32, u32, bool, i32, u32),
VertexAttribPointer2f(u32, i32, bool, i32, u32),
SetViewport(i32, i32, i32, i32),
Expand Down
22 changes: 21 additions & 1 deletion components/script/dom/vertexarrayobject.rs
Expand Up @@ -3,12 +3,13 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::dom::bindings::cell::{ref_filter_map, DomRefCell, Ref};
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants2;
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use crate::dom::bindings::root::{Dom, MutNullableDom};
use crate::dom::webglbuffer::WebGLBuffer;
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
use canvas_traits::webgl::{
ActiveAttribInfo, WebGLCommand, WebGLError, WebGLResult, WebGLVertexArrayId,
ActiveAttribInfo, WebGLCommand, WebGLError, WebGLResult, WebGLVersion, WebGLVertexArrayId,
};
use std::cell::Cell;

Expand Down Expand Up @@ -85,6 +86,10 @@ impl VertexArrayObject {
})
}

pub fn set_vertex_attrib_type(&self, index: u32, type_: u32) {
self.vertex_attribs.borrow_mut()[index as usize].type_ = type_;
}

pub fn vertex_attrib_pointer(
&self,
index: u32,
Expand All @@ -108,12 +113,27 @@ impl VertexArrayObject {
if stride < 0 || stride > 255 || offset < 0 {
return Err(WebGLError::InvalidValue);
}

let is_webgl2 = match self.context.webgl_version() {
WebGLVersion::WebGL2 => true,
_ => false,
};

let bytes_per_component: i32 = match type_ {
constants::BYTE | constants::UNSIGNED_BYTE => 1,
constants::SHORT | constants::UNSIGNED_SHORT => 2,
constants::FLOAT => 4,
constants::INT | constants::UNSIGNED_INT if is_webgl2 => 4,
constants2::HALF_FLOAT if is_webgl2 => 2,
sparkle::gl::FIXED if is_webgl2 => 4,
constants2::INT_2_10_10_10_REV | constants2::UNSIGNED_INT_2_10_10_10_REV
if is_webgl2 && size == 4 =>
{
4
},
_ => return Err(WebGLError::InvalidEnum),
};

if offset % bytes_per_component as i64 > 0 || stride % bytes_per_component > 0 {
return Err(WebGLError::InvalidOperation);
}
Expand Down
134 changes: 133 additions & 1 deletion components/script/dom/webgl2renderingcontext.rs
Expand Up @@ -25,7 +25,7 @@ use crate::dom::webglprogram::WebGLProgram;
use crate::dom::webglquery::WebGLQuery;
use crate::dom::webglrenderbuffer::WebGLRenderbuffer;
use crate::dom::webglrenderingcontext::{
uniform_get, uniform_typed, LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext,
uniform_get, uniform_typed, LayoutCanvasWebGLRenderingContextHelpers, VertexAttrib, WebGLRenderingContext,
};
use crate::dom::webglsampler::{WebGLSampler, WebGLSamplerValue};
use crate::dom::webglshader::WebGLShader;
Expand Down Expand Up @@ -230,6 +230,62 @@ impl WebGL2RenderingContext {
}
}

fn validate_vertex_attribs_for_draw(&self) {
let program = match self.base.current_program() {
Some(program) => program,
None => return,
};
let groups = [
[
constants::INT,
constants::INT_VEC2,
constants::INT_VEC3,
constants::INT_VEC4,
],
[
constants::UNSIGNED_INT,
constants::UNSIGNED_INT_VEC2,
constants::UNSIGNED_INT_VEC3,
constants::UNSIGNED_INT_VEC4,
],
[
constants::FLOAT,
constants::FLOAT_VEC2,
constants::FLOAT_VEC3,
constants::FLOAT_VEC4,
],
];
let vao = self.current_vao();
for prog_attrib in program.active_attribs().iter() {
let attrib = handle_potential_webgl_error!(
self.base,
vao.get_vertex_attrib(prog_attrib.location as u32)
.ok_or(InvalidOperation),
return
);

let current_vertex_attrib =
self.base.current_vertex_attribs()[prog_attrib.location as usize];
let attrib_data_base_type = if !attrib.enabled_as_array {
match current_vertex_attrib {
VertexAttrib::Int(_, _, _, _) => constants::INT,
VertexAttrib::Uint(_, _, _, _) => constants::UNSIGNED_INT,
VertexAttrib::Float(_, _, _, _) => constants::FLOAT,
}
} else {
attrib.type_
};

let contains = groups
.iter()
.find(|g| g.contains(&attrib_data_base_type) && g.contains(&prog_attrib.type_));
if contains.is_none() {
self.base.webgl_error(InvalidOperation);
return;
}
}
}

pub fn base_context(&self) -> DomRoot<WebGLRenderingContext> {
DomRoot::from_ref(&*self.base)
}
Expand Down Expand Up @@ -739,6 +795,28 @@ impl WebGL2RenderingContext {

true
}

fn vertex_attrib_i(&self, index: u32, x: i32, y: i32, z: i32, w: i32) {
if index >= self.base.limits().max_vertex_attribs {
return self.base.webgl_error(InvalidValue);
}
self.base.current_vertex_attribs()[index as usize] = VertexAttrib::Int(x, y, z, w);
self.current_vao()
.set_vertex_attrib_type(index, constants::INT);
self.base
.send_command(WebGLCommand::VertexAttribI(index, x, y, z, w));
}

fn vertex_attrib_u(&self, index: u32, x: u32, y: u32, z: u32, w: u32) {
if index >= self.base.limits().max_vertex_attribs {
return self.base.webgl_error(InvalidValue);
}
self.base.current_vertex_attribs()[index as usize] = VertexAttrib::Uint(x, y, z, w);
self.current_vao()
.set_vertex_attrib_type(index, constants::UNSIGNED_INT);
self.base
.send_command(WebGLCommand::VertexAttribU(index, x, y, z, w));
}
}

impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
Expand Down Expand Up @@ -1569,12 +1647,14 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11
fn DrawArrays(&self, mode: u32, first: i32, count: i32) {
self.validate_uniform_block_for_draw();
self.validate_vertex_attribs_for_draw();
self.base.DrawArrays(mode, first, count)
}

/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11
fn DrawElements(&self, mode: u32, count: i32, type_: u32, offset: i64) {
self.validate_uniform_block_for_draw();
self.validate_vertex_attribs_for_draw();
self.base.DrawElements(mode, count, type_, offset)
}

Expand Down Expand Up @@ -2591,6 +2671,40 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
self.base.VertexAttrib4fv(indx, v)
}

/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8
fn VertexAttribI4i(&self, index: u32, x: i32, y: i32, z: i32, w: i32) {
self.vertex_attrib_i(index, x, y, z, w)
}

/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8
fn VertexAttribI4iv(&self, index: u32, v: Int32ArrayOrLongSequence) {
let values = match v {
Int32ArrayOrLongSequence::Int32Array(v) => v.to_vec(),
Int32ArrayOrLongSequence::LongSequence(v) => v,
};
if values.len() < 4 {
return self.base.webgl_error(InvalidValue);
}
self.vertex_attrib_i(index, values[0], values[1], values[2], values[3]);
}

/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8
fn VertexAttribI4ui(&self, index: u32, x: u32, y: u32, z: u32, w: u32) {
self.vertex_attrib_u(index, x, y, z, w)
}

/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8
fn VertexAttribI4uiv(&self, index: u32, v: Uint32ArrayOrUnsignedLongSequence) {
let values = match v {
Uint32ArrayOrUnsignedLongSequence::Uint32Array(v) => v.to_vec(),
Uint32ArrayOrUnsignedLongSequence::UnsignedLongSequence(v) => v,
};
if values.len() < 4 {
return self.base.webgl_error(InvalidValue);
}
self.vertex_attrib_u(index, values[0], values[1], values[2], values[3]);
}

/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
fn VertexAttribPointer(
&self,
Expand All @@ -2605,6 +2719,21 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
.VertexAttribPointer(attrib_id, size, data_type, normalized, stride, offset)
}

/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8
fn VertexAttribIPointer(&self, index: u32, size: i32, type_: u32, stride: i32, offset: i64) {
match type_ {
constants::BYTE |
constants::UNSIGNED_BYTE |
constants::SHORT |
constants::UNSIGNED_SHORT |
constants::INT |
constants::UNSIGNED_INT => {},
_ => return self.base.webgl_error(InvalidEnum),
};
self.base
.VertexAttribPointer(index, size, type_, false, stride, offset)
}

/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4
fn Viewport(&self, x: i32, y: i32, width: i32, height: i32) {
self.base.Viewport(x, y, width, height)
Expand Down Expand Up @@ -2820,6 +2949,7 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.9
fn DrawArraysInstanced(&self, mode: u32, first: i32, count: i32, primcount: i32) {
self.validate_uniform_block_for_draw();
self.validate_vertex_attribs_for_draw();
handle_potential_webgl_error!(
self.base,
self.base
Expand All @@ -2837,6 +2967,7 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
primcount: i32,
) {
self.validate_uniform_block_for_draw();
self.validate_vertex_attribs_for_draw();
handle_potential_webgl_error!(
self.base,
self.base
Expand All @@ -2859,6 +2990,7 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
return;
}
self.validate_uniform_block_for_draw();
self.validate_vertex_attribs_for_draw();
handle_potential_webgl_error!(
self.base,
self.base
Expand Down

0 comments on commit 62f00df

Please sign in to comment.