diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index 88f03542d6b..c91fe3ea8c7 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -382,6 +382,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) } const char *glVendorString; + const char *glRendererString; if (mInitialized) { glVendorString = (const char *)fGetString(LOCAL_GL_VENDOR); @@ -393,11 +394,23 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) }; 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) { @@ -590,6 +603,15 @@ 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) @@ -688,7 +710,12 @@ 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(); @@ -851,7 +878,8 @@ 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 { @@ -2040,7 +2068,7 @@ GLContext::UploadSurfaceToTexture(gfxASurface *aSurface, 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, @@ -2091,6 +2119,10 @@ GLContext::TexImage2D(GLenum target, GLint level, GLint internalformat, 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, diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index 10fefe11ec5..0fa1da06e32 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -545,6 +545,7 @@ public: mHasRobustness(false), mContextLost(false), mVendor(-1), + mRenderer(-1), mDebugMode(0), mCreationFormat(aFormat), mSharedContext(aSharedContext), @@ -688,10 +689,21 @@ public: 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 @@ -767,6 +779,7 @@ protected: bool mFlushGuaranteesResolve; public: + void SetFlushGuaranteesResolve(bool aFlushGuaranteesResolve) { mFlushGuaranteesResolve = aFlushGuaranteesResolve; } @@ -1381,6 +1394,7 @@ protected: bool mContextLost; PRInt32 mVendor; + PRInt32 mRenderer; enum { DebugEnabled = 1 << 0, @@ -2683,23 +2697,23 @@ public: }; 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); + const char *occurrence = strstr(aString, aWantedString); - // aWantedVendor not found + // 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; diff --git a/gfx/gl/GLContextProviderGLX.cpp b/gfx/gl/GLContextProviderGLX.cpp index 38510a07470..2d6cf66108a 100644 --- a/gfx/gl/GLContextProviderGLX.cpp +++ b/gfx/gl/GLContextProviderGLX.cpp @@ -261,11 +261,11 @@ GLXLibrary::EnsureInitialized() 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;