mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
bug 900767 - Implement the WebGL extension ANGLE_instanced_arrays - r=jgilbert
This commit is contained in:
parent
e5911a1739
commit
25894203e2
@ -197,9 +197,7 @@ WebGLContext::WebGLContext()
|
||||
|
||||
mLastUseIndex = 0;
|
||||
|
||||
mBufferFetchingIsVerified = false;
|
||||
mMaxFetchedVertices = 0;
|
||||
mMaxFetchedInstances = 0;
|
||||
InvalidateBufferFetching();
|
||||
|
||||
mIsScreenCleared = false;
|
||||
|
||||
@ -1019,6 +1017,8 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case ANGLE_instanced_arrays:
|
||||
return WebGLExtensionInstancedArrays::IsSupported(this);
|
||||
default:
|
||||
// For warnings-as-errors.
|
||||
break;
|
||||
@ -1118,6 +1118,10 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
|
||||
{
|
||||
ext = WEBGL_draw_buffers;
|
||||
}
|
||||
else if (CompareWebGLExtensionName(name, "ANGLE_instanced_arrays"))
|
||||
{
|
||||
ext = ANGLE_instanced_arrays;
|
||||
}
|
||||
|
||||
if (ext == WebGLExtensionID_unknown_extension) {
|
||||
return nullptr;
|
||||
@ -1184,6 +1188,9 @@ WebGLContext::EnableExtension(WebGLExtensionID ext)
|
||||
case OES_vertex_array_object:
|
||||
obj = new WebGLExtensionVertexArray(this);
|
||||
break;
|
||||
case ANGLE_instanced_arrays:
|
||||
obj = new WebGLExtensionInstancedArrays(this);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "should not get there.");
|
||||
}
|
||||
@ -1592,6 +1599,8 @@ WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString>
|
||||
arr.AppendElement(NS_LITERAL_STRING("WEBGL_draw_buffers"));
|
||||
if (IsExtensionSupported(cx, OES_vertex_array_object))
|
||||
arr.AppendElement(NS_LITERAL_STRING("OES_vertex_array_object"));
|
||||
if (IsExtensionSupported(cx, ANGLE_instanced_arrays))
|
||||
arr.AppendElement(NS_LITERAL_STRING("ANGLE_instanced_arrays"));
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -815,6 +815,21 @@ public:
|
||||
void VertexAttribDivisor(WebGLuint index, WebGLuint divisor);
|
||||
|
||||
private:
|
||||
// Cache the max number of vertices and instances that can be read from
|
||||
// bound VBOs (result of ValidateBuffers).
|
||||
bool mBufferFetchingIsVerified;
|
||||
bool mBufferFetchingHasPerVertex;
|
||||
uint32_t mMaxFetchedVertices;
|
||||
uint32_t mMaxFetchedInstances;
|
||||
|
||||
inline void InvalidateBufferFetching()
|
||||
{
|
||||
mBufferFetchingIsVerified = false;
|
||||
mBufferFetchingHasPerVertex = false;
|
||||
mMaxFetchedVertices = 0;
|
||||
mMaxFetchedInstances = 0;
|
||||
}
|
||||
|
||||
bool DrawArrays_check(WebGLint first, WebGLsizei count, WebGLsizei primcount, const char* info);
|
||||
bool DrawElements_check(WebGLsizei count, WebGLenum type, WebGLintptr byteOffset,
|
||||
WebGLsizei primcount, const char* info);
|
||||
@ -895,19 +910,6 @@ protected:
|
||||
int32_t mGLMaxColorAttachments;
|
||||
int32_t mGLMaxDrawBuffers;
|
||||
|
||||
// Cache the max number of vertices and isntances that can be read from
|
||||
// bound VBOs (result of ValidateBuffers).
|
||||
bool mBufferFetchingIsVerified;
|
||||
uint32_t mMaxFetchedVertices;
|
||||
uint32_t mMaxFetchedInstances;
|
||||
|
||||
inline void InvalidateBufferFetching()
|
||||
{
|
||||
mBufferFetchingIsVerified = false;
|
||||
mMaxFetchedVertices = 0;
|
||||
mMaxFetchedInstances = 0;
|
||||
}
|
||||
|
||||
// Represents current status, or state, of the context. That is, is it lost
|
||||
// or stable and what part of the context lost process are we currently at.
|
||||
// This is used to support the WebGL spec's asyncronous nature in handling
|
||||
@ -942,6 +944,7 @@ protected:
|
||||
WEBGL_depth_texture,
|
||||
WEBGL_lose_context,
|
||||
WEBGL_draw_buffers,
|
||||
ANGLE_instanced_arrays,
|
||||
WebGLExtensionID_unknown_extension
|
||||
};
|
||||
nsTArray<nsRefPtr<WebGLExtensionBase> > mExtensions;
|
||||
|
@ -995,10 +995,9 @@ WebGLContext::InitAndValidateGL()
|
||||
if (IsWebGL2() &&
|
||||
(!IsExtensionSupported(OES_vertex_array_object) ||
|
||||
!IsExtensionSupported(WEBGL_draw_buffers) ||
|
||||
!IsExtensionSupported(ANGLE_instanced_arrays) ||
|
||||
!gl->IsExtensionSupported(gl::GLContext::EXT_gpu_shader4) ||
|
||||
!gl->IsExtensionSupported(gl::GLContext::EXT_blend_minmax) ||
|
||||
!gl->IsExtensionSupported(gl::GLContext::XXX_draw_instanced) ||
|
||||
!gl->IsExtensionSupported(gl::GLContext::XXX_instanced_arrays) ||
|
||||
(gl->IsGLES2() && !gl->IsExtensionSupported(gl::GLContext::EXT_occlusion_query_boolean))
|
||||
))
|
||||
{
|
||||
@ -1023,9 +1022,11 @@ WebGLContext::InitAndValidateGL()
|
||||
if (IsWebGL2()) {
|
||||
EnableExtension(OES_vertex_array_object);
|
||||
EnableExtension(WEBGL_draw_buffers);
|
||||
EnableExtension(ANGLE_instanced_arrays);
|
||||
|
||||
MOZ_ASSERT(IsExtensionEnabled(OES_vertex_array_object));
|
||||
MOZ_ASSERT(IsExtensionEnabled(WEBGL_draw_buffers));
|
||||
MOZ_ASSERT(IsExtensionEnabled(ANGLE_instanced_arrays));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -262,7 +262,7 @@ WebGLContext::GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname,
|
||||
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
|
||||
{
|
||||
if (IsWebGL2())
|
||||
if (IsExtensionEnabled(ANGLE_instanced_arrays))
|
||||
{
|
||||
return JS::Int32Value(mBoundVertexArray->mAttribBuffers[index].divisor);
|
||||
}
|
||||
@ -470,6 +470,16 @@ bool WebGLContext::DrawArrays_check(WebGLint first, WebGLsizei count, WebGLsizei
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mBufferFetchingHasPerVertex && !IsWebGL2()) {
|
||||
/* http://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_instanced_arrays.txt
|
||||
* If all of the enabled vertex attribute arrays that are bound to active
|
||||
* generic attributes in the program have a non-zero divisor, the draw
|
||||
* call should return INVALID_OPERATION.
|
||||
*/
|
||||
ErrorInvalidOperation("%s: at least one vertex attribute divisor should be 0", info);
|
||||
return false;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
@ -624,6 +634,16 @@ WebGLContext::DrawElements_check(WebGLsizei count, WebGLenum type, WebGLintptr b
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mBufferFetchingHasPerVertex && !IsWebGL2()) {
|
||||
/* http://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_instanced_arrays.txt
|
||||
* If all of the enabled vertex attribute arrays that are bound to active
|
||||
* generic attributes in the program have a non-zero divisor, the draw
|
||||
* call should return INVALID_OPERATION.
|
||||
*/
|
||||
ErrorInvalidOperation("%s: at least one vertex attribute divisor should be 0", info);
|
||||
return false;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
@ -674,7 +694,7 @@ WebGLContext::DrawElementsInstanced(WebGLenum mode, WebGLsizei count, WebGLenum
|
||||
return;
|
||||
|
||||
SetupContextLossTimer();
|
||||
gl->fDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset));
|
||||
gl->fDrawElementsInstanced(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset), primcount);
|
||||
|
||||
Draw_cleanup();
|
||||
}
|
||||
@ -722,6 +742,7 @@ WebGLContext::ValidateBufferFetching(const char *info)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasPerVertex = false;
|
||||
uint32_t maxVertices = UINT32_MAX;
|
||||
uint32_t maxInstances = UINT32_MAX;
|
||||
uint32_t attribs = mBoundVertexArray->mAttribBuffers.Length();
|
||||
@ -768,13 +789,16 @@ WebGLContext::ValidateBufferFetching(const char *info)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vd.divisor == 0)
|
||||
if (vd.divisor == 0) {
|
||||
maxVertices = std::min(maxVertices, checked_maxAllowedCount.value());
|
||||
else
|
||||
hasPerVertex = true;
|
||||
} else {
|
||||
maxInstances = std::min(maxInstances, checked_maxAllowedCount.value() / vd.divisor);
|
||||
}
|
||||
}
|
||||
|
||||
mBufferFetchingIsVerified = true;
|
||||
mBufferFetchingHasPerVertex = hasPerVertex;
|
||||
mMaxFetchedVertices = maxVertices;
|
||||
mMaxFetchedInstances = maxInstances;
|
||||
|
||||
|
53
content/canvas/src/WebGLExtensionInstancedArrays.cpp
Normal file
53
content/canvas/src/WebGLExtensionInstancedArrays.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLExtensions.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
WebGLExtensionInstancedArrays::WebGLExtensionInstancedArrays(WebGLContext* context)
|
||||
: WebGLExtensionBase(context)
|
||||
{
|
||||
MOZ_ASSERT(IsSupported(context), "should not construct WebGLExtensionInstancedArrays: "
|
||||
"ANGLE_instanced_arrays unsupported.");
|
||||
}
|
||||
|
||||
WebGLExtensionInstancedArrays::~WebGLExtensionInstancedArrays()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
WebGLExtensionInstancedArrays::DrawArraysInstancedANGLE(WebGLenum mode, WebGLint first,
|
||||
WebGLsizei count, WebGLsizei primcount)
|
||||
{
|
||||
mContext->DrawArraysInstanced(mode, first, count, primcount);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLExtensionInstancedArrays::DrawElementsInstancedANGLE(WebGLenum mode, WebGLsizei count,
|
||||
WebGLenum type, WebGLintptr offset,
|
||||
WebGLsizei primcount)
|
||||
{
|
||||
mContext->DrawElementsInstanced(mode, count, type, offset, primcount);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLExtensionInstancedArrays::VertexAttribDivisorANGLE(WebGLuint index, WebGLuint divisor)
|
||||
{
|
||||
mContext->VertexAttribDivisor(index, divisor);
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLExtensionInstancedArrays::IsSupported(const WebGLContext* context)
|
||||
{
|
||||
gl::GLContext* gl = context->GL();
|
||||
|
||||
return gl->IsExtensionSupported(gl::GLContext::XXX_draw_instanced) &&
|
||||
gl->IsExtensionSupported(gl::GLContext::XXX_instanced_arrays);
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionInstancedArrays)
|
@ -189,6 +189,25 @@ public:
|
||||
DECL_WEBGL_EXTENSION_GOOP
|
||||
};
|
||||
|
||||
class WebGLExtensionInstancedArrays
|
||||
: public WebGLExtensionBase
|
||||
{
|
||||
public:
|
||||
WebGLExtensionInstancedArrays(WebGLContext* context);
|
||||
virtual ~WebGLExtensionInstancedArrays();
|
||||
|
||||
void DrawArraysInstancedANGLE(WebGLenum mode, WebGLint first,
|
||||
WebGLsizei count, WebGLsizei primcount);
|
||||
void DrawElementsInstancedANGLE(WebGLenum mode, WebGLsizei count,
|
||||
WebGLenum type, WebGLintptr offset,
|
||||
WebGLsizei primcount);
|
||||
void VertexAttribDivisorANGLE(WebGLuint index, WebGLuint divisor);
|
||||
|
||||
static bool IsSupported(const WebGLContext* context);
|
||||
|
||||
DECL_WEBGL_EXTENSION_GOOP
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // WEBGLEXTENSIONS_H_
|
||||
|
@ -48,6 +48,7 @@ if CONFIG['MOZ_WEBGL']:
|
||||
'WebGLExtensionDepthTexture.cpp',
|
||||
'WebGLExtensionDrawBuffers.cpp',
|
||||
'WebGLExtensionElementIndexUint.cpp',
|
||||
'WebGLExtensionInstancedArrays.cpp',
|
||||
'WebGLExtensionLoseContext.cpp',
|
||||
'WebGLExtensionStandardDerivatives.cpp',
|
||||
'WebGLExtensionTextureFilterAnisotropic.cpp',
|
||||
|
@ -1305,6 +1305,11 @@ DOMInterfaces = {
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionInstancedArrays': {
|
||||
'nativeType': 'mozilla::WebGLExtensionInstancedArrays',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLFramebuffer': {
|
||||
'nativeType': 'mozilla::WebGLFramebuffer',
|
||||
'headerFile': 'WebGLFramebuffer.h'
|
||||
|
@ -896,3 +896,12 @@ interface WebGLExtensionVertexArray {
|
||||
[WebGLHandlesContextLoss] GLboolean isVertexArrayOES(WebGLVertexArray? arrayObject);
|
||||
void bindVertexArrayOES(WebGLVertexArray? arrayObject);
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface WebGLExtensionInstancedArrays {
|
||||
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);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user