Implement instanced WebGL drawing calls (part of #20791)

This commit is contained in:
Anthony Ramine 2018-03-20 10:11:46 +01:00
parent 0aefffc5bf
commit 4e6eea221a
12 changed files with 432 additions and 125 deletions

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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>();