diff options
author | Romain Guy <romainguy@google.com> | 2013-05-24 16:19:19 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2013-05-24 16:19:19 -0700 |
commit | a404e16e4933857464046d763ed7629cd0c86cbf (patch) | |
tree | fec5bfa47138b29d22b25b9d87dc84ebfea7f1e6 | |
parent | 64770d16b0907a8e1ee81ef6c8fa398a6bdbee79 (diff) | |
download | frameworks_base-a404e16e4933857464046d763ed7629cd0c86cbf.zip frameworks_base-a404e16e4933857464046d763ed7629cd0c86cbf.tar.gz frameworks_base-a404e16e4933857464046d763ed7629cd0c86cbf.tar.bz2 |
Make sure atlas antries can correctly filter/wrap textures
The virtual textures would each have their own values for wrapping
and filtering which could lead to conflict and/or extraneous GL
commands being issued.
Change-Id: I64cb59a03e598f46bf645bd1d30fccfa63a07431
-rw-r--r-- | libs/hwui/AssetAtlas.cpp | 60 | ||||
-rw-r--r-- | libs/hwui/AssetAtlas.h | 36 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 1 | ||||
-rw-r--r-- | libs/hwui/Texture.h | 10 |
5 files changed, 70 insertions, 39 deletions
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp index 4d2fc01..8511e7c 100644 --- a/libs/hwui/AssetAtlas.cpp +++ b/libs/hwui/AssetAtlas.cpp @@ -31,11 +31,12 @@ void AssetAtlas::init(sp<GraphicBuffer> buffer, int* map, int count) { } mImage = new Image(buffer); - mTexture = mImage->getTexture(); - if (mTexture) { - mWidth = buffer->getWidth(); - mHeight = buffer->getHeight(); + if (mImage->getTexture()) { + mTexture = new Texture(); + mTexture->id = mImage->getTexture(); + mTexture->width = buffer->getWidth(); + mTexture->height = buffer->getHeight(); createEntries(map, count); } else { @@ -43,6 +44,7 @@ void AssetAtlas::init(sp<GraphicBuffer> buffer, int* map, int count) { delete mImage; mImage = NULL; + mTexture = NULL; } } @@ -51,12 +53,13 @@ void AssetAtlas::terminate() { delete mImage; mImage = NULL; + delete mTexture; + mTexture = NULL; + for (size_t i = 0; i < mEntries.size(); i++) { delete mEntries.valueAt(i); } mEntries.clear(); - - mWidth = mHeight = 0; } } @@ -71,13 +74,36 @@ AssetAtlas::Entry* AssetAtlas::getEntry(SkBitmap* const bitmap) const { Texture* AssetAtlas::getEntryTexture(SkBitmap* const bitmap) const { ssize_t index = mEntries.indexOfKey(bitmap); - return index >= 0 ? &mEntries.valueAt(index)->texture : NULL; + return index >= 0 ? mEntries.valueAt(index)->texture : NULL; } /** + * Delegates changes to wrapping and filtering to the base atlas texture + * instead of applying the changes to the virtual textures. + */ +struct DelegateTexture: public Texture { + DelegateTexture(Texture* delegate): Texture(), mDelegate(delegate) { } + + virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false, + bool force = false, GLenum renderTarget = GL_TEXTURE_2D) { + mDelegate->setWrapST(wrapS, wrapT, bindTexture, force, renderTarget); + } + + virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false, + bool force = false, GLenum renderTarget = GL_TEXTURE_2D) { + mDelegate->setFilterMinMag(min, mag, bindTexture, force, renderTarget); + } +private: + Texture* const mDelegate; +}; // struct DelegateTexture + +/** * TODO: This method does not take the rotation flag into account */ void AssetAtlas::createEntries(int* map, int count) { + const float width = float(mTexture->width); + const float height = float(mTexture->height); + for (int i = 0; i < count; ) { SkBitmap* bitmap = (SkBitmap*) map[i++]; int x = map[i++]; @@ -88,15 +114,17 @@ void AssetAtlas::createEntries(int* map, int count) { if (!bitmap) continue; const UvMapper mapper( - x / (float) mWidth, (x + bitmap->width()) / (float) mWidth, - y / (float) mHeight, (y + bitmap->height()) / (float) mHeight); - - Entry* entry = new Entry(bitmap, x, y, rotated, mapper, *this); - entry->texture.id = mTexture; - entry->texture.blend = !bitmap->isOpaque(); - entry->texture.width = bitmap->width(); - entry->texture.height = bitmap->height(); - entry->texture.uvMapper = &entry->uvMapper; + x / width, (x + bitmap->width()) / width, + y / height, (y + bitmap->height()) / height); + + Texture* texture = new DelegateTexture(mTexture); + Entry* entry = new Entry(bitmap, x, y, rotated, texture, mapper, *this); + + texture->id = mTexture->id; + texture->blend = !bitmap->isOpaque(); + texture->width = bitmap->width(); + texture->height = bitmap->height(); + texture->uvMapper = &entry->uvMapper; mEntries.add(entry->bitmap, entry); } diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h index 0bbd2a7..793e300 100644 --- a/libs/hwui/AssetAtlas.h +++ b/libs/hwui/AssetAtlas.h @@ -64,6 +64,13 @@ public: */ bool rotated; + /* + * A "virtual texture" object that represents the texture + * this entry belongs to. This texture should never be + * modified. + */ + Texture* texture; + /** * Maps texture coordinates in the [0..1] range into the * correct range to sample this entry from the atlas. @@ -75,22 +82,20 @@ public: */ const AssetAtlas& atlas; - /* - * A "virtual texture" object that represents the texture - * this entry belongs to. This texture should never be - * modified. - */ - Texture texture; - private: Entry(SkBitmap* bitmap, int x, int y, bool rotated, - const UvMapper& mapper, const AssetAtlas& atlas): - bitmap(bitmap), x(x), y(y), rotated(rotated), uvMapper(mapper), atlas(atlas) { } + Texture* texture, const UvMapper& mapper, const AssetAtlas& atlas): + bitmap(bitmap), x(x), y(y), rotated(rotated), + texture(texture), uvMapper(mapper), atlas(atlas) { } + + ~Entry() { + delete texture; + } friend class AssetAtlas; }; - AssetAtlas(): mWidth(0), mHeight(0), mTexture(0), mImage(NULL) { } + AssetAtlas(): mTexture(NULL), mImage(NULL) { } ~AssetAtlas() { terminate(); } /** @@ -120,7 +125,7 @@ public: * Can return 0 if the atlas is not initialized. */ uint32_t getWidth() const { - return mWidth; + return mTexture ? mTexture->width : 0; } /** @@ -128,7 +133,7 @@ public: * Can return 0 if the atlas is not initialized. */ uint32_t getHeight() const { - return mHeight; + return mTexture ? mTexture->height : 0; } /** @@ -136,7 +141,7 @@ public: * Can return 0 if the atlas is not initialized. */ GLuint getTexture() const { - return mTexture; + return mTexture ? mTexture->id : 0; } /** @@ -154,10 +159,7 @@ public: private: void createEntries(int* map, int count); - uint32_t mWidth; - uint32_t mHeight; - - GLuint mTexture; + Texture* mTexture; Image* mImage; KeyedVector<SkBitmap*, Entry*> mEntries; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 2465b48..f12119a 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -2352,7 +2352,7 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, if (CC_LIKELY(mesh && mesh->verticesCount > 0)) { mCaches.activeTexture(0); - Texture* texture = entry ? &entry->texture : mCaches.textureCache.get(bitmap); + Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap); if (!texture) return DrawGlInfo::kStatusDone; const AutoTexture autoCleanup(texture); diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index d9ba93a..6286e94 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -1083,7 +1083,6 @@ private: // No-ops start/endTiling when set bool mSuppressTiling; - // If true, this renderer will setup drawing to emulate // an increment stencil buffer in the color buffer bool mCountOverdraw; diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h index dd39cae..f84cd67 100644 --- a/libs/hwui/Texture.h +++ b/libs/hwui/Texture.h @@ -48,13 +48,15 @@ struct Texture { uvMapper = NULL; } + virtual ~Texture() { } + void setWrap(GLenum wrap, bool bindTexture = false, bool force = false, GLenum renderTarget = GL_TEXTURE_2D) { setWrapST(wrap, wrap, bindTexture, force, renderTarget); } - void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false, - GLenum renderTarget = GL_TEXTURE_2D) { + virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false, + bool force = false, GLenum renderTarget = GL_TEXTURE_2D) { if (firstWrap || force || wrapS != this->wrapS || wrapT != this->wrapT) { firstWrap = false; @@ -76,8 +78,8 @@ struct Texture { setFilterMinMag(filter, filter, bindTexture, force, renderTarget); } - void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false, bool force = false, - GLenum renderTarget = GL_TEXTURE_2D) { + virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false, + bool force = false, GLenum renderTarget = GL_TEXTURE_2D) { if (firstFilter || force || min != minFilter || mag != magFilter) { firstFilter = false; |