--- a/dom/canvas/WebGL2ContextSamplers.cpp
+++ b/dom/canvas/WebGL2ContextSamplers.cpp
@@ -38,20 +38,17 @@ WebGL2Context::DeleteSampler(WebGLSample
bool
WebGL2Context::IsSampler(const WebGLSampler* const obj)
{
const FuncScope funcScope(*this, "isSampler");
if (!ValidateIsObject(obj))
return false;
- if (obj->IsDeleteRequested())
- return false;
-
- return true;
+ return gl->fIsSampler(obj->mGLName);
}
void
WebGL2Context::BindSampler(GLuint unit, WebGLSampler* sampler)
{
const FuncScope funcScope(*this, "bindSampler");
if (IsContextLost())
return;
--- a/dom/canvas/WebGL2ContextTransformFeedback.cpp
+++ b/dom/canvas/WebGL2ContextTransformFeedback.cpp
@@ -49,20 +49,17 @@ WebGL2Context::DeleteTransformFeedback(W
bool
WebGL2Context::IsTransformFeedback(const WebGLTransformFeedback* const obj)
{
const FuncScope funcScope(*this, "isTransformFeedback");
if (!ValidateIsObject(obj))
return false;
- if (obj->IsDeleteRequested())
- return false;
-
- return obj->mHasBeenBound;
+ return gl->fIsTransformFeedback(obj->mGLName);
}
void
WebGL2Context::BindTransformFeedback(GLenum target, WebGLTransformFeedback* tf)
{
const FuncScope funcScope(*this, "bindTransformFeedback");
if (IsContextLost())
return;
@@ -88,17 +85,16 @@ WebGL2Context::BindTransformFeedback(GLe
}
mBoundTransformFeedback = (tf ? tf : mDefaultTransformFeedback);
gl->fBindTransformFeedback(target, mBoundTransformFeedback->mGLName);
if (mBoundTransformFeedback) {
mBoundTransformFeedback->AddBufferBindCounts(+1);
- mBoundTransformFeedback->mHasBeenBound = true;
}
}
void
WebGL2Context::BeginTransformFeedback(GLenum primMode)
{
const FuncScope funcScope(*this, "beginTransformFeedback");
if (IsContextLost())
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -2496,20 +2496,17 @@ WebGLContext::ValidateIsObject(const Web
return false;
if (!object)
return false;
if (!object->IsCompatibleWithContext(this))
return false;
- if (object->IsDeleted())
- return false;
-
- return true;
+ return !object->IsDeleted();
}
bool
WebGLContext::ValidateDeleteObject(const WebGLDeletableObject* const object)
{
if (IsContextLost())
return false;
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -142,17 +142,19 @@ WebGLContext::BindFramebuffer(GLenum tar
if (wfb && !ValidateObject("fb", *wfb))
return;
if (!wfb) {
gl->fBindFramebuffer(target, 0);
} else {
GLuint framebuffername = wfb->mGLName;
gl->fBindFramebuffer(target, framebuffername);
- wfb->mHasBeenBound = true;
+#ifdef ANDROID
+ wfb->mIsFB = true;
+#endif
}
switch (target) {
case LOCAL_GL_FRAMEBUFFER:
mBoundDrawFramebuffer = wfb;
mBoundReadFramebuffer = wfb;
break;
case LOCAL_GL_DRAW_FRAMEBUFFER:
@@ -1058,65 +1060,61 @@ WebGLContext::Hint(GLenum target, GLenum
bool
WebGLContext::IsBuffer(const WebGLBuffer* const obj)
{
const FuncScope funcScope(*this, "isBuffer");
if (!ValidateIsObject(obj))
return false;
- if (obj->IsDeleteRequested())
- return false;
-
- return obj->Content() != WebGLBuffer::Kind::Undefined;
+ return gl->fIsBuffer(obj->mGLName);
}
bool
WebGLContext::IsFramebuffer(const WebGLFramebuffer* const obj)
{
const FuncScope funcScope(*this, "isFramebuffer");
if (!ValidateIsObject(obj))
return false;
- if (obj->IsDeleteRequested())
- return false;
-
- return obj->mHasBeenBound;
+#ifdef ANDROID
+ if (gl->WorkAroundDriverBugs() &&
+ gl->Renderer() == GLRenderer::AndroidEmulator)
+ {
+ return obj->mIsFB;
+ }
+#endif
+
+ return gl->fIsFramebuffer(obj->mGLName);
}
bool
WebGLContext::IsProgram(const WebGLProgram* const obj)
{
const FuncScope funcScope(*this, "isProgram");
return ValidateIsObject(obj);
}
bool
WebGLContext::IsQuery(const WebGLQuery* const obj)
{
const FuncScope funcScope(*this, "isQuery");
if (!ValidateIsObject(obj))
return false;
- if (obj->IsDeleteRequested())
- return false;
-
- return bool(obj->Target());
+ return obj->IsQuery();
}
bool
WebGLContext::IsRenderbuffer(const WebGLRenderbuffer* const obj)
{
const FuncScope funcScope(*this, "isRenderbuffer");
if (!ValidateIsObject(obj))
return false;
- if (obj->IsDeleteRequested())
- return false;
-
return obj->mHasBeenBound;
}
bool
WebGLContext::IsShader(const WebGLShader* const obj)
{
const FuncScope funcScope(*this, "isShader");
return ValidateIsObject(obj);
@@ -1124,33 +1122,27 @@ WebGLContext::IsShader(const WebGLShader
bool
WebGLContext::IsTexture(const WebGLTexture* const obj)
{
const FuncScope funcScope(*this, "isTexture");
if (!ValidateIsObject(obj))
return false;
- if (obj->IsDeleteRequested())
- return false;
-
- return bool(obj->Target());
+ return obj->IsTexture();
}
bool
WebGLContext::IsVertexArray(const WebGLVertexArray* const obj)
{
const FuncScope funcScope(*this, "isVertexArray");
if (!ValidateIsObject(obj))
return false;
- if (obj->IsDeleteRequested())
- return false;
-
- return obj->mHasBeenBound;
+ return obj->IsVertexArray();
}
// -
void
WebGLContext::LinkProgram(WebGLProgram& prog)
{
const FuncScope funcScope(*this, "linkProgram");
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -697,18 +697,18 @@ AssertUintParamCorrect(gl::GLContext*, G
void
WebGLContext::AssertCachedBindings() const
{
#ifdef DEBUG
GetAndFlushUnderlyingGLErrors();
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
- AssertUintParamCorrect(gl, LOCAL_GL_VERTEX_ARRAY_BINDING,
- mBoundVertexArray->mGLName);
+ GLuint bound = mBoundVertexArray ? mBoundVertexArray->GLName() : 0;
+ AssertUintParamCorrect(gl, LOCAL_GL_VERTEX_ARRAY_BINDING, bound);
}
GLint stencilBits = 0;
if (GetStencilBits(&stencilBits)) { // Depends on current draw framebuffer.
const GLuint stencilRefMask = (1 << stencilBits) - 1;
AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_REF, stencilRefMask, mStencilRefFront);
AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_REF, stencilRefMask, mStencilRefBack);
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -616,27 +616,33 @@ WebGLContext::InitAndValidateGL(FailureR
}
if (!gl->IsSupported(GLFeature::vertex_array_object)) {
*out_failReason = { "FEATURE_FAILURE_WEBGL_VAOS",
"Requires vertex_array_object." };
return false;
}
+ mDefaultVertexArray = WebGLVertexArray::Create(this);
+ mDefaultVertexArray->mAttribs.SetLength(mGLMaxVertexAttribs);
+ mBoundVertexArray = mDefaultVertexArray;
+
// OpenGL core profiles remove the default VAO object from version
// 4.0.0. We create a default VAO for all core profiles,
// regardless of version.
//
// GL Spec 4.0.0:
// (https://www.opengl.org/registry/doc/glspec40.core.20100311.pdf)
// in Section E.2.2 "Removed Features", pg 397: "[...] The default
// vertex array object (the name zero) is also deprecated. [...]"
- mDefaultVertexArray = WebGLVertexArray::Create(this);
- mDefaultVertexArray->BindVertexArray();
- mDefaultVertexArray->mAttribs.SetLength(mGLMaxVertexAttribs);
+
+ if (gl->IsCoreProfile()) {
+ mDefaultVertexArray->GenVertexArray();
+ mDefaultVertexArray->BindVertexArray();
+ }
mPixelStore_FlipY = false;
mPixelStore_PremultiplyAlpha = false;
mPixelStore_ColorspaceConversion = BROWSER_DEFAULT_WEBGL;
mPixelStore_RequireFastPath = false;
// GLES 3.0.4, p259:
mPixelStore_UnpackImageHeight = 0;
--- a/dom/canvas/WebGLContextVertexArray.cpp
+++ b/dom/canvas/WebGLContextVertexArray.cpp
@@ -30,28 +30,30 @@ WebGLContext::BindVertexArray(WebGLVerte
array = mDefaultVertexArray;
}
array->BindVertexArray();
MOZ_ASSERT(mBoundVertexArray == array);
if (mBoundVertexArray) {
mBoundVertexArray->AddBufferBindCounts(+1);
- mBoundVertexArray->mHasBeenBound = true;
}
}
already_AddRefed<WebGLVertexArray>
WebGLContext::CreateVertexArray()
{
const FuncScope funcScope(*this, "createVertexArray");
if (IsContextLost())
return nullptr;
RefPtr<WebGLVertexArray> globj = CreateVertexArrayImpl();
+
+ globj->GenVertexArray();
+
return globj.forget();
}
WebGLVertexArray*
WebGLContext::CreateVertexArrayImpl()
{
return WebGLVertexArray::Create(this);
}
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -503,16 +503,20 @@ WebGLFramebuffer::Delete()
for (auto& cur : mColorAttachments) {
cur.Clear();
}
mContext->gl->fDeleteFramebuffers(1, &mGLName);
LinkedListElement<WebGLFramebuffer>::removeFrom(mContext->mFramebuffers);
+
+#ifdef ANDROID
+ mIsFB = false;
+#endif
}
////
Maybe<WebGLFBAttachPoint*>
WebGLFramebuffer::GetColorAttachPoint(GLenum attachPoint)
{
if (attachPoint == LOCAL_GL_NONE)
@@ -1223,17 +1227,17 @@ WebGLFramebuffer::FramebufferTexture2D(G
return;
}
// `texture`
if (tex) {
if (!mContext->ValidateObject("texture", *tex))
return;
- if (!tex->Target()) {
+ if (!tex->HasEverBeenBound()) {
mContext->ErrorInvalidOperation("`texture` has never been bound.");
return;
}
const TexTarget destTexTarget = TexImageTargetToTexTarget(texImageTarget);
if (tex->Target() != destTexTarget) {
mContext->ErrorInvalidOperation("Mismatched texture and texture target.");
return;
@@ -1308,17 +1312,17 @@ WebGLFramebuffer::FramebufferTextureLaye
return mContext->ErrorInvalidValue("`level` must be >= 0.");
// `texture`
GLenum texImageTarget = LOCAL_GL_TEXTURE_3D;
if (tex) {
if (!mContext->ValidateObject("texture", *tex))
return;
- if (!tex->Target()) {
+ if (!tex->HasEverBeenBound()) {
mContext->ErrorInvalidOperation("`texture` has never been bound.");
return;
}
texImageTarget = tex->Target().get();
switch (texImageTarget) {
case LOCAL_GL_TEXTURE_3D:
if (uint32_t(layer) >= mContext->mGLMax3DTextureSize) {
--- a/dom/canvas/WebGLFramebuffer.h
+++ b/dom/canvas/WebGLFramebuffer.h
@@ -135,28 +135,38 @@ public:
class WebGLFramebuffer final
: public nsWrapperCache
, public WebGLRefCountedObject<WebGLFramebuffer>
, public LinkedListElement<WebGLFramebuffer>
, public SupportsWeakPtr<WebGLFramebuffer>
, public CacheInvalidator
{
+ friend class WebGLContext;
+
public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLFramebuffer)
const GLuint mGLName;
- bool mHasBeenBound = false;
private:
mutable uint64_t mNumFBStatusInvals = 0;
+protected:
+#ifdef ANDROID
+ // Bug 1140459: Some drivers (including our test slaves!) don't
+ // give reasonable answers for IsRenderbuffer, maybe others.
+ // This shows up on Android 2.3 emulator.
+ //
+ // So we track the `is a Framebuffer` state ourselves.
+ bool mIsFB = false;
+#endif
+
////
-protected:
WebGLFBAttachPoint mDepthAttachment;
WebGLFBAttachPoint mStencilAttachment;
WebGLFBAttachPoint mDepthStencilAttachment;
// In theory, this number can be unbounded based on the driver. However, no driver
// appears to expose more than 8. We might as well stop there too, for now.
// (http://opengl.gpuinfo.org/gl_stats_caps_single.php?listreportsbycap=GL_MAX_COLOR_ATTACHMENTS)
static const size_t kMaxColorAttachments = 8; // jgilbert's MacBook Pro exposes 8.
--- a/dom/canvas/WebGLRenderbuffer.cpp
+++ b/dom/canvas/WebGLRenderbuffer.cpp
@@ -47,16 +47,17 @@ EmulatePackedDepthStencil(gl::GLContext*
return !gl->IsSupported(gl::GLFeature::packed_depth_stencil);
}
WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext* webgl)
: WebGLRefCountedObject(webgl)
, mPrimaryRB( DoCreateRenderbuffer(webgl->gl) )
, mEmulatePackedDepthStencil( EmulatePackedDepthStencil(webgl->gl) )
, mSecondaryRB(0)
+ , mHasBeenBound(false)
{
mContext->mRenderbuffers.insertBack(this);
// Bind our RB, or we might end up calling FramebufferRenderbuffer before we ever call
// BindRenderbuffer, since webgl.bindRenderbuffer doesn't actually call
// glBindRenderbuffer anymore.
mContext->gl->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mPrimaryRB);
}
--- a/dom/canvas/WebGLRenderbuffer.h
+++ b/dom/canvas/WebGLRenderbuffer.h
@@ -21,25 +21,26 @@ struct FormatUsageInfo;
class WebGLRenderbuffer final
: public nsWrapperCache
, public WebGLRefCountedObject<WebGLRenderbuffer>
, public LinkedListElement<WebGLRenderbuffer>
, public WebGLRectangleObject
, public CacheInvalidator
{
+ friend class WebGLContext;
friend class WebGLFramebuffer;
friend class WebGLFBAttachPoint;
public:
const GLuint mPrimaryRB;
- bool mHasBeenBound = false;
protected:
const bool mEmulatePackedDepthStencil;
GLuint mSecondaryRB;
+ bool mHasBeenBound;
webgl::ImageInfo mImageInfo;
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLRenderbuffer)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLRenderbuffer)
explicit WebGLRenderbuffer(WebGLContext* webgl);
--- a/dom/canvas/WebGLSampler.cpp
+++ b/dom/canvas/WebGLSampler.cpp
@@ -6,16 +6,18 @@
#include "WebGLSampler.h"
#include "GLContext.h"
#include "mozilla/dom/WebGL2RenderingContextBinding.h"
#include "WebGLContext.h"
namespace mozilla {
+
+
WebGLSampler::WebGLSampler(WebGLContext* const webgl)
: WebGLRefCountedObject(webgl)
, mGLName([&]() {
GLuint ret = 0;
webgl->gl->fGenSamplers(1, &ret);
return ret;
}())
{
--- a/dom/canvas/WebGLSampler.h
+++ b/dom/canvas/WebGLSampler.h
@@ -15,16 +15,19 @@
namespace mozilla {
class WebGLSampler final
: public nsWrapperCache
, public WebGLRefCountedObject<WebGLSampler>
, public LinkedListElement<WebGLSampler>
, public CacheInvalidator
{
+ friend class WebGLContext2;
+ friend class WebGLTexture;
+
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSampler)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSampler)
public:
const GLuint mGLName;
private:
webgl::SamplingState mState;
--- a/dom/canvas/WebGLStrongTypes.h
+++ b/dom/canvas/WebGLStrongTypes.h
@@ -150,18 +150,16 @@ public:
bool operator<=(const StrongGLenum& other) const {
return get() <= other.get();
}
bool operator>=(const StrongGLenum& other) const {
return get() >= other.get();
}
- explicit operator bool() const { return bool(get()); }
-
static bool IsValueLegal(GLenum value) {
if (value > UINT16_MAX) {
return false;
}
return std::binary_search(Details::values(),
Details::values() + Details::valuesCount(),
uint16_t(value));
}
--- a/dom/canvas/WebGLTexture.cpp
+++ b/dom/canvas/WebGLTexture.cpp
@@ -693,17 +693,17 @@ WebGLTexture::ClampLevelBaseAndMax()
bool
WebGLTexture::BindTexture(TexTarget texTarget)
{
if (IsDeleted()) {
mContext->ErrorInvalidOperation("bindTexture: Cannot bind a deleted object.");
return false;
}
- const bool isFirstBinding = !mTarget;
+ const bool isFirstBinding = !HasEverBeenBound();
if (!isFirstBinding && mTarget != texTarget) {
mContext->ErrorInvalidOperation("bindTexture: This texture has already been bound"
" to a different target.");
return false;
}
mTarget = texTarget;
@@ -851,16 +851,22 @@ WebGLTexture::GetTexParameter(TexTarget
mContext->gl->fGetTexParameterfv(texTarget.get(), pname, &f);
return JS::NumberValue(float(f));
default:
MOZ_CRASH("GFX: Unhandled pname.");
}
}
+bool
+WebGLTexture::IsTexture() const
+{
+ return HasEverBeenBound() && !IsDeleted();
+}
+
// Here we have to support all pnames with both int and float params.
// See this discussion:
// https://www.khronos.org/webgl/public-mailing-list/archives/1008/msg00014.html
void
WebGLTexture::TexParameter(TexTarget texTarget, GLenum pname, const FloatOrInt& param)
{
bool isPNameValid = false;
switch (pname) {
--- a/dom/canvas/WebGLTexture.h
+++ b/dom/canvas/WebGLTexture.h
@@ -167,16 +167,17 @@ public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTexture)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTexture)
WebGLTexture(WebGLContext* webgl, GLuint tex);
void Delete();
+ bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; }
TexTarget Target() const { return mTarget; }
WebGLContext* GetParentObject() const {
return mContext;
}
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
@@ -186,16 +187,17 @@ protected:
}
public:
////////////////////////////////////
// GL calls
bool BindTexture(TexTarget texTarget);
void GenerateMipmap();
JS::Value GetTexParameter(TexTarget texTarget, GLenum pname);
+ bool IsTexture() const;
void TexParameter(TexTarget texTarget, GLenum pname, const FloatOrInt& param);
////////////////////////////////////
// WebGLTextureUpload.cpp
protected:
void TexOrSubImageBlob(bool isSubImage, TexImageTarget target,
GLint level, GLenum internalFormat, GLint xOffset,
--- a/dom/canvas/WebGLTransformFeedback.h
+++ b/dom/canvas/WebGLTransformFeedback.h
@@ -25,17 +25,16 @@ class WebGLTransformFeedback final
friend class WebGL2Context;
friend class WebGLProgram;
friend const webgl::CachedDrawFetchLimits*
ValidateDraw(WebGLContext*, GLenum, uint32_t);
public:
const GLuint mGLName;
- bool mHasBeenBound = false;
private:
// GLES 3.0.4 p267, Table 6.24 "Transform Feedback State"
// It's not yet in the ES3 spec, but the generic TF buffer bind point has been moved
// to context state, instead of TFO state.
std::vector<IndexedBufferBinding> mIndexedBindings;
bool mIsPaused;
bool mIsActive;
// Not in state tables:
--- a/dom/canvas/WebGLVertexArray.cpp
+++ b/dom/canvas/WebGLVertexArray.cpp
@@ -15,19 +15,19 @@
namespace mozilla {
JSObject*
WebGLVertexArray::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
{
return dom::WebGLVertexArrayObject_Binding::Wrap(cx, this, givenProto);
}
-WebGLVertexArray::WebGLVertexArray(WebGLContext* const webgl, const GLuint name)
+WebGLVertexArray::WebGLVertexArray(WebGLContext* webgl)
: WebGLRefCountedObject(webgl)
- , mGLName(name)
+ , mGLName(0)
{
mAttribs.SetLength(mContext->mGLMaxVertexAttribs);
mContext->mVertexArrays.insertBack(this);
}
WebGLVertexArray::~WebGLVertexArray()
{
MOZ_ASSERT(IsDeleted());
@@ -60,16 +60,22 @@ WebGLVertexArray::Delete()
{
DeleteImpl();
LinkedListElement<WebGLVertexArray>::removeFrom(mContext->mVertexArrays);
mElementArrayBuffer = nullptr;
mAttribs.Clear();
}
+bool
+WebGLVertexArray::IsVertexArray() const
+{
+ return IsVertexArrayImpl();
+}
+
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLVertexArray,
mAttribs,
mElementArrayBuffer)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLVertexArray, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLVertexArray, Release)
} // namespace mozilla
--- a/dom/canvas/WebGLVertexArray.h
+++ b/dom/canvas/WebGLVertexArray.h
@@ -26,40 +26,49 @@ class WebGLVertexArray
: public nsWrapperCache
, public WebGLRefCountedObject<WebGLVertexArray>
, public LinkedListElement<WebGLVertexArray>
, public CacheInvalidator
{
public:
static WebGLVertexArray* Create(WebGLContext* webgl);
+ void BindVertexArray() {
+ // Bind to dummy value to signal that this vertex array has ever been
+ // bound.
+ BindVertexArrayImpl();
+ };
+
+ // Implement parent classes:
void Delete();
+ bool IsVertexArray() const;
WebGLContext* GetParentObject() const {
return mContext;
}
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLVertexArray)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLVertexArray)
+ GLuint GLName() const { return mGLName; }
+
void AddBufferBindCounts(int8_t addVal) const;
protected:
- WebGLVertexArray(WebGLContext* webgl, GLuint name);
+ explicit WebGLVertexArray(WebGLContext* webgl);
virtual ~WebGLVertexArray();
- virtual void BindVertexArray() = 0;
+ virtual void GenVertexArray() = 0;
+ virtual void BindVertexArrayImpl() = 0;
virtual void DeleteImpl() = 0;
+ virtual bool IsVertexArrayImpl() const = 0;
-public:
- const GLuint mGLName;
- bool mHasBeenBound = false;
-protected:
+ GLuint mGLName;
nsTArray<WebGLVertexAttribData> mAttribs;
WebGLRefPtr<WebGLBuffer> mElementArrayBuffer;
friend class ScopedDrawHelper;
friend class WebGLContext;
friend class WebGLVertexArrayFake;
friend class WebGL2Context;
friend struct webgl::LinkedProgramInfo;
--- a/dom/canvas/WebGLVertexArrayFake.cpp
+++ b/dom/canvas/WebGLVertexArrayFake.cpp
@@ -6,21 +6,22 @@
#include "WebGLVertexArrayFake.h"
#include "GLContext.h"
#include "WebGLContext.h"
namespace mozilla {
WebGLVertexArrayFake::WebGLVertexArrayFake(WebGLContext* webgl)
- : WebGLVertexArray(webgl, 0)
+ : WebGLVertexArray(webgl)
+ , mIsVAO(false)
{ }
void
-WebGLVertexArrayFake::BindVertexArray()
+WebGLVertexArrayFake::BindVertexArrayImpl()
{
// Go through and re-bind all buffers and setup all
// vertex attribute pointers
gl::GLContext* gl = mContext->gl;
WebGLRefPtr<WebGLVertexArray> prevVertexArray = mContext->mBoundVertexArray;
mContext->mBoundVertexArray = this;
@@ -46,11 +47,24 @@ WebGLVertexArrayFake::BindVertexArray()
const auto& vd = prevVertexArray->mAttribs[i];
if (vd.mEnabled) {
gl->fDisableVertexAttribArray(i);
}
}
mContext->BindBuffer(LOCAL_GL_ARRAY_BUFFER, prevBuffer);
+ mIsVAO = true;
+}
+
+void
+WebGLVertexArrayFake::DeleteImpl()
+{
+ mIsVAO = false;
+}
+
+bool
+WebGLVertexArrayFake::IsVertexArrayImpl() const
+{
+ return mIsVAO;
}
} // namespace mozilla
--- a/dom/canvas/WebGLVertexArrayFake.h
+++ b/dom/canvas/WebGLVertexArrayFake.h
@@ -11,22 +11,26 @@
namespace mozilla {
class WebGLVertexArrayFake final
: public WebGLVertexArray
{
friend class WebGLVertexArray;
protected:
- virtual void BindVertexArray() override;
- virtual void DeleteImpl() override {}
+ virtual void BindVertexArrayImpl() override;
+ virtual void DeleteImpl() override;
+ virtual void GenVertexArray() override {};
+ virtual bool IsVertexArrayImpl() const override;
private:
explicit WebGLVertexArrayFake(WebGLContext* webgl);
~WebGLVertexArrayFake() {
DeleteOnce();
}
+
+ bool mIsVAO;
};
} // namespace mozilla
#endif // WEBGL_VERTEX_ARRAY_FAKE_H_
--- a/dom/canvas/WebGLVertexArrayGL.cpp
+++ b/dom/canvas/WebGLVertexArrayGL.cpp
@@ -6,37 +6,55 @@
#include "WebGLVertexArrayGL.h"
#include "GLContext.h"
#include "WebGLContext.h"
namespace mozilla {
WebGLVertexArrayGL::WebGLVertexArrayGL(WebGLContext* webgl)
- : WebGLVertexArray(webgl,
- [&]() {
- GLuint ret = 0;
- webgl->gl->fGenVertexArrays(1, &ret);
- return ret;
- }())
+ : WebGLVertexArray(webgl)
+ , mIsVAO(false)
{ }
WebGLVertexArrayGL::~WebGLVertexArrayGL()
{
DeleteOnce();
}
void
WebGLVertexArrayGL::DeleteImpl()
{
mElementArrayBuffer = nullptr;
mContext->gl->fDeleteVertexArrays(1, &mGLName);
+
+ mIsVAO = false;
+}
+
+void
+WebGLVertexArrayGL::BindVertexArrayImpl()
+{
+ mContext->mBoundVertexArray = this;
+ mContext->gl->fBindVertexArray(mGLName);
+
+ mIsVAO = true;
}
void
-WebGLVertexArrayGL::BindVertexArray()
+WebGLVertexArrayGL::GenVertexArray()
+{
+ mContext->gl->fGenVertexArrays(1, &mGLName);
+}
+
+bool
+WebGLVertexArrayGL::IsVertexArrayImpl() const
{
- mContext->mBoundVertexArray = this;
- mContext->gl->fBindVertexArray(mGLName);
+ gl::GLContext* gl = mContext->gl;
+ if (gl->WorkAroundDriverBugs())
+ {
+ return mIsVAO;
+ }
+
+ return mContext->gl->fIsVertexArray(mGLName) != 0;
}
} // namespace mozilla
--- a/dom/canvas/WebGLVertexArrayGL.h
+++ b/dom/canvas/WebGLVertexArrayGL.h
@@ -12,18 +12,26 @@ namespace mozilla {
class WebGLVertexArrayGL
: public WebGLVertexArray
{
friend class WebGLVertexArray;
public:
virtual void DeleteImpl() override;
- virtual void BindVertexArray() override;
+ virtual void BindVertexArrayImpl() override;
+ virtual void GenVertexArray() override;
+ virtual bool IsVertexArrayImpl() const override;
protected:
explicit WebGLVertexArrayGL(WebGLContext* webgl);
~WebGLVertexArrayGL();
+
+ // Bug 1140459: Some drivers (including our test slaves!) don't
+ // give reasonable answers for IsVertexArray, maybe others.
+ //
+ // So we track the `is a VAO` state ourselves.
+ bool mIsVAO;
};
} // namespace mozilla
#endif // WEBGL_VERTEX_ARRAY_GL_H_
--- a/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-vertex-array-object.html
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/extensions/oes-vertex-array-object.html
@@ -640,23 +640,22 @@ function runBoundDeleteTests() {
}
// If retained, everything should still work. If cleared, drawing should now fail.
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
var expectedError = (expectRetained ? gl.NO_ERROR : gl.INVALID_OPERATION);
wtu.glErrorShouldBe(gl, expectedError,
"Draw call should " + (expectRetained ? "not " : "") + "fail.");
- // https://github.com/KhronosGroup/WebGL/pull/2731
- //if (!gl.isBuffer(positionBuffer)) {
- // testFailed("References from unbound VAOs keep Position buffer alive.");
- //}
- //if (!gl.isBuffer(colorBuffer)) {
- // testFailed("References from unbound VAOs keep Color buffer alive");
- //}
+ if (!gl.isBuffer(positionBuffer)) {
+ testFailed("References from unbound VAOs keep Position buffer alive.");
+ }
+ if (!gl.isBuffer(colorBuffer)) {
+ testFailed("References from unbound VAOs keep Color buffer alive");
+ }
}
}
function runArrayBufferBindTests() {
debug("");
debug("Testing that buffer bindings on VAOs don't affect default VAO ARRAY_BUFFER binding.");
ext.bindVertexArrayOES(null);