diff options
| author | Romain Guy <romainguy@google.com> | 2013-06-11 16:19:24 -0700 |
|---|---|---|
| committer | Romain Guy <romainguy@google.com> | 2013-06-11 17:14:59 -0700 |
| commit | 4c2547fa9244e78115cde0a259291053108c3dc7 (patch) | |
| tree | 4337937e216918e4febe861daa7ef093b99aff03 /libs/hwui | |
| parent | fadd2081443dd2f59f8e8143256a34b7485fe72e (diff) | |
| download | frameworks_base-4c2547fa9244e78115cde0a259291053108c3dc7.zip frameworks_base-4c2547fa9244e78115cde0a259291053108c3dc7.tar.gz frameworks_base-4c2547fa9244e78115cde0a259291053108c3dc7.tar.bz2 | |
Avoid 9patch cache lookups when possible
This optimization saves up to 0.3ms per frame on the Play Store's
front page, on a Nexus 4 device.
Change-Id: Iaa4ef33c6e3b37e175efd5b9eea9ef59b43f14f3
Diffstat (limited to 'libs/hwui')
| -rw-r--r-- | libs/hwui/DisplayListOp.h | 19 | ||||
| -rw-r--r-- | libs/hwui/LayerRenderer.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/Matrix.h | 25 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 19 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.h | 2 | ||||
| -rw-r--r-- | libs/hwui/PatchCache.cpp | 17 | ||||
| -rw-r--r-- | libs/hwui/PatchCache.h | 9 | ||||
| -rw-r--r-- | libs/hwui/Program.cpp | 2 |
8 files changed, 71 insertions, 24 deletions
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 6839b18..028decd 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -932,13 +932,22 @@ public: DrawPatchOp(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode) : DrawBoundedOp(left, top, right, bottom, 0), - mBitmap(bitmap), mPatch(patch), mAlpha(alpha), mMode(mode) { + mBitmap(bitmap), mPatch(patch), mAlpha(alpha), mMode(mode), + mGenerationId(0), mMesh(NULL) { mEntry = Caches::getInstance().assetAtlas.getEntry(bitmap); }; virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { - // NOTE: not calling the virtual method, which takes a paint - return renderer.drawPatch(mBitmap, mPatch, mEntry, mLocalBounds.left, mLocalBounds.top, + if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) { + PatchCache& cache = renderer.getCaches().patchCache; + mMesh = cache.get(mEntry, mBitmap->width(), mBitmap->height(), + mLocalBounds.right - mLocalBounds.left, mLocalBounds.bottom - mLocalBounds.top, + mPatch); + mGenerationId = cache.getGenerationId(); + } + // We're not calling the public variant of drawPatch() here + // This method won't perform the quickReject() since we've already done it at this point + return renderer.drawPatch(mBitmap, mMesh, mEntry, mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom, mAlpha, mMode); } @@ -957,8 +966,12 @@ public: private: SkBitmap* mBitmap; Res_png_9patch* mPatch; + int mAlpha; SkXfermode::Mode mMode; + + uint32_t mGenerationId; + const Patch* mMesh; AssetAtlas::Entry* mEntry; }; diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 79e0b0c..cfb1e97 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -467,7 +467,7 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { mat4 texTransform(layer->getTexTransform()); mat4 invert; - invert.translate(0.0f, 1.0f, 0.0f); + invert.translate(0.0f, 1.0f); invert.scale(1.0f, -1.0f, 1.0f); layer->getTexTransform().multiply(invert); diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h index 75e280c..df744be 100644 --- a/libs/hwui/Matrix.h +++ b/libs/hwui/Matrix.h @@ -128,10 +128,27 @@ public: void multiply(float v); - void translate(float x, float y, float z) { - Matrix4 u; - u.loadTranslate(x, y, z); - multiply(u); + void translate(float x, float y) { + if ((getType() & sGeometryMask) == kTypeTranslate) { + data[kTranslateX] += x; + data[kTranslateY] += y; + } else { + // Doing a translation will only affect the translate bit of the type + // Save the type + uint32_t type = mType; + + Matrix4 u; + u.loadTranslate(x, y, 0.0f); + multiply(u); + + // Restore the type and fix the translate bit + mType = type; + if (data[kTranslateX] != 0.0f || data[kTranslateY] != 0.0f) { + mType |= kTypeTranslate; + } else { + mType &= ~kTypeTranslate; + } + } } void scale(float sx, float sy, float sz) { diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index f5343b1..d95a62c 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1407,7 +1407,7 @@ void OpenGLRenderer::setFullScreenClip() { /////////////////////////////////////////////////////////////////////////////// void OpenGLRenderer::translate(float dx, float dy) { - currentTransform().translate(dx, dy, 0.0f); + currentTransform().translate(dx, dy); } void OpenGLRenderer::rotate(float degrees) { @@ -2337,20 +2337,25 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); - return drawPatch(bitmap, patch, mCaches.assetAtlas.getEntry(bitmap), - left, top, right, bottom, alpha, mode); + if (quickReject(left, top, right, bottom)) { + return DrawGlInfo::kStatusDone; + } + + AssetAtlas::Entry* entry = mCaches.assetAtlas.getEntry(bitmap); + const Patch* mesh = mCaches.patchCache.get(entry, bitmap->width(), bitmap->height(), + right - left, bottom - top, patch); + + return drawPatch(bitmap, mesh, entry, left, top, right, bottom, alpha, mode); } -status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, +status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry, float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode) { + if (quickReject(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; } - const Patch* mesh = mCaches.patchCache.get(entry, bitmap->width(), bitmap->height(), - right - left, bottom - top, patch); - if (CC_LIKELY(mesh && mesh->verticesCount > 0)) { mCaches.activeTexture(0); Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap); diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index e9ea2f3..ce4ce42 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -266,7 +266,7 @@ public: float* vertices, int* colors, SkPaint* paint); virtual status_t drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top, float right, float bottom, SkPaint* paint); - status_t drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, AssetAtlas::Entry* entry, + status_t drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry, float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode); virtual status_t drawColor(int color, SkXfermode::Mode mode); virtual status_t drawRect(float left, float top, float right, float bottom, SkPaint* paint); diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp index c6ed275..c23e991 100644 --- a/libs/hwui/PatchCache.cpp +++ b/libs/hwui/PatchCache.cpp @@ -30,7 +30,9 @@ namespace uirenderer { // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// -PatchCache::PatchCache(): mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity) { +PatchCache::PatchCache(): + mSize(0), mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity), + mMeshBuffer(0), mGenerationId(0) { char property[PROPERTY_VALUE_MAX]; if (property_get(PROPERTY_PATCH_CACHE_SIZE, property, NULL) > 0) { INIT_LOGD(" Setting patch cache size to %skB", property); @@ -39,8 +41,6 @@ PatchCache::PatchCache(): mCache(LruCache<PatchDescription, Patch*>::kUnlimitedC INIT_LOGD(" Using default patch cache size of %.2fkB", DEFAULT_PATCH_CACHE_SIZE); mMaxSize = KB(DEFAULT_PATCH_CACHE_SIZE); } - mSize = 0; - mMeshBuffer = 0; } PatchCache::~PatchCache() { @@ -58,7 +58,7 @@ void PatchCache::init(Caches& caches) { caches.resetVertexPointers(); if (created) { - glBufferData(GL_ARRAY_BUFFER, mMaxSize, NULL, GL_DYNAMIC_DRAW); + createVertexBuffer(); } } @@ -99,6 +99,12 @@ void PatchCache::clearCache() { mCache.clear(); } +void PatchCache::createVertexBuffer() { + glBufferData(GL_ARRAY_BUFFER, mMaxSize, NULL, GL_DYNAMIC_DRAW); + mSize = 0; + mGenerationId++; +} + const Patch* PatchCache::get(const AssetAtlas::Entry* entry, const uint32_t bitmapWidth, const uint32_t bitmapHeight, const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch) { @@ -127,8 +133,7 @@ const Patch* PatchCache::get(const AssetAtlas::Entry* entry, uint32_t size = newMesh->getSize(); if (mSize + size > mMaxSize) { clearCache(); - glBufferData(GL_ARRAY_BUFFER, mMaxSize, NULL, GL_DYNAMIC_DRAW); - mSize = 0; + createVertexBuffer(); } newMesh->offset = (GLintptr) mSize; diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h index 530dad0..1829b89 100644 --- a/libs/hwui/PatchCache.h +++ b/libs/hwui/PatchCache.h @@ -70,8 +70,13 @@ public: return mMeshBuffer; } + uint32_t getGenerationId() const { + return mGenerationId; + } + private: void clearCache(); + void createVertexBuffer(); struct PatchDescription { PatchDescription(): mPatch(NULL), mBitmapWidth(0), mBitmapHeight(0), @@ -122,9 +127,11 @@ private: uint32_t mMaxSize; uint32_t mSize; + LruCache<PatchDescription, Patch*> mCache; + GLuint mMeshBuffer; - LruCache<PatchDescription, Patch*> mCache; + uint32_t mGenerationId; }; // class PatchCache }; // namespace uirenderer diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp index c127d68..9e4670e 100644 --- a/libs/hwui/Program.cpp +++ b/libs/hwui/Program.cpp @@ -172,7 +172,7 @@ void Program::set(const mat4& projectionMatrix, const mat4& modelViewMatrix, // up and to the left. // This offset value is based on an assumption that some hardware may use as // little as 12.4 precision, so we offset by slightly more than 1/16. - p.translate(.065, .065, 0); + p.translate(.065, .065); glUniformMatrix4fv(projection, 1, GL_FALSE, &p.data[0]); } mProjection = projectionMatrix; |
