mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Implement instanced WebGL drawing calls (part of #20791)
This commit is contained in:
parent
0aefffc5bf
commit
4e6eea221a
12 changed files with 432 additions and 125 deletions
|
@ -973,6 +973,15 @@ impl WebGLImpl {
|
|||
WebGLCommand::UseProgram(program_id) => {
|
||||
ctx.gl().use_program(program_id.map_or(0, |p| p.get()))
|
||||
}
|
||||
WebGLCommand::DrawArraysInstanced { mode, first, count, primcount } => {
|
||||
ctx.gl().draw_arrays_instanced(mode, first, count, primcount)
|
||||
}
|
||||
WebGLCommand::DrawElementsInstanced { mode, count, type_, offset, primcount } => {
|
||||
ctx.gl().draw_elements_instanced(mode, count, type_, offset, primcount)
|
||||
}
|
||||
WebGLCommand::VertexAttribDivisor { index, divisor } => {
|
||||
ctx.gl().vertex_attrib_divisor(index, divisor)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: update test expectations in order to enable debug assertions
|
||||
|
|
|
@ -282,6 +282,9 @@ pub enum WebGLCommand {
|
|||
GetTexParameterInt(u32, TexParameterInt, WebGLSender<i32>),
|
||||
TexParameteri(u32, TexParameterInt, i32),
|
||||
TexParameterf(u32, TexParameterFloat, f32),
|
||||
DrawArraysInstanced { mode: u32, first: i32, count: i32, primcount: i32 },
|
||||
DrawElementsInstanced { mode: u32, count: i32, type_: u32, offset: u32, primcount: i32 },
|
||||
VertexAttribDivisor { index: u32, divisor: u32 },
|
||||
}
|
||||
|
||||
macro_rules! define_resource_id_struct {
|
||||
|
|
|
@ -937,6 +937,34 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
|
|||
) -> Option<Vec<DomRoot<WebGLShader>>> {
|
||||
self.base.GetAttachedShaders(program)
|
||||
}
|
||||
|
||||
/// 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.base.draw_arrays_instanced(mode, first, count, primcount);
|
||||
}
|
||||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.9
|
||||
fn DrawElementsInstanced(
|
||||
&self,
|
||||
mode: u32,
|
||||
count: i32,
|
||||
type_: u32,
|
||||
offset: i64,
|
||||
primcount: i32,
|
||||
) {
|
||||
self.base.draw_elements_instanced(mode, count, type_, offset, primcount);
|
||||
}
|
||||
|
||||
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.9
|
||||
fn VertexAttribDivisor(&self, index: u32, divisor: u32) {
|
||||
self.base.vertex_attrib_divisor(index, divisor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use canvas_traits::webgl::WebGLVersion;
|
||||
use dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding;
|
||||
use dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding::ANGLEInstancedArraysConstants;
|
||||
use dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding::ANGLEInstancedArraysMethods;
|
||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||
use dom::bindings::root::{Dom, DomRoot};
|
||||
use dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use dom_struct::dom_struct;
|
||||
use super::{WebGLExtension, WebGLExtensions, WebGLExtensionSpec};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct ANGLEInstancedArrays {
|
||||
reflector_: Reflector,
|
||||
ctx: Dom<WebGLRenderingContext>,
|
||||
}
|
||||
|
||||
impl ANGLEInstancedArrays {
|
||||
fn new_inherited(ctx: &WebGLRenderingContext) -> Self {
|
||||
Self {
|
||||
reflector_: Reflector::new(),
|
||||
ctx: Dom::from_ref(ctx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WebGLExtension for ANGLEInstancedArrays {
|
||||
type Extension = Self;
|
||||
|
||||
fn new(ctx: &WebGLRenderingContext) -> DomRoot<Self> {
|
||||
reflect_dom_object(
|
||||
Box::new(ANGLEInstancedArrays::new_inherited(ctx)),
|
||||
&*ctx.global(),
|
||||
ANGLEInstancedArraysBinding::Wrap,
|
||||
)
|
||||
}
|
||||
|
||||
fn spec() -> WebGLExtensionSpec {
|
||||
WebGLExtensionSpec::Specific(WebGLVersion::WebGL1)
|
||||
}
|
||||
|
||||
fn is_supported(ext: &WebGLExtensions) -> bool {
|
||||
ext.supports_any_gl_extension(&[
|
||||
"GL_ANGLE_instanced_arrays",
|
||||
"GL_ARB_instanced_arrays",
|
||||
"GL_EXT_instanced_arrays",
|
||||
"GL_NV_instanced_arrays",
|
||||
])
|
||||
}
|
||||
|
||||
fn enable(ext: &WebGLExtensions) {
|
||||
ext.enable_get_vertex_attrib_name(
|
||||
ANGLEInstancedArraysConstants::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
|
||||
);
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
"ANGLE_instanced_arrays"
|
||||
}
|
||||
}
|
||||
|
||||
impl ANGLEInstancedArraysMethods for ANGLEInstancedArrays {
|
||||
// https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/
|
||||
fn DrawArraysInstancedANGLE(
|
||||
&self,
|
||||
mode: u32,
|
||||
first: i32,
|
||||
count: i32,
|
||||
primcount: i32,
|
||||
) {
|
||||
self.ctx.draw_arrays_instanced(mode, first, count, primcount);
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/
|
||||
fn DrawElementsInstancedANGLE(
|
||||
&self,
|
||||
mode: u32,
|
||||
count: i32,
|
||||
type_: u32,
|
||||
offset: i64,
|
||||
primcount: i32,
|
||||
) {
|
||||
self.ctx.draw_elements_instanced(mode, count, type_, offset, primcount);
|
||||
}
|
||||
|
||||
fn VertexAttribDivisorANGLE(&self, index: u32, divisor: u32) {
|
||||
self.ctx.vertex_attrib_divisor(index, divisor);
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||
use super::{ext_constants, WebGLExtension, WebGLExtensions, WebGLExtensionSpec};
|
||||
|
||||
pub mod angleinstancedarrays;
|
||||
pub mod extblendminmax;
|
||||
pub mod extshadertexturelod;
|
||||
pub mod exttexturefilteranisotropic;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use canvas_traits::webgl::{WebGLError, WebGLVersion};
|
||||
use dom::bindings::cell::DomRefCell;
|
||||
use dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding::ANGLEInstancedArraysConstants;
|
||||
use dom::bindings::codegen::Bindings::EXTTextureFilterAnisotropicBinding::EXTTextureFilterAnisotropicConstants;
|
||||
use dom::bindings::codegen::Bindings::OESStandardDerivativesBinding::OESStandardDerivativesConstants;
|
||||
use dom::bindings::codegen::Bindings::OESTextureHalfFloatBinding::OESTextureHalfFloatConstants;
|
||||
|
@ -54,6 +55,13 @@ const DEFAULT_DISABLED_GET_TEX_PARAMETER_NAMES_WEBGL1: [GLenum; 1] = [
|
|||
EXTTextureFilterAnisotropicConstants::TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
];
|
||||
|
||||
// Param names that are implemented for glGetVertexAttrib in a WebGL 1.0 context
|
||||
// but must trigger a InvalidEnum error until the related WebGL Extensions are enabled.
|
||||
// Example: https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/
|
||||
const DEFAULT_DISABLED_GET_VERTEX_ATTRIB_NAMES_WEBGL1: [GLenum; 1] = [
|
||||
ANGLEInstancedArraysConstants::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
|
||||
];
|
||||
|
||||
/// WebGL features that are enabled/disabled by WebGL Extensions.
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
struct WebGLExtensionFeatures {
|
||||
|
@ -68,6 +76,8 @@ struct WebGLExtensionFeatures {
|
|||
disabled_get_parameter_names: FnvHashSet<GLenum>,
|
||||
/// WebGL GetTexParameter() names enabled by extensions.
|
||||
disabled_get_tex_parameter_names: FnvHashSet<GLenum>,
|
||||
/// WebGL GetAttribVertex() names enabled by extensions.
|
||||
disabled_get_vertex_attrib_names: FnvHashSet<GLenum>,
|
||||
/// WebGL OES_element_index_uint extension.
|
||||
element_index_uint_enabled: bool,
|
||||
/// WebGL EXT_blend_minmax extension.
|
||||
|
@ -80,6 +90,7 @@ impl WebGLExtensionFeatures {
|
|||
disabled_tex_types,
|
||||
disabled_get_parameter_names,
|
||||
disabled_get_tex_parameter_names,
|
||||
disabled_get_vertex_attrib_names,
|
||||
element_index_uint_enabled,
|
||||
blend_minmax_enabled,
|
||||
) = match webgl_version {
|
||||
|
@ -88,12 +99,20 @@ impl WebGLExtensionFeatures {
|
|||
DEFAULT_DISABLED_TEX_TYPES_WEBGL1.iter().cloned().collect(),
|
||||
DEFAULT_DISABLED_GET_PARAMETER_NAMES_WEBGL1.iter().cloned().collect(),
|
||||
DEFAULT_DISABLED_GET_TEX_PARAMETER_NAMES_WEBGL1.iter().cloned().collect(),
|
||||
DEFAULT_DISABLED_GET_VERTEX_ATTRIB_NAMES_WEBGL1.iter().cloned().collect(),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
},
|
||||
WebGLVersion::WebGL2 => {
|
||||
(Default::default(), Default::default(), Default::default(), true, true)
|
||||
(
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
};
|
||||
Self {
|
||||
|
@ -105,6 +124,7 @@ impl WebGLExtensionFeatures {
|
|||
hint_targets: Default::default(),
|
||||
disabled_get_parameter_names,
|
||||
disabled_get_tex_parameter_names,
|
||||
disabled_get_vertex_attrib_names,
|
||||
element_index_uint_enabled,
|
||||
blend_minmax_enabled,
|
||||
}
|
||||
|
@ -269,7 +289,16 @@ impl WebGLExtensions {
|
|||
!self.features.borrow().disabled_get_tex_parameter_names.contains(&name)
|
||||
}
|
||||
|
||||
pub fn enable_get_vertex_attrib_name(&self, name: GLenum) {
|
||||
self.features.borrow_mut().disabled_get_vertex_attrib_names.remove(&name);
|
||||
}
|
||||
|
||||
pub fn is_get_vertex_attrib_name_enabled(&self, name: GLenum) -> bool {
|
||||
!self.features.borrow().disabled_get_vertex_attrib_names.contains(&name)
|
||||
}
|
||||
|
||||
fn register_all_extensions(&self) {
|
||||
self.register::<ext::angleinstancedarrays::ANGLEInstancedArrays>();
|
||||
self.register::<ext::extblendminmax::EXTBlendMinmax>();
|
||||
self.register::<ext::extshadertexturelod::EXTShaderTextureLod>();
|
||||
self.register::<ext::exttexturefilteranisotropic::EXTTextureFilterAnisotropic>();
|
||||
|
|
|
@ -12,6 +12,7 @@ use canvas_traits::webgl::{WebGLResult, WebGLSLVersion, WebGLVersion};
|
|||
use canvas_traits::webgl::{WebVRCommand, webgl_channel};
|
||||
use canvas_traits::webgl::WebGLError::*;
|
||||
use dom::bindings::cell::DomRefCell;
|
||||
use dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding::ANGLEInstancedArraysConstants;
|
||||
use dom::bindings::codegen::Bindings::EXTBlendMinmaxBinding::EXTBlendMinmaxConstants;
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{self, WebGLContextAttributes};
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||
|
@ -251,7 +252,7 @@ impl WebGLRenderingContext {
|
|||
current_vertex_attrib_0: Cell::new((0f32, 0f32, 0f32, 1f32)),
|
||||
current_scissor: Cell::new((0, 0, size.width, size.height)),
|
||||
current_clear_color: Cell::new((0.0, 0.0, 0.0, 0.0)),
|
||||
extension_manager: WebGLExtensions::new(webgl_version)
|
||||
extension_manager: WebGLExtensions::new(webgl_version),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1156,6 +1157,142 @@ impl WebGLRenderingContext {
|
|||
}
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/
|
||||
pub fn draw_arrays_instanced(
|
||||
&self,
|
||||
mode: u32,
|
||||
first: i32,
|
||||
count: i32,
|
||||
primcount: i32,
|
||||
) {
|
||||
match mode {
|
||||
constants::POINTS | constants::LINE_STRIP |
|
||||
constants::LINE_LOOP | constants::LINES |
|
||||
constants::TRIANGLE_STRIP | constants::TRIANGLE_FAN |
|
||||
constants::TRIANGLES => {},
|
||||
_ => {
|
||||
return self.webgl_error(InvalidEnum);
|
||||
}
|
||||
}
|
||||
if first < 0 || count < 0 || primcount < 0 {
|
||||
return self.webgl_error(InvalidValue);
|
||||
}
|
||||
|
||||
let current_program = handle_potential_webgl_error!(
|
||||
self,
|
||||
self.current_program.get().ok_or(InvalidOperation),
|
||||
return
|
||||
);
|
||||
|
||||
let required_len = if count > 0 {
|
||||
handle_potential_webgl_error!(
|
||||
self,
|
||||
first.checked_add(count).map(|len| len as u32).ok_or(InvalidOperation),
|
||||
return
|
||||
)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
handle_potential_webgl_error!(
|
||||
self,
|
||||
self.vertex_attribs.validate_for_draw(required_len, primcount as u32, ¤t_program.active_attribs()),
|
||||
return
|
||||
);
|
||||
|
||||
if !self.validate_framebuffer_complete() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.send_command(
|
||||
WebGLCommand::DrawArraysInstanced { mode, first, count, primcount },
|
||||
);
|
||||
self.mark_as_dirty();
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/
|
||||
pub fn draw_elements_instanced(
|
||||
&self,
|
||||
mode: u32,
|
||||
count: i32,
|
||||
type_: u32,
|
||||
offset: i64,
|
||||
primcount: i32,
|
||||
) {
|
||||
match mode {
|
||||
constants::POINTS | constants::LINE_STRIP |
|
||||
constants::LINE_LOOP | constants::LINES |
|
||||
constants::TRIANGLE_STRIP | constants::TRIANGLE_FAN |
|
||||
constants::TRIANGLES => {},
|
||||
_ => {
|
||||
return self.webgl_error(InvalidEnum);
|
||||
}
|
||||
}
|
||||
if count < 0 || offset < 0 || primcount < 0 {
|
||||
return self.webgl_error(InvalidValue);
|
||||
}
|
||||
let type_size = match type_ {
|
||||
constants::UNSIGNED_BYTE => 1,
|
||||
constants::UNSIGNED_SHORT => 2,
|
||||
_ => return self.webgl_error(InvalidEnum),
|
||||
};
|
||||
if offset % type_size != 0 {
|
||||
return self.webgl_error(InvalidOperation);
|
||||
}
|
||||
|
||||
let current_program = handle_potential_webgl_error!(
|
||||
self,
|
||||
self.current_program.get().ok_or(InvalidOperation),
|
||||
return
|
||||
);
|
||||
|
||||
if count > 0 && primcount > 0 {
|
||||
if let Some(array_buffer) = self.bound_buffer_element_array.get() {
|
||||
// WebGL Spec: check buffer overflows, must be a valid multiple of the size.
|
||||
let val = offset as u64 + (count as u64 * type_size as u64);
|
||||
if val > array_buffer.capacity() as u64 {
|
||||
return self.webgl_error(InvalidOperation);
|
||||
}
|
||||
} else {
|
||||
// From the WebGL spec
|
||||
//
|
||||
// a non-null WebGLBuffer must be bound to the ELEMENT_ARRAY_BUFFER binding point
|
||||
// or an INVALID_OPERATION error will be generated.
|
||||
//
|
||||
return self.webgl_error(InvalidOperation);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(nox): Pass the correct number of vertices required.
|
||||
handle_potential_webgl_error!(
|
||||
self,
|
||||
self.vertex_attribs.validate_for_draw(0, primcount as u32, ¤t_program.active_attribs()),
|
||||
return
|
||||
);
|
||||
|
||||
if !self.validate_framebuffer_complete() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.send_command(WebGLCommand::DrawElementsInstanced {
|
||||
mode,
|
||||
count,
|
||||
type_,
|
||||
offset: offset as u32,
|
||||
primcount,
|
||||
});
|
||||
self.mark_as_dirty();
|
||||
}
|
||||
|
||||
pub fn vertex_attrib_divisor(&self, index: u32, divisor: u32) {
|
||||
if index >= self.limits.max_vertex_attribs {
|
||||
return self.webgl_error(InvalidValue);
|
||||
}
|
||||
|
||||
self.vertex_attribs.set_divisor(index, divisor);
|
||||
self.send_command(WebGLCommand::VertexAttribDivisor { index, divisor });
|
||||
}
|
||||
|
||||
// Used by HTMLCanvasElement.toDataURL
|
||||
//
|
||||
// This emits errors quite liberally, but the spec says that this operation
|
||||
|
@ -2248,7 +2385,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
|
||||
handle_potential_webgl_error!(
|
||||
self,
|
||||
self.vertex_attribs.validate_for_draw(required_len, ¤t_program.active_attribs()),
|
||||
self.vertex_attribs.validate_for_draw(required_len, 1, ¤t_program.active_attribs()),
|
||||
return
|
||||
);
|
||||
|
||||
|
@ -2318,7 +2455,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
// TODO(nox): Pass the correct number of vertices required.
|
||||
handle_potential_webgl_error!(
|
||||
self,
|
||||
self.vertex_attribs.validate_for_draw(0, ¤t_program.active_attribs()),
|
||||
self.vertex_attribs.validate_for_draw(0, 1, ¤t_program.active_attribs()),
|
||||
return
|
||||
);
|
||||
|
||||
|
@ -2661,6 +2798,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
return ObjectValue(result.get());
|
||||
}
|
||||
|
||||
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),
|
||||
|
@ -2676,6 +2818,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
}
|
||||
jsval.get()
|
||||
}
|
||||
ANGLEInstancedArraysConstants::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE => {
|
||||
Int32Value(data.divisor as i32)
|
||||
}
|
||||
_ => {
|
||||
self.webgl_error(InvalidEnum);
|
||||
NullValue()
|
||||
|
@ -3903,6 +4048,7 @@ impl VertexAttribs {
|
|||
stride: stride as u8,
|
||||
offset: offset as u32,
|
||||
buffer: Some(Dom::from_ref(buffer)),
|
||||
divisor: data.divisor,
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
@ -3927,33 +4073,51 @@ impl VertexAttribs {
|
|||
self.attribs.borrow_mut()[index as usize].enabled_as_array = value;
|
||||
}
|
||||
|
||||
fn set_divisor(&self, index: u32, value: u32) {
|
||||
self.attribs.borrow_mut()[index as usize].divisor = value;
|
||||
}
|
||||
|
||||
fn validate_for_draw(
|
||||
&self,
|
||||
required_len: u32,
|
||||
instance_count: u32,
|
||||
active_attribs: &[ActiveAttribInfo],
|
||||
) -> WebGLResult<()> {
|
||||
// TODO(nox): Cache limits per VAO.
|
||||
let attribs = self.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(InvalidOperation);
|
||||
}
|
||||
if required_len == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
// TODO(nox): Cache that per VAO.
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.6
|
||||
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;
|
||||
}
|
||||
if attrib.max_vertices() < required_len {
|
||||
return Err(InvalidOperation);
|
||||
// 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(InvalidOperation);
|
||||
}
|
||||
} else if max_vertices.checked_mul(attrib.divisor).map_or(false, |v| v < instance_count) {
|
||||
return Err(InvalidOperation);
|
||||
}
|
||||
}
|
||||
}
|
||||
if has_active_attrib && !has_divisor_0 {
|
||||
return Err(InvalidOperation);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -3969,6 +4133,7 @@ pub struct VertexAttribData {
|
|||
stride: u8,
|
||||
offset: u32,
|
||||
buffer: Option<Dom<WebGLBuffer>>,
|
||||
divisor: u32,
|
||||
}
|
||||
|
||||
impl Default for VertexAttribData {
|
||||
|
@ -3983,6 +4148,7 @@ impl Default for VertexAttribData {
|
|||
stride: 0,
|
||||
offset: 0,
|
||||
buffer: None,
|
||||
divisor: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
15
components/script/dom/webidls/ANGLEInstancedArrays.webidl
Normal file
15
components/script/dom/webidls/ANGLEInstancedArrays.webidl
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* WebGL IDL definitions from the Khronos specification:
|
||||
* https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/
|
||||
*/
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface ANGLEInstancedArrays {
|
||||
const GLenum VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE = 0x88FE;
|
||||
void drawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
|
||||
void drawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, GLintptr offset, GLsizei primcount);
|
||||
void vertexAttribDivisorANGLE(GLuint index, GLuint divisor);
|
||||
};
|
|
@ -502,9 +502,9 @@ interface WebGL2RenderingContextBase
|
|||
// void vertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
|
||||
|
||||
/* Writing to the drawing buffer */
|
||||
// void vertexAttribDivisor(GLuint index, GLuint divisor);
|
||||
// void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount);
|
||||
// void drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, GLintptr offset, GLsizei instanceCount);
|
||||
void vertexAttribDivisor(GLuint index, GLuint divisor);
|
||||
void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount);
|
||||
void drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, GLintptr offset, GLsizei instanceCount);
|
||||
// void drawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, GLintptr offset);
|
||||
|
||||
/* Reading back pixels */
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
[angle-instanced-arrays-out-of-bounds.html]
|
||||
bug: https://github.com/servo/servo/issues/20599
|
||||
[WebGL test #175: getError expected: INVALID_OPERATION. Was NO_ERROR : after evaluating: ext.drawElementsInstancedANGLE(gl.TRIANGLES, 9, gl.UNSIGNED_BYTE, 0, 1)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #178: getError expected: INVALID_OPERATION. Was NO_ERROR : after evaluating: ext.drawElementsInstancedANGLE(gl.TRIANGLES, 9, gl.UNSIGNED_BYTE, 0, 1)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #180: getError expected: INVALID_OPERATION. Was NO_ERROR : after evaluating: ext.drawElementsInstancedANGLE(gl.TRIANGLES, 9, gl.UNSIGNED_BYTE, 0, 2)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #182: getError expected: INVALID_OPERATION. Was NO_ERROR : after evaluating: ext.drawElementsInstancedANGLE(gl.TRIANGLES, 9, gl.UNSIGNED_BYTE, 0, 4)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #183: getError expected: INVALID_OPERATION. Was NO_ERROR : after evaluating: ext.drawElementsInstancedANGLE(gl.TRIANGLES, 9, gl.UNSIGNED_BYTE, 0, 10000)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #184: getError expected: INVALID_OPERATION. Was NO_ERROR : after evaluating: ext.drawElementsInstancedANGLE(gl.TRIANGLES, 9, gl.UNSIGNED_BYTE, 0, 0x7fffffff)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #186: getError expected: INVALID_OPERATION. Was NO_ERROR : after evaluating: ext.drawElementsInstancedANGLE(gl.TRIANGLES, 9, gl.UNSIGNED_BYTE, 0, 3)]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #188: getError expected: INVALID_OPERATION. Was NO_ERROR : after evaluating: ext.drawElementsInstancedANGLE(gl.TRIANGLES, 9, gl.UNSIGNED_BYTE, 0, 5)]
|
||||
expected: FAIL
|
||||
|
|
@ -113,159 +113,150 @@
|
|||
[WebGL test #37: Property either does not exist or is not a function: vertexAttribIPointer]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #38: Property either does not exist or is not a function: vertexAttribDivisor]
|
||||
[WebGL test #38: Property either does not exist or is not a function: drawRangeElements]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #39: Property either does not exist or is not a function: drawArraysInstanced]
|
||||
[WebGL test #39: Property either does not exist or is not a function: drawBuffers]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #40: Property either does not exist or is not a function: drawElementsInstanced]
|
||||
[WebGL test #40: Property either does not exist or is not a function: clearBufferiv]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #41: Property either does not exist or is not a function: drawRangeElements]
|
||||
[WebGL test #41: Property either does not exist or is not a function: clearBufferuiv]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #42: Property either does not exist or is not a function: drawBuffers]
|
||||
[WebGL test #42: Property either does not exist or is not a function: clearBufferfv]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #43: Property either does not exist or is not a function: clearBufferiv]
|
||||
[WebGL test #43: Property either does not exist or is not a function: clearBufferfi]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #44: Property either does not exist or is not a function: clearBufferuiv]
|
||||
[WebGL test #44: Property either does not exist or is not a function: createQuery]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #45: Property either does not exist or is not a function: clearBufferfv]
|
||||
[WebGL test #45: Property either does not exist or is not a function: deleteQuery]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #46: Property either does not exist or is not a function: clearBufferfi]
|
||||
[WebGL test #46: Property either does not exist or is not a function: isQuery]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #47: Property either does not exist or is not a function: createQuery]
|
||||
[WebGL test #47: Property either does not exist or is not a function: beginQuery]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #48: Property either does not exist or is not a function: deleteQuery]
|
||||
[WebGL test #48: Property either does not exist or is not a function: endQuery]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #49: Property either does not exist or is not a function: isQuery]
|
||||
[WebGL test #49: Property either does not exist or is not a function: getQuery]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #50: Property either does not exist or is not a function: beginQuery]
|
||||
[WebGL test #50: Property either does not exist or is not a function: getQueryParameter]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #51: Property either does not exist or is not a function: endQuery]
|
||||
[WebGL test #51: Property either does not exist or is not a function: createSampler]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #52: Property either does not exist or is not a function: getQuery]
|
||||
[WebGL test #52: Property either does not exist or is not a function: deleteSampler]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #53: Property either does not exist or is not a function: getQueryParameter]
|
||||
[WebGL test #53: Property either does not exist or is not a function: isSampler]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #54: Property either does not exist or is not a function: createSampler]
|
||||
[WebGL test #54: Property either does not exist or is not a function: bindSampler]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #55: Property either does not exist or is not a function: deleteSampler]
|
||||
[WebGL test #55: Property either does not exist or is not a function: samplerParameteri]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #56: Property either does not exist or is not a function: isSampler]
|
||||
[WebGL test #56: Property either does not exist or is not a function: samplerParameterf]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #57: Property either does not exist or is not a function: bindSampler]
|
||||
[WebGL test #57: Property either does not exist or is not a function: getSamplerParameter]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #58: Property either does not exist or is not a function: samplerParameteri]
|
||||
[WebGL test #58: Property either does not exist or is not a function: fenceSync]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #59: Property either does not exist or is not a function: samplerParameterf]
|
||||
[WebGL test #59: Property either does not exist or is not a function: isSync]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #60: Property either does not exist or is not a function: getSamplerParameter]
|
||||
[WebGL test #60: Property either does not exist or is not a function: deleteSync]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #61: Property either does not exist or is not a function: fenceSync]
|
||||
[WebGL test #61: Property either does not exist or is not a function: clientWaitSync]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #62: Property either does not exist or is not a function: isSync]
|
||||
[WebGL test #62: Property either does not exist or is not a function: waitSync]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #63: Property either does not exist or is not a function: deleteSync]
|
||||
[WebGL test #63: Property either does not exist or is not a function: getSyncParameter]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #64: Property either does not exist or is not a function: clientWaitSync]
|
||||
[WebGL test #64: Property either does not exist or is not a function: createTransformFeedback]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #65: Property either does not exist or is not a function: waitSync]
|
||||
[WebGL test #65: Property either does not exist or is not a function: deleteTransformFeedback]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #66: Property either does not exist or is not a function: getSyncParameter]
|
||||
[WebGL test #66: Property either does not exist or is not a function: isTransformFeedback]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #67: Property either does not exist or is not a function: createTransformFeedback]
|
||||
[WebGL test #67: Property either does not exist or is not a function: bindTransformFeedback]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #68: Property either does not exist or is not a function: deleteTransformFeedback]
|
||||
[WebGL test #68: Property either does not exist or is not a function: beginTransformFeedback]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #69: Property either does not exist or is not a function: isTransformFeedback]
|
||||
[WebGL test #69: Property either does not exist or is not a function: endTransformFeedback]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #70: Property either does not exist or is not a function: bindTransformFeedback]
|
||||
[WebGL test #70: Property either does not exist or is not a function: transformFeedbackVaryings]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #71: Property either does not exist or is not a function: beginTransformFeedback]
|
||||
[WebGL test #71: Property either does not exist or is not a function: getTransformFeedbackVarying]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #72: Property either does not exist or is not a function: endTransformFeedback]
|
||||
[WebGL test #72: Property either does not exist or is not a function: pauseTransformFeedback]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #73: Property either does not exist or is not a function: transformFeedbackVaryings]
|
||||
[WebGL test #73: Property either does not exist or is not a function: resumeTransformFeedback]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #74: Property either does not exist or is not a function: getTransformFeedbackVarying]
|
||||
[WebGL test #74: Property either does not exist or is not a function: bindBufferBase]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #75: Property either does not exist or is not a function: pauseTransformFeedback]
|
||||
[WebGL test #75: Property either does not exist or is not a function: bindBufferRange]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #76: Property either does not exist or is not a function: resumeTransformFeedback]
|
||||
[WebGL test #76: Property either does not exist or is not a function: getIndexedParameter]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #77: Property either does not exist or is not a function: bindBufferBase]
|
||||
[WebGL test #77: Property either does not exist or is not a function: getUniformIndices]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #78: Property either does not exist or is not a function: bindBufferRange]
|
||||
[WebGL test #78: Property either does not exist or is not a function: getActiveUniforms]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #79: Property either does not exist or is not a function: getIndexedParameter]
|
||||
[WebGL test #79: Property either does not exist or is not a function: getUniformBlockIndex]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #80: Property either does not exist or is not a function: getUniformIndices]
|
||||
[WebGL test #80: Property either does not exist or is not a function: getActiveUniformBlockParameter]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #81: Property either does not exist or is not a function: getActiveUniforms]
|
||||
[WebGL test #81: Property either does not exist or is not a function: getActiveUniformBlockName]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #82: Property either does not exist or is not a function: getUniformBlockIndex]
|
||||
[WebGL test #82: Property either does not exist or is not a function: uniformBlockBinding]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #83: Property either does not exist or is not a function: getActiveUniformBlockParameter]
|
||||
[WebGL test #83: Property either does not exist or is not a function: createVertexArray]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #84: Property either does not exist or is not a function: getActiveUniformBlockName]
|
||||
[WebGL test #84: Property either does not exist or is not a function: deleteVertexArray]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #85: Property either does not exist or is not a function: uniformBlockBinding]
|
||||
[WebGL test #85: Property either does not exist or is not a function: isVertexArray]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #86: Property either does not exist or is not a function: createVertexArray]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #87: Property either does not exist or is not a function: deleteVertexArray]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #88: Property either does not exist or is not a function: isVertexArray]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #89: Property either does not exist or is not a function: bindVertexArray]
|
||||
[WebGL test #86: Property either does not exist or is not a function: bindVertexArray]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
[instanced-arrays.html]
|
||||
expected: ERROR
|
||||
[WebGL test #2: Default divisor of vertex attribute 0 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #3: Default divisor of vertex attribute 1 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #4: Default divisor of vertex attribute 2 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #5: Default divisor of vertex attribute 3 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #6: Default divisor of vertex attribute 4 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #7: Default divisor of vertex attribute 5 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #8: Default divisor of vertex attribute 6 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #9: Default divisor of vertex attribute 7 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #10: Default divisor of vertex attribute 8 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #11: Default divisor of vertex attribute 9 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #12: Default divisor of vertex attribute 10 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #13: Default divisor of vertex attribute 11 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #14: Default divisor of vertex attribute 12 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #15: Default divisor of vertex attribute 13 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #16: Default divisor of vertex attribute 14 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #17: Default divisor of vertex attribute 15 should be: 0, returned value was: null]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #18: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||
expected: FAIL
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue