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 } 7576d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger renderer->setupDrawColorFilter(paint->getColorFilter()); 76d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III renderer->setupDrawShader(paint->getShader()); 7776d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger renderer->setupDrawBlending(paint); 781e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawProgram(); 794063a0e03ba2e354cc6d19c0ffc073fd5b8aa2caChris Craik renderer->setupDrawModelView(kModelViewMode_Translate, false, 804063a0e03ba2e354cc6d19c0ffc073fd5b8aa2caChris Craik 0.0f, 0.0f, 0.0f, 0.0f, pureTranslate); 811e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // Calling setupDrawTexture with the name 0 will enable the 821e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // uv attributes and increase the texture unit count 831e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // texture binding will be performed by the font renderer as 841e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // needed 851e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawTexture(0); 861e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawPureColorUniforms(); 8776d3a1b8d035d27bc80b0f2fc480a903bd001514Derek Sollenberger renderer->setupDrawColorFilterUniforms(paint->getColorFilter()); 88d1ad5e62fda248c6d185cde3cb6d9f01a223066cLeon Scroggins III renderer->setupDrawShaderUniforms(paint->getShader(), pureTranslate); 891e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease renderer->setupDrawTextGammaUniforms(); 901e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 911e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return NO_ERROR; 921e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 931e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 941e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease/////////////////////////////////////////////////////////////////////////////// 95694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy// FontRenderer 96694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy/////////////////////////////////////////////////////////////////////////////// 97694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 98514fb18827186591d66973c2362c859b64b63556Romain Guystatic bool sLogFontRendererCreate = true; 99514fb18827186591d66973c2362c859b64b63556Romain Guy 100e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain GuyFontRenderer::FontRenderer() : 101e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy mActiveFonts(LruCache<Font::FontDescription, Font*>::kUnlimitedCapacity) { 102e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy 103c9855a53edfac818dc68714557185977556f849dRomain Guy if (sLogFontRendererCreate) { 104c9855a53edfac818dc68714557185977556f849dRomain Guy INIT_LOGD("Creating FontRenderer"); 105c9855a53edfac818dc68714557185977556f849dRomain Guy } 10651769a68a5cb34e9564740c6a854fcb93018789dRomain Guy 107b45c0c9774bd19a9dbe77d149abae4e124b08bf6Romain Guy mGammaTable = NULL; 108694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy mInitialized = false; 109694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 1107de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase mCurrentCacheTexture = NULL; 1119cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy 1122a47c14e2a6f152496b43104bc785c488583fd59Chet Haase mLinearFiltering = false; 1132a47c14e2a6f152496b43104bc785c488583fd59Chet Haase 114eb32a499194119b3783b86c925172df02e5d2685Chet Haase mSmallCacheWidth = DEFAULT_TEXT_SMALL_CACHE_WIDTH; 115eb32a499194119b3783b86c925172df02e5d2685Chet Haase mSmallCacheHeight = DEFAULT_TEXT_SMALL_CACHE_HEIGHT; 116eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheWidth = DEFAULT_TEXT_LARGE_CACHE_WIDTH; 117eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheHeight = DEFAULT_TEXT_LARGE_CACHE_HEIGHT; 11851769a68a5cb34e9564740c6a854fcb93018789dRomain Guy 11951769a68a5cb34e9564740c6a854fcb93018789dRomain Guy char property[PROPERTY_VALUE_MAX]; 120eb32a499194119b3783b86c925172df02e5d2685Chet Haase if (property_get(PROPERTY_TEXT_SMALL_CACHE_WIDTH, property, NULL) > 0) { 1217de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase mSmallCacheWidth = atoi(property); 12251769a68a5cb34e9564740c6a854fcb93018789dRomain Guy } 1239f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 124eb32a499194119b3783b86c925172df02e5d2685Chet Haase if (property_get(PROPERTY_TEXT_SMALL_CACHE_HEIGHT, property, NULL) > 0) { 1257de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase mSmallCacheHeight = atoi(property); 126eb32a499194119b3783b86c925172df02e5d2685Chet Haase } 1279f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 128eb32a499194119b3783b86c925172df02e5d2685Chet Haase if (property_get(PROPERTY_TEXT_LARGE_CACHE_WIDTH, property, NULL) > 0) { 129eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheWidth = atoi(property); 130eb32a499194119b3783b86c925172df02e5d2685Chet Haase } 1319f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 132eb32a499194119b3783b86c925172df02e5d2685Chet Haase if (property_get(PROPERTY_TEXT_LARGE_CACHE_HEIGHT, property, NULL) > 0) { 133eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheHeight = atoi(property); 134eb32a499194119b3783b86c925172df02e5d2685Chet Haase } 1359f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 1369f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint32_t maxTextureSize = (uint32_t) Caches::getInstance().maxTextureSize; 1379f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mSmallCacheWidth = mSmallCacheWidth > maxTextureSize ? maxTextureSize : mSmallCacheWidth; 1389f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mSmallCacheHeight = mSmallCacheHeight > maxTextureSize ? maxTextureSize : mSmallCacheHeight; 1399f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mLargeCacheWidth = mLargeCacheWidth > maxTextureSize ? maxTextureSize : mLargeCacheWidth; 1409f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mLargeCacheHeight = mLargeCacheHeight > maxTextureSize ? maxTextureSize : mLargeCacheHeight; 1419f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 142eb32a499194119b3783b86c925172df02e5d2685Chet Haase if (sLogFontRendererCreate) { 143eb32a499194119b3783b86c925172df02e5d2685Chet Haase INIT_LOGD(" Text cache sizes, in pixels: %i x %i, %i x %i, %i x %i, %i x %i", 144eb32a499194119b3783b86c925172df02e5d2685Chet Haase mSmallCacheWidth, mSmallCacheHeight, 145eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheWidth, mLargeCacheHeight >> 1, 146eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheWidth, mLargeCacheHeight >> 1, 147eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheWidth, mLargeCacheHeight); 14851769a68a5cb34e9564740c6a854fcb93018789dRomain Guy } 149514fb18827186591d66973c2362c859b64b63556Romain Guy 150514fb18827186591d66973c2362c859b64b63556Romain Guy sLogFontRendererCreate = false; 151694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 152694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 1531e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid clearCacheTextures(Vector<CacheTexture*>& cacheTextures) { 1541e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 1551e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease delete cacheTextures[i]; 156694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 1571e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease cacheTextures.clear(); 1581e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 1591e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 1601e546815bbb736c50679a8aefc25f48561026fc5Victoria LeaseFontRenderer::~FontRenderer() { 1611e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease clearCacheTextures(mACacheTextures); 1621e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease clearCacheTextures(mRGBACacheTextures); 163694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 164e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); 165e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy while (it.next()) { 166e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy delete it.value(); 167694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 168e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy mActiveFonts.clear(); 169694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 170694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 171694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guyvoid FontRenderer::flushAllAndInvalidate() { 172661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy issueDrawCommand(); 1739d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 174e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); 175e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy while (it.next()) { 176e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy it.value()->invalidateTextureCache(); 177694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 1789d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 1791e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < mACacheTextures.size(); i++) { 1801e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mACacheTextures[i]->init(); 1811e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 1821e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 1831e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < mRGBACacheTextures.size(); i++) { 1841e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mRGBACacheTextures[i]->init(); 185e816baea651476aca4407200d4a5e629b9ab8dfaChet Haase } 186694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 187694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 1881e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid FontRenderer::flushLargeCaches(Vector<CacheTexture*>& cacheTextures) { 189378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase // Start from 1; don't deallocate smallest/default texture 1901e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 1; i < cacheTextures.size(); i++) { 1911e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = cacheTextures[i]; 192cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (cacheTexture->getPixelBuffer()) { 193378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase cacheTexture->init(); 194e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); 195e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy while (it.next()) { 196e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy it.value()->invalidateTextureCache(cacheTexture); 1979a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase } 1988087246d9964b11de8ce116bc63b156faa4197e0Romain Guy cacheTexture->releaseTexture(); 1999a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase } 2009a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase } 2019a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase} 2029a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase 2031e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid FontRenderer::flushLargeCaches() { 2041e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease flushLargeCaches(mACacheTextures); 2051e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease flushLargeCaches(mRGBACacheTextures); 2061e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 2071e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 2081e546815bbb736c50679a8aefc25f48561026fc5Victoria LeaseCacheTexture* FontRenderer::cacheBitmapInTexture(Vector<CacheTexture*>& cacheTextures, 2091e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease const SkGlyph& glyph, uint32_t* startX, uint32_t* startY) { 2101e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 2111e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (cacheTextures[i]->fitBitmap(glyph, startX, startY)) { 2121e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return cacheTextures[i]; 213378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase } 214378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase } 215378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase // Could not fit glyph into current cache textures 216378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase return NULL; 217378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase} 218378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase 2197de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haasevoid FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, 220f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase uint32_t* retOriginX, uint32_t* retOriginY, bool precaching) { 2212efd5c5886d9acf747bc92f888d731ed558aabccChet Haase checkInit(); 222a4adcf0239039eb8f005be252409901c41b28839Romain Guy 223a4adcf0239039eb8f005be252409901c41b28839Romain Guy // If the glyph bitmap is empty let's assum the glyph is valid 224a4adcf0239039eb8f005be252409901c41b28839Romain Guy // so we can avoid doing extra work later on 225a4adcf0239039eb8f005be252409901c41b28839Romain Guy if (glyph.fWidth == 0 || glyph.fHeight == 0) { 226a4adcf0239039eb8f005be252409901c41b28839Romain Guy cachedGlyph->mIsValid = true; 227a4adcf0239039eb8f005be252409901c41b28839Romain Guy cachedGlyph->mCacheTexture = NULL; 228a4adcf0239039eb8f005be252409901c41b28839Romain Guy return; 229a4adcf0239039eb8f005be252409901c41b28839Romain Guy } 230a4adcf0239039eb8f005be252409901c41b28839Romain Guy 2317de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase cachedGlyph->mIsValid = false; 232a4adcf0239039eb8f005be252409901c41b28839Romain Guy 2331e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // choose an appropriate cache texture list for this glyph format 2341e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat); 2351e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease Vector<CacheTexture*>* cacheTextures = NULL; 2361e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease switch (format) { 2371e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kA8_Format: 238723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease case SkMask::kBW_Format: 2391e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease cacheTextures = &mACacheTextures; 2401e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 2411e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kARGB32_Format: 2421e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease cacheTextures = &mRGBACacheTextures; 2431e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 2441e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease default: 2451e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#if DEBUG_FONT_RENDERER 2461e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease ALOGD("getCacheTexturesForFormat: unknown SkMask format %x", format); 2471e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#endif 2481e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return; 2491e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 2501e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 251694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy // If the glyph is too tall, don't cache it 252378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > 2531e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease (*cacheTextures)[cacheTextures->size() - 1]->getHeight()) { 2542efd5c5886d9acf747bc92f888d731ed558aabccChet Haase ALOGE("Font size too large to fit in cache. width, height = %i, %i", 2552efd5c5886d9acf747bc92f888d731ed558aabccChet Haase (int) glyph.fWidth, (int) glyph.fHeight); 2567de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase return; 257694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 258694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 259694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy // Now copy the bitmap into the cache texture 260694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy uint32_t startX = 0; 261694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy uint32_t startY = 0; 262694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 2631e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY); 264694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 265378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase if (!cacheTexture) { 266f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase if (!precaching) { 267f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase // If the new glyph didn't fit and we are not just trying to precache it, 268f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase // clear out the cache and try again 269f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase flushAllAndInvalidate(); 2701e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY); 271f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase } 272694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 273378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase if (!cacheTexture) { 274f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase // either the glyph didn't fit or we're precaching and will cache it when we draw 2757de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase return; 276694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 277694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 278694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 279378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase cachedGlyph->mCacheTexture = cacheTexture; 2807de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase 281694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy *retOriginX = startX; 282694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy *retOriginY = startY; 283694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 284694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy uint32_t endX = startX + glyph.fWidth; 285694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy uint32_t endY = startY + glyph.fHeight; 286694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 2878087246d9964b11de8ce116bc63b156faa4197e0Romain Guy uint32_t cacheWidth = cacheTexture->getWidth(); 288694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 289cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (!cacheTexture->getPixelBuffer()) { 2908087246d9964b11de8ce116bc63b156faa4197e0Romain Guy Caches::getInstance().activeTexture(0); 2917de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase // Large-glyph texture memory is allocated only as needed 2928087246d9964b11de8ce116bc63b156faa4197e0Romain Guy cacheTexture->allocateTexture(); 2937de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase } 294661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (!cacheTexture->mesh()) { 295661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy cacheTexture->allocateMesh(); 296661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 2979d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 298cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint8_t* cacheBuffer = cacheTexture->getPixelBuffer()->map(); 299b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy uint8_t* bitmapBuffer = (uint8_t*) glyph.fImage; 3001e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease int srcStride = glyph.rowBytes(); 3010b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy 3021e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // Copy the glyph image, taking the mask format into account 303b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy switch (format) { 304b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy case SkMask::kA8_Format: { 3051e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 3061e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX 3071e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease - TEXTURE_BORDER_SIZE; 3081e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write leading border line 3091e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 3101e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write glyph data 311b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy if (mGammaTable) { 3121e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) { 3130b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy row = cacheY * cacheWidth; 3140b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; 315b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) { 316b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy uint8_t tempCol = bitmapBuffer[bY + bX]; 3170b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + cacheX] = mGammaTable[tempCol]; 318b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 3190b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; 320b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 321b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } else { 3221e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) { 3230b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy row = cacheY * cacheWidth; 3240b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy memcpy(&cacheBuffer[row + startX], &bitmapBuffer[bY], glyph.fWidth); 3250b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; 3260b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; 327b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 328b1d0a4ed21168fefcb82232c8f22cb95d60acb85Romain Guy } 3291e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write trailing border line 3301e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE; 3311e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 3321e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 3331e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 3341e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kARGB32_Format: { 3351e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // prep data lengths 3361e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease const size_t formatSize = PixelBuffer::formatSize(GL_RGBA); 3371e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease const size_t borderSize = formatSize * TEXTURE_BORDER_SIZE; 3381e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease size_t rowSize = formatSize * glyph.fWidth; 3391e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // prep advances 3401e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease size_t dstStride = formatSize * cacheWidth; 3411e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // prep indices 3421e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // - we actually start one row early, and then increment before first copy 3431e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* src = &bitmapBuffer[0 - srcStride]; 3441e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* dst = &cacheBuffer[cacheTexture->getOffset(startX, startY - 1)]; 3451e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* dstEnd = &cacheBuffer[cacheTexture->getOffset(startX, endY - 1)]; 3461e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* dstL = dst - borderSize; 3471e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* dstR = dst + rowSize; 3481e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write leading border line 3491e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(dstL, 0, rowSize + 2 * borderSize); 3501e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write glyph data 3511e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease while (dst < dstEnd) { 3521e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(dstL += dstStride, 0, borderSize); // leading border column 3531e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memcpy(dst += dstStride, src += srcStride, rowSize); // glyph data 3541e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(dstR += dstStride, 0, borderSize); // trailing border column 3551e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 3561e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write trailing border line 35716c84069a4cc0c0d3c35e798dc5e4b0130d4a26fVictoria Lease memset(dstL += dstStride, 0, rowSize + 2 * borderSize); 358b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy break; 359b1d0a4ed21168fefcb82232c8f22cb95d60acb85Romain Guy } 360b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy case SkMask::kBW_Format: { 3611e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 3621e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX 3631e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease - TEXTURE_BORDER_SIZE; 364b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy static const uint8_t COLORS[2] = { 0, 255 }; 3651e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write leading border line 3661e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 3671e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write glyph data 368b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy for (cacheY = startY; cacheY < endY; cacheY++) { 369b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy cacheX = startX; 3701e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease int rowBytes = srcStride; 371b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy uint8_t* buffer = bitmapBuffer; 372b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy 3730b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy row = cacheY * cacheWidth; 3740b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; 375b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy while (--rowBytes >= 0) { 376b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy uint8_t b = *buffer++; 377b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy for (int8_t mask = 7; mask >= 0 && cacheX < endX; mask--) { 378b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy cacheBuffer[cacheY * cacheWidth + cacheX++] = COLORS[(b >> mask) & 0x1]; 379b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 380b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 3810b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; 382b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy 3831e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease bitmapBuffer += srcStride; 384b1d0a4ed21168fefcb82232c8f22cb95d60acb85Romain Guy } 3851e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write trailing border line 3861e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE; 3871e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 388b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy break; 389694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 390b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy default: 3911e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease ALOGW("Unknown glyph format: 0x%x", format); 392b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy break; 393694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 3949777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 3957de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase cachedGlyph->mIsValid = true; 396694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 397694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 3981e546815bbb736c50679a8aefc25f48561026fc5Victoria LeaseCacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum format, 3991e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease bool allocate) { 4001e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = new CacheTexture(width, height, format, gMaxNumberOfQuads); 4019d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 4022a47c14e2a6f152496b43104bc785c488583fd59Chet Haase if (allocate) { 4038087246d9964b11de8ce116bc63b156faa4197e0Romain Guy Caches::getInstance().activeTexture(0); 4048087246d9964b11de8ce116bc63b156faa4197e0Romain Guy cacheTexture->allocateTexture(); 405661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy cacheTexture->allocateMesh(); 4062a47c14e2a6f152496b43104bc785c488583fd59Chet Haase } 4079d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 4082a47c14e2a6f152496b43104bc785c488583fd59Chet Haase return cacheTexture; 4097de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase} 4107de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase 4117de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haasevoid FontRenderer::initTextTexture() { 4121e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease clearCacheTextures(mACacheTextures); 4131e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease clearCacheTextures(mRGBACacheTextures); 4149d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 4157de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase mUploadTexture = false; 4161e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mACacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, 4171e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_ALPHA, true)); 4181e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, 4191e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_ALPHA, false)); 4201e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, 4211e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_ALPHA, false)); 4221e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight, 4231e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_ALPHA, false)); 4241e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mRGBACacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, 4251e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_RGBA, false)); 4261e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mRGBACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, 4271e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_RGBA, false)); 4281e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mCurrentCacheTexture = mACacheTextures[0]; 429694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 430694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 431694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy// We don't want to allocate anything unless we actually draw text 432694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guyvoid FontRenderer::checkInit() { 433694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy if (mInitialized) { 434694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy return; 435694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 436694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 437694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy initTextTexture(); 438694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 439694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy mInitialized = true; 440694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 441694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 4421e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid checkTextureUpdateForCache(Caches& caches, Vector<CacheTexture*>& cacheTextures, 4431e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease bool& resetPixelStore, GLuint& lastTextureId) { 4441e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 4451e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = cacheTextures[i]; 446cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (cacheTexture->isDirty() && cacheTexture->getPixelBuffer()) { 4478087246d9964b11de8ce116bc63b156faa4197e0Romain Guy if (cacheTexture->getTextureId() != lastTextureId) { 4488087246d9964b11de8ce116bc63b156faa4197e0Romain Guy lastTextureId = cacheTexture->getTextureId(); 4492d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy caches.activeTexture(0); 4508aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy caches.bindTexture(lastTextureId); 4510908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy } 4520908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy 453cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (cacheTexture->upload()) { 454cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy resetPixelStore = true; 4552d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy } 4569b9902ddbb01548f4a0199087b7035e7c10b2ae7Alex Sakhartchouk } 457694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 4581e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 4591e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 4601e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid FontRenderer::checkTextureUpdate() { 4611e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (!mUploadTexture) { 4621e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return; 4631e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 4641e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 4651e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease Caches& caches = Caches::getInstance(); 4661e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GLuint lastTextureId = 0; 4671e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 4681e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease bool resetPixelStore = false; 4691e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 4701e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 4711e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // Iterate over all the cache textures and see which ones need to be updated 4721e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease checkTextureUpdateForCache(caches, mACacheTextures, resetPixelStore, lastTextureId); 4731e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease checkTextureUpdateForCache(caches, mRGBACacheTextures, resetPixelStore, lastTextureId); 474694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 475cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // Unbind any PBO we might have used to update textures 476cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy caches.unbindPixelBuffer(); 477cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 4780908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy // Reset to default unpack row length to avoid affecting texture 4790908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy // uploads in other parts of the renderer 480cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (resetPixelStore) { 4810908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 4820908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy } 4830908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy 4849b9902ddbb01548f4a0199087b7035e7c10b2ae7Alex Sakhartchouk mUploadTexture = false; 4859b9902ddbb01548f4a0199087b7035e7c10b2ae7Alex Sakhartchouk} 4869b9902ddbb01548f4a0199087b7035e7c10b2ae7Alex Sakhartchouk 4871e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) { 4881e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease Caches& caches = Caches::getInstance(); 489661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy bool first = true; 490661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy bool force = false; 4911e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 4921e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* texture = cacheTextures[i]; 493661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (texture->canDraw()) { 494661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (first) { 4951e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (mFunctor) { 4961e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease TextSetupFunctor::Data functorData(texture->getFormat()); 4971e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease (*mFunctor)(0, &functorData); 4981e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 499257ae3502cfad43df681b1783528d645bdabc63fRomain Guy 500661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy checkTextureUpdate(); 50163d41abb40b3ce40d8b9bccb1cf186e8158a3687ztenghui caches.bindQuadIndicesBuffer(); 502661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 503661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (!mDrawn) { 504661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // If returns true, a VBO was bound and we must 505661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // rebind our vertex attrib pointers even if 506661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // they have the same values as the current pointers 507661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy force = caches.unbindMeshBuffer(); 508661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 50915bc6437f8b4cf10dba55c7638d349e7b9563f4fRomain Guy 510661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy caches.activeTexture(0); 511661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy first = false; 512661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 5137bb3cfe1cca4016ce95d3ef059761f4bb2d668bbSangkyu Lee 5148aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy caches.bindTexture(texture->getTextureId()); 515661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy texture->setLinearFiltering(mLinearFiltering, false); 5167bb3cfe1cca4016ce95d3ef059761f4bb2d668bbSangkyu Lee 517661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy TextureVertex* mesh = texture->mesh(); 5183380cfdc77100e87aa8390386ccf390834dea171Romain Guy caches.bindPositionVertexPointer(force, &mesh[0].x); 5193380cfdc77100e87aa8390386ccf390834dea171Romain Guy caches.bindTexCoordsVertexPointer(force, &mesh[0].u); 520661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy force = false; 521661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 522661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glDrawElements(GL_TRIANGLES, texture->meshElementCount(), 523661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy GL_UNSIGNED_SHORT, texture->indices()); 5247bb3cfe1cca4016ce95d3ef059761f4bb2d668bbSangkyu Lee 525661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy texture->resetMesh(); 526661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 5277bb3cfe1cca4016ce95d3ef059761f4bb2d668bbSangkyu Lee } 5281e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 5291e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 5301e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid FontRenderer::issueDrawCommand() { 5311e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease issueDrawCommand(mACacheTextures); 5321e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease issueDrawCommand(mRGBACacheTextures); 5335b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 5345b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mDrawn = true; 535694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 536694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 5379777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guyvoid FontRenderer::appendMeshQuadNoClip(float x1, float y1, float u1, float v1, 5389777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3, 5397de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase float x4, float y4, float u4, float v4, CacheTexture* texture) { 5407de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase if (texture != mCurrentCacheTexture) { 5417de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase // Now use the new texture id 5427de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase mCurrentCacheTexture = texture; 5437de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase } 54409147fbdc8206a0cac78bfe9083e7e15b3c5689cRomain Guy 545661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCurrentCacheTexture->addQuad(x1, y1, u1, v1, x2, y2, u2, v2, 546661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy x3, y3, u3, v3, x4, y4, u4, v4); 5479777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy} 5489777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5499777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guyvoid FontRenderer::appendMeshQuad(float x1, float y1, float u1, float v1, 5509777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3, 5519777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x4, float y4, float u4, float v4, CacheTexture* texture) { 5529777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5539777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy if (mClip && 5549777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy (x1 > mClip->right || y1 < mClip->top || x2 < mClip->left || y4 > mClip->bottom)) { 5559777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy return; 5569777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 5579777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5589777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture); 559694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 5605b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (mBounds) { 5615b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mBounds->left = fmin(mBounds->left, x1); 5625b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mBounds->top = fmin(mBounds->top, y3); 5635b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mBounds->right = fmax(mBounds->right, x3); 5645b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mBounds->bottom = fmax(mBounds->bottom, y1); 5655b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 5665b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 567661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (mCurrentCacheTexture->endOfMesh()) { 568694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy issueDrawCommand(); 569694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 570694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 571694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 5729777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guyvoid FontRenderer::appendRotatedMeshQuad(float x1, float y1, float u1, float v1, 5739777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3, 5749777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x4, float y4, float u4, float v4, CacheTexture* texture) { 5759777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5769777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture); 5779777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5789777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy if (mBounds) { 5799777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy mBounds->left = fmin(mBounds->left, fmin(x1, fmin(x2, fmin(x3, x4)))); 5809777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy mBounds->top = fmin(mBounds->top, fmin(y1, fmin(y2, fmin(y3, y4)))); 5819777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy mBounds->right = fmax(mBounds->right, fmax(x1, fmax(x2, fmax(x3, x4)))); 5829777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy mBounds->bottom = fmax(mBounds->bottom, fmax(y1, fmax(y2, fmax(y3, y4)))); 5839777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 5849777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 585661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (mCurrentCacheTexture->endOfMesh()) { 5869777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy issueDrawCommand(); 5879777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 5889777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy} 5899777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 59059744b79ec302000802cd56d30a1bf70f0183c80Chris Craikvoid FontRenderer::setFont(const SkPaint* paint, const SkMatrix& matrix) { 591e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy mCurrentFont = Font::create(this, paint, matrix); 592694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 5937975fb6d12cb1eb96b75e3a563627cd4c4081bd6Romain Guy 594d218a92c0afb8c0d98135b20b52ac87236e1c935Chris CraikFontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, const char *text, 595e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger uint32_t startIndex, uint32_t len, int numGlyphs, float radius, const float* positions) { 5961e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy checkInit(); 5971e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy 598cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy DropShadow image; 599cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.width = 0; 600cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.height = 0; 601cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.image = NULL; 602cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.penX = 0; 603cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.penY = 0; 604cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 6051e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy if (!mCurrentFont) { 6061e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy return image; 6071e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy } 608f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk 6092d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy mDrawn = false; 610ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy mClip = NULL; 611ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy mBounds = NULL; 612ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy 613f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk Rect bounds; 614416a847633680d94efb926837efdc18726d54918Raph Levien mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds, positions); 615ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy 616e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger uint32_t intRadius = Blur::convertRadiusToInt(radius); 617e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * intRadius; 618e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * intRadius; 619ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy 620cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint32_t maxSize = Caches::getInstance().maxTextureSize; 621cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (paddedWidth > maxSize || paddedHeight > maxSize) { 622cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy return image; 623cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 624cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 625e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#ifdef ANDROID_ENABLE_RENDERSCRIPT 626f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik // Align buffers for renderscript usage 627f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik if (paddedWidth & (RS_CPU_ALLOCATION_ALIGNMENT - 1)) { 628f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik paddedWidth += RS_CPU_ALLOCATION_ALIGNMENT - paddedWidth % RS_CPU_ALLOCATION_ALIGNMENT; 629f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk } 630f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik int size = paddedWidth * paddedHeight; 6316e2004089305cf2cd958b52b234459a49a4e5c83Romain Guy uint8_t* dataBuffer = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, size); 632e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#else 633e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill int size = paddedWidth * paddedHeight; 634e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill uint8_t* dataBuffer = (uint8_t*) malloc(size); 635e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#endif 636e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill 637f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik memset(dataBuffer, 0, size); 638f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik 639e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger int penX = intRadius - bounds.left; 640e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger int penY = intRadius - bounds.bottom; 641f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk 642dd8697c095272f19ddad214834a490b00f11a477Chris Craik if ((bounds.right > bounds.left) && (bounds.top > bounds.bottom)) { 643dd8697c095272f19ddad214834a490b00f11a477Chris Craik // text has non-whitespace, so draw and blur to create the shadow 644dd8697c095272f19ddad214834a490b00f11a477Chris Craik // NOTE: bounds.isEmpty() can't be used here, since vertical coordinates are inverted 645dd8697c095272f19ddad214834a490b00f11a477Chris Craik // TODO: don't draw pure whitespace in the first place, and avoid needing this check 646dd8697c095272f19ddad214834a490b00f11a477Chris Craik mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY, 647dd8697c095272f19ddad214834a490b00f11a477Chris Craik Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions); 648dd8697c095272f19ddad214834a490b00f11a477Chris Craik 649cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // Unbind any PBO we might have used 650cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy Caches::getInstance().unbindPixelBuffer(); 651cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 652dd8697c095272f19ddad214834a490b00f11a477Chris Craik blurImage(&dataBuffer, paddedWidth, paddedHeight, radius); 653dd8697c095272f19ddad214834a490b00f11a477Chris Craik } 654f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk 655f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.width = paddedWidth; 656f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.height = paddedHeight; 657f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.image = dataBuffer; 658f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.penX = penX; 659f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.penY = penY; 6602d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy 661f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk return image; 662f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk} 663694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 664257ae3502cfad43df681b1783528d645bdabc63fRomain Guyvoid FontRenderer::initRender(const Rect* clip, Rect* bounds, Functor* functor) { 665694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy checkInit(); 666694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 6675b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mDrawn = false; 6685b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mBounds = bounds; 669257ae3502cfad43df681b1783528d645bdabc63fRomain Guy mFunctor = functor; 67009147fbdc8206a0cac78bfe9083e7e15b3c5689cRomain Guy mClip = clip; 671671d6cf460531825a321edb200523d0faa7792c9Romain Guy} 672ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy 673671d6cf460531825a321edb200523d0faa7792c9Romain Guyvoid FontRenderer::finishRender() { 6745b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mBounds = NULL; 675ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy mClip = NULL; 676694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 677661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy issueDrawCommand(); 678671d6cf460531825a321edb200523d0faa7792c9Romain Guy} 679671d6cf460531825a321edb200523d0faa7792c9Romain Guy 680d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craikvoid FontRenderer::precache(const SkPaint* paint, const char* text, int numGlyphs, 68159744b79ec302000802cd56d30a1bf70f0183c80Chris Craik const SkMatrix& matrix) { 682e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy Font* font = Font::create(this, paint, matrix); 683e816baea651476aca4407200d4a5e629b9ab8dfaChet Haase font->precache(paint, text, numGlyphs); 684e816baea651476aca4407200d4a5e629b9ab8dfaChet Haase} 685e816baea651476aca4407200d4a5e629b9ab8dfaChet Haase 686cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid FontRenderer::endPrecaching() { 687cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy checkTextureUpdate(); 688cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 689cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 690d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craikbool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const char *text, 691671d6cf460531825a321edb200523d0faa7792c9Romain Guy uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, 692527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik const float* positions, Rect* bounds, Functor* functor, bool forceFinish) { 693671d6cf460531825a321edb200523d0faa7792c9Romain Guy if (!mCurrentFont) { 694671d6cf460531825a321edb200523d0faa7792c9Romain Guy ALOGE("No font set"); 695671d6cf460531825a321edb200523d0faa7792c9Romain Guy return false; 696671d6cf460531825a321edb200523d0faa7792c9Romain Guy } 697671d6cf460531825a321edb200523d0faa7792c9Romain Guy 698257ae3502cfad43df681b1783528d645bdabc63fRomain Guy initRender(clip, bounds, functor); 699671d6cf460531825a321edb200523d0faa7792c9Romain Guy mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y, positions); 700527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik 701527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik if (forceFinish) { 702527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik finishRender(); 703527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik } 7045b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 7055b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return mDrawn; 7069777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy} 7079777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 708d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craikbool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text, 709d218a92c0afb8c0d98135b20b52ac87236e1c935Chris Craik uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path, 7101e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease float hOffset, float vOffset, Rect* bounds, Functor* functor) { 7119777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy if (!mCurrentFont) { 7129777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy ALOGE("No font set"); 7139777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy return false; 7149777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 7159777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 7161e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease initRender(clip, bounds, functor); 7179777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy mCurrentFont->render(paint, text, startIndex, len, numGlyphs, path, hOffset, vOffset); 7189777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy finishRender(); 7199777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 7209777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy return mDrawn; 721694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 722694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 7239b1204baf4740b4d443e72157dea98571cf84e1fRomain Guyvoid FontRenderer::removeFont(const Font* font) { 724e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy mActiveFonts.remove(font->getDescription()); 7259b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 7269b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy if (mCurrentFont == font) { 7279b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy mCurrentFont = NULL; 7289b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy } 7299b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy} 7309b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 731e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenbergervoid FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, float radius) { 732e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger uint32_t intRadius = Blur::convertRadiusToInt(radius); 733e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#ifdef ANDROID_ENABLE_RENDERSCRIPT 734e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger if (width * height * intRadius >= RS_MIN_INPUT_CUTOFF) { 735e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill uint8_t* outImage = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height); 736e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill 737250b1cfc831fd2a271c09cab547efcc5e3d5f828Tim Murray if (mRs == 0) { 738e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill mRs = new RSC::RS(); 739abe55e92241fd9a19885f7b11db8d3043ab60c61Tim Murray // a null path is OK because there are no custom kernels used 740abe55e92241fd9a19885f7b11db8d3043ab60c61Tim Murray // hence nothing gets cached by RS 741abe55e92241fd9a19885f7b11db8d3043ab60c61Tim Murray if (!mRs->init("", RSC::RS_INIT_LOW_LATENCY | RSC::RS_INIT_SYNCHRONOUS)) { 742ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua mRs.clear(); 743e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill ALOGE("blur RS failed to init"); 744ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua } else { 745ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua mRsElement = RSC::Element::A_8(mRs); 746ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement); 747e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill } 748e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill } 749ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua if (mRs != 0) { 750ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0); 751ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t, 752ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RS_ALLOCATION_MIPMAP_NONE, 753ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, 754ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua *image); 755ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t, 756ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RS_ALLOCATION_MIPMAP_NONE, 757ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, 758ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua outImage); 759ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua 760ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua mRsScript->setRadius(radius); 761ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua mRsScript->setInput(ain); 762ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua mRsScript->forEach(aout); 763ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua 764ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua // replace the original image's pointer, avoiding a copy back to the original buffer 765ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua free(*image); 766ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua *image = outImage; 767f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik 768ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua return; 769ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua } 770f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik } 771e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#endif 772d71dd367af604571c7d00ca473184a1b9240eca2Romain Guy 773e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger float *gaussian = new float[2 * intRadius + 1]; 774e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger Blur::generateGaussianWeights(gaussian, intRadius); 775d71dd367af604571c7d00ca473184a1b9240eca2Romain Guy 776e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill uint8_t* scratch = new uint8_t[width * height]; 777e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger Blur::horizontal(gaussian, intRadius, *image, scratch, width, height); 778e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger Blur::vertical(gaussian, intRadius, scratch, *image, width, height); 779d71dd367af604571c7d00ca473184a1b9240eca2Romain Guy 780e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill delete[] gaussian; 781e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill delete[] scratch; 78289a524ac2d4a36739e51b01b336c0bade77e2ee0Alex Sakhartchouk} 78389a524ac2d4a36739e51b01b336c0bade77e2ee0Alex Sakhartchouk 7841e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasestatic uint32_t calculateCacheSize(const Vector<CacheTexture*>& cacheTextures) { 785cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint32_t size = 0; 7861e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 7871e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = cacheTextures[i]; 788cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (cacheTexture && cacheTexture->getPixelBuffer()) { 789cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy size += cacheTexture->getPixelBuffer()->getSize(); 790cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 791cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 792cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy return size; 793cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 794cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 7951e546815bbb736c50679a8aefc25f48561026fc5Victoria Leaseuint32_t FontRenderer::getCacheSize(GLenum format) const { 7961e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease switch (format) { 7971e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case GL_ALPHA: { 7981e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return calculateCacheSize(mACacheTextures); 7991e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 8001e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case GL_RGBA: { 8011e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return calculateCacheSize(mRGBACacheTextures); 8021e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 8031e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease default: { 8041e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return 0; 8051e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 8061e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 8071e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 8081e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 809694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy}; // namespace uirenderer 810694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy}; // namespace android 811