Bug 1247977 - Handle FakeBlackTexture creation fail. r=jgilbert
authorMorris Tseng <mtseng@mozilla.com>
Wed, 27 Jul 2016 09:42:09 +0800
changeset 306818 2da7497fc16b48c108506c5c2d64ea13b9fa8dc8
parent 306817 02e4e9890b4bd237dfd028a5aa64aad4465147f5
child 306819 c1ac662342a28384bedc60ed979fa23ddef0af1e
push id30499
push usercbook@mozilla.com
push dateWed, 27 Jul 2016 14:35:59 +0000
treeherdermozilla-central@fef429fba4c6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1247977
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1247977 - Handle FakeBlackTexture creation fail. r=jgilbert MozReview-Commit-ID: GiwoIcFsv2k
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextDraw.cpp
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -1388,33 +1388,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
@@ -131,17 +131,23 @@ ScopedResolveTexturesForDraw::ScopedReso
                                          funcName);
                 *out_error = true;
                 return;
             }
 
             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);
+                *out_error = true;
+                return;
+            }
+
             mRebindRequests.push_back({texUnit, tex});
         }
     }
 
     *out_error = false;
 }
 
 ScopedResolveTexturesForDraw::~ScopedResolveTexturesForDraw()
@@ -154,17 +160,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) {
@@ -193,22 +199,26 @@ WebGLContext::BindFakeBlack(uint32_t tex
 
     UniquePtr<FakeBlackTexture>* slot = fnGetSlot();
     if (!slot) {
         MOZ_CRASH("GFX: 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() ||
@@ -868,97 +878,74 @@ 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("GFX: 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("GFX: 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("GFX: 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);
 }