Bug 737182 - limit max texture size on Mac Intel driver - r=bgirard, a=akeybl
authorBenoit Jacob <bjacob@mozilla.com>
Mon, 26 Mar 2012 12:15:53 -0400
changeset 91991 3674e711982a5e249ae79cf36812ab556c252f0b
parent 91990 3ae20fbe49e65484912c5b0988173738af10d114
child 91992 b5ac0b5020792998f19fa1e3f0021c725bfaf1fd
push idunknown
push userunknown
push dateunknown
reviewersbgirard, akeybl
bugs737182
milestone13.0a2
Bug 737182 - limit max texture size on Mac Intel driver - r=bgirard, a=akeybl
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -510,17 +510,29 @@ GLContext::InitWithPrefix(const char *pr
 
         fGetIntegerv(LOCAL_GL_SCISSOR_BOX, v);
         mScissorStack.AppendElement(nsIntRect(v[0], v[1], v[2], v[3]));
 
         fGetIntegerv(LOCAL_GL_VIEWPORT, v);
         mViewportStack.AppendElement(nsIntRect(v[0], v[1], v[2], v[3]));
 
         fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+        fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
         fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
+
+#ifdef XP_MACOSX
+        if (mVendor == VendorIntel) {
+            // see bug 737182 for 2D textures, bug 684822 for cube map textures.
+            mMaxTextureSize        = NS_MIN(mMaxTextureSize,        4096);
+            mMaxCubeMapTextureSize = NS_MIN(mMaxCubeMapTextureSize, 512);
+            // for good measure, we align renderbuffers on what we do for 2D textures
+            mMaxRenderbufferSize   = NS_MIN(mMaxRenderbufferSize,   4096);
+        }
+#endif
+
         mMaxTextureImageSize = mMaxTextureSize;
 
         UpdateActualFormat();
     }
 
 #ifdef DEBUG
     if (PR_GetEnv("MOZ_GL_DEBUG"))
         sDebugMode |= DebugEnabled;
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -568,17 +568,21 @@ public:
         mOffscreenTexture(0),
         mFlipped(false),
         mBlitProgram(0),
         mBlitFramebuffer(0),
         mOffscreenDrawFBO(0),
         mOffscreenReadFBO(0),
         mOffscreenColorRB(0),
         mOffscreenDepthRB(0),
-        mOffscreenStencilRB(0)
+        mOffscreenStencilRB(0),
+        mMaxTextureSize(0),
+        mMaxCubeMapTextureSize(0),
+        mMaxTextureImageSize(0),
+        mMaxRenderbufferSize(0)
 #ifdef DEBUG
         , mGLError(LOCAL_GL_NO_ERROR)
 #endif
     {
         mUserData.Init();
     }
 
     virtual ~GLContext() {
@@ -1684,19 +1688,38 @@ protected:
         return biggerDimension <= maxAllowed;
     }
 
 protected:
     nsTArray<nsIntRect> mViewportStack;
     nsTArray<nsIntRect> mScissorStack;
 
     GLint mMaxTextureSize;
+    GLint mMaxCubeMapTextureSize;
     GLint mMaxTextureImageSize;
     GLint mMaxRenderbufferSize;
 
+    bool IsTextureSizeSafeToPassToDriver(GLenum target, GLsizei width, GLsizei height) const {
+#ifdef XP_MACOSX
+        if (mVendor == VendorIntel) {
+            // see bug 737182 for 2D textures, bug 684822 for cube map textures.
+            // some drivers handle incorrectly some large texture sizes that are below the
+            // max texture size that they report. So we check ourselves against our own values
+            // (mMax[CubeMap]TextureSize).
+            GLsizei maxSize = target == LOCAL_GL_TEXTURE_CUBE_MAP ||
+                                (target >= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
+                                target <= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
+                              ? mMaxCubeMapTextureSize
+                              : mMaxTextureSize;
+            return width <= maxSize && height <= maxSize;
+        }
+#endif
+        return true;
+    }
+
 public:
  
     /** \returns the first GL error, and guarantees that all GL error flags are cleared,
       * i.e. that a subsequent GetError call will return NO_ERROR
       */
     GLenum GetAndClearError() {
         // the first error is what we want to return
         GLenum error = fGetError();
@@ -2389,17 +2412,23 @@ public:
     void fStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {
         BEFORE_GL_CALL;
         mSymbols.fStencilOpSeparate(face, sfail, dpfail, dppass);
         AFTER_GL_CALL;
     }
 
     void fTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {
         BEFORE_GL_CALL;
-        mSymbols.fTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
+        if (IsTextureSizeSafeToPassToDriver(target, width, height)) {
+          mSymbols.fTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
+        } else {
+          // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
+          // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
+          mSymbols.fTexImage2D(target, -1, internalformat, -1, -1, -1, format, type, nsnull);
+        }
         AFTER_GL_CALL;
     }
 
     void fTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) {
         BEFORE_GL_CALL;
         mSymbols.fTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
         AFTER_GL_CALL;
     }
@@ -2587,19 +2616,29 @@ public:
     void fCompileShader(GLuint shader) {
         BEFORE_GL_CALL;
         mSymbols.fCompileShader(shader);
         AFTER_GL_CALL;
     }
 
     void raw_fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
         BEFORE_GL_CALL;
-        mSymbols.fCopyTexImage2D(target, level, internalformat, 
-                                 x, FixYValue(y, height),
-                                 width, height, border);
+        if (IsTextureSizeSafeToPassToDriver(target, width, height)) {
+          mSymbols.fCopyTexImage2D(target, level, internalformat, 
+                                   x, FixYValue(y, height),
+                                   width, height, border);
+
+        } else {
+          // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
+          // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
+          mSymbols.fCopyTexImage2D(target, -1, internalformat, 
+                                   x, FixYValue(y, height),
+                                   -1, -1, -1);
+
+        }
         AFTER_GL_CALL;
     }
 
     void raw_fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
         BEFORE_GL_CALL;
         mSymbols.fCopyTexSubImage2D(target, level, xoffset, yoffset, 
                                     x, FixYValue(y, height),
                                     width, height);