From 8aa195d7081b889f3a7b1f426cbd8556377aae5e Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Tue, 4 Jun 2013 18:00:09 -0700 Subject: Introduce Caches::bindTexture() to reduce glBindTexture calls Change-Id: Ic345422567c020c0a9035ff51dcf2ae2a1fc59f4 --- libs/hwui/TextDropShadowCache.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'libs/hwui/TextDropShadowCache.cpp') diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp index 6976eaa3d70e..3b6cb91086f2 100644 --- a/libs/hwui/TextDropShadowCache.cpp +++ b/libs/hwui/TextDropShadowCache.cpp @@ -18,6 +18,7 @@ #include +#include "Caches.h" #include "Debug.h" #include "TextDropShadowCache.h" #include "Properties.h" @@ -182,7 +183,9 @@ ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32 return NULL; } - texture = new ShadowTexture; + Caches& caches = Caches::getInstance(); + + texture = new ShadowTexture(caches); texture->left = shadow.penX; texture->top = shadow.penY; texture->width = shadow.width; @@ -202,7 +205,7 @@ ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32 glGenTextures(1, &texture->id); - glBindTexture(GL_TEXTURE_2D, texture->id); + caches.bindTexture(texture->id); // Textures are Alpha8 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); -- cgit v1.2.3-59-g8ed1b From be1b127c7bec252e0c6ab0e06ed6babed07d496f Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Thu, 6 Jun 2013 14:02:54 -0700 Subject: Assume a texture is unbound after deleting it Bug #9316260 The GL specification indicates that deleting a bound texture has the side effect of binding the default texture (name=0). This change replaces all calls to glDeleteTextures() by Caches::deleteTexture() to properly keep track of texture bindings. Change-Id: Ifbc60ef433e0f9776a668dd5bd5f0adbc65a77a0 --- libs/hwui/Caches.cpp | 22 ++++++++++++++++++++++ libs/hwui/Caches.h | 13 ++++++++++++- libs/hwui/Dither.cpp | 2 +- libs/hwui/GradientCache.cpp | 2 +- libs/hwui/Image.cpp | 2 +- libs/hwui/Layer.cpp | 2 +- libs/hwui/LayerRenderer.cpp | 2 +- libs/hwui/PathCache.cpp | 2 +- libs/hwui/TextDropShadowCache.cpp | 2 +- libs/hwui/Texture.cpp | 4 ++++ libs/hwui/Texture.h | 7 ++++++- libs/hwui/TextureCache.cpp | 2 +- libs/hwui/font/CacheTexture.cpp | 2 +- 13 files changed, 53 insertions(+), 11 deletions(-) (limited to 'libs/hwui/TextDropShadowCache.cpp') diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 23b5d76e4e7d..74aeddba1e7d 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -508,6 +508,28 @@ void Caches::bindTexture(GLenum target, GLuint texture) { } } +void Caches::deleteTexture(GLuint texture) { + // When glDeleteTextures() is called on a currently bound texture, + // OpenGL ES specifies that the texture is then considered unbound + // Consider the following series of calls: + // + // glGenTextures -> creates texture name 2 + // glBindTexture(2) + // glDeleteTextures(2) -> 2 is now unbound + // glGenTextures -> can return 2 again + // + // If we don't call glBindTexture(2) after the second glGenTextures + // call, any texture operation will be performed on the default + // texture (name=0) + + for (int i = 0; i < REQUIRED_TEXTURE_UNITS_COUNT; i++) { + if (mBoundTextures[i] == texture) { + mBoundTextures[i] = 0; + } + } + glDeleteTextures(1, &texture); +} + void Caches::resetBoundTextures() { memset(mBoundTextures, 0, REQUIRED_TEXTURE_UNITS_COUNT * sizeof(GLuint)); } diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index bd31ec390722..bdde8fbf4b6f 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -226,14 +226,25 @@ public: /** * Binds the specified texture as a GL_TEXTURE_2D texture. + * All texture bindings must be performed with this method or + * bindTexture(GLenum, GLuint). */ void bindTexture(GLuint texture); /** - * Binds the specified texture.. + * Binds the specified texture with the specified render target. + * All texture bindings must be performed with this method or + * bindTexture(GLuint). */ void bindTexture(GLenum target, GLuint texture); + /** + * Deletes the specified texture and clears it from the cache + * of bound textures. + * All textures must be deleted using this method. + */ + void deleteTexture(GLuint texture); + /** * Signals that the cache of bound textures should be cleared. * Other users of the context may have altered which textures are bound. diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp index 4dc85e068133..649a7bc5d0b6 100644 --- a/libs/hwui/Dither.cpp +++ b/libs/hwui/Dither.cpp @@ -77,7 +77,7 @@ void Dither::bindDitherTexture() { void Dither::clear() { if (mInitialized) { - glDeleteTextures(1, &mDitherTexture); + mCaches->deleteTexture(mDitherTexture); mInitialized = false; } } diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp index 1ed04faec94f..1815bffcc3fb 100644 --- a/libs/hwui/GradientCache.cpp +++ b/libs/hwui/GradientCache.cpp @@ -120,7 +120,7 @@ void GradientCache::operator()(GradientCacheEntry& shader, Texture*& texture) { const uint32_t size = texture->width * texture->height * bytesPerPixel(); mSize -= size; - glDeleteTextures(1, &texture->id); + texture->deleteTexture(); delete texture; } } diff --git a/libs/hwui/Image.cpp b/libs/hwui/Image.cpp index 77c23001f5b3..edf3930856ea 100644 --- a/libs/hwui/Image.cpp +++ b/libs/hwui/Image.cpp @@ -54,7 +54,7 @@ Image::~Image() { eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), mImage); mImage = EGL_NO_IMAGE_KHR; - glDeleteTextures(1, &mTexture); + Caches::getInstance().deleteTexture(mTexture); mTexture = 0; } } diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index 60c38bab7e50..134f452aa4d1 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -167,7 +167,7 @@ void Layer::generateTexture() { void Layer::deleteTexture() { if (texture.id) { - glDeleteTextures(1, &texture.id); + texture.deleteTexture(); texture.id = 0; } } diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 987daae46c34..79e0b0cee8cb 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -498,7 +498,7 @@ error: glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); layer->setAlpha(alpha, mode); layer->setFbo(previousLayerFbo); - glDeleteTextures(1, &texture); + caches.deleteTexture(texture); caches.fboCache.put(fbo); glViewport(previousViewport[0], previousViewport[1], previousViewport[2], previousViewport[3]); diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index 3f6485cbf718..3ab40dae9c6f 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -223,7 +223,7 @@ void PathCache::removeTexture(PathTexture* texture) { } if (texture->id) { - glDeleteTextures(1, &texture->id); + Caches::getInstance().deleteTexture(texture->id); } delete texture; } diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp index 3b6cb91086f2..0b2c130c738f 100644 --- a/libs/hwui/TextDropShadowCache.cpp +++ b/libs/hwui/TextDropShadowCache.cpp @@ -155,7 +155,7 @@ void TextDropShadowCache::operator()(ShadowText& text, ShadowTexture*& texture) ALOGD("Shadow texture deleted, size = %d", texture->bitmapSize); } - glDeleteTextures(1, &texture->id); + texture->deleteTexture(); delete texture; } } diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp index e06227cad76b..7923ce794e0f 100644 --- a/libs/hwui/Texture.cpp +++ b/libs/hwui/Texture.cpp @@ -76,5 +76,9 @@ void Texture::setFilterMinMag(GLenum min, GLenum mag, bool bindTexture, bool for } } +void Texture::deleteTexture() const { + mCaches.deleteTexture(id); +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h index d249741f703b..d48ec5924d62 100644 --- a/libs/hwui/Texture.h +++ b/libs/hwui/Texture.h @@ -51,6 +51,11 @@ public: virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false, bool force = false, GLenum renderTarget = GL_TEXTURE_2D); + /** + * Convenience method to call glDeleteTextures() on this texture's id. + */ + void deleteTexture() const; + /** * Name of the texture. */ @@ -113,7 +118,7 @@ public: AutoTexture(const Texture* texture): mTexture(texture) { } ~AutoTexture() { if (mTexture && mTexture->cleanup) { - glDeleteTextures(1, &mTexture->id); + mTexture->deleteTexture(); delete mTexture; } } diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index 7f5b80f1c081..a63cac663515 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -112,7 +112,7 @@ void TextureCache::operator()(SkBitmap*& bitmap, Texture*& texture) { if (mDebugEnabled) { ALOGD("Texture deleted, size = %d", texture->bitmapSize); } - glDeleteTextures(1, &texture->id); + texture->deleteTexture(); delete texture; } } diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp index 2d583388345c..5f157248bf71 100644 --- a/libs/hwui/font/CacheTexture.cpp +++ b/libs/hwui/font/CacheTexture.cpp @@ -156,7 +156,7 @@ void CacheTexture::releaseTexture() { mTexture = NULL; } if (mTextureId) { - glDeleteTextures(1, &mTextureId); + mCaches.deleteTexture(mTextureId); mTextureId = 0; } mDirty = false; -- cgit v1.2.3-59-g8ed1b