diff options
author | Romain Guy <romainguy@google.com> | 2011-11-04 15:12:29 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2011-11-04 16:23:47 -0700 |
commit | eca0ca2424afc1e98912405906edfc32f7733e16 (patch) | |
tree | 9f49527f35d77b0de3ee49f76e1b7bc99fac3ac6 /libs | |
parent | 650ee281ae9e007ce82ea79ff18bab9ef49503de (diff) | |
download | frameworks_base-eca0ca2424afc1e98912405906edfc32f7733e16.zip frameworks_base-eca0ca2424afc1e98912405906edfc32f7733e16.tar.gz frameworks_base-eca0ca2424afc1e98912405906edfc32f7733e16.tar.bz2 |
Memory optimizations for libhwui
Bug #5566149
Lazily initialize font renderers
Keep 60% of the texture cache when an app goes to the background
Delete least used font renderer when going to the background
Delete all font renderers on full memory trim
Change-Id: I3c2454d46dc1107ec0f0f72a9ce69cbbcc8825e7
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/Caches.cpp | 3 | ||||
-rw-r--r-- | libs/hwui/GammaFontRenderer.cpp | 63 | ||||
-rw-r--r-- | libs/hwui/GammaFontRenderer.h | 39 | ||||
-rw-r--r-- | libs/hwui/Properties.h | 5 | ||||
-rw-r--r-- | libs/hwui/TextureCache.cpp | 31 | ||||
-rw-r--r-- | libs/hwui/TextureCache.h | 13 |
6 files changed, 127 insertions, 27 deletions
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 24ec4e8..75b07de 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -170,8 +170,11 @@ void Caches::flush(FlushMode mode) { patchCache.clear(); dropShadowCache.clear(); gradientCache.clear(); + fontRenderer.clear(); // fall through case kFlushMode_Moderate: + fontRenderer.flush(); + textureCache.flush(); pathCache.clear(); roundRectShapeCache.clear(); circleShapeCache.clear(); diff --git a/libs/hwui/GammaFontRenderer.cpp b/libs/hwui/GammaFontRenderer.cpp index e8362dc..eb863e9 100644 --- a/libs/hwui/GammaFontRenderer.cpp +++ b/libs/hwui/GammaFontRenderer.cpp @@ -67,20 +67,63 @@ GammaFontRenderer::GammaFontRenderer() { const float whiteGamma = 1.0f / gamma; for (uint32_t i = 0; i <= 255; i++) { - mDefault[i] = i; + mGammaTable[i] = i; const float v = i / 255.0f; const float black = pow(v, blackGamma); const float white = pow(v, whiteGamma); - mBlackGamma[i] = uint8_t((float)::floor(black * 255.0f + 0.5f)); - mWhiteGamma[i] = uint8_t((float)::floor(white * 255.0f + 0.5f)); + mGammaTable[256 + i] = uint8_t((float)::floor(black * 255.0f + 0.5f)); + mGammaTable[512 + i] = uint8_t((float)::floor(white * 255.0f + 0.5f)); } - // Configure the font renderers - mDefaultRenderer.setGammaTable(&mDefault[0]); - mBlackGammaRenderer.setGammaTable(&mBlackGamma[0]); - mWhiteGammaRenderer.setGammaTable(&mWhiteGamma[0]); + memset(mRenderers, 0, sizeof(FontRenderer*) * kGammaCount); + memset(mRenderersUsageCount, 0, sizeof(uint32_t) * kGammaCount); +} + +GammaFontRenderer::~GammaFontRenderer() { + for (int i = 0; i < kGammaCount; i++) { + delete mRenderers[i]; + } +} + +void GammaFontRenderer::clear() { + for (int i = 0; i < kGammaCount; i++) { + delete mRenderers[i]; + mRenderers[i] = NULL; + } +} + +void GammaFontRenderer::flush() { + int count = 0; + int min = -1; + uint32_t minCount = UINT_MAX; + + for (int i = 0; i < kGammaCount; i++) { + if (mRenderers[i]) { + count++; + if (mRenderersUsageCount[i] < minCount) { + minCount = mRenderersUsageCount[i]; + min = i; + } + } + } + + if (count <= 1 || min < 0) return; + + delete mRenderers[min]; + mRenderers[min] = NULL; +} + +FontRenderer* GammaFontRenderer::getRenderer(Gamma gamma) { + FontRenderer* renderer = mRenderers[gamma]; + if (!renderer) { + renderer = new FontRenderer(); + mRenderers[gamma] = renderer; + renderer->setGammaTable(&mGammaTable[gamma * 256]); + } + mRenderersUsageCount[gamma]++; + return renderer; } FontRenderer& GammaFontRenderer::getFontRenderer(const SkPaint* paint) { @@ -92,12 +135,12 @@ FontRenderer& GammaFontRenderer::getFontRenderer(const SkPaint* paint) { const int luminance = (r * 2 + g * 5 + b) >> 3; if (luminance <= mBlackThreshold) { - return mBlackGammaRenderer; + return *getRenderer(kGammaBlack); } else if (luminance >= mWhiteThreshold) { - return mWhiteGammaRenderer; + return *getRenderer(kGammaWhite); } } - return mDefaultRenderer; + return *getRenderer(kGammaDefault); } }; // namespace uirenderer diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h index 96d960c..54c208e 100644 --- a/libs/hwui/GammaFontRenderer.h +++ b/libs/hwui/GammaFontRenderer.h @@ -26,36 +26,43 @@ namespace uirenderer { struct GammaFontRenderer { GammaFontRenderer(); + ~GammaFontRenderer(); + + enum Gamma { + kGammaDefault = 0, + kGammaBlack = 1, + kGammaWhite = 2, + kGammaCount = 3 + }; + + void clear(); + void flush(); FontRenderer& getFontRenderer(const SkPaint* paint); uint32_t getFontRendererCount() const { - return 3; + return kGammaCount; } uint32_t getFontRendererSize(uint32_t fontRenderer) const { - switch (fontRenderer) { - case 0: - return mDefaultRenderer.getCacheHeight() * mDefaultRenderer.getCacheWidth(); - case 1: - return mBlackGammaRenderer.getCacheHeight() * mBlackGammaRenderer.getCacheWidth(); - case 2: - return mWhiteGammaRenderer.getCacheHeight() * mWhiteGammaRenderer.getCacheWidth(); - } - return 0; + if (fontRenderer >= kGammaCount) return 0; + + FontRenderer* renderer = mRenderers[fontRenderer]; + if (!renderer) return 0; + + return renderer->getCacheHeight() * renderer->getCacheWidth(); } private: - FontRenderer mDefaultRenderer; - FontRenderer mBlackGammaRenderer; - FontRenderer mWhiteGammaRenderer; + FontRenderer* getRenderer(Gamma gamma); + + uint32_t mRenderersUsageCount[kGammaCount]; + FontRenderer* mRenderers[kGammaCount]; int mBlackThreshold; int mWhiteThreshold; - uint8_t mDefault[256]; - uint8_t mBlackGamma[256]; - uint8_t mWhiteGamma[256]; + uint8_t mGammaTable[256 * kGammaCount]; }; }; // namespace uirenderer diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 5bd0d4f..8c01e3a 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -61,6 +61,9 @@ enum DebugLevel { #define PROPERTY_DROP_SHADOW_CACHE_SIZE "ro.hwui.drop_shadow_cache_size" #define PROPERTY_FBO_CACHE_SIZE "ro.hwui.fbo_cache_size" +// These properties are defined in percentage (range 0..1) +#define PROPERTY_TEXTURE_CACHE_FLUSH_RATE "ro.hwui.texture_cache_flush_rate" + // These properties are defined in pixels #define PROPERTY_TEXT_CACHE_WIDTH "ro.hwui.text_cache_width" #define PROPERTY_TEXT_CACHE_HEIGHT "ro.hwui.text_cache_height" @@ -82,6 +85,8 @@ enum DebugLevel { #define DEFAULT_DROP_SHADOW_CACHE_SIZE 2.0f #define DEFAULT_FBO_CACHE_SIZE 16 +#define DEFAULT_TEXTURE_CACHE_FLUSH_RATE 0.6f + #define DEFAULT_TEXT_GAMMA 1.4f #define DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD 64 #define DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD 192 diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index fbdbf92..018ce3e 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -34,7 +34,8 @@ namespace uirenderer { TextureCache::TextureCache(): mCache(GenerationCache<SkBitmap*, Texture*>::kUnlimitedCapacity), - mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)) { + mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)), + mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE) { char property[PROPERTY_VALUE_MAX]; if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, NULL) > 0) { INIT_LOGD(" Setting texture cache size to %sMB", property); @@ -43,6 +44,15 @@ TextureCache::TextureCache(): INIT_LOGD(" Using default texture cache size of %.2fMB", DEFAULT_TEXTURE_CACHE_SIZE); } + if (property_get(PROPERTY_TEXTURE_CACHE_FLUSH_RATE, property, NULL) > 0) { + float flushRate = atof(property); + INIT_LOGD(" Setting texture cache flush rate to %.2f%%", flushRate * 100.0f); + setFlushRate(flushRate); + } else { + INIT_LOGD(" Using default texture cache flush rate of %.2f%%", + DEFAULT_TEXTURE_CACHE_FLUSH_RATE * 100.0f); + } + init(); } @@ -84,6 +94,10 @@ void TextureCache::setMaxSize(uint32_t maxSize) { } } +void TextureCache::setFlushRate(float flushRate) { + mFlushRate = fmaxf(0.0f, fminf(1.0f, flushRate)); +} + /////////////////////////////////////////////////////////////////////////////// // Callbacks /////////////////////////////////////////////////////////////////////////////// @@ -168,6 +182,21 @@ void TextureCache::clear() { TEXTURE_LOGD("TextureCache:clear(), mSize = %d", mSize); } +void TextureCache::flush() { + if (mFlushRate >= 1.0f || mCache.size() == 0) return; + if (mFlushRate <= 0.0f) { + clear(); + return; + } + + uint32_t targetSize = uint32_t(mSize * mFlushRate); + TEXTURE_LOGD("TextureCache::flush: target size: %d", targetSize); + + while (mSize > targetSize) { + mCache.removeOldest(); + } +} + void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate) { SkAutoLockPixels alp(*bitmap); diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index f7707f7..ce924b4 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -98,6 +98,17 @@ public: */ uint32_t getSize(); + /** + * Partially flushes the cache. The amount of memory freed by a flush + * is defined by the flush rate. + */ + void flush(); + /** + * Indicates the percentage of the cache to retain when a + * memory trim is requested (see Caches::flush). + */ + void setFlushRate(float flushRate); + private: /** * Generates the texture from a bitmap into the specified texture structure. @@ -119,6 +130,8 @@ private: uint32_t mMaxSize; GLint mMaxTextureSize; + float mFlushRate; + bool mDebugEnabled; Vector<SkBitmap*> mGarbage; |