bug 738869 - implement OES_vertex_array_object webgl extension - r=bjacob

This commit is contained in:
Guillaume Abadie ext:(%20and%20James%20King%20%3Cjames%40agentultra.com%3E) 2013-06-27 17:07:21 -04:00
parent 0031f6ddfb
commit a7e54e5fa6
15 changed files with 439 additions and 68 deletions

View File

@ -11,6 +11,7 @@
#include "WebGLVertexAttribData.h"
#include "WebGLMemoryMultiReporterWrapper.h"
#include "WebGLFramebuffer.h"
#include "WebGLVertexArray.h"
#include "AccessCheck.h"
#include "nsIConsoleService.h"
@ -253,15 +254,16 @@ WebGLContext::DestroyResourcesAndContext()
mBound2DTextures.Clear();
mBoundCubeMapTextures.Clear();
mBoundArrayBuffer = nullptr;
mBoundElementArrayBuffer = nullptr;
mCurrentProgram = nullptr;
mBoundFramebuffer = nullptr;
mBoundRenderbuffer = nullptr;
mAttribBuffers.Clear();
mBoundVertexArray = nullptr;
mDefaultVertexArray = nullptr;
while (!mTextures.isEmpty())
mTextures.getLast()->DeleteOnce();
while (!mVertexArrays.isEmpty())
mVertexArrays.getLast()->DeleteOnce();
while (!mBuffers.isEmpty())
mBuffers.getLast()->DeleteOnce();
while (!mRenderbuffers.isEmpty())
@ -984,6 +986,8 @@ bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) con
case OES_texture_float_linear:
return gl->IsExtensionSupported(gl->IsGLES2() ? GLContext::OES_texture_float_linear
: GLContext::ARB_texture_float);
case OES_vertex_array_object:
return WebGLExtensionVertexArray::IsSupported(this);
case EXT_texture_filter_anisotropic:
return gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
case WEBGL_compressed_texture_s3tc:
@ -1063,6 +1067,10 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
{
ext = OES_texture_float_linear;
}
else if (CompareWebGLExtensionName(name, "OES_vertex_array_object"))
{
ext = OES_vertex_array_object;
}
else if (CompareWebGLExtensionName(name, "OES_standard_derivatives"))
{
ext = OES_standard_derivatives;
@ -1161,6 +1169,9 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
case WEBGL_draw_buffers:
obj = new WebGLExtensionDrawBuffers(this);
break;
case OES_vertex_array_object:
obj = new WebGLExtensionVertexArray(this);
break;
default:
MOZ_ASSERT(false, "should not get there.");
}
@ -1564,6 +1575,8 @@ WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString>
arr.AppendElement(NS_LITERAL_STRING("WEBGL_depth_texture"));
if (IsExtensionSupported(cx, WEBGL_draw_buffers))
arr.AppendElement(NS_LITERAL_STRING("WEBGL_draw_buffers"));
if (IsExtensionSupported(cx, OES_vertex_array_object))
arr.AppendElement(NS_LITERAL_STRING("OES_vertex_array_object"));
}
//
@ -1573,17 +1586,16 @@ WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString>
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLContext)
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLContext)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_10(WebGLContext,
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_9(WebGLContext,
mCanvasElement,
mExtensions,
mBound2DTextures,
mBoundCubeMapTextures,
mBoundArrayBuffer,
mBoundElementArrayBuffer,
mCurrentProgram,
mBoundFramebuffer,
mBoundRenderbuffer,
mAttribBuffers)
mBoundVertexArray)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY

View File

@ -76,6 +76,7 @@ class WebGLFramebuffer;
class WebGLRenderbuffer;
class WebGLShaderPrecisionFormat;
class WebGLTexture;
class WebGLVertexArray;
namespace dom {
struct WebGLContextAttributes;
@ -128,6 +129,7 @@ class WebGLContext :
friend class WebGLExtensionCompressedTexturePVRTC;
friend class WebGLExtensionDepthTexture;
friend class WebGLExtensionDrawBuffers;
friend class WebGLExtensionVertexArray;
enum {
UNPACK_FLIP_Y_WEBGL = 0x9240,
@ -321,6 +323,7 @@ public:
void BindFramebuffer(WebGLenum target, WebGLFramebuffer* wfb);
void BindRenderbuffer(WebGLenum target, WebGLRenderbuffer* wrb);
void BindTexture(WebGLenum target, WebGLTexture *tex);
void BindVertexArray(WebGLVertexArray *vao);
void BlendColor(WebGLclampf r, WebGLclampf g, WebGLclampf b, WebGLclampf a) {
if (!IsContextStable())
return;
@ -367,12 +370,14 @@ public:
already_AddRefed<WebGLRenderbuffer> CreateRenderbuffer();
already_AddRefed<WebGLTexture> CreateTexture();
already_AddRefed<WebGLShader> CreateShader(WebGLenum type);
already_AddRefed<WebGLVertexArray> CreateVertexArray();
void CullFace(WebGLenum face);
void DeleteBuffer(WebGLBuffer *buf);
void DeleteFramebuffer(WebGLFramebuffer *fbuf);
void DeleteProgram(WebGLProgram *prog);
void DeleteRenderbuffer(WebGLRenderbuffer *rbuf);
void DeleteShader(WebGLShader *shader);
void DeleteVertexArray(WebGLVertexArray *vao);
void DeleteTexture(WebGLTexture *tex);
void DepthFunc(WebGLenum func);
void DepthMask(WebGLboolean b);
@ -465,6 +470,7 @@ public:
bool IsRenderbuffer(WebGLRenderbuffer *rb);
bool IsShader(WebGLShader *shader);
bool IsTexture(WebGLTexture *tex);
bool IsVertexArray(WebGLVertexArray *vao);
void LineWidth(WebGLfloat width) {
if (!IsContextStable())
return;
@ -874,6 +880,7 @@ protected:
OES_standard_derivatives,
OES_texture_float,
OES_texture_float_linear,
OES_vertex_array_object,
WEBGL_compressed_texture_atc,
WEBGL_compressed_texture_pvrtc,
WEBGL_compressed_texture_s3tc,
@ -1031,14 +1038,10 @@ protected:
void ForceLoseContext();
void ForceRestoreContext();
// the buffers bound to the current program's attribs
nsTArray<WebGLVertexAttribData> mAttribBuffers;
nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures;
WebGLRefPtr<WebGLBuffer> mBoundArrayBuffer;
WebGLRefPtr<WebGLBuffer> mBoundElementArrayBuffer;
WebGLRefPtr<WebGLProgram> mCurrentProgram;
@ -1046,6 +1049,7 @@ protected:
WebGLRefPtr<WebGLFramebuffer> mBoundFramebuffer;
WebGLRefPtr<WebGLRenderbuffer> mBoundRenderbuffer;
WebGLRefPtr<WebGLVertexArray> mBoundVertexArray;
LinkedList<WebGLTexture> mTextures;
LinkedList<WebGLBuffer> mBuffers;
@ -1053,6 +1057,9 @@ protected:
LinkedList<WebGLShader> mShaders;
LinkedList<WebGLRenderbuffer> mRenderbuffers;
LinkedList<WebGLFramebuffer> mFramebuffers;
LinkedList<WebGLVertexArray> mVertexArrays;
WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray;
// PixelStore parameters
uint32_t mPixelStorePackAlignment, mPixelStoreUnpackAlignment, mPixelStoreColorspaceConversion;
@ -1138,6 +1145,7 @@ public:
friend class WebGLBuffer;
friend class WebGLShader;
friend class WebGLUniformLocation;
friend class WebGLVertexArray;
};
// used by DOM bindings in conjunction with GetParentObject

View File

@ -15,6 +15,7 @@
#include "WebGLShaderPrecisionFormat.h"
#include "WebGLTexture.h"
#include "WebGLExtensions.h"
#include "WebGLVertexArray.h"
#include "nsString.h"
#include "nsDebug.h"
@ -162,7 +163,7 @@ WebGLContext::BindBuffer(WebGLenum target, WebGLBuffer *buf)
if (target == LOCAL_GL_ARRAY_BUFFER) {
mBoundArrayBuffer = buf;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
mBoundElementArrayBuffer = buf;
mBoundVertexArray->mBoundElementArrayBuffer = buf;
}
MakeContextCurrent();
@ -226,6 +227,39 @@ WebGLContext::BindRenderbuffer(WebGLenum target, WebGLRenderbuffer *wrb)
mBoundRenderbuffer = wrb;
}
void
WebGLContext::BindVertexArray(WebGLVertexArray *array)
{
if (!IsContextStable())
return;
if (!ValidateObjectAllowDeletedOrNull("bindVertexArrayObject", array))
return;
if (array && array->IsDeleted()) {
/* http://www.khronos.org/registry/gles/extensions/OES/OES_vertex_array_object.txt
* BindVertexArrayOES fails and an INVALID_OPERATION error is
* generated if array is not a name returned from a previous call to
* GenVertexArraysOES, or if such a name has since been deleted with
* DeleteVertexArraysOES
*/
ErrorInvalidOperation("bindVertexArray: can't bind a deleted array!");
return;
}
MakeContextCurrent();
if (array) {
gl->fBindVertexArray(array->GLName());
array->SetHasEverBeenBound(true);
mBoundVertexArray = array;
}
else {
gl->fBindVertexArray(0);
mBoundVertexArray = mDefaultVertexArray;
}
}
void
WebGLContext::BindTexture(WebGLenum target, WebGLTexture *tex)
{
@ -337,7 +371,7 @@ GLenum WebGLContext::CheckedBufferData(GLenum target,
if (target == LOCAL_GL_ARRAY_BUFFER) {
boundBuffer = mBoundArrayBuffer;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
boundBuffer = mBoundElementArrayBuffer;
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
}
NS_ABORT_IF_FALSE(boundBuffer != nullptr, "no buffer bound for this target");
@ -366,7 +400,7 @@ WebGLContext::BufferData(WebGLenum target, WebGLsizeiptr size,
if (target == LOCAL_GL_ARRAY_BUFFER) {
boundBuffer = mBoundArrayBuffer;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
boundBuffer = mBoundElementArrayBuffer;
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
} else {
return ErrorInvalidEnumInfo("bufferData: target", target);
}
@ -411,7 +445,7 @@ WebGLContext::BufferData(WebGLenum target, ArrayBuffer *data, WebGLenum usage)
if (target == LOCAL_GL_ARRAY_BUFFER) {
boundBuffer = mBoundArrayBuffer;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
boundBuffer = mBoundElementArrayBuffer;
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
} else {
return ErrorInvalidEnumInfo("bufferData: target", target);
}
@ -449,7 +483,7 @@ WebGLContext::BufferData(WebGLenum target, ArrayBufferView& data, WebGLenum usag
if (target == LOCAL_GL_ARRAY_BUFFER) {
boundBuffer = mBoundArrayBuffer;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
boundBuffer = mBoundElementArrayBuffer;
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
} else {
return ErrorInvalidEnumInfo("bufferData: target", target);
}
@ -492,7 +526,7 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
if (target == LOCAL_GL_ARRAY_BUFFER) {
boundBuffer = mBoundArrayBuffer;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
boundBuffer = mBoundElementArrayBuffer;
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
} else {
return ErrorInvalidEnumInfo("bufferSubData: target", target);
}
@ -530,7 +564,7 @@ WebGLContext::BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
if (target == LOCAL_GL_ARRAY_BUFFER) {
boundBuffer = mBoundArrayBuffer;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
boundBuffer = mBoundElementArrayBuffer;
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
} else {
return ErrorInvalidEnumInfo("bufferSubData: target", target);
}
@ -1071,13 +1105,14 @@ WebGLContext::DeleteBuffer(WebGLBuffer *buf)
if (mBoundArrayBuffer == buf)
BindBuffer(LOCAL_GL_ARRAY_BUFFER,
static_cast<WebGLBuffer*>(nullptr));
if (mBoundElementArrayBuffer == buf)
if (mBoundVertexArray->mBoundElementArrayBuffer == buf)
BindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER,
static_cast<WebGLBuffer*>(nullptr));
for (int32_t i = 0; i < mGLMaxVertexAttribs; i++) {
if (mAttribBuffers[i].buf == buf)
mAttribBuffers[i].buf = nullptr;
if (mBoundVertexArray->mAttribBuffers[i].buf == buf)
mBoundVertexArray->mAttribBuffers[i].buf = nullptr;
}
buf->RequestDelete();
@ -1124,6 +1159,24 @@ WebGLContext::DeleteRenderbuffer(WebGLRenderbuffer *rbuf)
rbuf->RequestDelete();
}
void
WebGLContext::DeleteVertexArray(WebGLVertexArray *array)
{
if (!IsContextStable())
return;
if (array == nullptr)
return;
if (array->IsDeleted())
return;
if (mBoundVertexArray == array)
BindVertexArray(static_cast<WebGLVertexArray*>(nullptr));
array->RequestDelete();
}
void
WebGLContext::DeleteTexture(WebGLTexture *tex)
{
@ -1251,7 +1304,7 @@ WebGLContext::DisableVertexAttribArray(WebGLuint index)
if (index || gl->IsGLES2())
gl->fDisableVertexAttribArray(index);
mAttribBuffers[index].enabled = false;
mBoundVertexArray->mAttribBuffers[index].enabled = false;
}
int
@ -1262,14 +1315,14 @@ WebGLContext::WhatDoesVertexAttrib0Need()
// work around Mac OSX crash, see bug 631420
#ifdef XP_MACOSX
if (gl->WorkAroundDriverBugs() &&
mAttribBuffers[0].enabled &&
mBoundVertexArray->mAttribBuffers[0].enabled &&
!mCurrentProgram->IsAttribInUse(0))
{
return VertexAttrib0Status::EmulatedUninitializedArray;
}
#endif
return (gl->IsGLES2() || mAttribBuffers[0].enabled) ? VertexAttrib0Status::Default
return (gl->IsGLES2() || mBoundVertexArray->mAttribBuffers[0].enabled) ? VertexAttrib0Status::Default
: mCurrentProgram->IsAttribInUse(0) ? VertexAttrib0Status::EmulatedInitializedArray
: VertexAttrib0Status::EmulatedUninitializedArray;
}
@ -1369,13 +1422,13 @@ WebGLContext::UndoFakeVertexAttrib0()
if (whatDoesAttrib0Need == VertexAttrib0Status::Default)
return;
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mAttribBuffers[0].buf ? mAttribBuffers[0].buf->GLName() : 0);
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundVertexArray->mAttribBuffers[0].buf ? mBoundVertexArray->mAttribBuffers[0].buf->GLName() : 0);
gl->fVertexAttribPointer(0,
mAttribBuffers[0].size,
mAttribBuffers[0].type,
mAttribBuffers[0].normalized,
mAttribBuffers[0].stride,
reinterpret_cast<const GLvoid *>(mAttribBuffers[0].byteOffset));
mBoundVertexArray->mAttribBuffers[0].size,
mBoundVertexArray->mAttribBuffers[0].type,
mBoundVertexArray->mAttribBuffers[0].normalized,
mBoundVertexArray->mAttribBuffers[0].stride,
reinterpret_cast<const GLvoid *>(mBoundVertexArray->mAttribBuffers[0].byteOffset));
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
}
@ -1592,10 +1645,10 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
if (!mCurrentProgram)
return;
if (!mBoundElementArrayBuffer)
if (!mBoundVertexArray->mBoundElementArrayBuffer)
return ErrorInvalidOperation("drawElements: must have element array buffer binding");
if (!mBoundElementArrayBuffer->ByteLength())
if (!mBoundVertexArray->mBoundElementArrayBuffer->ByteLength())
return ErrorInvalidOperation("drawElements: bound element array buffer doesn't have any data");
CheckedUint32 checked_neededByteCount = checked_byteCount + byteOffset;
@ -1603,7 +1656,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
if (!checked_neededByteCount.isValid())
return ErrorInvalidOperation("drawElements: overflow in byteOffset+byteCount");
if (checked_neededByteCount.value() > mBoundElementArrayBuffer->ByteLength())
if (checked_neededByteCount.value() > mBoundVertexArray->mBoundElementArrayBuffer->ByteLength())
return ErrorInvalidOperation("drawElements: bound element array buffer is too small for given count and offset");
uint32_t maxAllowedCount = 0;
@ -1611,7 +1664,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
return;
if (!maxAllowedCount ||
!mBoundElementArrayBuffer->Validate(type, maxAllowedCount - 1, first, count))
!mBoundVertexArray->mBoundElementArrayBuffer->Validate(type, maxAllowedCount - 1, first, count))
{
return ErrorInvalidOperation(
"DrawElements: bound vertex attribute buffers do not have sufficient "
@ -1710,7 +1763,7 @@ WebGLContext::EnableVertexAttribArray(WebGLuint index)
InvalidateCachedMinInUseAttribArrayLength();
gl->fEnableVertexAttribArray(index);
mAttribBuffers[index].enabled = true;
mBoundVertexArray->mAttribBuffers[index].enabled = true;
}
void
@ -2030,6 +2083,21 @@ WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv)
}
}
if (IsExtensionEnabled(OES_vertex_array_object)) {
switch (pname) {
case LOCAL_GL_VERTEX_ARRAY_BINDING:
{
if (mBoundVertexArray == mDefaultVertexArray){
return WebGLObjectAsJSValue(cx, (WebGLVertexArray *) nullptr, rv);
}
return WebGLObjectAsJSValue(cx, mBoundVertexArray.get(), rv);
}
}
}
switch (pname) {
//
// String params
@ -2291,7 +2359,7 @@ WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv)
case LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING:
{
return WebGLObjectAsJSValue(cx, mBoundElementArrayBuffer.get(), rv);
return WebGLObjectAsJSValue(cx, mBoundVertexArray->mBoundElementArrayBuffer.get(), rv);
}
case LOCAL_GL_RENDERBUFFER_BINDING:
@ -2955,7 +3023,7 @@ WebGLContext::GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname,
if (!IsContextStable())
return JS::NullValue();
if (!ValidateAttribIndex(index, "getVertexAttrib"))
if (!mBoundVertexArray->EnsureAttribIndex(index, "getVertexAttrib"))
return JS::NullValue();
MakeContextCurrent();
@ -2963,18 +3031,18 @@ WebGLContext::GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname,
switch (pname) {
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
{
return WebGLObjectAsJSValue(cx, mAttribBuffers[index].buf.get(), rv);
return WebGLObjectAsJSValue(cx, mBoundVertexArray->mAttribBuffers[index].buf.get(), rv);
}
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE:
return JS::Int32Value(mAttribBuffers[index].stride);
return JS::Int32Value(mBoundVertexArray->mAttribBuffers[index].stride);
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE:
{
if (!ValidateAttribIndex(index, "enableVertexAttribArray"))
return JS::NullValue();
if (!mAttribBuffers[index].enabled)
if (!mBoundVertexArray->mAttribBuffers[index].enabled)
return JS::Int32Value(4);
// Don't break; fall through.
@ -3009,14 +3077,12 @@ WebGLContext::GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname,
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED:
{
return JS::BooleanValue(mAttribBuffers[index].enabled);
return JS::BooleanValue(mBoundVertexArray->mAttribBuffers[index].enabled);
}
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
{
GLint i = 0;
gl->fGetVertexAttribiv(index, pname, &i);
return JS::BooleanValue(bool(i));
return JS::BooleanValue(mBoundVertexArray->mAttribBuffers[index].normalized);
}
default:
@ -3040,7 +3106,7 @@ WebGLContext::GetVertexAttribOffset(WebGLuint index, WebGLenum pname)
return 0;
}
return mAttribBuffers[index].byteOffset;
return mBoundVertexArray->mAttribBuffers[index].byteOffset;
}
void
@ -3109,6 +3175,20 @@ WebGLContext::IsRenderbuffer(WebGLRenderbuffer *rb)
rb->HasEverBeenBound();
}
bool
WebGLContext::IsVertexArray(WebGLVertexArray *array)
{
if (!IsContextStable())
return false;
if (!array)
return false;
return ValidateObjectAllowDeleted("isVertexArray", array) &&
!array->IsDeleted() &&
array->HasEverBeenBound();
}
bool
WebGLContext::IsShader(WebGLShader *shader)
{
@ -4330,6 +4410,22 @@ WebGLContext::CreateRenderbuffer()
return globj.forget();
}
already_AddRefed<WebGLVertexArray>
WebGLContext::CreateVertexArray()
{
if (!IsContextStable())
return nullptr;
nsRefPtr<WebGLVertexArray> globj = new WebGLVertexArray(this);
MakeContextCurrent();
gl->fGenVertexArrays(1, &globj->mGLName);
mVertexArrays.insertBack(globj);
return globj.forget();
}
void
WebGLContext::Viewport(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height)
{
@ -4889,8 +4985,9 @@ WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type
// requiredAlignment should always be a power of two.
WebGLsizei requiredAlignmentMask = requiredAlignment - 1;
if (!ValidateAttribIndex(index, "vertexAttribPointer"))
if ( !mBoundVertexArray->EnsureAttribIndex(index, "vertexAttribPointer") ) {
return;
}
if (size < 1 || size > 4)
return ErrorInvalidValue("vertexAttribPointer: invalid element size");
@ -4919,7 +5016,7 @@ WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type
return ErrorInvalidOperation("vertexAttribPointer: type must match bound VBO type: %d != %d", type, mBoundArrayBuffer->GLType());
*/
WebGLVertexAttribData &vd = mAttribBuffers[index];
WebGLVertexAttribData &vd = mBoundVertexArray->mAttribBuffers[index];
vd.buf = mBoundArrayBuffer;
vd.stride = stride;

View File

@ -12,6 +12,7 @@
#include "WebGLFramebuffer.h"
#include "WebGLRenderbuffer.h"
#include "WebGLTexture.h"
#include "WebGLVertexArray.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/Preferences.h"
@ -112,9 +113,9 @@ WebGLContext::ValidateBuffers(uint32_t *maxAllowedCount, const char *info)
}
uint32_t maxAllowed = UINT32_MAX;
uint32_t attribs = mAttribBuffers.Length();
uint32_t attribs = mBoundVertexArray->mAttribBuffers.Length();
for (uint32_t i = 0; i < attribs; ++i) {
const WebGLVertexAttribData& vd = mAttribBuffers[i];
const WebGLVertexAttribData& vd = mBoundVertexArray->mAttribBuffers[i];
// If the attrib array isn't enabled, there's nothing to check;
// it's a static value.
@ -850,18 +851,7 @@ WebGLContext::ValidateUniformSetter(const char* name, WebGLUniformLocation *loca
bool WebGLContext::ValidateAttribIndex(WebGLuint index, const char *info)
{
if (index >= mAttribBuffers.Length()) {
if (index == WebGLuint(-1)) {
ErrorInvalidValue("%s: index -1 is invalid. That probably comes from a getAttribLocation() call, "
"where this return value -1 means that the passed name didn't correspond to an active attribute in "
"the specified program.", info);
} else {
ErrorInvalidValue("%s: index %d is out of range", info, index);
}
return false;
} else {
return true;
}
return mBoundVertexArray->EnsureAttribIndex(index, info);
}
bool WebGLContext::ValidateStencilParamsForDrawCall()
@ -905,13 +895,10 @@ WebGLContext::InitAndValidateGL()
mActiveTexture = 0;
mWebGLError = LOCAL_GL_NO_ERROR;
mAttribBuffers.Clear();
mBound2DTextures.Clear();
mBoundCubeMapTextures.Clear();
mBoundArrayBuffer = nullptr;
mBoundElementArrayBuffer = nullptr;
mCurrentProgram = nullptr;
mBoundFramebuffer = nullptr;
@ -934,8 +921,6 @@ WebGLContext::InitAndValidateGL()
return false;
}
mAttribBuffers.SetLength(mGLMaxVertexAttribs);
// Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
// even though the hardware supports much more. The
// GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
@ -1084,5 +1069,9 @@ WebGLContext::InitAndValidateGL()
false);
}
mDefaultVertexArray = new WebGLVertexArray(this);
mDefaultVertexArray->mAttribBuffers.SetLength(mGLMaxVertexAttribs);
mBoundVertexArray = mDefaultVertexArray;
return true;
}

View File

@ -0,0 +1,57 @@
/* -*- 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 "WebGLBuffer.h"
#include "WebGLVertexArray.h"
#include "WebGLExtensions.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
using namespace mozilla;
WebGLExtensionVertexArray::WebGLExtensionVertexArray(WebGLContext* context)
: WebGLExtensionBase(context)
{
MOZ_ASSERT(IsSupported(context), "should not construct WebGLExtensionVertexArray :"
"OES_vertex_array_object unsuported.");
}
WebGLExtensionVertexArray::~WebGLExtensionVertexArray()
{
}
already_AddRefed<WebGLVertexArray> WebGLExtensionVertexArray::CreateVertexArrayOES()
{
return mContext->CreateVertexArray();
}
void WebGLExtensionVertexArray::DeleteVertexArrayOES(WebGLVertexArray* array)
{
mContext->DeleteVertexArray(array);
}
bool WebGLExtensionVertexArray::IsVertexArrayOES(WebGLVertexArray* array)
{
return mContext->IsVertexArray(array);
}
void WebGLExtensionVertexArray::BindVertexArrayOES(WebGLVertexArray* array)
{
mContext->BindVertexArray(array);
}
bool WebGLExtensionVertexArray::IsSupported(const WebGLContext* context)
{
gl::GLContext* gl = context->GL();
if (gl->IsGLES2()) {
return gl->IsExtensionSupported(gl::GLContext::OES_vertex_array_object);
}
return gl->IsExtensionSupported(gl::GLContext::ARB_vertex_array_object) ||
gl->IsExtensionSupported(gl::GLContext::APPLE_vertex_array_object);
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionVertexArray)

View File

@ -172,6 +172,23 @@ public:
DECL_WEBGL_EXTENSION_GOOP
};
class WebGLExtensionVertexArray
: public WebGLExtensionBase
{
public:
WebGLExtensionVertexArray(WebGLContext*);
virtual ~WebGLExtensionVertexArray();
already_AddRefed<WebGLVertexArray> CreateVertexArrayOES();
void DeleteVertexArrayOES(WebGLVertexArray* array);
bool IsVertexArrayOES(WebGLVertexArray* array);
void BindVertexArrayOES(WebGLVertexArray* array);
static bool IsSupported(const WebGLContext* context);
DECL_WEBGL_EXTENSION_GOOP
};
} // namespace mozilla
#endif // WEBGLEXTENSIONS_H_

View File

@ -0,0 +1,69 @@
/* -*- 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 "WebGLBuffer.h"
#include "WebGLVertexArray.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "nsContentUtils.h"
using namespace mozilla;
JSObject*
WebGLVertexArray::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope) {
return dom::WebGLVertexArrayBinding::Wrap(cx, scope, this);
}
WebGLVertexArray::WebGLVertexArray(WebGLContext* context)
: WebGLContextBoundObject(context)
, mGLName(0)
, mHasEverBeenBound(false)
{
SetIsDOMBinding();
}
void WebGLVertexArray::Delete() {
if (mGLName != 0) {
mBoundElementArrayBuffer = nullptr;
mContext->MakeContextCurrent();
mContext->gl->fDeleteVertexArrays(1, &mGLName);
LinkedListElement<WebGLVertexArray>::removeFrom(mContext->mVertexArrays);
}
mBoundElementArrayBuffer = nullptr;
mAttribBuffers.Clear();
}
bool WebGLVertexArray::EnsureAttribIndex(WebGLuint index, const char *info)
{
if (index >= WebGLuint(mContext->mGLMaxVertexAttribs)) {
if (index == WebGLuint(-1)) {
mContext->ErrorInvalidValue("%s: index -1 is invalid. That probably comes from a getAttribLocation() call, "
"where this return value -1 means that the passed name didn't correspond to an active attribute in "
"the specified program.", info);
} else {
mContext->ErrorInvalidValue("%s: index %d is out of range", info, index);
}
return false;
}
else if (index >= mAttribBuffers.Length()) {
mAttribBuffers.SetLength(index + 1);
}
return true;
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(WebGLVertexArray,
mAttribBuffers,
mBoundElementArrayBuffer)
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLVertexArray)
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLVertexArray)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLVertexArray)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END

View File

@ -0,0 +1,62 @@
/* -*- Mode: C++; tab-width: 4; 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/. */
#ifndef WEBGLVERTEXARRAY_H_
#define WEBGLVERTEXARRAY_H_
#include "WebGLObjectModel.h"
#include "WebGLVertexAttribData.h"
#include "nsWrapperCache.h"
#include "mozilla/LinkedList.h"
namespace mozilla {
class WebGLVertexArray MOZ_FINAL
: public nsISupports
, public WebGLRefCountedObject<WebGLVertexArray>
, public LinkedListElement<WebGLVertexArray>
, public WebGLContextBoundObject
, public nsWrapperCache
{
public:
WebGLVertexArray(WebGLContext *context);
~WebGLVertexArray() {
DeleteOnce();
};
void Delete();
bool HasEverBeenBound() { return mHasEverBeenBound; }
void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
WebGLuint GLName() const { return mGLName; }
WebGLContext* GetParentObject() const {
return Context();
}
bool EnsureAttribIndex(WebGLuint index, const char *info);
virtual JSObject* WrapObject(JSContext *cx,
JS::Handle<JSObject*> scope) MOZ_OVERRIDE;
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebGLVertexArray)
WebGLuint mGLName;
bool mHasEverBeenBound;
nsTArray<WebGLVertexAttribData> mAttribBuffers;
WebGLRefPtr<WebGLBuffer> mBoundElementArrayBuffer;
friend class WebGLContext;
friend class WebGLExtensionVertexArray;
};
} // namespace mozilla
#endif

View File

@ -47,6 +47,7 @@ if CONFIG['MOZ_WEBGL']:
'WebGLExtensionTextureFilterAnisotropic.cpp',
'WebGLExtensionTextureFloat.cpp',
'WebGLExtensionTextureFloatLinear.cpp',
'WebGLExtensionVertexArray.cpp',
'WebGLFramebuffer.cpp',
'WebGLObjectModel.cpp',
'WebGLProgram.cpp',
@ -56,6 +57,7 @@ if CONFIG['MOZ_WEBGL']:
'WebGLTexelConversions.cpp',
'WebGLTexture.cpp',
'WebGLUniformLocation.cpp',
'WebGLVertexArray.cpp',
]
else:
CPP_SOURCES += [

View File

@ -148,7 +148,11 @@ function runObjectTest() {
ext.bindVertexArrayOES(null);
shouldBeTrue("ext.isVertexArrayOES(vao)");
shouldBeFalse("ext.isVertexArrayOES()");
/*
* Issue found in the conformance test. The public webgl mailing list has been notified about it.
* The tests have already been fixed upstream.
*/
//shouldBeFalse("ext.isVertexArrayOES()");
shouldBeFalse("ext.isVertexArrayOES(null)");
ext.deleteVertexArrayOES(vao);

View File

@ -1196,6 +1196,11 @@ DOMInterfaces = {
'headerFile': 'WebGLExtensions.h'
},
'WebGLExtensionVertexArray': {
'nativeType': 'mozilla::WebGLExtensionVertexArray',
'headerFile': 'WebGLExtensions.h'
},
'WebGLFramebuffer': {
'nativeType': 'mozilla::WebGLFramebuffer',
'headerFile': 'WebGLFramebuffer.h'
@ -1241,6 +1246,11 @@ DOMInterfaces = {
'wrapperCache': False
},
'WebGLVertexArray': {
'nativeType': 'mozilla::WebGLVertexArray',
'headerFile': 'WebGLVertexArray.h'
},
'WebSocket': {
'headerFile': 'WebSocket.h',
'implicitJSContext': [ 'constructor' ]

View File

@ -64,6 +64,9 @@ interface WebGLTexture {
interface WebGLUniformLocation {
};
interface WebGLVertexArray {
};
interface WebGLActiveInfo {
readonly attribute GLint size;
readonly attribute GLenum type;
@ -883,3 +886,13 @@ interface WebGLExtensionDrawBuffers {
interface WebGLExtensionTextureFloatLinear
{
};
[NoInterfaceObject]
interface WebGLExtensionVertexArray {
const GLenum VERTEX_ARRAY_BINDING_OES = 0x85B5;
WebGLVertexArray? createVertexArrayOES();
void deleteVertexArrayOES(WebGLVertexArray? arrayObject);
[WebGLHandlesContextLoss] GLboolean isVertexArrayOES(WebGLVertexArray? arrayObject);
void bindVertexArrayOES(WebGLVertexArray? arrayObject);
};

View File

@ -88,6 +88,7 @@ static const char *sExtensionNames[] = {
"GL_OES_element_index_uint",
"GL_OES_vertex_array_object",
"GL_ARB_vertex_array_object",
"GL_APPLE_vertex_array_object",
"GL_ARB_draw_buffers",
"GL_EXT_draw_buffers",
nullptr
@ -552,11 +553,12 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
}
}
if (IsExtensionSupported(OES_vertex_array_object)) {
if (IsExtensionSupported(ARB_vertex_array_object) ||
IsExtensionSupported(OES_vertex_array_object)) {
SymLoadStruct vaoSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArray", "IsVertexArrayOES", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArrays", "GenVertexArraysOES", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArrays", "BindVertexArrayOES", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArray", "BindVertexArrayOES", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArrays", "DeleteVertexArraysOES", nullptr } },
{ nullptr, { nullptr } },
};
@ -564,7 +566,32 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
MarkExtensionUnsupported(ARB_vertex_array_object);
MarkExtensionUnsupported(OES_vertex_array_object);
MarkExtensionUnsupported(APPLE_vertex_array_object);
mSymbols.fIsVertexArray = nullptr;
mSymbols.fGenVertexArrays = nullptr;
mSymbols.fBindVertexArray = nullptr;
mSymbols.fDeleteVertexArrays = nullptr;
}
}
else if (IsExtensionSupported(APPLE_vertex_array_object)) {
/*
* separate call to LoadSymbols with APPLE_vertex_array_object to work around
* a driver bug : the IsVertexArray symbol (without suffix) can be present but unusable.
*/
SymLoadStruct vaoSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArrayAPPLE", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArraysAPPLE", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArrayAPPLE", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArraysAPPLE", nullptr } },
{ nullptr, { nullptr } },
};
if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
MarkExtensionUnsupported(APPLE_vertex_array_object);
mSymbols.fIsVertexArray = nullptr;
mSymbols.fGenVertexArrays = nullptr;
mSymbols.fBindVertexArray = nullptr;

View File

@ -1026,6 +1026,7 @@ public:
OES_element_index_uint,
OES_vertex_array_object,
ARB_vertex_array_object,
APPLE_vertex_array_object,
ARB_draw_buffers,
EXT_draw_buffers,
Extensions_Max

View File

@ -3029,6 +3029,9 @@ typedef uint64_t EGLTime;
#define LOCAL_GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
#define LOCAL_GL_WIN_swap_hint 1
// ARB_vertex_array_object
#define LOCAL_GL_VERTEX_ARRAY_BINDING 0x85B5
// ARB_sync
#define LOCAL_GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
#define LOCAL_GL_OBJECT_TYPE 0x9112