Skip to content

Commit

Permalink
Auto merge of #21129 - servo:webgl, r=emilio
Browse files Browse the repository at this point in the history
Implement instanced WebGL drawing calls (part of #20791)

This is half of #20599. The check for drawElements is a bit more complex to implement.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21129)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Jul 8, 2018
2 parents bd0c001 + 4e6eea2 commit 41e1057
Show file tree
Hide file tree
Showing 44 changed files with 612 additions and 487 deletions.
16 changes: 16 additions & 0 deletions components/canvas/webgl_thread.rs
Expand Up @@ -885,6 +885,13 @@ impl WebGLImpl {
}
sender.send(value[0]).unwrap()
}
WebGLCommand::GetParameterInt2(param, ref sender) => {
let mut value = [0; 2];
unsafe {
ctx.gl().get_integer_v(param as u32, &mut value);
}
sender.send(value).unwrap()
}
WebGLCommand::GetParameterInt4(param, ref sender) => {
let mut value = [0; 4];
unsafe {
Expand Down Expand Up @@ -966,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
Expand Down
7 changes: 7 additions & 0 deletions components/canvas_traits/webgl.rs
Expand Up @@ -268,6 +268,7 @@ pub enum WebGLCommand {
GetParameterBool(ParameterBool, WebGLSender<bool>),
GetParameterBool4(ParameterBool4, WebGLSender<[bool; 4]>),
GetParameterInt(ParameterInt, WebGLSender<i32>),
GetParameterInt2(ParameterInt2, WebGLSender<[i32; 2]>),
GetParameterInt4(ParameterInt4, WebGLSender<[i32; 4]>),
GetParameterFloat(ParameterFloat, WebGLSender<f32>),
GetParameterFloat2(ParameterFloat2, WebGLSender<[f32; 2]>),
Expand All @@ -281,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 {
Expand Down Expand Up @@ -522,6 +526,9 @@ parameters! {
SubpixelBits = gl::SUBPIXEL_BITS,
UnpackAlignment = gl::UNPACK_ALIGNMENT,
}),
Int2(ParameterInt2 {
MaxViewportDims = gl::MAX_VIEWPORT_DIMS,
}),
Int4(ParameterInt4 {
ScissorBox = gl::SCISSOR_BOX,
Viewport = gl::VIEWPORT,
Expand Down
28 changes: 28 additions & 0 deletions components/script/dom/webgl2renderingcontext.rs
Expand Up @@ -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);
}
}


Expand Down
92 changes: 92 additions & 0 deletions components/script/dom/webgl_extensions/ext/angleinstancedarrays.rs
@@ -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);
}
}
1 change: 1 addition & 0 deletions components/script/dom/webgl_extensions/ext/mod.rs
Expand Up @@ -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;
Expand Down
31 changes: 30 additions & 1 deletion components/script/dom/webgl_extensions/extensions.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand All @@ -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.
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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,
}
Expand Down Expand Up @@ -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>();
Expand Down

0 comments on commit 41e1057

Please sign in to comment.