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