Bug 1048666 - WebGL2 - Implement ClearBufferXXX APIs.; r=jgilbert,bjacob
authorDan Glastonbury <dglastonbury@mozilla.com>
Thu, 18 Sep 2014 10:17:00 +1000
changeset 206135 952adddb379b3717812215fdf0a368221fbf5e22
parent 206134 14fd498c098516a29fa0458bf26516663cfe9863
child 206136 f1fd44eebac78525a4055757386d54ac7bbf4d70
push id27513
push usercbook@mozilla.com
push dateFri, 19 Sep 2014 12:15:35 +0000
treeherdermozilla-central@dadafedc0760 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert, bjacob
bugs1048666
milestone35.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 1048666 - WebGL2 - Implement ClearBufferXXX APIs.; r=jgilbert,bjacob
dom/canvas/WebGL2Context.h
dom/canvas/WebGL2ContextMRTs.cpp
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextFeatures.cpp
gfx/gl/GLContextSymbols.h
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -140,24 +140,30 @@ public:
 
 
     // ------------------------------------------------------------------------
     // Multiple Render Targets - WebGL2ContextMRTs.cpp
     // TODO(djg): Implemented in WebGLContext
 /*
     void DrawBuffers(const dom::Sequence<GLenum>& buffers);
 */
+
+    void ClearBufferiv_base(GLenum buffer, GLint drawbuffer, const GLint* value);
+    void ClearBufferuiv_base(GLenum buffer, GLint drawbuffer, const GLuint* value);
+    void ClearBufferfv_base(GLenum buffer, GLint drawbuffer, const GLfloat* value);
+
     void ClearBufferiv(GLenum buffer, GLint drawbuffer, const dom::Int32Array& value);
     void ClearBufferiv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLint>& value);
     void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const dom::Uint32Array& value);
     void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLuint>& value);
     void ClearBufferfv(GLenum buffer, GLint drawbuffer, const dom::Float32Array& value);
     void ClearBufferfv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLfloat>& value);
     void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
 
+    bool ValidateClearBuffer(const char* info, GLenum buffer, GLint drawbuffer, size_t elemCount);
 
     // -------------------------------------------------------------------------
     // Query Objects - WebGL2ContextQueries.cpp
     // TODO(djg): Implemented in WebGLContext
     /* already_AddRefed<WebGLQuery> CreateQuery();
     void DeleteQuery(WebGLQuery* query);
     bool IsQuery(WebGLQuery* query);
     void BeginQuery(GLenum target, WebGLQuery* query);
--- a/dom/canvas/WebGL2ContextMRTs.cpp
+++ b/dom/canvas/WebGL2ContextMRTs.cpp
@@ -4,49 +4,139 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGL2Context.h"
 #include "GLContext.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
+bool WebGL2Context::ValidateClearBuffer(const char* info, GLenum buffer, GLint drawbuffer, size_t elemCount)
+{
+    size_t requiredElements = -1;
+    GLint maxDrawbuffer = -1;
+    switch (buffer) {
+      case LOCAL_GL_COLOR:
+      case LOCAL_GL_FRONT:
+      case LOCAL_GL_BACK:
+      case LOCAL_GL_LEFT:
+      case LOCAL_GL_RIGHT:
+      case LOCAL_GL_FRONT_AND_BACK:
+          requiredElements = 4;
+          maxDrawbuffer = mGLMaxDrawBuffers - 1;
+          break;
+
+      case LOCAL_GL_DEPTH:
+      case LOCAL_GL_STENCIL:
+          requiredElements = 1;
+          maxDrawbuffer = 0;
+          break;
+
+      default:
+          ErrorInvalidEnumInfo(info, buffer);
+          return false;
+    }
+
+    if (drawbuffer < 0 || drawbuffer > maxDrawbuffer) {
+        ErrorInvalidValue("%s: invalid drawbuffer %d. This buffer only supports drawbuffer values between 0 and %d",
+                          info, drawbuffer, maxDrawbuffer);
+        return false;
+    }
+
+    if (elemCount < requiredElements) {
+        ErrorInvalidValue("%s: Not enough elements. Require %u. Given %u.",
+                          info, requiredElements, elemCount);
+        return false;
+    }
+    return true;
+}
+
+// Common base functionality. These a good candidates to be moved into WebGLContextUnchecked.cpp
+void
+WebGL2Context::ClearBufferiv_base(GLenum buffer, GLint drawbuffer, const GLint* value)
+{
+    MakeContextCurrent();
+    gl->fClearBufferiv(buffer, drawbuffer, value);
+}
+
+void
+WebGL2Context::ClearBufferuiv_base(GLenum buffer, GLint drawbuffer, const GLuint* value)
+{
+    MakeContextCurrent();
+    gl->fClearBufferuiv(buffer, drawbuffer, value);
+}
+
+void
+WebGL2Context::ClearBufferfv_base(GLenum buffer, GLint drawbuffer, const GLfloat* value)
+{
+    MakeContextCurrent();
+    gl->fClearBufferfv(buffer, drawbuffer, value);
+}
+
 void
 WebGL2Context::ClearBufferiv(GLenum buffer, GLint drawbuffer, const dom::Int32Array& value)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (!ValidateClearBuffer("clearBufferiv", buffer, drawbuffer, value.Length())) {
+        return;
+    }
+
+    ClearBufferiv_base(buffer, drawbuffer, value.Data());
 }
 
 void
 WebGL2Context::ClearBufferiv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLint>& value)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (!ValidateClearBuffer("clearBufferiv", buffer, drawbuffer, value.Length())) {
+        return;
+    }
+
+    ClearBufferiv_base(buffer, drawbuffer, value.Elements());
 }
 
 void
 WebGL2Context::ClearBufferuiv(GLenum buffer, GLint drawbuffer, const dom::Uint32Array& value)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (!ValidateClearBuffer("clearBufferuiv", buffer, drawbuffer, value.Length())) {
+        return;
+    }
+
+    ClearBufferuiv_base(buffer, drawbuffer, value.Data());
 }
 
 void
 WebGL2Context::ClearBufferuiv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLuint>& value)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (!ValidateClearBuffer("clearBufferuiv", buffer, drawbuffer, value.Length())) {
+        return;
+    }
+
+    ClearBufferuiv_base(buffer, drawbuffer, value.Elements());
 }
 
 void
 WebGL2Context::ClearBufferfv(GLenum buffer, GLint drawbuffer, const dom::Float32Array& value)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (!ValidateClearBuffer("clearBufferfv", buffer, drawbuffer, value.Length())) {
+        return;
+    }
+
+    ClearBufferfv_base(buffer, drawbuffer, value.Data());
 }
 
 void
 WebGL2Context::ClearBufferfv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLfloat>& value)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (!ValidateClearBuffer("clearBufferfv", buffer, drawbuffer, value.Length())) {
+        return;
+    }
+
+    ClearBufferfv_base(buffer, drawbuffer, value.Elements());
 }
 
 void
 WebGL2Context::ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (buffer != LOCAL_GL_DEPTH_STENCIL) {
+        return ErrorInvalidEnumInfo("clearBufferfi: buffer", buffer);
+    }
+    MakeContextCurrent();
+    gl->fClearBufferfi(buffer, drawbuffer, depth, stencil);
 }
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -1007,16 +1007,33 @@ GLContext::InitWithPrefix(const char *pr
             if (!LoadSymbols(useCore ? coreSymbols : extSymbols, trygl, prefix)) {
                 NS_ERROR("GL supports query objects iv getter without supplying its function.");
 
                 MarkUnsupported(GLFeature::get_query_object_iv);
                 ClearSymbols(coreSymbols);
             }
         }
 
+        if (IsSupported(GLFeature::clear_buffers)) {
+            SymLoadStruct clearBuffersSymbols[] = {
+                { (PRFuncPtr*) &mSymbols.fClearBufferfi,  { "ClearBufferfi",  nullptr } },
+                { (PRFuncPtr*) &mSymbols.fClearBufferfv,  { "ClearBufferfv",  nullptr } },
+                { (PRFuncPtr*) &mSymbols.fClearBufferiv,  { "ClearBufferiv",  nullptr } },
+                { (PRFuncPtr*) &mSymbols.fClearBufferuiv, { "ClearBufferuiv", nullptr } },
+                END_SYMBOLS
+            };
+
+            if (!LoadSymbols(clearBuffersSymbols, trygl, prefix)) {
+                NS_ERROR("GL supports clear_buffers without supplying its functions.");
+
+                MarkUnsupported(GLFeature::clear_buffers);
+                ClearSymbols(clearBuffersSymbols);
+            }
+        }
+
         if (IsSupported(GLFeature::draw_buffers)) {
             SymLoadStruct coreSymbols[] = {
                 { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
                 END_SYMBOLS
             };
 
             SymLoadStruct extSymbols[] = {
                 { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffersARB", "DrawBuffersEXT", nullptr } },
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -75,16 +75,17 @@ namespace mozilla {
 }
 
 namespace mozilla {
 namespace gl {
 
 MOZ_BEGIN_ENUM_CLASS(GLFeature)
     bind_buffer_offset,
     blend_minmax,
+    clear_buffers,
     depth_texture,
     draw_buffers,
     draw_instanced,
     draw_range_elements,
     element_index_uint,
     ES2_compatibility,
     ES3_compatibility,
     frag_color_float,
@@ -941,16 +942,40 @@ private:
 
 public:
     void fClear(GLbitfield mask) {
         BeforeGLDrawCall();
         raw_fClear(mask);
         AfterGLDrawCall();
     }
 
+    void fClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
+        BEFORE_GL_CALL;
+        mSymbols.fClearBufferfi(buffer, drawbuffer, depth, stencil);
+        AFTER_GL_CALL;
+    }
+
+    void fClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) {
+        BEFORE_GL_CALL;
+        mSymbols.fClearBufferfv(buffer, drawbuffer, value);
+        AFTER_GL_CALL;
+    }
+
+    void fClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {
+        BEFORE_GL_CALL;
+        mSymbols.fClearBufferiv(buffer, drawbuffer, value);
+        AFTER_GL_CALL;
+    }
+
+    void fClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) {
+        BEFORE_GL_CALL;
+        mSymbols.fClearBufferuiv(buffer, drawbuffer, value);
+        AFTER_GL_CALL;
+    }
+
     void fClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a) {
         BEFORE_GL_CALL;
         mSymbols.fClearColor(r, g, b, a);
         AFTER_GL_CALL;
     }
 
     void fClearStencil(GLint s) {
         BEFORE_GL_CALL;
--- a/gfx/gl/GLContextFeatures.cpp
+++ b/gfx/gl/GLContextFeatures.cpp
@@ -67,16 +67,25 @@ static const FeatureInfo sFeatureInfoArr
         300, // OpenGL ES version
         GLContext::Extension_None,
         {
             GLContext::EXT_blend_minmax,
             GLContext::Extensions_End
         }
     },
     {
+        "clear_buffers",
+        300, // OpenGL version
+        300, // OpenGL ES version
+        GLContext::Extension_None,
+        {
+            GLContext::Extensions_End
+        }
+    },
+    {
         "depth_texture",
         200, // OpenGL version
         300, // OpenGL ES version
         GLContext::Extension_None,
         {
             GLContext::ARB_depth_texture,
             GLContext::OES_depth_texture,
             // Intentionally avoid putting ANGLE_depth_texture here,
--- a/gfx/gl/GLContextSymbols.h
+++ b/gfx/gl/GLContextSymbols.h
@@ -60,16 +60,24 @@ struct GLContextSymbols
     typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
     PFNGLBLENDFUNCSEPARATEPROC fBlendFuncSeparate;
     typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
     PFNGLBUFFERDATAPROC fBufferData;
     typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
     PFNGLBUFFERSUBDATAPROC fBufferSubData;
     typedef void (GLAPIENTRY * PFNGLCLEARPROC) (GLbitfield);
     PFNGLCLEARPROC fClear;
+    typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+    PFNGLCLEARBUFFERFIPROC fClearBufferfi;
+    typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat* value);
+    PFNGLCLEARBUFFERFVPROC fClearBufferfv;
+    typedef void (GLAPIENTRY * PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint* value);
+    PFNGLCLEARBUFFERIVPROC fClearBufferiv;
+    typedef void (GLAPIENTRY * PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint* value);
+    PFNGLCLEARBUFFERUIVPROC fClearBufferuiv;
     typedef void (GLAPIENTRY * PFNGLCLEARCOLORPROC) (GLclampf, GLclampf, GLclampf, GLclampf);
     PFNGLCLEARCOLORPROC fClearColor;
     typedef void (GLAPIENTRY * PFNGLCLEARSTENCILPROC) (GLint);
     PFNGLCLEARSTENCILPROC fClearStencil;
     typedef void (GLAPIENTRY * PFNGLCOLORMASKPROC) (realGLboolean red, realGLboolean green, realGLboolean blue, realGLboolean alpha);
     PFNGLCOLORMASKPROC fColorMask;
     typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *pixels);
     PFNGLCOMPRESSEDTEXIMAGE2D fCompressedTexImage2D;