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