Bug 721467 - Add a codepath to only use glTexImage2D instead of glTexSubImage2D when texture uploading in GLContext
authorGeorge Wright <gwright@mozilla.com>
Mon, 30 Jan 2012 15:09:02 -0500
changeset 92380 f042470aaafc1677161d98d19a94dc72b41849db
parent 92379 d47c32d6795d85dcfa04bd74eea8b4017f94bb22
child 92381 0b940c84521d36d1a4303293d32b029edc8591db
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs721467
milestone12.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 721467 - Add a codepath to only use glTexImage2D instead of glTexSubImage2D when texture uploading in GLContext
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextProviderGLX.cpp
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -377,32 +377,45 @@ GLContext::InitWithPrefix(const char *pr
             if (!LoadSymbols(&symbols_desktop[0], trygl, prefix)) {
                 NS_RUNTIMEABORT("Desktop symbols failed to load.");
                 mInitialized = false;
             }
         }
     }
 
     const char *glVendorString;
+    const char *glRendererString;
 
     if (mInitialized) {
         glVendorString = (const char *)fGetString(LOCAL_GL_VENDOR);
         const char *vendorMatchStrings[VendorOther] = {
                 "Intel",
                 "NVIDIA",
                 "ATI",
                 "Qualcomm"
         };
         mVendor = VendorOther;
         for (int i = 0; i < VendorOther; ++i) {
-            if (DoesVendorStringMatch(glVendorString, vendorMatchStrings[i])) {
+            if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) {
                 mVendor = i;
                 break;
             }
         }
+
+        glRendererString = (const char *)fGetString(LOCAL_GL_RENDERER);
+        const char *rendererMatchStrings[RendererOther] = {
+                "Adreno 200"
+        };
+        mRenderer = RendererOther;
+        for (int i = 0; i < RendererOther; ++i) {
+            if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) {
+                mRenderer = i;
+                break;
+            }
+        }
     }
 
     if (mInitialized) {
 #ifdef DEBUG
         static bool once = false;
         if (!once) {
             const char *vendors[VendorOther] = {
                 "Intel",
@@ -585,16 +598,25 @@ GLContext::InitExtensions()
 }
 
 bool
 GLContext::IsExtensionSupported(const char *extension)
 {
     return ListHasExtension(fGetString(LOCAL_GL_EXTENSIONS), extension);
 }
 
+bool
+GLContext::CanUploadSubTextures()
+{
+    // There are certain GPUs that we don't want to use glTexSubImage2D on
+    // because that function can be very slow and/or buggy
+
+    return !(Renderer() == RendererAdreno200);
+}
+
 // Common code for checking for both GL extensions and GLX extensions.
 bool
 GLContext::ListHasExtension(const GLubyte *extensions, const char *extension)
 {
     // fix bug 612572 - we were crashing as we were calling this function with extensions==null
     if (extensions == nsnull || extension == nsnull)
         return false;
 
@@ -683,17 +705,22 @@ BasicTextureImage::~BasicTextureImage()
 }
 
 gfxASurface*
 BasicTextureImage::BeginUpdate(nsIntRegion& aRegion)
 {
     NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
 
     // determine the region the client will need to repaint
-    GetUpdateRegion(aRegion);
+    if (mGLContext->CanUploadSubTextures()) {
+        GetUpdateRegion(aRegion);
+    } else {
+        aRegion = nsIntRect(nsIntPoint(0, 0), mSize);
+    }
+
     mUpdateRegion = aRegion;
 
     nsIntRect rgnSize = mUpdateRegion.GetBounds();
     if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(rgnSize)) {
         NS_ERROR("update outside of image");
         return NULL;
     }
 
@@ -846,17 +873,18 @@ TiledTextureImage::TiledTextureImage(GLC
 TiledTextureImage::~TiledTextureImage()
 {
 }
 
 bool 
 TiledTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
 {
     nsIntRegion region;
-    if (mTextureState != Valid) {
+
+    if (mTextureState != Valid || !mGL->CanUploadSubTextures()) {
         nsIntRect bounds = nsIntRect(0, 0, mSize.width, mSize.height);
         region = nsIntRegion(bounds);
     } else {
         region = aRegion;
     }
 
     bool result = true;
     for (unsigned i = 0; i < mImages.Length(); i++) {
@@ -2044,17 +2072,17 @@ GLContext::UploadSurfaceToTexture(gfxASu
         // bounding rectangle. We need to find the offset of this rect
         // within the region and adjust the data pointer accordingly.
         unsigned char *rectData = 
             data + DataOffset(imageSurface, iterRect->TopLeft() - topLeft);
 
         NS_ASSERTION(textureInited || (iterRect->x == 0 && iterRect->y == 0), 
                      "Must be uploading to the origin when we don't have an existing texture");
 
-        if (textureInited) {
+        if (textureInited && CanUploadSubTextures()) {
             TexSubImage2D(LOCAL_GL_TEXTURE_2D,
                           0,
                           iterRect->x,
                           iterRect->y,
                           iterRect->width,
                           iterRect->height,
                           stride,
                           pixelSize,
@@ -2095,16 +2123,20 @@ static GLint GetAddressAlignment(ptrdiff
 
 void
 GLContext::TexImage2D(GLenum target, GLint level, GLint internalformat, 
                       GLsizei width, GLsizei height, GLsizei stride,
                       GLint pixelsize, GLint border, GLenum format, 
                       GLenum type, const GLvoid *pixels)
 {
 #ifdef USE_GLES2
+
+    NS_ASSERTION(format == internalformat,
+                 "format and internalformat not the same for glTexImage2D on GLES2");
+
     // Use GLES-specific workarounds for GL_UNPACK_ROW_LENGTH; these are
     // implemented in TexSubImage2D.
     fTexImage2D(target,
                 border,
                 internalformat,
                 width,
                 height,
                 border,
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -540,16 +540,17 @@ public:
         mIsGLES2(true),
 #else
         mIsGLES2(false),
 #endif
         mIsGlobalSharedContext(false),
         mHasRobustness(false),
         mContextLost(false),
         mVendor(-1),
+        mRenderer(-1),
         mDebugMode(0),
         mCreationFormat(aFormat),
         mSharedContext(aSharedContext),
         mOffscreenTexture(0),
         mFlipped(false),
         mBlitProgram(0),
         mBlitFramebuffer(0),
         mOffscreenDrawFBO(0),
@@ -683,20 +684,31 @@ public:
     enum {
         VendorIntel,
         VendorNVIDIA,
         VendorATI,
         VendorQualcomm,
         VendorOther
     };
 
+    enum {
+        RendererAdreno200,
+        RendererOther
+    };
+
     int Vendor() const {
         return mVendor;
     }
 
+    int Renderer() const {
+        return mRenderer;
+    }
+
+    bool CanUploadSubTextures();
+
     /**
      * If this context wraps a double-buffered target, swap the back
      * and front buffers.  It should be assumed that after a swap, the
      * contents of the new back buffer are undefined.
      */
     virtual bool SwapBuffers() { return false; }
 
     /**
@@ -762,16 +774,17 @@ public:
     bool IsOffscreen() {
         return mIsOffscreen;
     }
 
 protected:
     bool mFlushGuaranteesResolve;
 
 public:
+
     void SetFlushGuaranteesResolve(bool aFlushGuaranteesResolve) {
         mFlushGuaranteesResolve = aFlushGuaranteesResolve;
     }
     
     // Before reads from offscreen texture
     void GuaranteeResolve() {
         if (mFlushGuaranteesResolve) {
             BlitDirtyFBOs();
@@ -1376,16 +1389,17 @@ protected:
     bool mInitialized;
     bool mIsOffscreen;
     bool mIsGLES2;
     bool mIsGlobalSharedContext;
     bool mHasRobustness;
     bool mContextLost;
 
     PRInt32 mVendor;
+    PRInt32 mRenderer;
 
     enum {
         DebugEnabled = 1 << 0,
         DebugTrace = 1 << 1,
         DebugAbortOnError = 1 << 2
     };
 
     PRUint32 mDebugMode;
@@ -2678,33 +2692,33 @@ public:
     nsTArray<NamedResource> mTrackedFramebuffers;
     nsTArray<NamedResource> mTrackedRenderbuffers;
     nsTArray<NamedResource> mTrackedBuffers;
 #endif
 
 };
 
 inline bool
-DoesVendorStringMatch(const char* aVendorString, const char *aWantedVendor)
+DoesStringMatch(const char* aString, const char *aWantedString)
 {
-    if (!aVendorString || !aWantedVendor)
+    if (!aString || !aWantedString)
         return false;
 
-    const char *occurrence = strstr(aVendorString, aWantedVendor);
-
-    // aWantedVendor not found
+    const char *occurrence = strstr(aString, aWantedString);
+
+    // aWanted not found
     if (!occurrence)
         return false;
 
-    // aWantedVendor preceded by alpha character
-    if (occurrence != aVendorString && isalpha(*(occurrence-1)))
+    // aWantedString preceded by alpha character
+    if (occurrence != aString && isalpha(*(occurrence-1)))
         return false;
 
     // aWantedVendor followed by alpha character
-    const char *afterOccurrence = occurrence + strlen(aWantedVendor);
+    const char *afterOccurrence = occurrence + strlen(aWantedString);
     if (isalpha(*afterOccurrence))
         return false;
 
     return true;
 }
 
 } /* namespace gl */
 } /* namespace mozilla */
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -256,21 +256,21 @@ GLXLibrary::EnsureInitialized()
         NS_WARNING("Texture from pixmap disabled");
     }
 
     if (HasExtension(extensionsStr, "GLX_ARB_create_context_robustness") &&
         LibrarySymbolLoader::LoadSymbols(mOGLLibrary, symbols_robustness)) {
         mHasRobustness = true;
     }
 
-    gIsATI = serverVendor && DoesVendorStringMatch(serverVendor, "ATI");
+    gIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI");
     gIsChromium = (serverVendor &&
-                   DoesVendorStringMatch(serverVendor, "Chromium")) ||
+                   DoesStringMatch(serverVendor, "Chromium")) ||
         (serverVersionStr &&
-         DoesVendorStringMatch(serverVersionStr, "Chromium"));
+         DoesStringMatch(serverVersionStr, "Chromium"));
 
     mInitialized = true;
     return true;
 }
 
 bool
 GLXLibrary::SupportsTextureFromPixmap(gfxASurface* aSurface)
 {