Bug 797664 - Add runtime asserts so calling null functions is more obvious - r=bjacob
authorJeff Gilbert <jgilbert@mozilla.com>
Tue, 18 Dec 2012 23:16:01 -0800
changeset 125615 83ac1379e10e
parent 125614 1d72507cbd59
child 125616 3ef80b6f2622
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbjacob
bugs797664
milestone20.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 797664 - Add runtime asserts so calling null functions is more obvious - r=bjacob
gfx/gl/GLContext.h
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -1723,16 +1723,25 @@ public:
 
 #else
 
 #define BEFORE_GL_CALL do { } while (0)
 #define AFTER_GL_CALL do { } while (0)
 
 #endif
 
+#define ASSERT_SYMBOL_PRESENT(func) \
+    do {\
+        MOZ_ASSERT(strstr(MOZ_FUNCTION_NAME, #func) != nullptr, "Mismatched symbol check.");\
+        if (MOZ_UNLIKELY(!mSymbols.func)) {\
+            printf_stderr("RUNTIME ASSERT: Uninitialized GL function: %s\n", #func);\
+            MOZ_CRASH();\
+        }\
+    } while (0)
+
     /*** In GL debug mode, we completely override glGetError ***/
 
     GLenum fGetError() {
 #ifdef DEBUG
         // debug mode ends up eating the error in AFTER_GL_CALL
         if (DebugMode()) {
             GLenum err = mGLError;
             mGLError = LOCAL_GL_NO_ERROR;
@@ -2135,31 +2144,26 @@ public:
     const GLubyte* fGetString(GLenum name) {
         BEFORE_GL_CALL;
         const GLubyte *result = mSymbols.fGetString(name);
         AFTER_GL_CALL;
         return result;
     }
 
     void fGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *img) {
-        if (!mSymbols.fGetTexImage) {
-            return;
-        }
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fGetTexImage);
         mSymbols.fGetTexImage(target, level, format, type, img);
         AFTER_GL_CALL;
     }
 
     void fGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
     {  
-        if (!mSymbols.fGetTexLevelParameteriv) {
-            *params = 0;
-            return;
-        }
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fGetTexLevelParameteriv);
         mSymbols.fGetTexLevelParameteriv(target, level, pname, params);
         AFTER_GL_CALL;
     }
 
     void fGetTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) {
         BEFORE_GL_CALL;
         mSymbols.fGetTexParameterfv(target, pname, params);
         AFTER_GL_CALL;
@@ -2216,38 +2220,38 @@ public:
 
     realGLboolean fIsBuffer(GLuint buffer) {
         BEFORE_GL_CALL;
         realGLboolean retval = mSymbols.fIsBuffer(buffer);
         AFTER_GL_CALL;
         return retval;
     }
 
-    realGLboolean fIsEnabled (GLenum capability) {
+    realGLboolean fIsEnabled(GLenum capability) {
         BEFORE_GL_CALL;
         realGLboolean retval = mSymbols.fIsEnabled(capability);
         AFTER_GL_CALL;
         return retval;
     }
 
-    realGLboolean fIsProgram (GLuint program) {
+    realGLboolean fIsProgram(GLuint program) {
         BEFORE_GL_CALL;
         realGLboolean retval = mSymbols.fIsProgram(program);
         AFTER_GL_CALL;
         return retval;
     }
 
-    realGLboolean fIsShader (GLuint shader) {
+    realGLboolean fIsShader(GLuint shader) {
         BEFORE_GL_CALL;
         realGLboolean retval = mSymbols.fIsShader(shader);
         AFTER_GL_CALL;
         return retval;
     }
 
-    realGLboolean fIsTexture (GLuint texture) {
+    realGLboolean fIsTexture(GLuint texture) {
         BEFORE_GL_CALL;
         realGLboolean retval = mSymbols.fIsTexture(texture);
         AFTER_GL_CALL;
         return retval;
     }
 
     void fLineWidth(GLfloat width) {
         BEFORE_GL_CALL;
@@ -2582,16 +2586,17 @@ public:
         AFTER_GL_CALL;
     }
 
 private:
     void raw_fGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
         MOZ_ASSERT(mIsGLES2);
 
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fGetShaderPrecisionFormat);
         mSymbols.fGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
         AFTER_GL_CALL;
     }
 
 public:
     void fGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
        if (mIsGLES2) {
             raw_fGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
@@ -2663,16 +2668,17 @@ public:
         realGLboolean retval = mSymbols.fIsFramebuffer(framebuffer);
         AFTER_GL_CALL;
         return retval;
     }
 
 private:
     void raw_fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fBlitFramebuffer);
         mSymbols.fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
         AFTER_GL_CALL;
     }
 
 public:
     realGLboolean fIsRenderbuffer (GLuint renderbuffer) {
         BEFORE_GL_CALL;
         realGLboolean retval = mSymbols.fIsRenderbuffer(renderbuffer);
@@ -2683,49 +2689,54 @@ public:
     void fRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height) {
         BEFORE_GL_CALL;
         mSymbols.fRenderbufferStorage(target, internalFormat, width, height);
         AFTER_GL_CALL;
     }
 
     void fRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height) {
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fRenderbufferStorageMultisample);
         mSymbols.fRenderbufferStorageMultisample(target, samples, internalFormat, width, height);
         AFTER_GL_CALL;
     }
 
 private:
     void raw_fDepthRange(GLclampf a, GLclampf b) {
         MOZ_ASSERT(!mIsGLES2);
 
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fDepthRange);
         mSymbols.fDepthRange(a, b);
         AFTER_GL_CALL;
     }
 
     void raw_fDepthRangef(GLclampf a, GLclampf b) {
         MOZ_ASSERT(mIsGLES2);
 
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fDepthRangef);
         mSymbols.fDepthRangef(a, b);
         AFTER_GL_CALL;
     }
 
     void raw_fClearDepth(GLclampf v) {
         MOZ_ASSERT(!mIsGLES2);
 
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fClearDepth);
         mSymbols.fClearDepth(v);
         AFTER_GL_CALL;
     }
 
     void raw_fClearDepthf(GLclampf v) {
         MOZ_ASSERT(mIsGLES2);
 
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fClearDepthf);
         mSymbols.fClearDepthf(v);
         AFTER_GL_CALL;
     }
 
 public:
     void fDepthRange(GLclampf a, GLclampf b) {
         if (mIsGLES2) {
             raw_fDepthRangef(a, b);
@@ -2739,23 +2750,25 @@ public:
             raw_fClearDepthf(v);
         } else {
             raw_fClearDepth(v);
         }
     }
 
     void* fMapBuffer(GLenum target, GLenum access) {
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fMapBuffer);
         void *ret = mSymbols.fMapBuffer(target, access);
         AFTER_GL_CALL;
         return ret;
     }
 
     realGLboolean fUnmapBuffer(GLenum target) {
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fUnmapBuffer);
         realGLboolean ret = mSymbols.fUnmapBuffer(target);
         AFTER_GL_CALL;
         return ret;
     }
 
 
 private:
 #ifdef DEBUG
@@ -2911,75 +2924,87 @@ public:
 
     void fDeleteTextures(GLsizei n, GLuint *names) {
         raw_fDeleteTextures(n, names);
         TRACKING_CONTEXT(DeletedTextures(this, n, names));
     }
 
 
     GLenum GLAPIENTRY fGetGraphicsResetStatus() {
+        MOZ_ASSERT(mHasRobustness);
+
         BEFORE_GL_CALL;
-        GLenum ret = mHasRobustness ? mSymbols.fGetGraphicsResetStatus() : 0;
+        ASSERT_SYMBOL_PRESENT(fGetGraphicsResetStatus);
+        GLenum ret = mSymbols.fGetGraphicsResetStatus();
         AFTER_GL_CALL;
         return ret;
     }
 
     GLsync GLAPIENTRY fFenceSync(GLenum condition, GLbitfield flags) {
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fFenceSync);
         GLsync ret = mSymbols.fFenceSync(condition, flags);
         AFTER_GL_CALL;
         return ret;
     }
 
     realGLboolean GLAPIENTRY fIsSync(GLsync sync) {
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fIsSync);
         realGLboolean ret = mSymbols.fIsSync(sync);
         AFTER_GL_CALL;
         return ret;
     }
 
     void GLAPIENTRY fDeleteSync(GLsync sync) {
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fDeleteSync);
         mSymbols.fDeleteSync(sync);
         AFTER_GL_CALL;
     }
 
     GLenum GLAPIENTRY fClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fClientWaitSync);
         GLenum ret = mSymbols.fClientWaitSync(sync, flags, timeout);
         AFTER_GL_CALL;
         return ret;
     }
 
     void GLAPIENTRY fWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fWaitSync);
         mSymbols.fWaitSync(sync, flags, timeout);
         AFTER_GL_CALL;
     }
 
     void GLAPIENTRY fGetInteger64v(GLenum pname, GLint64 *params) {
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fGetInteger64v);
         mSymbols.fGetInteger64v(pname, params);
         AFTER_GL_CALL;
     }
 
     void GLAPIENTRY fGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fGetSynciv);
         mSymbols.fGetSynciv(sync, pname, bufSize, length, values);
         AFTER_GL_CALL;
     }
 
     // OES_EGL_image (GLES)
-    void fEGLImageTargetTexture2D(GLenum target, GLeglImage image)
-    {
+    void fEGLImageTargetTexture2D(GLenum target, GLeglImage image) {
         BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fEGLImageTargetTexture2D);
         mSymbols.fEGLImageTargetTexture2D(target, image);
         AFTER_GL_CALL;
     }
 
+#undef ASSERT_SYMBOL_PRESENT
+
 #ifdef DEBUG
     void THEBES_API CreatedProgram(GLContext *aOrigin, GLuint aName);
     void THEBES_API CreatedShader(GLContext *aOrigin, GLuint aName);
     void THEBES_API CreatedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
     void THEBES_API CreatedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
     void THEBES_API CreatedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
     void THEBES_API CreatedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
     void THEBES_API DeletedProgram(GLContext *aOrigin, GLuint aName);