Bug 1247977 - Handle FakeBlackTexture creation fail. r=jgilbert, a=sledru
authorMorris Tseng <mtseng@mozilla.com>
Fri, 29 Jul 2016 18:22:00 -0400
changeset 340153 8847dd9e9a2da7a4ad074ab97e085295e50746c3
parent 340152 589e1f984537e280ff84591e94afdc3c5bfe2710
child 340154 1efa2bee386f53eaa0dc450fe5c866137ffd0b9e
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert, sledru
bugs1247977
milestone49.0a2
Bug 1247977 - Handle FakeBlackTexture creation fail. r=jgilbert, a=sledru MozReview-Commit-ID: ajNEo2XiX6
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextDraw.cpp
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -1431,33 +1431,37 @@ protected:
 
     GLenum mPixelStore_ColorspaceConversion;
     bool mPixelStore_FlipY;
     bool mPixelStore_PremultiplyAlpha;
 
     ////////////////////////////////////
     class FakeBlackTexture {
     public:
+        static UniquePtr<FakeBlackTexture> Create(gl::GLContext* gl,
+                                                  TexTarget target,
+                                                  FakeBlackType type);
         gl::GLContext* const mGL;
         const GLuint mGLName;
 
-        FakeBlackTexture(gl::GLContext* gl, TexTarget target, FakeBlackType type);
         ~FakeBlackTexture();
+    protected:
+        explicit FakeBlackTexture(gl::GLContext* gl);
     };
 
     UniquePtr<FakeBlackTexture> mFakeBlack_2D_0000;
     UniquePtr<FakeBlackTexture> mFakeBlack_2D_0001;
     UniquePtr<FakeBlackTexture> mFakeBlack_CubeMap_0000;
     UniquePtr<FakeBlackTexture> mFakeBlack_CubeMap_0001;
     UniquePtr<FakeBlackTexture> mFakeBlack_3D_0000;
     UniquePtr<FakeBlackTexture> mFakeBlack_3D_0001;
     UniquePtr<FakeBlackTexture> mFakeBlack_2D_Array_0000;
     UniquePtr<FakeBlackTexture> mFakeBlack_2D_Array_0001;
 
-    void BindFakeBlack(uint32_t texUnit, TexTarget target, FakeBlackType fakeBlack);
+    bool BindFakeBlack(uint32_t texUnit, TexTarget target, FakeBlackType fakeBlack);
 
     ////////////////////////////////////
 
     // Generic Vertex Attributes
     UniquePtr<GLenum[]> mVertexAttribType;
     GLfloat mVertexAttrib0Vector[4];
     GLfloat mFakeVertexAttrib0BufferObjectVector[4];
     size_t mFakeVertexAttrib0BufferObjectSize;
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -61,17 +61,22 @@ ScopedResolveTexturesForDraw::ScopedReso
 
             FakeBlackType fakeBlack;
             if (!tex->ResolveForDraw(funcName, texUnit, &fakeBlack))
                 return false;
 
             if (fakeBlack == FakeBlackType::None)
                 continue;
 
-            mWebGL->BindFakeBlack(texUnit, tex->Target(), fakeBlack);
+            if (!mWebGL->BindFakeBlack(texUnit, tex->Target(), fakeBlack)) {
+                mWebGL->ErrorOutOfMemory("%s: Failed to create fake black texture.",
+                                         funcName);
+                return false;
+            }
+
             mRebindRequests.push_back({texUnit, tex});
         }
 
         return true;
     };
 
     bool ok = true;
     ok &= fnResolveAll(mWebGL->mBound2DTextures);
@@ -96,17 +101,17 @@ ScopedResolveTexturesForDraw::~ScopedRes
     for (const auto& itr : mRebindRequests) {
         gl->fActiveTexture(LOCAL_GL_TEXTURE0 + itr.texUnit);
         gl->fBindTexture(itr.tex->Target().get(), itr.tex->mGLName);
     }
 
     gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mWebGL->mActiveTexture);
 }
 
-void
+bool
 WebGLContext::BindFakeBlack(uint32_t texUnit, TexTarget target, FakeBlackType fakeBlack)
 {
     MOZ_ASSERT(fakeBlack == FakeBlackType::RGBA0000 ||
                fakeBlack == FakeBlackType::RGBA0001);
 
     const auto fnGetSlot = [this, target, fakeBlack]() -> UniquePtr<FakeBlackTexture>*
     {
         switch (fakeBlack) {
@@ -135,22 +140,26 @@ WebGLContext::BindFakeBlack(uint32_t tex
 
     UniquePtr<FakeBlackTexture>* slot = fnGetSlot();
     if (!slot) {
         MOZ_CRASH("fnGetSlot failed.");
     }
     UniquePtr<FakeBlackTexture>& fakeBlackTex = *slot;
 
     if (!fakeBlackTex) {
-        fakeBlackTex.reset(new FakeBlackTexture(gl, target, fakeBlack));
+        fakeBlackTex = FakeBlackTexture::Create(gl, target, fakeBlack);
+        if (!fakeBlackTex) {
+            return false;
+        }
     }
 
     gl->fActiveTexture(LOCAL_GL_TEXTURE0 + texUnit);
     gl->fBindTexture(target.get(), fakeBlackTex->mGLName);
     gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mActiveTexture);
+    return true;
 }
 
 ////////////////////////////////////////
 
 bool
 WebGLContext::DrawInstanced_check(const char* info)
 {
     MOZ_ASSERT(IsWebGL2() ||
@@ -806,98 +815,76 @@ static GLuint
 CreateGLTexture(gl::GLContext* gl)
 {
     MOZ_ASSERT(gl->IsCurrent());
     GLuint ret = 0;
     gl->fGenTextures(1, &ret);
     return ret;
 }
 
-WebGLContext::FakeBlackTexture::FakeBlackTexture(gl::GLContext* gl, TexTarget target,
-                                                 FakeBlackType type)
-    : mGL(gl)
-    , mGLName(CreateGLTexture(gl))
+UniquePtr<WebGLContext::FakeBlackTexture>
+WebGLContext::FakeBlackTexture::Create(gl::GLContext* gl, TexTarget target,
+                                       FakeBlackType type)
 {
     GLenum texFormat;
     switch (type) {
     case FakeBlackType::RGBA0000:
         texFormat = LOCAL_GL_RGBA;
         break;
 
     case FakeBlackType::RGBA0001:
         texFormat = LOCAL_GL_RGB;
         break;
 
     default:
         MOZ_CRASH("bad type");
     }
 
-    gl::ScopedBindTexture scopedBind(mGL, mGLName, target.get());
+    UniquePtr<FakeBlackTexture> result(new FakeBlackTexture(gl));
+    gl::ScopedBindTexture scopedBind(gl, result->mGLName, target.get());
 
-    mGL->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
-    mGL->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
+    gl->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
+    gl->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
 
     // We allocate our zeros on the heap, and we overallocate (16 bytes instead of 4) to
     // minimize the risk of running into a driver bug in texImage2D, as it is a bit
     // unusual maybe to create 1x1 textures, and the stack may not have the alignment that
     // TexImage2D expects.
 
     const webgl::DriverUnpackInfo dui = {texFormat, texFormat, LOCAL_GL_UNSIGNED_BYTE};
     UniqueBuffer zeros = moz_xcalloc(1, 16); // Infallible allocation.
 
     MOZ_ASSERT(gl->IsCurrent());
-    auto logANGLEError = [](GLenum source, GLenum type, GLuint id, GLenum severity,
-                            GLsizei length, const GLchar* message, const GLvoid* userParam)
-    {
-        gfxCriticalNote << message;
-    };
-
-    if (gl->IsANGLE()) {
-      gl->fEnable(LOCAL_GL_DEBUG_OUTPUT);
-      gl->fDebugMessageCallback(logANGLEError, nullptr);
-      gl->fDebugMessageControl(LOCAL_GL_DONT_CARE,
-                               LOCAL_GL_DONT_CARE,
-                               LOCAL_GL_DONT_CARE,
-                               0, nullptr,
-                               true);
-    }
 
     if (target == LOCAL_GL_TEXTURE_CUBE_MAP) {
         for (int i = 0; i < 6; ++i) {
             const TexImageTarget curTarget = LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
-            const GLenum error = DoTexImage(mGL, curTarget.get(), 0, &dui, 1, 1, 1,
+            const GLenum error = DoTexImage(gl, curTarget.get(), 0, &dui, 1, 1, 1,
                                             zeros.get());
             if (error) {
-                const nsPrintfCString text("DoTexImage failed with `error`: 0x%04x, "
-                                           "for `curTarget`: 0x%04x, "
-                                           "`dui`: {0x%04x, 0x%04x, 0x%04x}.",
-                                           error, curTarget.get(), dui.internalFormat,
-                                           dui.unpackFormat, dui.unpackType);
-                gfxCriticalError() << text.BeginReading();
-                MOZ_CRASH("Unexpected error during cube map FakeBlack creation.");
+                return nullptr;
             }
         }
     } else {
-        const GLenum error = DoTexImage(mGL, target.get(), 0, &dui, 1, 1, 1,
+        const GLenum error = DoTexImage(gl, target.get(), 0, &dui, 1, 1, 1,
                                         zeros.get());
         if (error) {
-            const nsPrintfCString text("DoTexImage failed with `error`: 0x%04x, "
-                                       "for `target`: 0x%04x, "
-                                       "`dui`: {0x%04x, 0x%04x, 0x%04x}.",
-                                       error, target.get(), dui.internalFormat,
-                                       dui.unpackFormat, dui.unpackType);
-            gfxCriticalError() << text.BeginReading();
-            MOZ_CRASH("Unexpected error during FakeBlack creation.");
+            return nullptr;
         }
     }
 
-    if (gl->IsANGLE()) {
-      gl->fDisable(LOCAL_GL_DEBUG_OUTPUT);
-    }
+    return result;
 }
 
+WebGLContext::FakeBlackTexture::FakeBlackTexture(gl::GLContext* gl)
+    : mGL(gl)
+    , mGLName(CreateGLTexture(gl))
+{
+}
+
+
 WebGLContext::FakeBlackTexture::~FakeBlackTexture()
 {
     mGL->MakeCurrent();
     mGL->fDeleteTextures(1, &mGLName);
 }
 
 } // namespace mozilla