mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Store vertex attribs data in DOM and optimise GetVertexAttrib
This commit is contained in:
parent
0814bd6699
commit
cde6023ed4
3 changed files with 143 additions and 168 deletions
|
@ -746,8 +746,6 @@ impl WebGLImpl {
|
|||
Self::get_renderbuffer_parameter(ctx.gl(), target, pname, chan),
|
||||
WebGLCommand::GetFramebufferAttachmentParameter(target, attachment, pname, ref chan) =>
|
||||
Self::get_framebuffer_attachment_parameter(ctx.gl(), target, attachment, pname, chan),
|
||||
WebGLCommand::GetVertexAttribOffset(index, pname, ref chan) =>
|
||||
Self::vertex_attrib_offset(ctx.gl(), index, pname, chan),
|
||||
WebGLCommand::GetShaderPrecisionFormat(shader_type, precision_type, ref chan) =>
|
||||
Self::shader_precision_format(ctx.gl(), shader_type, precision_type, chan),
|
||||
WebGLCommand::GetExtensions(ref chan) =>
|
||||
|
@ -949,56 +947,12 @@ impl WebGLImpl {
|
|||
}
|
||||
sender.send(value[0]).unwrap()
|
||||
}
|
||||
WebGLCommand::GetVertexAttribBool(index, param, ref sender) => {
|
||||
// FIXME(nox): https://github.com/servo/servo/issues/20608
|
||||
let mut max = [0];
|
||||
unsafe {
|
||||
ctx.gl().get_integer_v(gl::MAX_VERTEX_ATTRIBS, &mut max);
|
||||
}
|
||||
let result = if index >= max[0] as u32 {
|
||||
Err(WebGLError::InvalidValue)
|
||||
} else {
|
||||
let mut value = [0];
|
||||
unsafe {
|
||||
ctx.gl().get_vertex_attrib_iv(index, param as u32, &mut value);
|
||||
}
|
||||
Ok(value[0] != 0)
|
||||
};
|
||||
sender.send(result).unwrap();
|
||||
}
|
||||
WebGLCommand::GetVertexAttribInt(index, param, ref sender) => {
|
||||
// FIXME(nox): https://github.com/servo/servo/issues/20608
|
||||
let mut max = [0];
|
||||
unsafe {
|
||||
ctx.gl().get_integer_v(gl::MAX_VERTEX_ATTRIBS, &mut max);
|
||||
}
|
||||
let result = if index >= max[0] as u32 {
|
||||
Err(WebGLError::InvalidValue)
|
||||
} else {
|
||||
let mut value = [0];
|
||||
unsafe {
|
||||
ctx.gl().get_vertex_attrib_iv(index, param as u32, &mut value);
|
||||
}
|
||||
Ok(value[0])
|
||||
};
|
||||
sender.send(result).unwrap();
|
||||
}
|
||||
WebGLCommand::GetVertexAttribFloat4(index, param, ref sender) => {
|
||||
// FIXME(nox): https://github.com/servo/servo/issues/20608
|
||||
let mut max = [0];
|
||||
unsafe {
|
||||
ctx.gl().get_integer_v(gl::MAX_VERTEX_ATTRIBS, &mut max);
|
||||
}
|
||||
let result = if index >= max[0] as u32 {
|
||||
Err(WebGLError::InvalidValue)
|
||||
} else {
|
||||
WebGLCommand::GetCurrentVertexAttrib(index, ref sender) => {
|
||||
let mut value = [0.; 4];
|
||||
unsafe {
|
||||
ctx.gl().get_vertex_attrib_fv(index, param as u32, &mut value);
|
||||
ctx.gl().get_vertex_attrib_fv(index, gl::CURRENT_VERTEX_ATTRIB, &mut value);
|
||||
}
|
||||
Ok(value)
|
||||
};
|
||||
sender.send(result).unwrap();
|
||||
sender.send(value).unwrap();
|
||||
}
|
||||
WebGLCommand::GetTexParameterFloat(target, param, ref sender) => {
|
||||
sender.send(ctx.gl().get_tex_parameter_fv(target, param as u32)).unwrap();
|
||||
|
@ -1092,14 +1046,6 @@ impl WebGLImpl {
|
|||
chan.send(()).unwrap();
|
||||
}
|
||||
|
||||
fn vertex_attrib_offset(gl: &gl::Gl,
|
||||
index: u32,
|
||||
pname: u32,
|
||||
chan: &WebGLSender<isize>) {
|
||||
let result = gl.get_vertex_attrib_pointer_v(index, pname);
|
||||
chan.send(result).unwrap();
|
||||
}
|
||||
|
||||
fn shader_precision_format(gl: &gl::Gl,
|
||||
shader_type: u32,
|
||||
precision_type: u32,
|
||||
|
|
|
@ -211,7 +211,6 @@ pub enum WebGLCommand {
|
|||
GetActiveUniform(WebGLProgramId, u32, WebGLSender<WebGLResult<(i32, u32, String)>>),
|
||||
GetAttribLocation(WebGLProgramId, String, WebGLSender<Option<i32>>),
|
||||
GetUniformLocation(WebGLProgramId, String, WebGLSender<Option<i32>>),
|
||||
GetVertexAttribOffset(u32, u32, WebGLSender<isize>),
|
||||
GetShaderInfoLog(WebGLShaderId, WebGLSender<String>),
|
||||
GetProgramInfoLog(WebGLProgramId, WebGLSender<String>),
|
||||
GetFramebufferAttachmentParameter(u32, u32, u32, WebGLSender<i32>),
|
||||
|
@ -278,9 +277,7 @@ pub enum WebGLCommand {
|
|||
GetProgramParameterInt(WebGLProgramId, ProgramParameterInt, WebGLSender<i32>),
|
||||
GetShaderParameterBool(WebGLShaderId, ShaderParameterBool, WebGLSender<bool>),
|
||||
GetShaderParameterInt(WebGLShaderId, ShaderParameterInt, WebGLSender<i32>),
|
||||
GetVertexAttribBool(u32, VertexAttribBool, WebGLSender<WebGLResult<bool>>),
|
||||
GetVertexAttribInt(u32, VertexAttribInt, WebGLSender<WebGLResult<i32>>),
|
||||
GetVertexAttribFloat4(u32, VertexAttribFloat4, WebGLSender<WebGLResult<[f32; 4]>>),
|
||||
GetCurrentVertexAttrib(u32, WebGLSender<[f32; 4]>),
|
||||
GetTexParameterFloat(u32, TexParameterFloat, WebGLSender<f32>),
|
||||
GetTexParameterInt(u32, TexParameterInt, WebGLSender<i32>),
|
||||
TexParameteri(u32, TexParameterInt, i32),
|
||||
|
@ -568,20 +565,3 @@ parameters! {
|
|||
}),
|
||||
}
|
||||
}
|
||||
|
||||
parameters! {
|
||||
VertexAttrib {
|
||||
Bool(VertexAttribBool {
|
||||
VertexAttribArrayEnabled = gl::VERTEX_ATTRIB_ARRAY_ENABLED,
|
||||
VertexAttribArrayNormalized = gl::VERTEX_ATTRIB_ARRAY_NORMALIZED,
|
||||
}),
|
||||
Int(VertexAttribInt {
|
||||
VertexAttribArraySize = gl::VERTEX_ATTRIB_ARRAY_SIZE,
|
||||
VertexAttribArrayStride = gl::VERTEX_ATTRIB_ARRAY_STRIDE,
|
||||
VertexAttribArrayType = gl::VERTEX_ATTRIB_ARRAY_TYPE,
|
||||
}),
|
||||
Float4(VertexAttribFloat4 {
|
||||
CurrentVertexAttrib = gl::CURRENT_VERTEX_ATTRIB,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt};
|
||||
use canvas_traits::canvas::{byte_swap, multiply_u8_pixel};
|
||||
use canvas_traits::webgl::{DOMToTextureCommand, Parameter, ProgramParameter};
|
||||
use canvas_traits::webgl::{ShaderParameter, TexParameter, VertexAttrib, WebGLCommand};
|
||||
use canvas_traits::webgl::{ShaderParameter, TexParameter, WebGLCommand};
|
||||
use canvas_traits::webgl::{WebGLContextShareMode, WebGLError};
|
||||
use canvas_traits::webgl::{WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender};
|
||||
use canvas_traits::webgl::{WebGLResult, WebGLSLVersion, WebGLVersion};
|
||||
|
@ -2579,43 +2579,44 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
#[allow(unsafe_code)]
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
|
||||
unsafe fn GetVertexAttrib(&self, cx: *mut JSContext, index: u32, param: u32) -> JSVal {
|
||||
if index == 0 && param == constants::CURRENT_VERTEX_ATTRIB {
|
||||
rooted!(in(cx) let mut result = UndefinedValue());
|
||||
let data = handle_potential_webgl_error!(
|
||||
self,
|
||||
self.vertex_attribs.get(index).ok_or(InvalidValue),
|
||||
return NullValue()
|
||||
);
|
||||
if param == constants::CURRENT_VERTEX_ATTRIB {
|
||||
let value = if index == 0 {
|
||||
let (x, y, z, w) = self.current_vertex_attrib_0.get();
|
||||
let attrib = vec![x, y, z, w];
|
||||
attrib.to_jsval(cx, result.handle_mut());
|
||||
return result.get()
|
||||
}
|
||||
|
||||
if param == constants::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING {
|
||||
rooted!(in(cx) let mut jsval = NullValue());
|
||||
if let Some(buffer) = self.vertex_attribs.get(index) {
|
||||
buffer.to_jsval(cx, jsval.handle_mut());
|
||||
}
|
||||
return jsval.get();
|
||||
}
|
||||
|
||||
match handle_potential_webgl_error!(self, VertexAttrib::from_u32(param), return NullValue()) {
|
||||
VertexAttrib::Bool(param) => {
|
||||
[x, y, z, w]
|
||||
} else {
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
self.send_command(WebGLCommand::GetVertexAttribBool(index, param, sender));
|
||||
let value = handle_potential_webgl_error!(self, receiver.recv().unwrap(), return NullValue());
|
||||
BooleanValue(value)
|
||||
}
|
||||
VertexAttrib::Int(param) => {
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
self.send_command(WebGLCommand::GetVertexAttribInt(index, param, sender));
|
||||
let value = handle_potential_webgl_error!(self, receiver.recv().unwrap(), return NullValue());
|
||||
Int32Value(value)
|
||||
}
|
||||
VertexAttrib::Float4(param) => {
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
self.send_command(WebGLCommand::GetVertexAttribFloat4(index, param, sender));
|
||||
let value = handle_potential_webgl_error!(self, receiver.recv().unwrap(), return NullValue());
|
||||
self.send_command(WebGLCommand::GetCurrentVertexAttrib(index, sender));
|
||||
receiver.recv().unwrap()
|
||||
};
|
||||
// FIXME(nox): https://github.com/servo/servo/issues/20655
|
||||
rooted!(in(cx) let mut result = UndefinedValue());
|
||||
value.to_jsval(cx, result.handle_mut());
|
||||
result.get()
|
||||
return result.get();
|
||||
}
|
||||
|
||||
match param {
|
||||
constants::VERTEX_ATTRIB_ARRAY_ENABLED => BooleanValue(data.enabled_as_array),
|
||||
constants::VERTEX_ATTRIB_ARRAY_SIZE => Int32Value(data.size as i32),
|
||||
constants::VERTEX_ATTRIB_ARRAY_TYPE => Int32Value(data.type_ as i32),
|
||||
constants::VERTEX_ATTRIB_ARRAY_NORMALIZED => BooleanValue(data.normalized),
|
||||
constants::VERTEX_ATTRIB_ARRAY_STRIDE => Int32Value(data.stride as i32),
|
||||
constants::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING => {
|
||||
rooted!(in(cx) let mut jsval = NullValue());
|
||||
if let Some(data) = self.vertex_attribs.get(index) {
|
||||
if let Some(buffer) = data.buffer() {
|
||||
buffer.to_jsval(cx, jsval.handle_mut());
|
||||
}
|
||||
}
|
||||
jsval.get()
|
||||
}
|
||||
_ => {
|
||||
self.webgl_error(InvalidEnum);
|
||||
NullValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2626,10 +2627,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
self.webgl_error(InvalidEnum);
|
||||
return 0;
|
||||
}
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
self.send_command(WebGLCommand::GetVertexAttribOffset(index, pname, sender));
|
||||
|
||||
receiver.recv().unwrap() as i64
|
||||
let data = handle_potential_webgl_error!(
|
||||
self,
|
||||
self.vertex_attribs.get(index).ok_or(InvalidValue),
|
||||
return 0
|
||||
);
|
||||
data.offset as i64
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
|
||||
|
@ -3316,49 +3319,30 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||
fn VertexAttribPointer(&self, attrib_id: u32, size: i32, data_type: u32,
|
||||
normalized: bool, stride: i32, offset: i64) {
|
||||
if attrib_id >= self.limits.max_vertex_attribs {
|
||||
return self.webgl_error(InvalidValue);
|
||||
}
|
||||
fn VertexAttribPointer(
|
||||
&self,
|
||||
index: u32,
|
||||
size: i32,
|
||||
type_: u32,
|
||||
normalized: bool,
|
||||
stride: i32,
|
||||
offset: i64,
|
||||
) {
|
||||
handle_potential_webgl_error!(
|
||||
self,
|
||||
self.vertex_attribs.set_pointer(
|
||||
index,
|
||||
size,
|
||||
type_,
|
||||
normalized,
|
||||
stride,
|
||||
offset,
|
||||
self.bound_buffer_array.get().as_ref().map(|buffer| &**buffer),
|
||||
),
|
||||
return
|
||||
);
|
||||
|
||||
// GLES spec: If offset or stride is negative, an INVALID_VALUE error will be generated
|
||||
// WebGL spec: the maximum supported stride is 255
|
||||
if stride < 0 || stride > 255 || offset < 0 {
|
||||
return self.webgl_error(InvalidValue);
|
||||
}
|
||||
if size < 1 || size > 4 {
|
||||
return self.webgl_error(InvalidValue);
|
||||
}
|
||||
|
||||
let buffer_array = match self.bound_buffer_array.get() {
|
||||
Some(buffer) => buffer,
|
||||
None => {
|
||||
return self.webgl_error(InvalidOperation);
|
||||
}
|
||||
};
|
||||
|
||||
// stride and offset must be multiple of data_type
|
||||
match data_type {
|
||||
constants::BYTE | constants::UNSIGNED_BYTE => {},
|
||||
constants::SHORT | constants::UNSIGNED_SHORT => {
|
||||
if offset % 2 > 0 || stride % 2 > 0 {
|
||||
return self.webgl_error(InvalidOperation);
|
||||
}
|
||||
},
|
||||
constants::FLOAT => {
|
||||
if offset % 4 > 0 || stride % 4 > 0 {
|
||||
return self.webgl_error(InvalidOperation);
|
||||
}
|
||||
},
|
||||
_ => return self.webgl_error(InvalidEnum),
|
||||
|
||||
}
|
||||
|
||||
self.vertex_attribs.bind_buffer(attrib_id, &buffer_array);
|
||||
|
||||
let msg = WebGLCommand::VertexAttribPointer(attrib_id, size, data_type, normalized, stride, offset as u32);
|
||||
self.send_command(msg);
|
||||
self.send_command(WebGLCommand::VertexAttribPointer(index, size, type_, normalized, stride, offset as u32));
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4
|
||||
|
@ -3815,6 +3799,57 @@ impl VertexAttribs {
|
|||
self.attribs.borrow_mut().clone_from_slice(&other.attribs.borrow());
|
||||
}
|
||||
|
||||
pub fn set_pointer(
|
||||
&self,
|
||||
index: u32,
|
||||
size: i32,
|
||||
type_: u32,
|
||||
normalized: bool,
|
||||
stride: i32,
|
||||
offset: i64,
|
||||
buffer: Option<&WebGLBuffer>,
|
||||
) -> WebGLResult<()> {
|
||||
let mut attribs = self.attribs.borrow_mut();
|
||||
let data = attribs.get_mut(index as usize).ok_or(InvalidValue)?;
|
||||
|
||||
if size < 1 || size > 4 {
|
||||
return Err(InvalidValue);
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#BUFFER_OFFSET_AND_STRIDE
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#VERTEX_STRIDE
|
||||
if stride < 0 || stride > 255 || offset < 0 {
|
||||
return Err(InvalidValue);
|
||||
}
|
||||
match type_ {
|
||||
constants::BYTE | constants::UNSIGNED_BYTE => {},
|
||||
constants::SHORT | constants::UNSIGNED_SHORT => {
|
||||
if offset % 2 > 0 || stride % 2 > 0 {
|
||||
return Err(InvalidOperation);
|
||||
}
|
||||
},
|
||||
constants::FLOAT => {
|
||||
if offset % 4 > 0 || stride % 4 > 0 {
|
||||
return Err(InvalidOperation);
|
||||
}
|
||||
},
|
||||
_ => return Err(InvalidEnum),
|
||||
}
|
||||
|
||||
let buffer = buffer.ok_or(InvalidOperation)?;
|
||||
|
||||
*data = VertexAttribData {
|
||||
enabled_as_array: data.enabled_as_array,
|
||||
size: size as u8,
|
||||
type_,
|
||||
normalized,
|
||||
stride: stride as u8,
|
||||
offset: offset as u32,
|
||||
buffer: Some(Dom::from_ref(buffer)),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn borrow(&self) -> Ref<[VertexAttribData]> {
|
||||
Ref::map(self.attribs.borrow(), |attribs| &**attribs)
|
||||
}
|
||||
|
@ -3827,20 +3862,14 @@ impl VertexAttribs {
|
|||
}
|
||||
}
|
||||
|
||||
fn get(&self, index: u32) -> Option<Ref<WebGLBuffer>> {
|
||||
ref_filter_map(self.attribs.borrow(), |attribs| {
|
||||
attribs[index as usize].buffer.as_ref().map(|buffer| &**buffer)
|
||||
})
|
||||
fn get(&self, index: u32) -> Option<Ref<VertexAttribData>> {
|
||||
ref_filter_map(self.attribs.borrow(), |attribs| attribs.get(index as usize))
|
||||
}
|
||||
|
||||
fn enabled_as_array(&self, index: u32, value: bool) {
|
||||
self.attribs.borrow_mut()[index as usize].enabled_as_array = value;
|
||||
}
|
||||
|
||||
fn bind_buffer(&self, index: u32, buffer: &WebGLBuffer) {
|
||||
self.attribs.borrow_mut()[index as usize].buffer = Some(Dom::from_ref(buffer));
|
||||
}
|
||||
|
||||
fn validate_for_draw(&self) -> WebGLResult<()> {
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.2
|
||||
if self.borrow().iter().any(|data| data.enabled_as_array && data.buffer.is_none()) {
|
||||
|
@ -3850,13 +3879,33 @@ impl VertexAttribs {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, JSTraceable, MallocSizeOf)]
|
||||
#[derive(Clone, JSTraceable, MallocSizeOf)]
|
||||
#[must_root]
|
||||
pub struct VertexAttribData {
|
||||
enabled_as_array: bool,
|
||||
size: u8,
|
||||
type_: u32,
|
||||
normalized: bool,
|
||||
stride: u8,
|
||||
offset: u32,
|
||||
buffer: Option<Dom<WebGLBuffer>>,
|
||||
}
|
||||
|
||||
impl Default for VertexAttribData {
|
||||
#[allow(unrooted_must_root)]
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
enabled_as_array: false,
|
||||
size: 4,
|
||||
type_: constants::FLOAT,
|
||||
normalized: false,
|
||||
stride: 0,
|
||||
offset: 0,
|
||||
buffer: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VertexAttribData {
|
||||
pub fn buffer(&self) -> Option<&WebGLBuffer> {
|
||||
self.buffer.as_ref().map(|b| &**b)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue