summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2011-11-04 15:12:29 -0700
committerRomain Guy <romainguy@google.com>2011-11-04 16:23:47 -0700
commiteca0ca2424afc1e98912405906edfc32f7733e16 (patch)
tree9f49527f35d77b0de3ee49f76e1b7bc99fac3ac6 /libs
parent650ee281ae9e007ce82ea79ff18bab9ef49503de (diff)
downloadframeworks_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.cpp3
-rw-r--r--libs/hwui/GammaFontRenderer.cpp63
-rw-r--r--libs/hwui/GammaFontRenderer.h39
-rw-r--r--libs/hwui/Properties.h5
-rw-r--r--libs/hwui/TextureCache.cpp31
-rw-r--r--libs/hwui/TextureCache.h13
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;