GammaFontRenderer.cpp revision 4121063313ac0d6f69f6253cac821d0c1c122086
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "OpenGLRenderer" 18 19#include "Debug.h" 20#include "GammaFontRenderer.h" 21#include "Properties.h" 22 23namespace android { 24namespace uirenderer { 25 26/////////////////////////////////////////////////////////////////////////////// 27// Utils 28/////////////////////////////////////////////////////////////////////////////// 29 30static int luminance(const SkPaint* paint) { 31 uint32_t c = paint->getColor(); 32 const int r = (c >> 16) & 0xFF; 33 const int g = (c >> 8) & 0xFF; 34 const int b = (c ) & 0xFF; 35 return (r * 2 + g * 5 + b) >> 3; 36} 37 38/////////////////////////////////////////////////////////////////////////////// 39// Base class GammaFontRenderer 40/////////////////////////////////////////////////////////////////////////////// 41 42GammaFontRenderer* GammaFontRenderer::createRenderer() { 43 // Choose the best renderer 44 char property[PROPERTY_VALUE_MAX]; 45 if (property_get(PROPERTY_TEXT_GAMMA_SHADER, property, DEFAULT_TEXT_GAMMA_SHADER) > 0) { 46 if (!strcasecmp(property, "true")) { 47 return new ShaderGammaFontRenderer(); 48 } 49 } 50 51#if DEBUG_FONT_RENDERER_FORCE_SHADER_GAMMA 52 return new ShaderGammaFontRenderer(); 53#else 54 return new LookupGammaFontRenderer(); 55#endif 56} 57 58GammaFontRenderer::GammaFontRenderer() { 59 // Get the renderer properties 60 char property[PROPERTY_VALUE_MAX]; 61 62 // Get the gamma 63 mGamma = DEFAULT_TEXT_GAMMA; 64 if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { 65 INIT_LOGD(" Setting text gamma to %s", property); 66 mGamma = atof(property); 67 } else { 68 INIT_LOGD(" Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA); 69 } 70 71 // Get the black gamma threshold 72 mBlackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 73 if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { 74 INIT_LOGD(" Setting text black gamma threshold to %s", property); 75 mBlackThreshold = atoi(property); 76 } else { 77 INIT_LOGD(" Using default text black gamma threshold of %d", 78 DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD); 79 } 80 81 // Get the white gamma threshold 82 mWhiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 83 if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { 84 INIT_LOGD(" Setting text white gamma threshold to %s", property); 85 mWhiteThreshold = atoi(property); 86 } else { 87 INIT_LOGD(" Using default white black gamma threshold of %d", 88 DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD); 89 } 90} 91 92GammaFontRenderer::~GammaFontRenderer() { 93} 94 95/////////////////////////////////////////////////////////////////////////////// 96// Shader-based renderer 97/////////////////////////////////////////////////////////////////////////////// 98 99ShaderGammaFontRenderer::ShaderGammaFontRenderer(): GammaFontRenderer() { 100 INIT_LOGD("Creating shader gamma font renderer"); 101 mRenderer = NULL; 102} 103 104void ShaderGammaFontRenderer::describe(ProgramDescription& description, 105 const SkPaint* paint) const { 106 if (paint->getShader() == NULL) { 107 const int l = luminance(paint); 108 109 if (l <= mBlackThreshold) { 110 description.hasGammaCorrection = true; 111 description.gamma = mGamma; 112 } else if (l >= mWhiteThreshold) { 113 description.hasGammaCorrection = true; 114 description.gamma = 1.0f / mGamma; 115 } 116 } 117} 118 119void ShaderGammaFontRenderer::setupProgram(ProgramDescription& description, 120 Program* program) const { 121 if (description.hasGammaCorrection) { 122 glUniform1f(program->getUniform("gamma"), description.gamma); 123 } 124} 125 126/////////////////////////////////////////////////////////////////////////////// 127// Lookup-based renderer 128/////////////////////////////////////////////////////////////////////////////// 129 130LookupGammaFontRenderer::LookupGammaFontRenderer(): GammaFontRenderer() { 131 INIT_LOGD("Creating lookup gamma font renderer"); 132 133 // Compute the gamma tables 134 const float blackGamma = mGamma; 135 const float whiteGamma = 1.0f / mGamma; 136 137 for (uint32_t i = 0; i <= 255; i++) { 138 mGammaTable[i] = i; 139 140 const float v = i / 255.0f; 141 const float black = pow(v, blackGamma); 142 const float white = pow(v, whiteGamma); 143 144 mGammaTable[256 + i] = uint8_t((float)::floor(black * 255.0f + 0.5f)); 145 mGammaTable[512 + i] = uint8_t((float)::floor(white * 255.0f + 0.5f)); 146 } 147 148 memset(mRenderers, 0, sizeof(FontRenderer*) * kGammaCount); 149 memset(mRenderersUsageCount, 0, sizeof(uint32_t) * kGammaCount); 150} 151 152LookupGammaFontRenderer::~LookupGammaFontRenderer() { 153 for (int i = 0; i < kGammaCount; i++) { 154 delete mRenderers[i]; 155 } 156} 157 158void LookupGammaFontRenderer::clear() { 159 for (int i = 0; i < kGammaCount; i++) { 160 delete mRenderers[i]; 161 mRenderers[i] = NULL; 162 } 163} 164 165void LookupGammaFontRenderer::flush() { 166 int count = 0; 167 int min = -1; 168 uint32_t minCount = UINT_MAX; 169 170 for (int i = 0; i < kGammaCount; i++) { 171 if (mRenderers[i]) { 172 count++; 173 if (mRenderersUsageCount[i] < minCount) { 174 minCount = mRenderersUsageCount[i]; 175 min = i; 176 } 177 } 178 } 179 180 if (count <= 1 || min < 0) return; 181 182 delete mRenderers[min]; 183 mRenderers[min] = NULL; 184 185 // Also eliminate the caches for large glyphs, as they consume significant memory 186 for (int i = 0; i < kGammaCount; ++i) { 187 if (mRenderers[i]) { 188 mRenderers[i]->flushLargeCaches(); 189 } 190 } 191} 192 193FontRenderer* LookupGammaFontRenderer::getRenderer(Gamma gamma) { 194 FontRenderer* renderer = mRenderers[gamma]; 195 if (!renderer) { 196 renderer = new FontRenderer(); 197 mRenderers[gamma] = renderer; 198 renderer->setGammaTable(&mGammaTable[gamma * 256]); 199 } 200 mRenderersUsageCount[gamma]++; 201 return renderer; 202} 203 204FontRenderer& LookupGammaFontRenderer::getFontRenderer(const SkPaint* paint) { 205 if (paint->getShader() == NULL) { 206 const int l = luminance(paint); 207 208 if (l <= mBlackThreshold) { 209 return *getRenderer(kGammaBlack); 210 } else if (l >= mWhiteThreshold) { 211 return *getRenderer(kGammaWhite); 212 } 213 } 214 return *getRenderer(kGammaDefault); 215} 216 217}; // namespace uirenderer 218}; // namespace android 219