aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/mod.rs2
-rw-r--r--components/script/dom/vertexarrayobject.rs296
-rw-r--r--components/script/dom/webgl2renderingcontext.rs42
-rw-r--r--components/script/dom/webglrenderingcontext.rs290
-rw-r--r--components/script/dom/webglvertexarrayobject.rs100
-rw-r--r--components/script/dom/webglvertexarrayobjectoes.rs251
-rw-r--r--components/script/dom/webidls/WebGL2RenderingContext.webidl8
-rw-r--r--components/script/dom/webidls/WebGLVertexArrayObject.webidl11
8 files changed, 682 insertions, 318 deletions
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index 0e1b4789ad4..3691ba5a299 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -527,6 +527,7 @@ pub mod userscripts;
pub mod validation;
pub mod validitystate;
pub mod values;
+pub mod vertexarrayobject;
pub mod videotrack;
pub mod videotracklist;
pub mod virtualmethods;
@@ -560,6 +561,7 @@ pub mod webglsync;
pub mod webgltexture;
pub mod webgltransformfeedback;
pub mod webgluniformlocation;
+pub mod webglvertexarrayobject;
pub mod webglvertexarrayobjectoes;
pub mod websocket;
pub mod wheelevent;
diff --git a/components/script/dom/vertexarrayobject.rs b/components/script/dom/vertexarrayobject.rs
new file mode 100644
index 00000000000..025cff9194a
--- /dev/null
+++ b/components/script/dom/vertexarrayobject.rs
@@ -0,0 +1,296 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use crate::dom::bindings::cell::{ref_filter_map, DomRefCell, Ref};
+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,
+};
+use std::cell::Cell;
+
+#[derive(JSTraceable, MallocSizeOf)]
+#[unrooted_must_root_lint::must_root]
+pub struct VertexArrayObject {
+ context: Dom<WebGLRenderingContext>,
+ id: Option<WebGLVertexArrayId>,
+ ever_bound: Cell<bool>,
+ is_deleted: Cell<bool>,
+ vertex_attribs: DomRefCell<Box<[VertexAttribData]>>,
+ element_array_buffer: MutNullableDom<WebGLBuffer>,
+}
+
+impl VertexArrayObject {
+ pub fn new(context: &WebGLRenderingContext, id: Option<WebGLVertexArrayId>) -> Self {
+ let max_vertex_attribs = context.limits().max_vertex_attribs as usize;
+ Self {
+ context: Dom::from_ref(context),
+ id,
+ ever_bound: Default::default(),
+ is_deleted: Default::default(),
+ vertex_attribs: DomRefCell::new(vec![Default::default(); max_vertex_attribs].into()),
+ element_array_buffer: Default::default(),
+ }
+ }
+
+ pub fn id(&self) -> Option<WebGLVertexArrayId> {
+ self.id
+ }
+
+ pub fn is_deleted(&self) -> bool {
+ self.is_deleted.get()
+ }
+
+ pub fn delete(&self, fallible: bool) {
+ assert!(self.id.is_some());
+ if self.is_deleted.get() {
+ return;
+ }
+ self.is_deleted.set(true);
+ let cmd = WebGLCommand::DeleteVertexArray(self.id.unwrap());
+ if fallible {
+ self.context.send_command_ignored(cmd);
+ } else {
+ self.context.send_command(cmd);
+ }
+
+ for attrib_data in &**self.vertex_attribs.borrow() {
+ if let Some(buffer) = attrib_data.buffer() {
+ buffer.decrement_attached_counter();
+ }
+ }
+ if let Some(buffer) = self.element_array_buffer.get() {
+ buffer.decrement_attached_counter();
+ }
+ }
+
+ pub fn ever_bound(&self) -> bool {
+ return self.ever_bound.get();
+ }
+
+ pub fn set_ever_bound(&self) {
+ self.ever_bound.set(true);
+ }
+
+ pub fn element_array_buffer(&self) -> &MutNullableDom<WebGLBuffer> {
+ &self.element_array_buffer
+ }
+
+ pub fn get_vertex_attrib(&self, index: u32) -> Option<Ref<VertexAttribData>> {
+ ref_filter_map(self.vertex_attribs.borrow(), |attribs| {
+ attribs.get(index as usize)
+ })
+ }
+
+ pub fn vertex_attrib_pointer(
+ &self,
+ index: u32,
+ size: i32,
+ type_: u32,
+ normalized: bool,
+ stride: i32,
+ offset: i64,
+ ) -> WebGLResult<()> {
+ let mut attribs = self.vertex_attribs.borrow_mut();
+ let data = attribs
+ .get_mut(index as usize)
+ .ok_or(WebGLError::InvalidValue)?;
+
+ if size < 1 || size > 4 {
+ return Err(WebGLError::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(WebGLError::InvalidValue);
+ }
+ let bytes_per_component: i32 = match type_ {
+ constants::BYTE | constants::UNSIGNED_BYTE => 1,
+ constants::SHORT | constants::UNSIGNED_SHORT => 2,
+ constants::FLOAT => 4,
+ _ => return Err(WebGLError::InvalidEnum),
+ };
+ if offset % bytes_per_component as i64 > 0 || stride % bytes_per_component > 0 {
+ return Err(WebGLError::InvalidOperation);
+ }
+
+ let buffer = self.context.array_buffer();
+ match buffer {
+ Some(ref buffer) => buffer.increment_attached_counter(),
+ None if offset != 0 => {
+ // https://github.com/KhronosGroup/WebGL/pull/2228
+ return Err(WebGLError::InvalidOperation);
+ },
+ _ => {},
+ }
+ self.context.send_command(WebGLCommand::VertexAttribPointer(
+ index,
+ size,
+ type_,
+ normalized,
+ stride,
+ offset as u32,
+ ));
+ if let Some(old) = data.buffer() {
+ old.decrement_attached_counter();
+ }
+
+ *data = VertexAttribData {
+ enabled_as_array: data.enabled_as_array,
+ size: size as u8,
+ type_,
+ bytes_per_vertex: size as u8 * bytes_per_component as u8,
+ normalized,
+ stride: stride as u8,
+ offset: offset as u32,
+ buffer: buffer.map(|b| Dom::from_ref(&*b)),
+ divisor: data.divisor,
+ };
+
+ Ok(())
+ }
+
+ pub fn vertex_attrib_divisor(&self, index: u32, value: u32) {
+ self.vertex_attribs.borrow_mut()[index as usize].divisor = value;
+ }
+
+ pub fn enabled_vertex_attrib_array(&self, index: u32, value: bool) {
+ self.vertex_attribs.borrow_mut()[index as usize].enabled_as_array = value;
+ }
+
+ pub fn unbind_buffer(&self, buffer: &WebGLBuffer) {
+ for attrib in &mut **self.vertex_attribs.borrow_mut() {
+ if let Some(b) = attrib.buffer() {
+ if b.id() != buffer.id() {
+ continue;
+ }
+ b.decrement_attached_counter();
+ }
+ attrib.buffer = None;
+ }
+ if self
+ .element_array_buffer
+ .get()
+ .map_or(false, |b| buffer == &*b)
+ {
+ buffer.decrement_attached_counter();
+ self.element_array_buffer.set(None);
+ }
+ }
+
+ pub fn validate_for_draw(
+ &self,
+ required_len: u32,
+ instance_count: u32,
+ active_attribs: &[ActiveAttribInfo],
+ ) -> WebGLResult<()> {
+ // TODO(nox): Cache limits per VAO.
+ let attribs = self.vertex_attribs.borrow();
+ // https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.2
+ if attribs
+ .iter()
+ .any(|data| data.enabled_as_array && data.buffer.is_none())
+ {
+ return Err(WebGLError::InvalidOperation);
+ }
+ let mut has_active_attrib = false;
+ let mut has_divisor_0 = false;
+ for active_info in active_attribs {
+ if active_info.location < 0 {
+ continue;
+ }
+ has_active_attrib = true;
+ let attrib = &attribs[active_info.location as usize];
+ if attrib.divisor == 0 {
+ has_divisor_0 = true;
+ }
+ if !attrib.enabled_as_array {
+ continue;
+ }
+ // https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.6
+ if required_len > 0 && instance_count > 0 {
+ let max_vertices = attrib.max_vertices();
+ if attrib.divisor == 0 {
+ if max_vertices < required_len {
+ return Err(WebGLError::InvalidOperation);
+ }
+ } else if max_vertices
+ .checked_mul(attrib.divisor)
+ .map_or(false, |v| v < instance_count)
+ {
+ return Err(WebGLError::InvalidOperation);
+ }
+ }
+ }
+ if has_active_attrib && !has_divisor_0 {
+ return Err(WebGLError::InvalidOperation);
+ }
+ Ok(())
+ }
+}
+
+impl Drop for VertexArrayObject {
+ fn drop(&mut self) {
+ if self.id.is_some() {
+ self.delete(true);
+ }
+ }
+}
+
+#[derive(Clone, JSTraceable, MallocSizeOf)]
+#[unrooted_must_root_lint::must_root]
+pub struct VertexAttribData {
+ pub enabled_as_array: bool,
+ pub size: u8,
+ pub type_: u32,
+ bytes_per_vertex: u8,
+ pub normalized: bool,
+ pub stride: u8,
+ pub offset: u32,
+ pub buffer: Option<Dom<WebGLBuffer>>,
+ pub divisor: u32,
+}
+
+impl Default for VertexAttribData {
+ #[allow(unrooted_must_root)]
+ fn default() -> Self {
+ Self {
+ enabled_as_array: false,
+ size: 4,
+ type_: constants::FLOAT,
+ bytes_per_vertex: 16,
+ normalized: false,
+ stride: 0,
+ offset: 0,
+ buffer: None,
+ divisor: 0,
+ }
+ }
+}
+
+impl VertexAttribData {
+ pub fn buffer(&self) -> Option<&WebGLBuffer> {
+ self.buffer.as_ref().map(|b| &**b)
+ }
+
+ pub fn max_vertices(&self) -> u32 {
+ let capacity = (self.buffer().unwrap().capacity() as u32).saturating_sub(self.offset);
+ if capacity < self.bytes_per_vertex as u32 {
+ 0
+ } else if self.stride == 0 {
+ capacity / self.bytes_per_vertex as u32
+ } else if self.stride < self.bytes_per_vertex {
+ (capacity - (self.bytes_per_vertex - self.stride) as u32) / self.stride as u32
+ } else {
+ let mut max = capacity / self.stride as u32;
+ if capacity % self.stride as u32 >= self.bytes_per_vertex as u32 {
+ max += 1;
+ }
+ max
+ }
+ }
+}
diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs
index 1c458778a1c..699631de5d2 100644
--- a/components/script/dom/webgl2renderingcontext.rs
+++ b/components/script/dom/webgl2renderingcontext.rs
@@ -36,6 +36,7 @@ use crate::dom::webglsync::WebGLSync;
use crate::dom::webgltexture::WebGLTexture;
use crate::dom::webgltransformfeedback::WebGLTransformFeedback;
use crate::dom::webgluniformlocation::WebGLUniformLocation;
+use crate::dom::webglvertexarrayobject::WebGLVertexArrayObject;
use crate::dom::window::Window;
use crate::js::conversions::ToJSValConvertible;
use crate::script_runtime::JSContext;
@@ -181,6 +182,10 @@ impl WebGL2RenderingContext {
self.base.recreate(size)
}
+ pub fn current_vao(&self) -> DomRoot<WebGLVertexArrayObject> {
+ self.base.current_vao_webgl2()
+ }
+
pub fn base_context(&self) -> DomRoot<WebGLRenderingContext> {
DomRoot::from_ref(&*self.base)
}
@@ -193,6 +198,7 @@ impl WebGL2RenderingContext {
constants::PIXEL_UNPACK_BUFFER => Ok(self.bound_pixel_unpack_buffer.get()),
constants::TRANSFORM_FEEDBACK_BUFFER => Ok(self.bound_transform_feedback_buffer.get()),
constants::UNIFORM_BUFFER => Ok(self.bound_uniform_buffer.get()),
+ constants::ELEMENT_ARRAY_BUFFER => Ok(self.current_vao().element_array_buffer().get()),
_ => self.base.bound_buffer(target),
}
}
@@ -777,6 +783,15 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
self.current_transform_feedback.get()
);
},
+ constants::ELEMENT_ARRAY_BUFFER_BINDING => unsafe {
+ let buffer = self.current_vao().element_array_buffer().get();
+ return optional_root_object_to_js_or_null!(*cx, buffer);
+ },
+ constants::VERTEX_ARRAY_BINDING => unsafe {
+ let vao = self.current_vao();
+ let vao = vao.id().map(|_| &*vao);
+ return optional_root_object_to_js_or_null!(*cx, vao);
+ },
// NOTE: DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING, handled on the WebGL1 side
constants::READ_FRAMEBUFFER_BINDING => unsafe {
return optional_root_object_to_js_or_null!(
@@ -942,6 +957,7 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.2
fn BindBuffer(&self, target: u32, buffer: Option<&WebGLBuffer>) {
+ let current_vao;
let slot = match target {
constants::COPY_READ_BUFFER => &self.bound_copy_read_buffer,
constants::COPY_WRITE_BUFFER => &self.bound_copy_write_buffer,
@@ -949,6 +965,10 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
constants::PIXEL_UNPACK_BUFFER => &self.bound_pixel_unpack_buffer,
constants::TRANSFORM_FEEDBACK_BUFFER => &self.bound_transform_feedback_buffer,
constants::UNIFORM_BUFFER => &self.bound_uniform_buffer,
+ constants::ELEMENT_ARRAY_BUFFER => {
+ current_vao = self.current_vao();
+ current_vao.element_array_buffer()
+ },
_ => return self.base.BindBuffer(target, buffer),
};
self.base.bind_buffer_maybe(&slot, target, buffer);
@@ -1409,6 +1429,11 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
self.base.CreateShader(shader_type)
}
+ /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.17
+ fn CreateVertexArray(&self) -> Option<DomRoot<WebGLVertexArrayObject>> {
+ self.base.create_vertex_array_webgl2()
+ }
+
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
fn DeleteBuffer(&self, buffer: Option<&WebGLBuffer>) {
let buffer = match buffer {
@@ -1419,7 +1444,7 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
if buffer.is_marked_for_deletion() {
return;
}
- self.base.current_vao().unbind_buffer(buffer);
+ self.current_vao().unbind_buffer(buffer);
self.unbind_from(&self.base.array_buffer_slot(), &buffer);
self.unbind_from(&self.bound_copy_read_buffer, &buffer);
self.unbind_from(&self.bound_copy_write_buffer, &buffer);
@@ -1463,6 +1488,11 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
self.base.DeleteShader(shader)
}
+ /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.17
+ fn DeleteVertexArray(&self, vertex_array: Option<&WebGLVertexArrayObject>) {
+ self.base.delete_vertex_array_webgl2(vertex_array);
+ }
+
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11
fn DrawArrays(&self, mode: u32, first: i32, count: i32) {
self.base.DrawArrays(mode, first, count)
@@ -1662,6 +1692,11 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
self.base.IsTexture(texture)
}
+ /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.17
+ fn IsVertexArray(&self, vertex_array: Option<&WebGLVertexArrayObject>) -> bool {
+ self.base.is_vertex_array_webgl2(vertex_array)
+ }
+
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
fn LineWidth(&self, width: f32) {
self.base.LineWidth(width)
@@ -3042,6 +3077,11 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
}
}
+ /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.17
+ fn BindVertexArray(&self, array: Option<&WebGLVertexArrayObject>) {
+ self.base.bind_vertex_array_webgl2(array);
+ }
+
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.13
fn SamplerParameteri(&self, sampler: &WebGLSampler, pname: u32, param: i32) {
handle_potential_webgl_error!(self.base, self.base.validate_ownership(sampler), return);
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index 65134a631e1..bda7c036d60 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use crate::dom::bindings::cell::Ref;
use crate::dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding::ANGLEInstancedArraysConstants;
use crate::dom::bindings::codegen::Bindings::EXTBlendMinmaxBinding::EXTBlendMinmaxConstants;
use crate::dom::bindings::codegen::Bindings::OESVertexArrayObjectBinding::OESVertexArrayObjectConstants;
@@ -26,6 +27,7 @@ use crate::dom::htmlcanvaselement::HTMLCanvasElement;
use crate::dom::htmliframeelement::HTMLIFrameElement;
use crate::dom::node::{document_from_node, window_from_node, Node, NodeDamage};
use crate::dom::promise::Promise;
+use crate::dom::vertexarrayobject::VertexAttribData;
use crate::dom::webgl_extensions::WebGLExtensions;
use crate::dom::webgl_validations::tex_image_2d::{
CommonCompressedTexImage2DValidatorResult, CommonTexImage2DValidator,
@@ -47,6 +49,7 @@ use crate::dom::webglshader::WebGLShader;
use crate::dom::webglshaderprecisionformat::WebGLShaderPrecisionFormat;
use crate::dom::webgltexture::{TexParameterValue, WebGLTexture};
use crate::dom::webgluniformlocation::WebGLUniformLocation;
+use crate::dom::webglvertexarrayobject::WebGLVertexArrayObject;
use crate::dom::webglvertexarrayobjectoes::WebGLVertexArrayObjectOES;
use crate::dom::window::Window;
use crate::script_runtime::JSContext as SafeJSContext;
@@ -183,6 +186,8 @@ pub struct WebGLRenderingContext {
capabilities: Capabilities,
default_vao: DomOnceCell<WebGLVertexArrayObjectOES>,
current_vao: MutNullableDom<WebGLVertexArrayObjectOES>,
+ default_vao_webgl2: DomOnceCell<WebGLVertexArrayObject>,
+ current_vao_webgl2: MutNullableDom<WebGLVertexArrayObject>,
textures: Textures,
api_type: GlType,
}
@@ -242,6 +247,8 @@ impl WebGLRenderingContext {
capabilities: Default::default(),
default_vao: Default::default(),
current_vao: Default::default(),
+ default_vao_webgl2: Default::default(),
+ current_vao_webgl2: Default::default(),
textures: Textures::new(max_combined_texture_image_units),
api_type: ctx_data.api_type,
}
@@ -294,6 +301,15 @@ impl WebGLRenderingContext {
})
}
+ pub fn current_vao_webgl2(&self) -> DomRoot<WebGLVertexArrayObject> {
+ self.current_vao_webgl2.or_init(|| {
+ DomRoot::from_ref(
+ self.default_vao_webgl2
+ .init_once(|| WebGLVertexArrayObject::new(self, None)),
+ )
+ })
+ }
+
pub fn recreate(&self, size: Size2D<u32>) {
let (sender, receiver) = webgl_channel().unwrap();
self.webgl_sender.send_resize(size, sender).unwrap();
@@ -889,11 +905,18 @@ impl WebGLRenderingContext {
0
};
- self.current_vao().validate_for_draw(
- required_len,
- primcount as u32,
- &current_program.active_attribs(),
- )?;
+ match self.webgl_version() {
+ WebGLVersion::WebGL1 => self.current_vao().validate_for_draw(
+ required_len,
+ primcount as u32,
+ &current_program.active_attribs(),
+ )?,
+ WebGLVersion::WebGL2 => self.current_vao_webgl2().validate_for_draw(
+ required_len,
+ primcount as u32,
+ &current_program.active_attribs(),
+ )?,
+ };
self.validate_framebuffer()?;
@@ -950,11 +973,11 @@ impl WebGLRenderingContext {
}
let current_program = self.current_program.get().ok_or(InvalidOperation)?;
- let array_buffer = self
- .current_vao()
- .element_array_buffer()
- .get()
- .ok_or(InvalidOperation)?;
+ let array_buffer = match self.webgl_version() {
+ WebGLVersion::WebGL1 => self.current_vao().element_array_buffer().get(),
+ WebGLVersion::WebGL2 => self.current_vao_webgl2().element_array_buffer().get(),
+ }
+ .ok_or(InvalidOperation)?;
if count > 0 && primcount > 0 {
// This operation cannot overflow in u64 and we know all those values are nonnegative.
@@ -965,11 +988,18 @@ impl WebGLRenderingContext {
}
// TODO(nox): Pass the correct number of vertices required.
- self.current_vao().validate_for_draw(
- 0,
- primcount as u32,
- &current_program.active_attribs(),
- )?;
+ match self.webgl_version() {
+ WebGLVersion::WebGL1 => self.current_vao().validate_for_draw(
+ 0,
+ primcount as u32,
+ &current_program.active_attribs(),
+ )?,
+ WebGLVersion::WebGL2 => self.current_vao_webgl2().validate_for_draw(
+ 0,
+ primcount as u32,
+ &current_program.active_attribs(),
+ )?,
+ };
self.validate_framebuffer()?;
@@ -1003,7 +1033,12 @@ impl WebGLRenderingContext {
return self.webgl_error(InvalidValue);
}
- self.current_vao().vertex_attrib_divisor(index, divisor);
+ match self.webgl_version() {
+ WebGLVersion::WebGL1 => self.current_vao().vertex_attrib_divisor(index, divisor),
+ WebGLVersion::WebGL2 => self
+ .current_vao_webgl2()
+ .vertex_attrib_divisor(index, divisor),
+ };
self.send_command(WebGLCommand::VertexAttribDivisor { index, divisor });
}
@@ -1066,6 +1101,15 @@ impl WebGLRenderingContext {
.map(|id| WebGLVertexArrayObjectOES::new(self, Some(id)))
}
+ pub fn create_vertex_array_webgl2(&self) -> Option<DomRoot<WebGLVertexArrayObject>> {
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.send_command(WebGLCommand::CreateVertexArray(sender));
+ receiver
+ .recv()
+ .unwrap()
+ .map(|id| WebGLVertexArrayObject::new(self, Some(id)))
+ }
+
pub fn delete_vertex_array(&self, vao: Option<&WebGLVertexArrayObjectOES>) {
if let Some(vao) = vao {
handle_potential_webgl_error!(self, self.validate_ownership(vao), return);
@@ -1084,6 +1128,24 @@ impl WebGLRenderingContext {
}
}
+ pub fn delete_vertex_array_webgl2(&self, vao: Option<&WebGLVertexArrayObject>) {
+ if let Some(vao) = vao {
+ handle_potential_webgl_error!(self, self.validate_ownership(vao), return);
+ // The default vertex array has no id and should never be passed around.
+ assert!(vao.id().is_some());
+ if vao.is_deleted() {
+ return;
+ }
+ if vao == &*self.current_vao_webgl2() {
+ // Setting it to None will make self.current_vao() reset it to the default one
+ // next time it is called.
+ self.current_vao_webgl2.set(None);
+ self.send_command(WebGLCommand::BindVertexArray(None));
+ }
+ vao.delete(false);
+ }
+ }
+
pub fn is_vertex_array(&self, vao: Option<&WebGLVertexArrayObjectOES>) -> bool {
vao.map_or(false, |vao| {
// The default vertex array has no id and should never be passed around.
@@ -1092,6 +1154,14 @@ impl WebGLRenderingContext {
})
}
+ pub fn is_vertex_array_webgl2(&self, vao: Option<&WebGLVertexArrayObject>) -> bool {
+ vao.map_or(false, |vao| {
+ // The default vertex array has no id and should never be passed around.
+ assert!(vao.id().is_some());
+ self.validate_ownership(vao).is_ok() && vao.ever_bound() && !vao.is_deleted()
+ })
+ }
+
pub fn bind_vertex_array(&self, vao: Option<&WebGLVertexArrayObjectOES>) {
if let Some(vao) = vao {
// The default vertex array has no id and should never be passed around.
@@ -1108,6 +1178,22 @@ impl WebGLRenderingContext {
self.current_vao.set(vao);
}
+ pub fn bind_vertex_array_webgl2(&self, vao: Option<&WebGLVertexArrayObject>) {
+ if let Some(vao) = vao {
+ // The default vertex array has no id and should never be passed around.
+ assert!(vao.id().is_some());
+ handle_potential_webgl_error!(self, self.validate_ownership(vao), return);
+ if vao.is_deleted() {
+ return self.webgl_error(InvalidOperation);
+ }
+ vao.set_ever_bound();
+ }
+ self.send_command(WebGLCommand::BindVertexArray(vao.and_then(|vao| vao.id())));
+ // Setting it to None will make self.current_vao() reset it to the default one
+ // next time it is called.
+ self.current_vao_webgl2.set(vao);
+ }
+
fn validate_blend_mode(&self, mode: u32) -> WebGLResult<()> {
match mode {
constants::FUNC_ADD | constants::FUNC_SUBTRACT | constants::FUNC_REVERSE_SUBTRACT => {
@@ -2552,9 +2638,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if attrib_id >= self.limits.max_vertex_attribs {
return self.webgl_error(InvalidValue);
}
-
- self.current_vao()
- .enabled_vertex_attrib_array(attrib_id, true);
+ match self.webgl_version() {
+ WebGLVersion::WebGL1 => self
+ .current_vao()
+ .enabled_vertex_attrib_array(attrib_id, true),
+ WebGLVersion::WebGL2 => self
+ .current_vao_webgl2()
+ .enabled_vertex_attrib_array(attrib_id, true),
+ };
self.send_command(WebGLCommand::EnableVertexAttribArray(attrib_id));
}
@@ -2563,9 +2654,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if attrib_id >= self.limits.max_vertex_attribs {
return self.webgl_error(InvalidValue);
}
-
- self.current_vao()
- .enabled_vertex_attrib_array(attrib_id, false);
+ match self.webgl_version() {
+ WebGLVersion::WebGL1 => self
+ .current_vao()
+ .enabled_vertex_attrib_array(attrib_id, false),
+ WebGLVersion::WebGL2 => self
+ .current_vao_webgl2()
+ .enabled_vertex_attrib_array(attrib_id, false),
+ };
self.send_command(WebGLCommand::DisableVertexAttribArray(attrib_id));
}
@@ -2890,56 +2986,73 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
#[allow(unsafe_code)]
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
fn GetVertexAttrib(&self, cx: SafeJSContext, index: u32, param: u32) -> JSVal {
- let current_vao = self.current_vao();
- let data = handle_potential_webgl_error!(
- self,
- current_vao.get_vertex_attrib(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();
- [x, y, z, w]
- } else {
- let (sender, receiver) = webgl_channel().unwrap();
- self.send_command(WebGLCommand::GetCurrentVertexAttrib(index, sender));
- receiver.recv().unwrap()
- };
- unsafe {
- rooted!(in(*cx) let mut result = ptr::null_mut::<JSObject>());
- let _ = Float32Array::create(*cx, CreateWith::Slice(&value), result.handle_mut())
- .unwrap();
- return ObjectValue(result.get());
+ let get_attrib = |data: Ref<VertexAttribData>| -> JSVal {
+ if param == constants::CURRENT_VERTEX_ATTRIB {
+ let value = if index == 0 {
+ let (x, y, z, w) = self.current_vertex_attrib_0.get();
+ [x, y, z, w]
+ } else {
+ let (sender, receiver) = webgl_channel().unwrap();
+ self.send_command(WebGLCommand::GetCurrentVertexAttrib(index, sender));
+ receiver.recv().unwrap()
+ };
+ unsafe {
+ rooted!(in(*cx) let mut result = ptr::null_mut::<JSObject>());
+ let _ =
+ Float32Array::create(*cx, CreateWith::Slice(&value), result.handle_mut())
+ .unwrap();
+ return ObjectValue(result.get());
+ }
+ }
+ if !self
+ .extension_manager
+ .is_get_vertex_attrib_name_enabled(param)
+ {
+ self.webgl_error(WebGLError::InvalidEnum);
+ return NullValue();
}
- }
- if !self
- .extension_manager
- .is_get_vertex_attrib_name_enabled(param)
- {
- self.webgl_error(WebGLError::InvalidEnum);
- return NullValue();
- }
+ 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 => unsafe {
+ rooted!(in(*cx) let mut jsval = NullValue());
+ if let Some(buffer) = data.buffer() {
+ buffer.to_jsval(*cx, jsval.handle_mut());
+ }
+ jsval.get()
+ },
+ ANGLEInstancedArraysConstants::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE => {
+ UInt32Value(data.divisor)
+ },
+ _ => {
+ self.webgl_error(InvalidEnum);
+ NullValue()
+ },
+ }
+ };
- 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 => unsafe {
- rooted!(in(*cx) let mut jsval = NullValue());
- if let Some(buffer) = data.buffer() {
- buffer.to_jsval(*cx, jsval.handle_mut());
- }
- jsval.get()
- },
- ANGLEInstancedArraysConstants::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE => {
- UInt32Value(data.divisor)
+ match self.webgl_version() {
+ WebGLVersion::WebGL1 => {
+ let current_vao = self.current_vao();
+ let data = handle_potential_webgl_error!(
+ self,
+ current_vao.get_vertex_attrib(index).ok_or(InvalidValue),
+ return NullValue()
+ );
+ get_attrib(data)
},
- _ => {
- self.webgl_error(InvalidEnum);
- NullValue()
+ WebGLVersion::WebGL2 => {
+ let current_vao = self.current_vao_webgl2();
+ let data = handle_potential_webgl_error!(
+ self,
+ current_vao.get_vertex_attrib(index).ok_or(InvalidValue),
+ return NullValue()
+ );
+ get_attrib(data)
},
}
}
@@ -2950,13 +3063,26 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
self.webgl_error(InvalidEnum);
return 0;
}
- let vao = self.current_vao();
- let data = handle_potential_webgl_error!(
- self,
- vao.get_vertex_attrib(index).ok_or(InvalidValue),
- return 0
- );
- data.offset as i64
+ match self.webgl_version() {
+ WebGLVersion::WebGL1 => {
+ let current_vao = self.current_vao();
+ let data = handle_potential_webgl_error!(
+ self,
+ current_vao.get_vertex_attrib(index).ok_or(InvalidValue),
+ return 0
+ );
+ data.offset as i64
+ },
+ WebGLVersion::WebGL2 => {
+ let current_vao = self.current_vao_webgl2();
+ let data = handle_potential_webgl_error!(
+ self,
+ current_vao.get_vertex_attrib(index).ok_or(InvalidValue),
+ return 0
+ );
+ data.offset as i64
+ },
+ }
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
@@ -3819,11 +3945,15 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
stride: i32,
offset: i64,
) {
- handle_potential_webgl_error!(
- self,
- self.current_vao()
- .vertex_attrib_pointer(index, size, type_, normalized, stride, offset)
- );
+ let res = match self.webgl_version() {
+ WebGLVersion::WebGL1 => self
+ .current_vao()
+ .vertex_attrib_pointer(index, size, type_, normalized, stride, offset),
+ WebGLVersion::WebGL2 => self
+ .current_vao_webgl2()
+ .vertex_attrib_pointer(index, size, type_, normalized, stride, offset),
+ };
+ handle_potential_webgl_error!(self, res);
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4
diff --git a/components/script/dom/webglvertexarrayobject.rs b/components/script/dom/webglvertexarrayobject.rs
new file mode 100644
index 00000000000..48355d05557
--- /dev/null
+++ b/components/script/dom/webglvertexarrayobject.rs
@@ -0,0 +1,100 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use crate::dom::bindings::cell::Ref;
+use crate::dom::bindings::codegen::Bindings::WebGLVertexArrayObjectBinding;
+use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
+use crate::dom::bindings::root::{DomRoot, MutNullableDom};
+use crate::dom::vertexarrayobject::{VertexArrayObject, VertexAttribData};
+use crate::dom::webglbuffer::WebGLBuffer;
+use crate::dom::webglobject::WebGLObject;
+use crate::dom::webglrenderingcontext::WebGLRenderingContext;
+use canvas_traits::webgl::{ActiveAttribInfo, WebGLResult, WebGLVertexArrayId};
+use dom_struct::dom_struct;
+
+#[dom_struct]
+pub struct WebGLVertexArrayObject {
+ webgl_object_: WebGLObject,
+ array_object: VertexArrayObject,
+}
+
+impl WebGLVertexArrayObject {
+ fn new_inherited(context: &WebGLRenderingContext, id: Option<WebGLVertexArrayId>) -> Self {
+ Self {
+ webgl_object_: WebGLObject::new_inherited(context),
+ array_object: VertexArrayObject::new(context, id),
+ }
+ }
+
+ pub fn new(context: &WebGLRenderingContext, id: Option<WebGLVertexArrayId>) -> DomRoot<Self> {
+ reflect_dom_object(
+ Box::new(WebGLVertexArrayObject::new_inherited(context, id)),
+ &*context.global(),
+ WebGLVertexArrayObjectBinding::Wrap,
+ )
+ }
+
+ pub fn id(&self) -> Option<WebGLVertexArrayId> {
+ self.array_object.id()
+ }
+
+ pub fn is_deleted(&self) -> bool {
+ self.array_object.is_deleted()
+ }
+
+ pub fn delete(&self, fallible: bool) {
+ self.array_object.delete(fallible);
+ }
+
+ pub fn ever_bound(&self) -> bool {
+ self.array_object.ever_bound()
+ }
+
+ pub fn set_ever_bound(&self) {
+ self.array_object.set_ever_bound();
+ }
+
+ pub fn element_array_buffer(&self) -> &MutNullableDom<WebGLBuffer> {
+ self.array_object.element_array_buffer()
+ }
+
+ pub fn get_vertex_attrib(&self, index: u32) -> Option<Ref<VertexAttribData>> {
+ self.array_object.get_vertex_attrib(index)
+ }
+
+ pub fn vertex_attrib_pointer(
+ &self,
+ index: u32,
+ size: i32,
+ type_: u32,
+ normalized: bool,
+ stride: i32,
+ offset: i64,
+ ) -> WebGLResult<()> {
+ self.array_object
+ .vertex_attrib_pointer(index, size, type_, normalized, stride, offset)
+ }
+
+ pub fn vertex_attrib_divisor(&self, index: u32, value: u32) {
+ self.array_object.vertex_attrib_divisor(index, value);
+ }
+
+ pub fn enabled_vertex_attrib_array(&self, index: u32, value: bool) {
+ self.array_object.enabled_vertex_attrib_array(index, value);
+ }
+
+ pub fn unbind_buffer(&self, buffer: &WebGLBuffer) {
+ self.array_object.unbind_buffer(buffer);
+ }
+
+ pub fn validate_for_draw(
+ &self,
+ required_len: u32,
+ instance_count: u32,
+ active_attribs: &[ActiveAttribInfo],
+ ) -> WebGLResult<()> {
+ self.array_object
+ .validate_for_draw(required_len, instance_count, active_attribs)
+ }
+}
diff --git a/components/script/dom/webglvertexarrayobjectoes.rs b/components/script/dom/webglvertexarrayobjectoes.rs
index 1d802968ae1..2c03f084031 100644
--- a/components/script/dom/webglvertexarrayobjectoes.rs
+++ b/components/script/dom/webglvertexarrayobjectoes.rs
@@ -2,41 +2,28 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-use crate::dom::bindings::cell::{ref_filter_map, DomRefCell, Ref};
-use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
+use crate::dom::bindings::cell::Ref;
use crate::dom::bindings::codegen::Bindings::WebGLVertexArrayObjectOESBinding;
-use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
-use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
+use crate::dom::bindings::root::{DomRoot, MutNullableDom};
+use crate::dom::vertexarrayobject::{VertexArrayObject, VertexAttribData};
use crate::dom::webglbuffer::WebGLBuffer;
use crate::dom::webglobject::WebGLObject;
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
-use canvas_traits::webgl::{
- ActiveAttribInfo, WebGLCommand, WebGLError, WebGLResult, WebGLVertexArrayId,
-};
+use canvas_traits::webgl::{ActiveAttribInfo, WebGLResult, WebGLVertexArrayId};
use dom_struct::dom_struct;
-use std::cell::Cell;
#[dom_struct]
pub struct WebGLVertexArrayObjectOES {
webgl_object_: WebGLObject,
- id: Option<WebGLVertexArrayId>,
- ever_bound: Cell<bool>,
- is_deleted: Cell<bool>,
- vertex_attribs: DomRefCell<Box<[VertexAttribData]>>,
- element_array_buffer: MutNullableDom<WebGLBuffer>,
+ array_object: VertexArrayObject,
}
impl WebGLVertexArrayObjectOES {
fn new_inherited(context: &WebGLRenderingContext, id: Option<WebGLVertexArrayId>) -> Self {
- let max_vertex_attribs = context.limits().max_vertex_attribs as usize;
Self {
webgl_object_: WebGLObject::new_inherited(context),
- id,
- ever_bound: Default::default(),
- is_deleted: Default::default(),
- vertex_attribs: DomRefCell::new(vec![Default::default(); max_vertex_attribs].into()),
- element_array_buffer: Default::default(),
+ array_object: VertexArrayObject::new(context, id),
}
}
@@ -49,54 +36,31 @@ impl WebGLVertexArrayObjectOES {
}
pub fn id(&self) -> Option<WebGLVertexArrayId> {
- self.id
+ self.array_object.id()
}
pub fn is_deleted(&self) -> bool {
- self.is_deleted.get()
+ self.array_object.is_deleted()
}
pub fn delete(&self, fallible: bool) {
- assert!(self.id.is_some());
- if self.is_deleted.get() {
- return;
- }
- self.is_deleted.set(true);
-
- let context = self.upcast::<WebGLObject>().context();
- let cmd = WebGLCommand::DeleteVertexArray(self.id.unwrap());
- if fallible {
- context.send_command_ignored(cmd);
- } else {
- context.send_command(cmd);
- }
-
- for attrib_data in &**self.vertex_attribs.borrow() {
- if let Some(buffer) = attrib_data.buffer() {
- buffer.decrement_attached_counter();
- }
- }
- if let Some(buffer) = self.element_array_buffer.get() {
- buffer.decrement_attached_counter();
- }
+ self.array_object.delete(fallible);
}
pub fn ever_bound(&self) -> bool {
- return self.ever_bound.get();
+ self.array_object.ever_bound()
}
pub fn set_ever_bound(&self) {
- self.ever_bound.set(true);
+ self.array_object.set_ever_bound();
}
pub fn element_array_buffer(&self) -> &MutNullableDom<WebGLBuffer> {
- &self.element_array_buffer
+ self.array_object.element_array_buffer()
}
pub fn get_vertex_attrib(&self, index: u32) -> Option<Ref<VertexAttribData>> {
- ref_filter_map(self.vertex_attribs.borrow(), |attribs| {
- attribs.get(index as usize)
- })
+ self.array_object.get_vertex_attrib(index)
}
pub fn vertex_attrib_pointer(
@@ -108,93 +72,20 @@ impl WebGLVertexArrayObjectOES {
stride: i32,
offset: i64,
) -> WebGLResult<()> {
- let mut attribs = self.vertex_attribs.borrow_mut();
- let data = attribs
- .get_mut(index as usize)
- .ok_or(WebGLError::InvalidValue)?;
-
- if size < 1 || size > 4 {
- return Err(WebGLError::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(WebGLError::InvalidValue);
- }
- let bytes_per_component: i32 = match type_ {
- constants::BYTE | constants::UNSIGNED_BYTE => 1,
- constants::SHORT | constants::UNSIGNED_SHORT => 2,
- constants::FLOAT => 4,
- _ => return Err(WebGLError::InvalidEnum),
- };
- if offset % bytes_per_component as i64 > 0 || stride % bytes_per_component > 0 {
- return Err(WebGLError::InvalidOperation);
- }
-
- let context = self.upcast::<WebGLObject>().context();
- let buffer = context.array_buffer();
- match buffer {
- Some(ref buffer) => buffer.increment_attached_counter(),
- None if offset != 0 => {
- // https://github.com/KhronosGroup/WebGL/pull/2228
- return Err(WebGLError::InvalidOperation);
- },
- _ => {},
- }
- context.send_command(WebGLCommand::VertexAttribPointer(
- index,
- size,
- type_,
- normalized,
- stride,
- offset as u32,
- ));
- if let Some(old) = data.buffer() {
- old.decrement_attached_counter();
- }
-
- *data = VertexAttribData {
- enabled_as_array: data.enabled_as_array,
- size: size as u8,
- type_,
- bytes_per_vertex: size as u8 * bytes_per_component as u8,
- normalized,
- stride: stride as u8,
- offset: offset as u32,
- buffer: buffer.map(|b| Dom::from_ref(&*b)),
- divisor: data.divisor,
- };
-
- Ok(())
+ self.array_object
+ .vertex_attrib_pointer(index, size, type_, normalized, stride, offset)
}
pub fn vertex_attrib_divisor(&self, index: u32, value: u32) {
- self.vertex_attribs.borrow_mut()[index as usize].divisor = value;
+ self.array_object.vertex_attrib_divisor(index, value);
}
pub fn enabled_vertex_attrib_array(&self, index: u32, value: bool) {
- self.vertex_attribs.borrow_mut()[index as usize].enabled_as_array = value;
+ self.array_object.enabled_vertex_attrib_array(index, value);
}
pub fn unbind_buffer(&self, buffer: &WebGLBuffer) {
- for attrib in &mut **self.vertex_attribs.borrow_mut() {
- if let Some(b) = attrib.buffer() {
- if b.id() != buffer.id() {
- continue;
- }
- b.decrement_attached_counter();
- }
- attrib.buffer = None;
- }
- if self
- .element_array_buffer
- .get()
- .map_or(false, |b| buffer == &*b)
- {
- buffer.decrement_attached_counter();
- self.element_array_buffer.set(None);
- }
+ self.array_object.unbind_buffer(buffer);
}
pub fn validate_for_draw(
@@ -203,109 +94,7 @@ impl WebGLVertexArrayObjectOES {
instance_count: u32,
active_attribs: &[ActiveAttribInfo],
) -> WebGLResult<()> {
- // TODO(nox): Cache limits per VAO.
- let attribs = self.vertex_attribs.borrow();
- // https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.2
- if attribs
- .iter()
- .any(|data| data.enabled_as_array && data.buffer.is_none())
- {
- return Err(WebGLError::InvalidOperation);
- }
- let mut has_active_attrib = false;
- let mut has_divisor_0 = false;
- for active_info in active_attribs {
- if active_info.location < 0 {
- continue;
- }
- has_active_attrib = true;
- let attrib = &attribs[active_info.location as usize];
- if attrib.divisor == 0 {
- has_divisor_0 = true;
- }
- if !attrib.enabled_as_array {
- continue;
- }
- // https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.6
- if required_len > 0 && instance_count > 0 {
- let max_vertices = attrib.max_vertices();
- if attrib.divisor == 0 {
- if max_vertices < required_len {
- return Err(WebGLError::InvalidOperation);
- }
- } else if max_vertices
- .checked_mul(attrib.divisor)
- .map_or(false, |v| v < instance_count)
- {
- return Err(WebGLError::InvalidOperation);
- }
- }
- }
- if has_active_attrib && !has_divisor_0 {
- return Err(WebGLError::InvalidOperation);
- }
- Ok(())
- }
-}
-
-impl Drop for WebGLVertexArrayObjectOES {
- fn drop(&mut self) {
- if self.id.is_some() {
- self.delete(true);
- }
- }
-}
-
-#[derive(Clone, JSTraceable, MallocSizeOf)]
-#[unrooted_must_root_lint::must_root]
-pub struct VertexAttribData {
- pub enabled_as_array: bool,
- pub size: u8,
- pub type_: u32,
- bytes_per_vertex: u8,
- pub normalized: bool,
- pub stride: u8,
- pub offset: u32,
- pub buffer: Option<Dom<WebGLBuffer>>,
- pub divisor: u32,
-}
-
-impl Default for VertexAttribData {
- #[allow(unrooted_must_root)]
- fn default() -> Self {
- Self {
- enabled_as_array: false,
- size: 4,
- type_: constants::FLOAT,
- bytes_per_vertex: 16,
- normalized: false,
- stride: 0,
- offset: 0,
- buffer: None,
- divisor: 0,
- }
- }
-}
-
-impl VertexAttribData {
- pub fn buffer(&self) -> Option<&WebGLBuffer> {
- self.buffer.as_ref().map(|b| &**b)
- }
-
- fn max_vertices(&self) -> u32 {
- let capacity = (self.buffer().unwrap().capacity() as u32).saturating_sub(self.offset);
- if capacity < self.bytes_per_vertex as u32 {
- 0
- } else if self.stride == 0 {
- capacity / self.bytes_per_vertex as u32
- } else if self.stride < self.bytes_per_vertex {
- (capacity - (self.bytes_per_vertex - self.stride) as u32) / self.stride as u32
- } else {
- let mut max = capacity / self.stride as u32;
- if capacity % self.stride as u32 >= self.bytes_per_vertex as u32 {
- max += 1;
- }
- max
- }
+ self.array_object
+ .validate_for_draw(required_len, instance_count, active_attribs)
}
}
diff --git a/components/script/dom/webidls/WebGL2RenderingContext.webidl b/components/script/dom/webidls/WebGL2RenderingContext.webidl
index e25174b858d..72bd68a9f8a 100644
--- a/components/script/dom/webidls/WebGL2RenderingContext.webidl
+++ b/components/script/dom/webidls/WebGL2RenderingContext.webidl
@@ -11,10 +11,6 @@
typedef long long GLint64;
typedef unsigned long long GLuint64;
-
-// interface WebGLVertexArrayObject : WebGLObject {
-// };
-
typedef (/*[AllowShared]*/ Uint32Array or sequence<GLuint>) Uint32List;
interface mixin WebGL2RenderingContextBase
@@ -540,10 +536,10 @@ interface mixin WebGL2RenderingContextBase
void uniformBlockBinding(WebGLProgram program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
/* Vertex Array Objects */
- /*WebGLVertexArrayObject? createVertexArray();
+ WebGLVertexArrayObject? createVertexArray();
void deleteVertexArray(WebGLVertexArrayObject? vertexArray);
[WebGLHandlesContextLoss] GLboolean isVertexArray(WebGLVertexArrayObject? vertexArray);
- void bindVertexArray(WebGLVertexArrayObject? array);*/
+ void bindVertexArray(WebGLVertexArrayObject? array);
};
[Exposed=Window, Pref="dom.webgl2.enabled"]
diff --git a/components/script/dom/webidls/WebGLVertexArrayObject.webidl b/components/script/dom/webidls/WebGLVertexArrayObject.webidl
new file mode 100644
index 00000000000..a42d8cbe051
--- /dev/null
+++ b/components/script/dom/webidls/WebGLVertexArrayObject.webidl
@@ -0,0 +1,11 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+//
+// WebGL IDL definitions scraped from the Khronos specification:
+// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.17
+//
+
+[Exposed=(Window), Pref="dom.webgl2.enabled"]
+interface WebGLVertexArrayObject : WebGLObject {
+};