Merge "Memory optimizations for libhwui Bug #5566149" into ics-mr1
This commit is contained in:
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user