Bug 1289655 - Add primitive restart for WebGL 2. - r=mtseng draft
authorJeff Gilbert <jgilbert@mozilla.com>
Tue, 26 Jul 2016 20:05:45 -0700
changeset 394560 d36a63e11871e2e56f3cce3f93c8c28725c5bae1
parent 394559 5f4b32c6bb13a4c5dcb2e0273b70009d9054beec
child 394561 0f356b7a063f8b08084b0e0906ac4ca68e7f4a70
push id24605
push userbmo:jgilbert@mozilla.com
push dateFri, 29 Jul 2016 23:50:29 +0000
reviewersmtseng
bugs1289655
milestone50.0a1
Bug 1289655 - Add primitive restart for WebGL 2. - r=mtseng MozReview-Commit-ID: 6SfI8yfROGI
dom/canvas/WebGL2Context.cpp
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextDraw.cpp
dom/canvas/WebGLContextValidate.cpp
--- a/dom/canvas/WebGL2Context.cpp
+++ b/dom/canvas/WebGL2Context.cpp
@@ -128,16 +128,19 @@ WebGLContext::InitWebGL2(FailureReason* 
 
 #ifdef XP_MACOSX
     // On OSX, GL core profile is used. This requires texture swizzle
     // support to emulate legacy texture formats: ALPHA, LUMINANCE,
     // and LUMINANCE_ALPHA.
     fnGatherMissing(gl::GLFeature::texture_swizzle);
 #endif
 
+    fnGatherMissing2(gl::GLFeature::prim_restart_fixed,
+                     gl::GLFeature::prim_restart);
+
     ////
 
     if (missingList.size()) {
         nsAutoCString exts;
         for (auto itr = missingList.begin(); itr != missingList.end(); ++itr) {
             exts.AppendLiteral("\n  ");
             exts.Append(gl::GLContext::GetFeatureName(*itr));
         }
@@ -156,23 +159,31 @@ WebGLContext::InitWebGL2(FailureReason* 
                      &mGLMaxUniformBufferBindings);
 
     mBoundTransformFeedbackBuffers.SetLength(mGLMaxTransformFeedbackSeparateAttribs);
     mBoundUniformBuffers.SetLength(mGLMaxUniformBufferBindings);
 
     mDefaultTransformFeedback = new WebGLTransformFeedback(this, 0);
     mBoundTransformFeedback = mDefaultTransformFeedback;
 
+    ////
+
     if (!gl->IsGLES()) {
         // Desktop OpenGL requires the following to be enabled in order to
         // support sRGB operations on framebuffers.
-        gl->MakeCurrent();
         gl->fEnable(LOCAL_GL_FRAMEBUFFER_SRGB_EXT);
     }
 
+    if (gl->IsSupported(gl::GLFeature::prim_restart_fixed)) {
+        gl->fEnable(LOCAL_GL_PRIMITIVE_RESTART_FIXED_INDEX);
+    } else {
+        MOZ_ASSERT(gl->IsSupported(gl::GLFeature::prim_restart));
+        gl->fEnable(LOCAL_GL_PRIMITIVE_RESTART);
+    }
+
     //////
 
     static const GLenum kWebGL2_CompressedFormats[] = {
         LOCAL_GL_COMPRESSED_R11_EAC,
         LOCAL_GL_COMPRESSED_SIGNED_R11_EAC,
         LOCAL_GL_COMPRESSED_RG11_EAC,
         LOCAL_GL_COMPRESSED_SIGNED_RG11_EAC,
         LOCAL_GL_COMPRESSED_RGB8_ETC2,
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -914,16 +914,18 @@ protected:
                                    WebGLTexture** const out_texture,
                                    WebGLTexture::ImageInfo** const out_imageInfo);
 
     bool ValidateUnpackInfo(const char* funcName, bool usePBOs, GLenum format,
                             GLenum type, webgl::PackingInfo* const out);
 
 // -----------------------------------------------------------------------------
 // Vertices Feature (WebGLContextVertices.cpp)
+    GLenum mPrimRestartTypeBytes;
+
 public:
     void DrawArrays(GLenum mode, GLint first, GLsizei count);
     void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count,
                              GLsizei primcount);
     void DrawElements(GLenum mode, GLsizei count, GLenum type,
                       WebGLintptr byteOffset);
     void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
                                WebGLintptr byteOffset, GLsizei primcount);
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -253,16 +253,25 @@ WebGLContext::DrawArrays_check(GLint fir
         ErrorInvalidValue("%s: negative primcount", info);
         return false;
     }
 
     if (!ValidateStencilParamsForDrawCall()) {
         return false;
     }
 
+    if (IsWebGL2() && !gl->IsSupported(gl::GLFeature::prim_restart_fixed)) {
+        MOZ_ASSERT(gl->IsSupported(gl::GLFeature::prim_restart));
+        if (mPrimRestartTypeBytes) {
+            mPrimRestartTypeBytes = 0;
+
+            gl->fPrimitiveRestartIndex(0);
+        }
+    }
+
     // If count is 0, there's nothing to do.
     if (count == 0 || primcount == 0) {
         return false;
     }
 
     if (!ValidateBufferFetching(info)) {
         return false;
     }
@@ -409,16 +418,30 @@ WebGLContext::DrawElements_check(GLsizei
     }
 
     if (byteOffset % bytesPerElem != 0) {
         ErrorInvalidOperation("%s: `byteOffset` must be a multiple of the size of `type`",
                               info);
         return false;
     }
 
+    ////
+
+    if (IsWebGL2() && !gl->IsSupported(gl::GLFeature::prim_restart_fixed)) {
+        MOZ_ASSERT(gl->IsSupported(gl::GLFeature::prim_restart));
+        if (mPrimRestartTypeBytes != bytesPerElem) {
+            mPrimRestartTypeBytes = bytesPerElem;
+
+            const uint32_t ones = UINT32_MAX >> (4 - mPrimRestartTypeBytes);
+            gl->fPrimitiveRestartIndex(ones);
+        }
+    }
+
+    ////
+
     const GLsizei first = byteOffset / bytesPerElem;
     const CheckedUint32 checked_byteCount = bytesPerElem * CheckedUint32(count);
 
     if (!checked_byteCount.isValid()) {
         ErrorInvalidValue("%s: overflow in byteCount", info);
         return false;
     }
 
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -996,16 +996,18 @@ WebGLContext::InitAndValidateGL(FailureR
     mPixelStore_UnpackSkipRows = 0;
     mPixelStore_UnpackSkipPixels = 0;
     mPixelStore_UnpackAlignment = 4;
     mPixelStore_PackRowLength = 0;
     mPixelStore_PackSkipRows = 0;
     mPixelStore_PackSkipPixels = 0;
     mPixelStore_PackAlignment = 4;
 
+    mPrimRestartTypeBytes = 0;
+
     return true;
 }
 
 bool
 WebGLContext::ValidateFramebufferTarget(GLenum target,
                                         const char* const info)
 {
     bool isValid = true;