Refactor GammaFontRenderer
This change is the first step to a shader-based text antialias
gamma correction.
Change-Id: I9eb02d4c56cb95d05219f712290c865b46141954
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 214cc92..56eb317 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -49,6 +49,7 @@
Caches::Caches(): Singleton<Caches>(), mInitialized(false) {
init();
+ initFont();
initExtensions();
initConstraints();
@@ -74,6 +75,7 @@
mTexCoordsArrayEnabled = false;
+ glDisable(GL_SCISSOR_TEST);
scissorEnabled = false;
mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
@@ -90,6 +92,10 @@
mInitialized = true;
}
+void Caches::initFont() {
+ fontRenderer = GammaFontRenderer::createRenderer();
+}
+
void Caches::initExtensions() {
if (extensions.hasDebugMarker()) {
eventMark = glInsertEventMarkerEXT;
@@ -170,8 +176,8 @@
arcShapeCache.getSize(), arcShapeCache.getMaxSize());
log.appendFormat(" TextDropShadowCache %8d / %8d\n", dropShadowCache.getSize(),
dropShadowCache.getMaxSize());
- for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
- const uint32_t size = fontRenderer.getFontRendererSize(i);
+ for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
+ const uint32_t size = fontRenderer->getFontRendererSize(i);
log.appendFormat(" FontRenderer %d %8d / %8d\n", i, size, size);
}
log.appendFormat("Other:\n");
@@ -191,8 +197,8 @@
total += ovalShapeCache.getSize();
total += rectShapeCache.getSize();
total += arcShapeCache.getSize();
- for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
- total += fontRenderer.getFontRendererSize(i);
+ for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
+ total += fontRenderer->getFontRendererSize(i);
}
log.appendFormat("Total memory usage:\n");
@@ -245,10 +251,10 @@
patchCache.clear();
dropShadowCache.clear();
gradientCache.clear();
- fontRenderer.clear();
+ fontRenderer->clear();
// fall through
case kFlushMode_Moderate:
- fontRenderer.flush();
+ fontRenderer->flush();
textureCache.flush();
pathCache.clear();
roundRectShapeCache.clear();
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index f83e291..5e09d94 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -249,9 +249,10 @@
PatchCache patchCache;
TextDropShadowCache dropShadowCache;
FboCache fboCache;
- GammaFontRenderer fontRenderer;
ResourceCache resourceCache;
+ GammaFontRenderer* fontRenderer;
+
// Debug methods
PFNGLINSERTEVENTMARKEREXTPROC eventMark;
PFNGLPUSHGROUPMARKEREXTPROC startMark;
@@ -261,6 +262,7 @@
PFNGLGETOBJECTLABELEXTPROC getLabel;
private:
+ void initFont();
void initExtensions();
void initConstraints();
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 0d6e62a..3b3691c 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -677,10 +677,19 @@
unsigned int stride = glyph.rowBytes();
uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
- for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
- for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY++) {
- uint8_t tempCol = bitmapBuffer[bY * stride + bX];
- cacheBuffer[cacheY * cacheWidth + cacheX] = mGammaTable[tempCol];
+ if (mGammaTable) {
+ for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
+ for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY++) {
+ uint8_t tempCol = bitmapBuffer[bY * stride + bX];
+ cacheBuffer[cacheY * cacheWidth + cacheX] = mGammaTable[tempCol];
+ }
+ }
+ } else {
+ for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
+ for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY++) {
+ uint8_t tempCol = bitmapBuffer[bY * stride + bX];
+ cacheBuffer[cacheY * cacheWidth + cacheX] = tempCol;
+ }
}
}
diff --git a/libs/hwui/GammaFontRenderer.cpp b/libs/hwui/GammaFontRenderer.cpp
index 1be957f..75d5b10 100644
--- a/libs/hwui/GammaFontRenderer.cpp
+++ b/libs/hwui/GammaFontRenderer.cpp
@@ -24,20 +24,30 @@
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
-// Constructors/destructor
+// Base class GammaFontRenderer
///////////////////////////////////////////////////////////////////////////////
-GammaFontRenderer::GammaFontRenderer() {
- INIT_LOGD("Creating gamma font renderer");
+GammaFontRenderer* GammaFontRenderer::createRenderer() {
+ // Choose the best renderer
+ char property[PROPERTY_VALUE_MAX];
+ if (property_get(PROPERTY_TEXT_GAMMA_SHADER, property, DEFAULT_TEXT_GAMMA_SHADER) > 0) {
+ if (!strcasecmp(property, "true")) {
+ return new ShaderGammaFontRenderer();
+ }
+ }
+ return new LookupGammaFontRenderer();
+}
+
+GammaFontRenderer::GammaFontRenderer() {
// Get the renderer properties
char property[PROPERTY_VALUE_MAX];
// Get the gamma
- float gamma = DEFAULT_TEXT_GAMMA;
+ mGamma = DEFAULT_TEXT_GAMMA;
if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) {
INIT_LOGD(" Setting text gamma to %s", property);
- gamma = atof(property);
+ mGamma = atof(property);
} else {
INIT_LOGD(" Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA);
}
@@ -61,10 +71,29 @@
INIT_LOGD(" Using default white black gamma threshold of %d",
DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD);
}
+}
+
+GammaFontRenderer::~GammaFontRenderer() {
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Shader-based renderer
+///////////////////////////////////////////////////////////////////////////////
+
+ShaderGammaFontRenderer::ShaderGammaFontRenderer(): GammaFontRenderer() {
+ INIT_LOGD("Creating shader gamma font renderer");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Lookup-based renderer
+///////////////////////////////////////////////////////////////////////////////
+
+LookupGammaFontRenderer::LookupGammaFontRenderer(): GammaFontRenderer() {
+ INIT_LOGD("Creating lookup gamma font renderer");
// Compute the gamma tables
- const float blackGamma = gamma;
- const float whiteGamma = 1.0f / gamma;
+ const float blackGamma = mGamma;
+ const float whiteGamma = 1.0f / mGamma;
for (uint32_t i = 0; i <= 255; i++) {
mGammaTable[i] = i;
@@ -81,20 +110,20 @@
memset(mRenderersUsageCount, 0, sizeof(uint32_t) * kGammaCount);
}
-GammaFontRenderer::~GammaFontRenderer() {
+LookupGammaFontRenderer::~LookupGammaFontRenderer() {
for (int i = 0; i < kGammaCount; i++) {
delete mRenderers[i];
}
}
-void GammaFontRenderer::clear() {
+void LookupGammaFontRenderer::clear() {
for (int i = 0; i < kGammaCount; i++) {
delete mRenderers[i];
mRenderers[i] = NULL;
}
}
-void GammaFontRenderer::flush() {
+void LookupGammaFontRenderer::flush() {
int count = 0;
int min = -1;
uint32_t minCount = UINT_MAX;
@@ -122,7 +151,7 @@
}
}
-FontRenderer* GammaFontRenderer::getRenderer(Gamma gamma) {
+FontRenderer* LookupGammaFontRenderer::getRenderer(Gamma gamma) {
FontRenderer* renderer = mRenderers[gamma];
if (!renderer) {
renderer = new FontRenderer();
@@ -133,7 +162,7 @@
return renderer;
}
-FontRenderer& GammaFontRenderer::getFontRenderer(const SkPaint* paint) {
+FontRenderer& LookupGammaFontRenderer::getFontRenderer(const SkPaint* paint) {
if (paint->getShader() == NULL) {
uint32_t c = paint->getColor();
const int r = (c >> 16) & 0xFF;
diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h
index 99f08f0..988947a 100644
--- a/libs/hwui/GammaFontRenderer.h
+++ b/libs/hwui/GammaFontRenderer.h
@@ -24,16 +24,72 @@
namespace android {
namespace uirenderer {
-struct GammaFontRenderer {
- GammaFontRenderer();
- ~GammaFontRenderer();
+class GammaFontRenderer {
+public:
+ virtual ~GammaFontRenderer();
- enum Gamma {
- kGammaDefault = 0,
- kGammaBlack = 1,
- kGammaWhite = 2,
- kGammaCount = 3
- };
+ virtual void clear() = 0;
+ virtual void flush() = 0;
+
+ virtual FontRenderer& getFontRenderer(const SkPaint* paint) = 0;
+
+ virtual uint32_t getFontRendererCount() const = 0;
+
+ virtual uint32_t getFontRendererSize(uint32_t fontRenderer) const = 0;
+
+ static GammaFontRenderer* createRenderer();
+
+protected:
+ GammaFontRenderer();
+
+ int mBlackThreshold;
+ int mWhiteThreshold;
+
+ float mGamma;
+};
+
+class ShaderGammaFontRenderer: public GammaFontRenderer {
+public:
+ ~ShaderGammaFontRenderer() {
+ delete mRenderer;
+ }
+
+ void clear() {
+ delete mRenderer;
+ }
+
+ void flush() {
+ if (mRenderer) {
+ mRenderer->flushLargeCaches();
+ }
+ }
+
+ FontRenderer& getFontRenderer(const SkPaint* paint) {
+ if (!mRenderer) {
+ mRenderer = new FontRenderer;
+ }
+ return *mRenderer;
+ }
+
+ uint32_t getFontRendererCount() const {
+ return 1;
+ }
+
+ uint32_t getFontRendererSize(uint32_t fontRenderer) const {
+ return mRenderer->getCacheSize();
+ }
+
+private:
+ ShaderGammaFontRenderer();
+
+ FontRenderer* mRenderer;
+
+ friend class GammaFontRenderer;
+};
+
+class LookupGammaFontRenderer: public GammaFontRenderer {
+public:
+ ~LookupGammaFontRenderer();
void clear();
void flush();
@@ -54,15 +110,23 @@
}
private:
+ LookupGammaFontRenderer();
+
+ enum Gamma {
+ kGammaDefault = 0,
+ kGammaBlack = 1,
+ kGammaWhite = 2,
+ kGammaCount = 3
+ };
+
FontRenderer* getRenderer(Gamma gamma);
uint32_t mRenderersUsageCount[kGammaCount];
FontRenderer* mRenderers[kGammaCount];
- int mBlackThreshold;
- int mWhiteThreshold;
-
uint8_t mGammaTable[256 * kGammaCount];
+
+ friend class GammaFontRenderer;
};
}; // namespace uirenderer
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index cbf7b02..ca798db 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2277,7 +2277,7 @@
y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
}
- FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer(paint);
+ FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()),
paint->getTextSize());
@@ -2367,7 +2367,7 @@
ALOGD("OpenGLRenderer drawText() with FontID=%d", SkTypeface::UniqueID(paint->getTypeface()));
#endif
- FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer(paint);
+ FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()),
paint->getTextSize());
@@ -2466,7 +2466,7 @@
return DrawGlInfo::kStatusDone;
}
- FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer(paint);
+ FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()),
paint->getTextSize());
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index c0311fb..4a12e39 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -73,6 +73,10 @@
#define PROPERTY_TEXT_CACHE_WIDTH "ro.hwui.text_cache_width"
#define PROPERTY_TEXT_CACHE_HEIGHT "ro.hwui.text_cache_height"
+// Indicates whether gamma correction should be applied in the shaders
+// or in lookup tables. Accepted values: true, false
+#define PROPERTY_TEXT_GAMMA_SHADER "ro.hwui.text_gamma_shader"
+
// Gamma (>= 1.0, <= 10.0)
#define PROPERTY_TEXT_GAMMA "ro.text_gamma"
#define PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD "ro.text_gamma.black_threshold"
@@ -92,6 +96,8 @@
#define DEFAULT_TEXTURE_CACHE_FLUSH_RATE 0.6f
+#define DEFAULT_TEXT_GAMMA_SHADER "false"
+
#define DEFAULT_TEXT_GAMMA 1.4f
#define DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD 64
#define DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD 192