1694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy/* 2694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * Copyright (C) 2010 The Android Open Source Project 3694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * 4694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * you may not use this file except in compliance with the License. 6694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * You may obtain a copy of the License at 7694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * 8694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 9694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * 10694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * Unless required by applicable law or agreed to in writing, software 11694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * distributed under the License is distributed on an "AS IS" BASIS, 12694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * See the License for the specific language governing permissions and 14694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * limitations under the License. 15694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy */ 16694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 17694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy#define LOG_TAG "OpenGLRenderer" 18694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 19ca79cf69d09efa0c327e9b1237d86a119aea5da7Derek Sollenberger#include <SkGlyph.h> 20694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy#include <SkUtils.h> 21694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 2251769a68a5cb34e9564740c6a854fcb93018789dRomain Guy#include <cutils/properties.h> 23e2d345ea67e2960b37bfdc0fc8626d1bfa747404Romain Guy 2451769a68a5cb34e9564740c6a854fcb93018789dRomain Guy#include <utils/Log.h> 2551769a68a5cb34e9564740c6a854fcb93018789dRomain Guy 26e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#ifdef ANDROID_ENABLE_RENDERSCRIPT 276e2004089305cf2cd958b52b234459a49a4e5c83Romain Guy#include <RenderScript.h> 28e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#endif 29f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik 306e2004089305cf2cd958b52b234459a49a4e5c83Romain Guy#include "utils/Blur.h" 31f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik#include "utils/Timing.h" 326e2004089305cf2cd958b52b234459a49a4e5c83Romain Guy 3315bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy#include "Caches.h" 34c9855a53edfac818dc68714557185977556f849dRomain Guy#include "Debug.h" 350908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy#include "Extensions.h" 3651769a68a5cb34e9564740c6a854fcb93018789dRomain Guy#include "FontRenderer.h" 371e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#include "OpenGLRenderer.h" 38cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy#include "PixelBuffer.h" 399f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#include "Rect.h" 4051769a68a5cb34e9564740c6a854fcb93018789dRomain Guy 41694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guynamespace android { 42694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guynamespace uirenderer { 43694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 44f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik// blur inputs smaller than this constant will bypass renderscript 45f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik#define RS_MIN_INPUT_CUTOFF 10000 46f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik 47694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy/////////////////////////////////////////////////////////////////////////////// 481e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease// TextSetupFunctor 491e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease/////////////////////////////////////////////////////////////////////////////// 501e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasestatus_t TextSetupFunctor::operator ()(int what, void* data) { 511e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease Data* typedData = reinterpret_cast<Data*>(data); 521e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GLenum glyphFormat = typedData ? typedData->glyphFormat : GL_ALPHA; 531e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 541e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDraw(); 551e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawTextGamma(paint); 561e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawDirtyRegionsDisabled(); 571e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawWithTexture(glyphFormat == GL_ALPHA); 581e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease switch (glyphFormat) { 591e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case GL_ALPHA: { 601e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawAlpha8Color(paint->getColor(), alpha); 611e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 621e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 631e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case GL_RGBA: { 641e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease float floatAlpha = alpha / 255.0f; 651e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawColor(floatAlpha, floatAlpha, floatAlpha, floatAlpha); 661e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 671e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 681e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease default: { 691e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#if DEBUG_FONT_RENDERER 701e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease ALOGD("TextSetupFunctor: called with unknown glyph format %x", glyphFormat); 711e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#endif 721e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 731e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 741e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 751e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawColorFilter(); 761e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawShader(); 771e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawBlending(true, mode); 781e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawProgram(); 791e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawModelView(x, y, x, y, pureTranslate, true); 801e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // Calling setupDrawTexture with the name 0 will enable the 811e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // uv attributes and increase the texture unit count 821e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // texture binding will be performed by the font renderer as 831e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // needed 841e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawTexture(0); 851e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawPureColorUniforms(); 861e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawColorFilterUniforms(); 871e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawShaderUniforms(pureTranslate); 881e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawTextGammaUniforms(); 891e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 901e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return NO_ERROR; 911e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 921e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 931e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease/////////////////////////////////////////////////////////////////////////////// 94694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy// FontRenderer 95694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy/////////////////////////////////////////////////////////////////////////////// 96694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 97514fb18827186591d66973c2362c859b64b63556Romain Guystatic bool sLogFontRendererCreate = true; 98514fb18827186591d66973c2362c859b64b63556Romain Guy 99e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain GuyFontRenderer::FontRenderer() : 100e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy mActiveFonts(LruCache<Font::FontDescription, Font*>::kUnlimitedCapacity) { 101e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy 102c9855a53edfac818dc68714557185977556f849dRomain Guy if (sLogFontRendererCreate) { 103c9855a53edfac818dc68714557185977556f849dRomain Guy INIT_LOGD("Creating FontRenderer"); 104c9855a53edfac818dc68714557185977556f849dRomain Guy } 10551769a68a5cb34e9564740c6a854fcb93018789dRomain Guy 106b45c0c9774bd19a9dbe77d149abae4e124b08bf6Romain Guy mGammaTable = NULL; 107694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy mInitialized = false; 108694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 1097de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase mCurrentCacheTexture = NULL; 1109cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy 1112a47c14e2a6f152496b43104bc785c488583fd59Chet Haase mLinearFiltering = false; 1122a47c14e2a6f152496b43104bc785c488583fd59Chet Haase 113eb32a499194119b3783b86c925172df02e5d2685Chet Haase mSmallCacheWidth = DEFAULT_TEXT_SMALL_CACHE_WIDTH; 114eb32a499194119b3783b86c925172df02e5d2685Chet Haase mSmallCacheHeight = DEFAULT_TEXT_SMALL_CACHE_HEIGHT; 115eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheWidth = DEFAULT_TEXT_LARGE_CACHE_WIDTH; 116eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheHeight = DEFAULT_TEXT_LARGE_CACHE_HEIGHT; 11751769a68a5cb34e9564740c6a854fcb93018789dRomain Guy 11851769a68a5cb34e9564740c6a854fcb93018789dRomain Guy char property[PROPERTY_VALUE_MAX]; 119eb32a499194119b3783b86c925172df02e5d2685Chet Haase if (property_get(PROPERTY_TEXT_SMALL_CACHE_WIDTH, property, NULL) > 0) { 1207de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase mSmallCacheWidth = atoi(property); 12151769a68a5cb34e9564740c6a854fcb93018789dRomain Guy } 1229f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 123eb32a499194119b3783b86c925172df02e5d2685Chet Haase if (property_get(PROPERTY_TEXT_SMALL_CACHE_HEIGHT, property, NULL) > 0) { 1247de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase mSmallCacheHeight = atoi(property); 125eb32a499194119b3783b86c925172df02e5d2685Chet Haase } 1269f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 127eb32a499194119b3783b86c925172df02e5d2685Chet Haase if (property_get(PROPERTY_TEXT_LARGE_CACHE_WIDTH, property, NULL) > 0) { 128eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheWidth = atoi(property); 129eb32a499194119b3783b86c925172df02e5d2685Chet Haase } 1309f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 131eb32a499194119b3783b86c925172df02e5d2685Chet Haase if (property_get(PROPERTY_TEXT_LARGE_CACHE_HEIGHT, property, NULL) > 0) { 132eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheHeight = atoi(property); 133eb32a499194119b3783b86c925172df02e5d2685Chet Haase } 1349f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 1359f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint32_t maxTextureSize = (uint32_t) Caches::getInstance().maxTextureSize; 1369f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mSmallCacheWidth = mSmallCacheWidth > maxTextureSize ? maxTextureSize : mSmallCacheWidth; 1379f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mSmallCacheHeight = mSmallCacheHeight > maxTextureSize ? maxTextureSize : mSmallCacheHeight; 1389f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mLargeCacheWidth = mLargeCacheWidth > maxTextureSize ? maxTextureSize : mLargeCacheWidth; 1399f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mLargeCacheHeight = mLargeCacheHeight > maxTextureSize ? maxTextureSize : mLargeCacheHeight; 1409f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 141eb32a499194119b3783b86c925172df02e5d2685Chet Haase if (sLogFontRendererCreate) { 142eb32a499194119b3783b86c925172df02e5d2685Chet Haase INIT_LOGD(" Text cache sizes, in pixels: %i x %i, %i x %i, %i x %i, %i x %i", 143eb32a499194119b3783b86c925172df02e5d2685Chet Haase mSmallCacheWidth, mSmallCacheHeight, 144eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheWidth, mLargeCacheHeight >> 1, 145eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheWidth, mLargeCacheHeight >> 1, 146eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheWidth, mLargeCacheHeight); 14751769a68a5cb34e9564740c6a854fcb93018789dRomain Guy } 148514fb18827186591d66973c2362c859b64b63556Romain Guy 149514fb18827186591d66973c2362c859b64b63556Romain Guy sLogFontRendererCreate = false; 150694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 151694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 1521e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid clearCacheTextures(Vector<CacheTexture*>& cacheTextures) { 1531e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 1541e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease delete cacheTextures[i]; 155694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 1561e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease cacheTextures.clear(); 1571e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 1581e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 1591e546815bbb736c50679a8aefc25f48561026fc5Victoria LeaseFontRenderer::~FontRenderer() { 1601e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease clearCacheTextures(mACacheTextures); 1611e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease clearCacheTextures(mRGBACacheTextures); 162694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 163e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); 164e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy while (it.next()) { 165e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy delete it.value(); 166694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 167e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy mActiveFonts.clear(); 168694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 169694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 170694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guyvoid FontRenderer::flushAllAndInvalidate() { 171661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy issueDrawCommand(); 1729d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 173e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); 174e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy while (it.next()) { 175e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy it.value()->invalidateTextureCache(); 176694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 1779d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 1781e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < mACacheTextures.size(); i++) { 1791e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mACacheTextures[i]->init(); 1801e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 1811e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 1821e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < mRGBACacheTextures.size(); i++) { 1831e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mRGBACacheTextures[i]->init(); 184e816baea651476aca4407200d4a5e629b9ab8dfaChet Haase } 185694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 186694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 1871e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid FontRenderer::flushLargeCaches(Vector<CacheTexture*>& cacheTextures) { 188378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase // Start from 1; don't deallocate smallest/default texture 1891e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 1; i < cacheTextures.size(); i++) { 1901e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = cacheTextures[i]; 191cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (cacheTexture->getPixelBuffer()) { 192378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase cacheTexture->init(); 193e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); 194e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy while (it.next()) { 195e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy it.value()->invalidateTextureCache(cacheTexture); 1969a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase } 1978087246d9964b11de8ce116bc63b156faa4197e0Romain Guy cacheTexture->releaseTexture(); 1989a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase } 1999a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase } 2009a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase} 2019a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase 2021e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid FontRenderer::flushLargeCaches() { 2031e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease flushLargeCaches(mACacheTextures); 2041e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease flushLargeCaches(mRGBACacheTextures); 2051e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 2061e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 2071e546815bbb736c50679a8aefc25f48561026fc5Victoria LeaseCacheTexture* FontRenderer::cacheBitmapInTexture(Vector<CacheTexture*>& cacheTextures, 2081e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease const SkGlyph& glyph, uint32_t* startX, uint32_t* startY) { 2091e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 2101e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (cacheTextures[i]->fitBitmap(glyph, startX, startY)) { 2111e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return cacheTextures[i]; 212378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase } 213378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase } 214378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase // Could not fit glyph into current cache textures 215378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase return NULL; 216378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase} 217378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase 2187de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haasevoid FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, 219f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase uint32_t* retOriginX, uint32_t* retOriginY, bool precaching) { 2202efd5c5886d9acf747bc92f888d731ed558aabccChet Haase checkInit(); 221a4adcf0239039eb8f005be252409901c41b28839Romain Guy 222a4adcf0239039eb8f005be252409901c41b28839Romain Guy // If the glyph bitmap is empty let's assum the glyph is valid 223a4adcf0239039eb8f005be252409901c41b28839Romain Guy // so we can avoid doing extra work later on 224a4adcf0239039eb8f005be252409901c41b28839Romain Guy if (glyph.fWidth == 0 || glyph.fHeight == 0) { 225a4adcf0239039eb8f005be252409901c41b28839Romain Guy cachedGlyph->mIsValid = true; 226a4adcf0239039eb8f005be252409901c41b28839Romain Guy cachedGlyph->mCacheTexture = NULL; 227a4adcf0239039eb8f005be252409901c41b28839Romain Guy return; 228a4adcf0239039eb8f005be252409901c41b28839Romain Guy } 229a4adcf0239039eb8f005be252409901c41b28839Romain Guy 2307de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase cachedGlyph->mIsValid = false; 231a4adcf0239039eb8f005be252409901c41b28839Romain Guy 2321e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // choose an appropriate cache texture list for this glyph format 2331e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat); 2341e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease Vector<CacheTexture*>* cacheTextures = NULL; 2351e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease switch (format) { 2361e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kA8_Format: 237723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease case SkMask::kBW_Format: 2381e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease cacheTextures = &mACacheTextures; 2391e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 2401e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kARGB32_Format: 2411e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease cacheTextures = &mRGBACacheTextures; 2421e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 2431e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease default: 2441e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#if DEBUG_FONT_RENDERER 2451e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease ALOGD("getCacheTexturesForFormat: unknown SkMask format %x", format); 2461e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#endif 2471e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return; 2481e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 2491e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 250694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy // If the glyph is too tall, don't cache it 251378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > 2521e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease (*cacheTextures)[cacheTextures->size() - 1]->getHeight()) { 2532efd5c5886d9acf747bc92f888d731ed558aabccChet Haase ALOGE("Font size too large to fit in cache. width, height = %i, %i", 2542efd5c5886d9acf747bc92f888d731ed558aabccChet Haase (int) glyph.fWidth, (int) glyph.fHeight); 2557de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase return; 256694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 257694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 258694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy // Now copy the bitmap into the cache texture 259694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy uint32_t startX = 0; 260694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy uint32_t startY = 0; 261694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 2621e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY); 263694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 264378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase if (!cacheTexture) { 265f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase if (!precaching) { 266f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase // If the new glyph didn't fit and we are not just trying to precache it, 267f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase // clear out the cache and try again 268f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase flushAllAndInvalidate(); 2691e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY); 270f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase } 271694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 272378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase if (!cacheTexture) { 273f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase // either the glyph didn't fit or we're precaching and will cache it when we draw 2747de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase return; 275694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 276694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 277694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 278378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase cachedGlyph->mCacheTexture = cacheTexture; 2797de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase 280694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy *retOriginX = startX; 281694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy *retOriginY = startY; 282694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 283694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy uint32_t endX = startX + glyph.fWidth; 284694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy uint32_t endY = startY + glyph.fHeight; 285694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 2868087246d9964b11de8ce116bc63b156faa4197e0Romain Guy uint32_t cacheWidth = cacheTexture->getWidth(); 287694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 288cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (!cacheTexture->getPixelBuffer()) { 2898087246d9964b11de8ce116bc63b156faa4197e0Romain Guy Caches::getInstance().activeTexture(0); 2907de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase // Large-glyph texture memory is allocated only as needed 2918087246d9964b11de8ce116bc63b156faa4197e0Romain Guy cacheTexture->allocateTexture(); 2927de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase } 293661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (!cacheTexture->mesh()) { 294661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy cacheTexture->allocateMesh(); 295661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 2969d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 297cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint8_t* cacheBuffer = cacheTexture->getPixelBuffer()->map(); 298b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy uint8_t* bitmapBuffer = (uint8_t*) glyph.fImage; 2991e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease int srcStride = glyph.rowBytes(); 3000b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy 3011e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // Copy the glyph image, taking the mask format into account 302b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy switch (format) { 303b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy case SkMask::kA8_Format: { 3041e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 3051e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX 3061e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease - TEXTURE_BORDER_SIZE; 3071e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write leading border line 3081e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 3091e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write glyph data 310b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy if (mGammaTable) { 3111e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) { 3120b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy row = cacheY * cacheWidth; 3130b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; 314b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) { 315b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy uint8_t tempCol = bitmapBuffer[bY + bX]; 3160b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + cacheX] = mGammaTable[tempCol]; 317b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 3180b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; 319b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 320b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } else { 3211e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) { 3220b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy row = cacheY * cacheWidth; 3230b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy memcpy(&cacheBuffer[row + startX], &bitmapBuffer[bY], glyph.fWidth); 3240b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; 3250b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; 326b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 327b1d0a4ed21168fefcb82232c8f22cb95d60acb85Romain Guy } 3281e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write trailing border line 3291e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE; 3301e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 3311e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 3321e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 3331e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kARGB32_Format: { 3341e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // prep data lengths 3351e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease const size_t formatSize = PixelBuffer::formatSize(GL_RGBA); 3361e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease const size_t borderSize = formatSize * TEXTURE_BORDER_SIZE; 3371e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease size_t rowSize = formatSize * glyph.fWidth; 3381e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // prep advances 3391e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease size_t dstStride = formatSize * cacheWidth; 3401e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // prep indices 3411e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // - we actually start one row early, and then increment before first copy 3421e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* src = &bitmapBuffer[0 - srcStride]; 3431e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* dst = &cacheBuffer[cacheTexture->getOffset(startX, startY - 1)]; 3441e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* dstEnd = &cacheBuffer[cacheTexture->getOffset(startX, endY - 1)]; 3451e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* dstL = dst - borderSize; 3461e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* dstR = dst + rowSize; 3471e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write leading border line 3481e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(dstL, 0, rowSize + 2 * borderSize); 3491e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write glyph data 3501e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease while (dst < dstEnd) { 3511e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(dstL += dstStride, 0, borderSize); // leading border column 3521e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memcpy(dst += dstStride, src += srcStride, rowSize); // glyph data 3531e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(dstR += dstStride, 0, borderSize); // trailing border column 3541e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 3551e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write trailing border line 35616c84069a4cc0c0d3c35e798dc5e4b0130d4a26fVictoria Lease memset(dstL += dstStride, 0, rowSize + 2 * borderSize); 357b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy break; 358b1d0a4ed21168fefcb82232c8f22cb95d60acb85Romain Guy } 359b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy case SkMask::kBW_Format: { 3601e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 3611e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX 3621e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease - TEXTURE_BORDER_SIZE; 363b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy static const uint8_t COLORS[2] = { 0, 255 }; 3641e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write leading border line 3651e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 3661e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write glyph data 367b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy for (cacheY = startY; cacheY < endY; cacheY++) { 368b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy cacheX = startX; 3691e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease int rowBytes = srcStride; 370b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy uint8_t* buffer = bitmapBuffer; 371b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy 3720b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy row = cacheY * cacheWidth; 3730b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; 374b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy while (--rowBytes >= 0) { 375b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy uint8_t b = *buffer++; 376b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy for (int8_t mask = 7; mask >= 0 && cacheX < endX; mask--) { 377b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy cacheBuffer[cacheY * cacheWidth + cacheX++] = COLORS[(b >> mask) & 0x1]; 378b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 379b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 3800b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; 381b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy 3821e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease bitmapBuffer += srcStride; 383b1d0a4ed21168fefcb82232c8f22cb95d60acb85Romain Guy } 3841e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write trailing border line 3851e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE; 3861e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 387b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy break; 388694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 389b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy default: 3901e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease ALOGW("Unknown glyph format: 0x%x", format); 391b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy break; 392694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 3939777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 3947de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase cachedGlyph->mIsValid = true; 395694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 396694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 3971e546815bbb736c50679a8aefc25f48561026fc5Victoria LeaseCacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum format, 3981e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease bool allocate) { 3991e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = new CacheTexture(width, height, format, gMaxNumberOfQuads); 4009d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 4012a47c14e2a6f152496b43104bc785c488583fd59Chet Haase if (allocate) { 4028087246d9964b11de8ce116bc63b156faa4197e0Romain Guy Caches::getInstance().activeTexture(0); 4038087246d9964b11de8ce116bc63b156faa4197e0Romain Guy cacheTexture->allocateTexture(); 404661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy cacheTexture->allocateMesh(); 4052a47c14e2a6f152496b43104bc785c488583fd59Chet Haase } 4069d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 4072a47c14e2a6f152496b43104bc785c488583fd59Chet Haase return cacheTexture; 4087de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase} 4097de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase 4107de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haasevoid FontRenderer::initTextTexture() { 4111e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease clearCacheTextures(mACacheTextures); 4121e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease clearCacheTextures(mRGBACacheTextures); 4139d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 4147de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase mUploadTexture = false; 4151e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mACacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, 4161e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_ALPHA, true)); 4171e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, 4181e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_ALPHA, false)); 4191e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, 4201e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_ALPHA, false)); 4211e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight, 4221e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_ALPHA, false)); 4231e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mRGBACacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, 4241e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_RGBA, false)); 4251e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mRGBACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, 4261e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_RGBA, false)); 4271e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mCurrentCacheTexture = mACacheTextures[0]; 428694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 429694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 430694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy// We don't want to allocate anything unless we actually draw text 431694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guyvoid FontRenderer::checkInit() { 432694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy if (mInitialized) { 433694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy return; 434694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 435694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 436694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy initTextTexture(); 437694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 438694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy mInitialized = true; 439694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 440694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 4411e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid checkTextureUpdateForCache(Caches& caches, Vector<CacheTexture*>& cacheTextures, 4421e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease bool& resetPixelStore, GLuint& lastTextureId) { 4431e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 4441e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = cacheTextures[i]; 445cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (cacheTexture->isDirty() && cacheTexture->getPixelBuffer()) { 4468087246d9964b11de8ce116bc63b156faa4197e0Romain Guy if (cacheTexture->getTextureId() != lastTextureId) { 4478087246d9964b11de8ce116bc63b156faa4197e0Romain Guy lastTextureId = cacheTexture->getTextureId(); 4482d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy caches.activeTexture(0); 4498aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy caches.bindTexture(lastTextureId); 4500908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy } 4510908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy 452cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (cacheTexture->upload()) { 453cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy resetPixelStore = true; 4542d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy } 4559b9902ddbb01548f4a0199087b7035e7c10b2ae7Alex Sakhartchouk } 456694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 4571e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 4581e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 4591e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid FontRenderer::checkTextureUpdate() { 4601e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (!mUploadTexture) { 4611e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return; 4621e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 4631e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 4641e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease Caches& caches = Caches::getInstance(); 4651e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GLuint lastTextureId = 0; 4661e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 4671e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease bool resetPixelStore = false; 4681e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 4691e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 4701e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // Iterate over all the cache textures and see which ones need to be updated 4711e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease checkTextureUpdateForCache(caches, mACacheTextures, resetPixelStore, lastTextureId); 4721e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease checkTextureUpdateForCache(caches, mRGBACacheTextures, resetPixelStore, lastTextureId); 473694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 474cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // Unbind any PBO we might have used to update textures 475cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy caches.unbindPixelBuffer(); 476cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 4770908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy // Reset to default unpack row length to avoid affecting texture 4780908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy // uploads in other parts of the renderer 479cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (resetPixelStore) { 4800908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 4810908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy } 4820908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy 4839b9902ddbb01548f4a0199087b7035e7c10b2ae7Alex Sakhartchouk mUploadTexture = false; 4849b9902ddbb01548f4a0199087b7035e7c10b2ae7Alex Sakhartchouk} 4859b9902ddbb01548f4a0199087b7035e7c10b2ae7Alex Sakhartchouk 4861e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) { 4871e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease Caches& caches = Caches::getInstance(); 488661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy bool first = true; 489661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy bool force = false; 4901e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 4911e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* texture = cacheTextures[i]; 492661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (texture->canDraw()) { 493661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (first) { 4941e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (mFunctor) { 4951e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease TextSetupFunctor::Data functorData(texture->getFormat()); 4961e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease (*mFunctor)(0, &functorData); 4971e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 498257ae3502cfad43df681b1783528d645bdabc63fRomain Guy 499661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy checkTextureUpdate(); 50031e08e953fe7bdb1b1cbc247156cb6a19917a2f1Romain Guy caches.bindIndicesBuffer(); 501661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 502661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (!mDrawn) { 503661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // If returns true, a VBO was bound and we must 504661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // rebind our vertex attrib pointers even if 505661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // they have the same values as the current pointers 506661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy force = caches.unbindMeshBuffer(); 507661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 50815bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy 509661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy caches.activeTexture(0); 510661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy first = false; 511661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 5127bb3cfe1cca4016ce95d3ef059761f4bb2d668bbSangkyu Lee 5138aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy caches.bindTexture(texture->getTextureId()); 514661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy texture->setLinearFiltering(mLinearFiltering, false); 5157bb3cfe1cca4016ce95d3ef059761f4bb2d668bbSangkyu Lee 516661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy TextureVertex* mesh = texture->mesh(); 517661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy caches.bindPositionVertexPointer(force, &mesh[0].position[0]); 518661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy caches.bindTexCoordsVertexPointer(force, &mesh[0].texture[0]); 519661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy force = false; 520661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 521661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glDrawElements(GL_TRIANGLES, texture->meshElementCount(), 522661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy GL_UNSIGNED_SHORT, texture->indices()); 5237bb3cfe1cca4016ce95d3ef059761f4bb2d668bbSangkyu Lee 524661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy texture->resetMesh(); 525661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 5267bb3cfe1cca4016ce95d3ef059761f4bb2d668bbSangkyu Lee } 5271e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 5281e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 5291e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid FontRenderer::issueDrawCommand() { 5301e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease issueDrawCommand(mACacheTextures); 5311e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease issueDrawCommand(mRGBACacheTextures); 5325b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 5335b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mDrawn = true; 534694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 535694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 5369777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guyvoid FontRenderer::appendMeshQuadNoClip(float x1, float y1, float u1, float v1, 5379777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3, 5387de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase float x4, float y4, float u4, float v4, CacheTexture* texture) { 5397de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase if (texture != mCurrentCacheTexture) { 5407de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase // Now use the new texture id 5417de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase mCurrentCacheTexture = texture; 5427de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase } 54309147fbdc8206a0cac78bfe9083e7e15b3c5689cRomain Guy 544661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCurrentCacheTexture->addQuad(x1, y1, u1, v1, x2, y2, u2, v2, 545661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy x3, y3, u3, v3, x4, y4, u4, v4); 5469777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy} 5479777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5489777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guyvoid FontRenderer::appendMeshQuad(float x1, float y1, float u1, float v1, 5499777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3, 5509777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x4, float y4, float u4, float v4, CacheTexture* texture) { 5519777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5529777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy if (mClip && 5539777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy (x1 > mClip->right || y1 < mClip->top || x2 < mClip->left || y4 > mClip->bottom)) { 5549777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy return; 5559777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 5569777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5579777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture); 558694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 5595b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (mBounds) { 5605b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mBounds->left = fmin(mBounds->left, x1); 5615b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mBounds->top = fmin(mBounds->top, y3); 5625b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mBounds->right = fmax(mBounds->right, x3); 5635b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mBounds->bottom = fmax(mBounds->bottom, y1); 5645b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 5655b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 566661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (mCurrentCacheTexture->endOfMesh()) { 567694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy issueDrawCommand(); 568694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 569694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 570694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 5719777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guyvoid FontRenderer::appendRotatedMeshQuad(float x1, float y1, float u1, float v1, 5729777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3, 5739777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x4, float y4, float u4, float v4, CacheTexture* texture) { 5749777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5759777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture); 5769777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5779777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy if (mBounds) { 5789777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy mBounds->left = fmin(mBounds->left, fmin(x1, fmin(x2, fmin(x3, x4)))); 5799777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy mBounds->top = fmin(mBounds->top, fmin(y1, fmin(y2, fmin(y3, y4)))); 5809777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy mBounds->right = fmax(mBounds->right, fmax(x1, fmax(x2, fmax(x3, x4)))); 5819777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy mBounds->bottom = fmax(mBounds->bottom, fmax(y1, fmax(y2, fmax(y3, y4)))); 5829777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 5839777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 584661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (mCurrentCacheTexture->endOfMesh()) { 5859777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy issueDrawCommand(); 5869777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 5879777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy} 5889777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 589e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guyvoid FontRenderer::setFont(SkPaint* paint, const mat4& matrix) { 590e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy mCurrentFont = Font::create(this, paint, matrix); 591694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 5927975fb6d12cb1eb96b75e3a563627cd4c4081bd6Romain Guy 593f18136cb3c881a9d16c1a4f0f341732c276936bfAlex SakhartchoukFontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text, 594416a847633680d94efb926837efdc18726d54918Raph Levien uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) { 5951e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy checkInit(); 5961e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy 597cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy DropShadow image; 598cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.width = 0; 599cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.height = 0; 600cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.image = NULL; 601cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.penX = 0; 602cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.penY = 0; 603cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 6041e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy if (!mCurrentFont) { 6051e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy return image; 6061e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy } 607f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk 6082d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy mDrawn = false; 609ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy mClip = NULL; 610ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy mBounds = NULL; 611ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy 612f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk Rect bounds; 613416a847633680d94efb926837efdc18726d54918Raph Levien mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds, positions); 614ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy 6151e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius; 6161e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius; 617ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy 618cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint32_t maxSize = Caches::getInstance().maxTextureSize; 619cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (paddedWidth > maxSize || paddedHeight > maxSize) { 620cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy return image; 621cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 622cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 623e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#ifdef ANDROID_ENABLE_RENDERSCRIPT 624f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik // Align buffers for renderscript usage 625f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik if (paddedWidth & (RS_CPU_ALLOCATION_ALIGNMENT - 1)) { 626f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik paddedWidth += RS_CPU_ALLOCATION_ALIGNMENT - paddedWidth % RS_CPU_ALLOCATION_ALIGNMENT; 627f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk } 628f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik int size = paddedWidth * paddedHeight; 6296e2004089305cf2cd958b52b234459a49a4e5c83Romain Guy uint8_t* dataBuffer = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, size); 630e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#else 631e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill int size = paddedWidth * paddedHeight; 632e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill uint8_t* dataBuffer = (uint8_t*) malloc(size); 633e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#endif 634e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill 635f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik memset(dataBuffer, 0, size); 636f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik 637f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk int penX = radius - bounds.left; 638f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk int penY = radius - bounds.bottom; 639f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk 640dd8697c095272f19ddad214834a490b00f11a477Chris Craik if ((bounds.right > bounds.left) && (bounds.top > bounds.bottom)) { 641dd8697c095272f19ddad214834a490b00f11a477Chris Craik // text has non-whitespace, so draw and blur to create the shadow 642dd8697c095272f19ddad214834a490b00f11a477Chris Craik // NOTE: bounds.isEmpty() can't be used here, since vertical coordinates are inverted 643dd8697c095272f19ddad214834a490b00f11a477Chris Craik // TODO: don't draw pure whitespace in the first place, and avoid needing this check 644dd8697c095272f19ddad214834a490b00f11a477Chris Craik mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY, 645dd8697c095272f19ddad214834a490b00f11a477Chris Craik Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions); 646dd8697c095272f19ddad214834a490b00f11a477Chris Craik 647cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // Unbind any PBO we might have used 648cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy Caches::getInstance().unbindPixelBuffer(); 649cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 650dd8697c095272f19ddad214834a490b00f11a477Chris Craik blurImage(&dataBuffer, paddedWidth, paddedHeight, radius); 651dd8697c095272f19ddad214834a490b00f11a477Chris Craik } 652f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk 653f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.width = paddedWidth; 654f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.height = paddedHeight; 655f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.image = dataBuffer; 656f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.penX = penX; 657f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.penY = penY; 6582d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy 659f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk return image; 660f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk} 661694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 662257ae3502cfad43df681b1783528d645bdabc63fRomain Guyvoid FontRenderer::initRender(const Rect* clip, Rect* bounds, Functor* functor) { 663694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy checkInit(); 664694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 6655b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mDrawn = false; 6665b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mBounds = bounds; 667257ae3502cfad43df681b1783528d645bdabc63fRomain Guy mFunctor = functor; 66809147fbdc8206a0cac78bfe9083e7e15b3c5689cRomain Guy mClip = clip; 669671d6cf460531825a321edb200523d0faa7792c9Romain Guy} 670ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy 671671d6cf460531825a321edb200523d0faa7792c9Romain Guyvoid FontRenderer::finishRender() { 6725b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mBounds = NULL; 673ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy mClip = NULL; 674694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 675661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy issueDrawCommand(); 676671d6cf460531825a321edb200523d0faa7792c9Romain Guy} 677671d6cf460531825a321edb200523d0faa7792c9Romain Guy 678e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guyvoid FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs, const mat4& matrix) { 679e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy Font* font = Font::create(this, paint, matrix); 680e816baea651476aca4407200d4a5e629b9ab8dfaChet Haase font->precache(paint, text, numGlyphs); 681e816baea651476aca4407200d4a5e629b9ab8dfaChet Haase} 682e816baea651476aca4407200d4a5e629b9ab8dfaChet Haase 683cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid FontRenderer::endPrecaching() { 684cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy checkTextureUpdate(); 685cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 686cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 687671d6cf460531825a321edb200523d0faa7792c9Romain Guybool FontRenderer::renderPosText(SkPaint* paint, const Rect* clip, const char *text, 688671d6cf460531825a321edb200523d0faa7792c9Romain Guy uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, 689527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik const float* positions, Rect* bounds, Functor* functor, bool forceFinish) { 690671d6cf460531825a321edb200523d0faa7792c9Romain Guy if (!mCurrentFont) { 691671d6cf460531825a321edb200523d0faa7792c9Romain Guy ALOGE("No font set"); 692671d6cf460531825a321edb200523d0faa7792c9Romain Guy return false; 693671d6cf460531825a321edb200523d0faa7792c9Romain Guy } 694671d6cf460531825a321edb200523d0faa7792c9Romain Guy 695257ae3502cfad43df681b1783528d645bdabc63fRomain Guy initRender(clip, bounds, functor); 696671d6cf460531825a321edb200523d0faa7792c9Romain Guy mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y, positions); 697527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik 698527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik if (forceFinish) { 699527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik finishRender(); 700527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik } 7015b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 7025b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return mDrawn; 7039777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy} 7049777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 7059777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guybool FontRenderer::renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, 7069777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy uint32_t startIndex, uint32_t len, int numGlyphs, SkPath* path, 7071e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease float hOffset, float vOffset, Rect* bounds, Functor* functor) { 7089777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy if (!mCurrentFont) { 7099777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy ALOGE("No font set"); 7109777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy return false; 7119777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 7129777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 7131e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease initRender(clip, bounds, functor); 7149777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy mCurrentFont->render(paint, text, startIndex, len, numGlyphs, path, hOffset, vOffset); 7159777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy finishRender(); 7169777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 7179777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy return mDrawn; 718694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 719694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 7209b1204baf4740b4d443e72157dea98571cf84e1fRomain Guyvoid FontRenderer::removeFont(const Font* font) { 721e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy mActiveFonts.remove(font->getDescription()); 7229b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 7239b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy if (mCurrentFont == font) { 7249b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy mCurrentFont = NULL; 7259b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy } 7269b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy} 7279b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 728f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craikvoid FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, int32_t radius) { 729e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#ifdef ANDROID_ENABLE_RENDERSCRIPT 730e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill if (width * height * radius >= RS_MIN_INPUT_CUTOFF) { 731e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill uint8_t* outImage = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height); 732e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill 733250b1cfc831fd2a271c09cab547efcc5e3d5f828Tim Murray if (mRs == 0) { 734e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill mRs = new RSC::RS(); 7357a454ba5fee0bbb9f2e1292f8eede655516c0f2cTim Murray if (!mRs->init(RSC::RS_INIT_LOW_LATENCY | RSC::RS_INIT_SYNCHRONOUS)) { 736e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill ALOGE("blur RS failed to init"); 737e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill } 73889a524ac2d4a36739e51b01b336c0bade77e2ee0Alex Sakhartchouk 739e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill mRsElement = RSC::Element::A_8(mRs); 740d8c8aaa82ef90f30df647ca42453e953ee52af0fTim Murray mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement); 741e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill } 742f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik 743250b1cfc831fd2a271c09cab547efcc5e3d5f828Tim Murray RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0); 744250b1cfc831fd2a271c09cab547efcc5e3d5f828Tim Murray RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t, 745250b1cfc831fd2a271c09cab547efcc5e3d5f828Tim Murray RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, 746250b1cfc831fd2a271c09cab547efcc5e3d5f828Tim Murray *image); 747250b1cfc831fd2a271c09cab547efcc5e3d5f828Tim Murray RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t, 748250b1cfc831fd2a271c09cab547efcc5e3d5f828Tim Murray RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, 749250b1cfc831fd2a271c09cab547efcc5e3d5f828Tim Murray outImage); 750f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik 751e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill mRsScript->setRadius(radius); 752d8c8aaa82ef90f30df647ca42453e953ee52af0fTim Murray mRsScript->setInput(ain); 753d8c8aaa82ef90f30df647ca42453e953ee52af0fTim Murray mRsScript->forEach(aout); 754f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik 755e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill // replace the original image's pointer, avoiding a copy back to the original buffer 756e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill free(*image); 757e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill *image = outImage; 758f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik 759e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill return; 760f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik } 761e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#endif 762d71dd367af604571c7d00ca473184a1b9240eca2Romain Guy 763e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill float *gaussian = new float[2 * radius + 1]; 764e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill Blur::generateGaussianWeights(gaussian, radius); 765d71dd367af604571c7d00ca473184a1b9240eca2Romain Guy 766e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill uint8_t* scratch = new uint8_t[width * height]; 767e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill Blur::horizontal(gaussian, radius, *image, scratch, width, height); 768e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill Blur::vertical(gaussian, radius, scratch, *image, width, height); 769d71dd367af604571c7d00ca473184a1b9240eca2Romain Guy 770e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill delete[] gaussian; 771e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill delete[] scratch; 77289a524ac2d4a36739e51b01b336c0bade77e2ee0Alex Sakhartchouk} 77389a524ac2d4a36739e51b01b336c0bade77e2ee0Alex Sakhartchouk 7741e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasestatic uint32_t calculateCacheSize(const Vector<CacheTexture*>& cacheTextures) { 775cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint32_t size = 0; 7761e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 7771e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = cacheTextures[i]; 778cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (cacheTexture && cacheTexture->getPixelBuffer()) { 779cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy size += cacheTexture->getPixelBuffer()->getSize(); 780cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 781cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 782cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy return size; 783cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 784cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 7851e546815bbb736c50679a8aefc25f48561026fc5Victoria Leaseuint32_t FontRenderer::getCacheSize(GLenum format) const { 7861e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease switch (format) { 7871e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case GL_ALPHA: { 7881e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return calculateCacheSize(mACacheTextures); 7891e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 7901e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case GL_RGBA: { 7911e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return calculateCacheSize(mRGBACacheTextures); 7921e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 7931e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease default: { 7941e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return 0; 7951e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 7961e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 7971e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 7981e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 799694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy}; // namespace uirenderer 800694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy}; // namespace android 801