Bug 1324972 - Catch ANGLE's zealous index-out-of-bounds INVALID_OPs. - r=daoshengmu draft
authorJeff Gilbert <jgilbert@mozilla.com>
Wed, 21 Dec 2016 00:17:38 -0800
changeset 453830 d921063e5d06aebecc2c018c3506a7b43671a8ba
parent 453829 a00d1c3e920e4e11eef7ed1e96f44ac3afbeeb09
child 453831 b000dbca1d44f7f767c4a0e70245fe79e722002b
push id39740
push userbmo:jgilbert@mozilla.com
push dateSun, 25 Dec 2016 08:04:43 +0000
reviewersdaoshengmu
bugs1324972
milestone53.0a1
Bug 1324972 - Catch ANGLE's zealous index-out-of-bounds INVALID_OPs. - r=daoshengmu MozReview-Commit-ID: ECbWZB9Hvms
dom/canvas/WebGLContextDraw.cpp
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -689,16 +689,36 @@ WebGLContext::DrawElements_check(const c
         GenerateWarning("%s: bound element array buffer previously used with a type other than "
                         "%s, this will affect performance.",
                         funcName, WebGLContext::EnumName(type));
     }
 
     return true;
 }
 
+static void
+HandleDrawElementsErrors(WebGLContext* webgl, const char* funcName,
+                         gl::GLContext::LocalErrorScope& errorScope)
+{
+    const auto err = errorScope.GetError();
+    if (err == LOCAL_GL_INVALID_OPERATION) {
+        webgl->ErrorInvalidOperation("%s: Driver rejected indexed draw call, possibly"
+                                     " due to out-of-bounds indices.", funcName);
+        return;
+    }
+
+    MOZ_ASSERT(!err);
+    if (err) {
+        webgl->ErrorImplementationBug("%s: Unexpected driver error during indexed draw"
+                                      " call. Please file a bug.",
+                                      funcName);
+        return;
+    }
+}
+
 void
 WebGLContext::DrawElements(GLenum mode, GLsizei vertCount, GLenum type,
                            WebGLintptr byteOffset)
 {
     const char funcName[] = "drawElements";
     if (IsContextLost())
         return;
 
@@ -715,18 +735,30 @@ WebGLContext::DrawElements(GLenum mode, 
 
     const ScopedDrawHelper scopedHelper(this, funcName, 0, mMaxFetchedVertices, instanceCount,
                                         &error);
     if (error)
         return;
 
     {
         ScopedDrawCallWrapper wrapper(*this);
-        gl->fDrawElements(mode, vertCount, type,
-                          reinterpret_cast<GLvoid*>(byteOffset));
+        {
+            UniquePtr<gl::GLContext::LocalErrorScope> errorScope;
+
+            if (gl->IsANGLE()) {
+                errorScope.reset(new gl::GLContext::LocalErrorScope(*gl));
+            }
+
+            gl->fDrawElements(mode, vertCount, type,
+                              reinterpret_cast<GLvoid*>(byteOffset));
+
+            if (errorScope) {
+                HandleDrawElementsErrors(this, funcName, *errorScope);
+            }
+        }
     }
 
     Draw_cleanup(funcName);
 }
 
 void
 WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei vertCount, GLenum type,
                                     WebGLintptr byteOffset, GLsizei instanceCount)
@@ -750,19 +782,30 @@ WebGLContext::DrawElementsInstanced(GLen
 
     const ScopedDrawHelper scopedHelper(this, funcName, 0, mMaxFetchedVertices, instanceCount,
                                         &error);
     if (error)
         return;
 
     {
         ScopedDrawCallWrapper wrapper(*this);
-        gl->fDrawElementsInstanced(mode, vertCount, type,
-                                   reinterpret_cast<GLvoid*>(byteOffset),
-                                   instanceCount);
+        {
+            UniquePtr<gl::GLContext::LocalErrorScope> errorScope;
+
+            if (gl->IsANGLE()) {
+                errorScope.reset(new gl::GLContext::LocalErrorScope(*gl));
+            }
+
+            gl->fDrawElementsInstanced(mode, vertCount, type,
+                                       reinterpret_cast<GLvoid*>(byteOffset),
+                                       instanceCount);
+            if (errorScope) {
+                HandleDrawElementsErrors(this, funcName, *errorScope);
+            }
+        }
     }
 
     Draw_cleanup(funcName);
 }
 
 ////////////////////////////////////////
 
 void