FontRenderer.cpp revision 804ff38bff2fbb0ee258b13b4bb66eb33d565724
1d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka/* 2d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * Copyright (C) 2010 The Android Open Source Project 3d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * 4d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * Licensed under the Apache License, Version 2.0 (the "License"); 5d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * you may not use this file except in compliance with the License. 6d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * You may obtain a copy of the License at 7d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * 8d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * http://www.apache.org/licenses/LICENSE-2.0 9d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * 10d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * Unless required by applicable law or agreed to in writing, software 11d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * distributed under the License is distributed on an "AS IS" BASIS, 12d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * See the License for the specific language governing permissions and 14d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * limitations under the License. 15d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka */ 16d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka 17d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka#define LOG_TAG "OpenGLRenderer" 18d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka 19b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa#include <SkGlyph.h> 20d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include <SkUtils.h> 21d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 22d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include <cutils/properties.h> 239b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 24d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa#include <utils/Log.h> 25d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka 26d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka#ifdef ANDROID_ENABLE_RENDERSCRIPT 27d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka#include <RenderScript.h> 28d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka#endif 294013940b62ae2227c9b30d8761d7533ee6190a9fYohei Yukawa 304013940b62ae2227c9b30d8761d7533ee6190a9fYohei Yukawa#include "utils/Blur.h" 314013940b62ae2227c9b30d8761d7533ee6190a9fYohei Yukawa#include "utils/Timing.h" 32d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 33d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include "Caches.h" 34d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include "Debug.h" 35d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include "Extensions.h" 36d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include "FontRenderer.h" 37d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include "OpenGLRenderer.h" 38d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include "PixelBuffer.h" 3907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa#include "Rect.h" 40d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 41d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokanamespace android { 42d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokanamespace uirenderer { 43d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka 445a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa// blur inputs smaller than this constant will bypass renderscript 455a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa#define RS_MIN_INPUT_CUTOFF 10000 465a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa 475a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa/////////////////////////////////////////////////////////////////////////////// 48d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka// TextSetupFunctor 49d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka/////////////////////////////////////////////////////////////////////////////// 50d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokastatus_t TextSetupFunctor::operator ()(int what, void* data) { 51d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka Data* typedData = reinterpret_cast<Data*>(data); 52d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka GLenum glyphFormat = typedData ? typedData->glyphFormat : GL_ALPHA; 53d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 54d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka renderer->setupDraw(); 55d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka renderer->setupDrawTextGamma(paint); 56d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka renderer->setupDrawDirtyRegionsDisabled(); 57d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka renderer->setupDrawWithTexture(glyphFormat == GL_ALPHA); 58d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka switch (glyphFormat) { 5971cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa case GL_ALPHA: { 6071cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa renderer->setupDrawAlpha8Color(paint->getColor(), alpha); 61d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka break; 62d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 63d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka case GL_RGBA: { 64d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka float floatAlpha = alpha / 255.0f; 65d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka renderer->setupDrawColor(floatAlpha, floatAlpha, floatAlpha, floatAlpha); 66d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka break; 67d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 68d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka default: { 69d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#if DEBUG_FONT_RENDERER 70d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka ALOGD("TextSetupFunctor: called with unknown glyph format %x", glyphFormat); 71d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#endif 72d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka break; 7371cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa } 7471cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa } 7571cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa renderer->setupDrawColorFilter(); 7671cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa renderer->setupDrawShader(); 7771cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa renderer->setupDrawBlending(true, mode); 7871cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa renderer->setupDrawProgram(); 7971cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa renderer->setupDrawModelView(x, y, x, y, pureTranslate, true); 8071cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa // Calling setupDrawTexture with the name 0 will enable the 8171cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa // uv attributes and increase the texture unit count 8271cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa // texture binding will be performed by the font renderer as 8371cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa // needed 8471cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa renderer->setupDrawTexture(0); 8571cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa renderer->setupDrawPureColorUniforms(); 8671cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa renderer->setupDrawColorFilterUniforms(); 8771cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa renderer->setupDrawShaderUniforms(pureTranslate); 8871cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa renderer->setupDrawTextGammaUniforms(); 8971cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa 9071cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa return NO_ERROR; 9171cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa} 9271cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa 9371cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa/////////////////////////////////////////////////////////////////////////////// 9471cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa// FontRenderer 95d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka/////////////////////////////////////////////////////////////////////////////// 96d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 97d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokastatic bool sLogFontRendererCreate = true; 98d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 99d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi KataokaFontRenderer::FontRenderer() : 100d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mActiveFonts(LruCache<Font::FontDescription, Font*>::kUnlimitedCapacity) { 101d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 102d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (sLogFontRendererCreate) { 103d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka INIT_LOGD("Creating FontRenderer"); 104d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 105d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 106d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mGammaTable = NULL; 107d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mInitialized = false; 108d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 109d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mCurrentCacheTexture = NULL; 110d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 111d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mLinearFiltering = false; 112d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 113d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mSmallCacheWidth = DEFAULT_TEXT_SMALL_CACHE_WIDTH; 114d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mSmallCacheHeight = DEFAULT_TEXT_SMALL_CACHE_HEIGHT; 115d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mLargeCacheWidth = DEFAULT_TEXT_LARGE_CACHE_WIDTH; 116d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mLargeCacheHeight = DEFAULT_TEXT_LARGE_CACHE_HEIGHT; 117d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 118d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka char property[PROPERTY_VALUE_MAX]; 119d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (property_get(PROPERTY_TEXT_SMALL_CACHE_WIDTH, property, NULL) > 0) { 120d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mSmallCacheWidth = atoi(property); 121d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 122d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 123d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (property_get(PROPERTY_TEXT_SMALL_CACHE_HEIGHT, property, NULL) > 0) { 124d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mSmallCacheHeight = atoi(property); 125d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 126d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 127d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (property_get(PROPERTY_TEXT_LARGE_CACHE_WIDTH, property, NULL) > 0) { 128d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mLargeCacheWidth = atoi(property); 129d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 130d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 131d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (property_get(PROPERTY_TEXT_LARGE_CACHE_HEIGHT, property, NULL) > 0) { 1321c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa mLargeCacheHeight = atoi(property); 1331c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa } 1341c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa 1351c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa uint32_t maxTextureSize = (uint32_t) Caches::getInstance().maxTextureSize; 1361c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa mSmallCacheWidth = mSmallCacheWidth > maxTextureSize ? maxTextureSize : mSmallCacheWidth; 1371c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa mSmallCacheHeight = mSmallCacheHeight > maxTextureSize ? maxTextureSize : mSmallCacheHeight; 1381c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa mLargeCacheWidth = mLargeCacheWidth > maxTextureSize ? maxTextureSize : mLargeCacheWidth; 1391c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa mLargeCacheHeight = mLargeCacheHeight > maxTextureSize ? maxTextureSize : mLargeCacheHeight; 1401c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa 1411c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa if (sLogFontRendererCreate) { 1421c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa INIT_LOGD(" Text cache sizes, in pixels: %i x %i, %i x %i, %i x %i, %i x %i", 14307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa mSmallCacheWidth, mSmallCacheHeight, 14407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa mLargeCacheWidth, mLargeCacheHeight >> 1, 14507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa mLargeCacheWidth, mLargeCacheHeight >> 1, 14607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa mLargeCacheWidth, mLargeCacheHeight); 14707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 14807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 14907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa sLogFontRendererCreate = false; 15007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa} 15107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 15207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawavoid clearCacheTextures(Vector<CacheTexture*>& cacheTextures) { 15307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa for (uint32_t i = 0; i < cacheTextures.size(); i++) { 15407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa delete cacheTextures[i]; 15507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 15607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa cacheTextures.clear(); 15707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa} 15807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 15907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei YukawaFontRenderer::~FontRenderer() { 16007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa clearCacheTextures(mACacheTextures); 161d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka clearCacheTextures(mRGBACacheTextures); 162d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 163d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); 164d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka while (it.next()) { 165d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka delete it.value(); 166d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 167d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mActiveFonts.clear(); 168d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka} 169d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 170d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawavoid FontRenderer::flushAllAndInvalidate() { 171d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka issueDrawCommand(); 172d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 173d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); 174d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka while (it.next()) { 175d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka it.value()->invalidateTextureCache(); 176d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 177d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 178d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka for (uint32_t i = 0; i < mACacheTextures.size(); i++) { 1797025964d1230e4fc064658e1911fea9aab3def68Yohei Yukawa mACacheTextures[i]->init(); 180d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 181d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 182d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka for (uint32_t i = 0; i < mRGBACacheTextures.size(); i++) { 183d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mRGBACacheTextures[i]->init(); 184d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 185d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka} 186d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 187d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokavoid FontRenderer::flushLargeCaches(Vector<CacheTexture*>& cacheTextures) { 188d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka // Start from 1; don't deallocate smallest/default texture 189d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka for (uint32_t i = 1; i < cacheTextures.size(); i++) { 190d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka CacheTexture* cacheTexture = cacheTextures[i]; 191d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (cacheTexture->getPixelBuffer()) { 192d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka cacheTexture->init(); 193d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); 194d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka while (it.next()) { 195d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka it.value()->invalidateTextureCache(cacheTexture); 196d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 1975f8e731f18c5cbfd345236c691db0b09aceb7c5dYohei Yukawa cacheTexture->releaseTexture(); 1987025964d1230e4fc064658e1911fea9aab3def68Yohei Yukawa } 199d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 200d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka} 201d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 202d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokavoid FontRenderer::flushLargeCaches() { 203d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka flushLargeCaches(mACacheTextures); 204d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka flushLargeCaches(mRGBACacheTextures); 20514e139179be7daab6ed452105387a3922752c219Seigo Nonaka} 20614e139179be7daab6ed452105387a3922752c219Seigo Nonaka 20714e139179be7daab6ed452105387a3922752c219Seigo NonakaCacheTexture* FontRenderer::cacheBitmapInTexture(Vector<CacheTexture*>& cacheTextures, 20814e139179be7daab6ed452105387a3922752c219Seigo Nonaka const SkGlyph& glyph, uint32_t* startX, uint32_t* startY) { 20914e139179be7daab6ed452105387a3922752c219Seigo Nonaka for (uint32_t i = 0; i < cacheTextures.size(); i++) { 21014e139179be7daab6ed452105387a3922752c219Seigo Nonaka if (cacheTextures[i]->fitBitmap(glyph, startX, startY)) { 211d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return cacheTextures[i]; 212d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 213d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 214d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka // Could not fit glyph into current cache textures 215d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return NULL; 216d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka} 217d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 2187025964d1230e4fc064658e1911fea9aab3def68Yohei Yukawavoid FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, 219d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka uint32_t* retOriginX, uint32_t* retOriginY, bool precaching) { 220d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka checkInit(); 221d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 222d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka // If the glyph bitmap is empty let's assum the glyph is valid 2235f8e731f18c5cbfd345236c691db0b09aceb7c5dYohei Yukawa // so we can avoid doing extra work later on 224d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (glyph.fWidth == 0 || glyph.fHeight == 0) { 225d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka cachedGlyph->mIsValid = true; 226d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka cachedGlyph->mCacheTexture = NULL; 227d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return; 228d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 229d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 230d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka cachedGlyph->mIsValid = false; 231d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 232d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka // choose an appropriate cache texture list for this glyph format 23314e139179be7daab6ed452105387a3922752c219Seigo Nonaka SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat); 234d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka Vector<CacheTexture*>* cacheTextures = NULL; 235d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka switch (format) { 236d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka case SkMask::kA8_Format: 237d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka case SkMask::kBW_Format: 238d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka cacheTextures = &mACacheTextures; 239d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka break; 240d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka case SkMask::kARGB32_Format: 241d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka cacheTextures = &mRGBACacheTextures; 242d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka break; 243d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka default: 244d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#if DEBUG_FONT_RENDERER 245d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka ALOGD("getCacheTexturesForFormat: unknown SkMask format %x", format); 246d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#endif 247d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return; 248d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 249d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 250d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka // If the glyph is too tall, don't cache it 251d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > 252d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka (*cacheTextures)[cacheTextures->size() - 1]->getHeight()) { 253d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka ALOGE("Font size too large to fit in cache. width, height = %i, %i", 254d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka (int) glyph.fWidth, (int) glyph.fHeight); 255d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return; 256d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 2579b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 2589b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa // Now copy the bitmap into the cache texture 2599b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa uint32_t startX = 0; 2609b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa uint32_t startY = 0; 261d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa 2629b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa CacheTexture* cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY); 2639b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 2649b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (!cacheTexture) { 2659b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (!precaching) { 266d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa // If the new glyph didn't fit and we are not just trying to precache it, 2679b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa // clear out the cache and try again 2689b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa flushAllAndInvalidate(); 2699b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY); 2709b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 2719b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 2729b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (!cacheTexture) { 2739b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa // either the glyph didn't fit or we're precaching and will cache it when we draw 2749b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa return; 2759b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 2769b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 2779b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 2789b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa cachedGlyph->mCacheTexture = cacheTexture; 2799b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 2809b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa *retOriginX = startX; 2819b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa *retOriginY = startY; 2829b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 2839b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa uint32_t endX = startX + glyph.fWidth; 2849b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa uint32_t endY = startY + glyph.fHeight; 2859b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 286d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa uint32_t cacheWidth = cacheTexture->getWidth(); 2879b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 288b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa if (!cacheTexture->getPixelBuffer()) { 289b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa Caches::getInstance().activeTexture(0); 290b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa // Large-glyph texture memory is allocated only as needed 291b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa cacheTexture->allocateTexture(); 292b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa } 293b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa if (!cacheTexture->mesh()) { 294b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa cacheTexture->allocateMesh(); 295b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa } 296b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa 297b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa uint8_t* cacheBuffer = cacheTexture->getPixelBuffer()->map(); 298b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa uint8_t* bitmapBuffer = (uint8_t*) glyph.fImage; 299b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa int srcStride = glyph.rowBytes(); 300b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa 301b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa // Copy the glyph image, taking the mask format into account 3029b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa switch (format) { 303b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa case SkMask::kA8_Format: { 3049b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 3059b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX 306a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa - TEXTURE_BORDER_SIZE; 3079b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa // write leading border line 3089b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 3099b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa // write glyph data 3109b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (mGammaTable) { 3119b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) { 3129b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa row = cacheY * cacheWidth; 3139b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; 3149b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) { 315d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa uint8_t tempCol = bitmapBuffer[bY + bX]; 316b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa cacheBuffer[row + cacheX] = mGammaTable[tempCol]; 317d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa } 3189b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; 3199b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 320a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa } else { 321a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) { 3229b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa row = cacheY * cacheWidth; 323a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa memcpy(&cacheBuffer[row + startX], &bitmapBuffer[bY], glyph.fWidth); 324d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; 325a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; 326d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa } 327a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa } 328d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa // write trailing border line 329d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE; 330d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 331d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa break; 332d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa } 333d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa case SkMask::kARGB32_Format: { 334d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa // prep data lengths 335d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa const size_t formatSize = PixelBuffer::formatSize(GL_RGBA); 336d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa const size_t borderSize = formatSize * TEXTURE_BORDER_SIZE; 337d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa size_t rowSize = formatSize * glyph.fWidth; 338d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa // prep advances 339d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka size_t dstStride = formatSize * cacheWidth; 340a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa // prep indices 341a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa // - we actually start one row early, and then increment before first copy 342a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa uint8_t* src = &bitmapBuffer[0 - srcStride]; 343a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa uint8_t* dst = &cacheBuffer[cacheTexture->getOffset(startX, startY - 1)]; 344a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa uint8_t* dstEnd = &cacheBuffer[cacheTexture->getOffset(startX, endY - 1)]; 34507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa uint8_t* dstL = dst - borderSize; 346a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa uint8_t* dstR = dst + rowSize; 347a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa // write leading border line 348a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa memset(dstL, 0, rowSize + 2 * borderSize); 349a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa // write glyph data 350a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa while (dst < dstEnd) { 351a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa memset(dstL += dstStride, 0, borderSize); // leading border column 352a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa memcpy(dst += dstStride, src += srcStride, rowSize); // glyph data 353a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa memset(dstR += dstStride, 0, borderSize); // trailing border column 354a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 355a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa // write trailing border line 356a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa memset(dstL += dstStride, 0, rowSize + 2 * borderSize); 357a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa break; 358a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 359a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa case SkMask::kBW_Format: { 360a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 361a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX 362a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa - TEXTURE_BORDER_SIZE; 363a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa static const uint8_t COLORS[2] = { 0, 255 }; 364a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa // write leading border line 365a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 366a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa // write glyph data 367a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa for (cacheY = startY; cacheY < endY; cacheY++) { 368a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa cacheX = startX; 369a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa int rowBytes = srcStride; 370a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa uint8_t* buffer = bitmapBuffer; 371a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 372a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa row = cacheY * cacheWidth; 373a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; 374a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa while (--rowBytes >= 0) { 375a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa uint8_t b = *buffer++; 376a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa for (int8_t mask = 7; mask >= 0 && cacheX < endX; mask--) { 377a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa cacheBuffer[cacheY * cacheWidth + cacheX++] = COLORS[(b >> mask) & 0x1]; 378a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 379a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 380a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; 381a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 382a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa bitmapBuffer += srcStride; 383a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 384a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa // write trailing border line 385a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE; 386a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 387a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa break; 388a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 389b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa default: 390b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa ALOGW("Unknown glyph format: 0x%x", format); 391b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa break; 392b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa } 393b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa 394b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa cachedGlyph->mIsValid = true; 395b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa} 396b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa 397b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei YukawaCacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum format, 398b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa bool allocate) { 399b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa CacheTexture* cacheTexture = new CacheTexture(width, height, format, gMaxNumberOfQuads); 400b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa 401b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa if (allocate) { 402b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa Caches::getInstance().activeTexture(0); 403a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa cacheTexture->allocateTexture(); 404b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa cacheTexture->allocateMesh(); 405a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 406a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 407a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa return cacheTexture; 408a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa} 409a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 410a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawavoid FontRenderer::initTextTexture() { 411a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa clearCacheTextures(mACacheTextures); 412a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa clearCacheTextures(mRGBACacheTextures); 413a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 414d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa mUploadTexture = false; 415d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa mACacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, 416a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa GL_ALPHA, true)); 417a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, 418a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa GL_ALPHA, false)); 419a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, 420a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa GL_ALPHA, false)); 421a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight, 422a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa GL_ALPHA, false)); 423a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mRGBACacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, 424a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa GL_RGBA, false)); 425a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mRGBACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, 426a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa GL_RGBA, false)); 427d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa mCurrentCacheTexture = mACacheTextures[0]; 428d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa} 429d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa 430d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa// We don't want to allocate anything unless we actually draw text 431d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawavoid FontRenderer::checkInit() { 432d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa if (mInitialized) { 433d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa return; 434d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa } 435a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 436a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa initTextTexture(); 4379b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 4389b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa mInitialized = true; 43907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa} 44007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 44107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawavoid checkTextureUpdateForCache(Caches& caches, Vector<CacheTexture*>& cacheTextures, 44207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa bool& resetPixelStore, GLuint& lastTextureId) { 44307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa for (uint32_t i = 0; i < cacheTextures.size(); i++) { 44407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa CacheTexture* cacheTexture = cacheTextures[i]; 44507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (cacheTexture->isDirty() && cacheTexture->getPixelBuffer()) { 44607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (cacheTexture->getTextureId() != lastTextureId) { 44707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa lastTextureId = cacheTexture->getTextureId(); 44807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa caches.activeTexture(0); 44907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa caches.bindTexture(lastTextureId); 45007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 45107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 45207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (cacheTexture->upload()) { 45307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa resetPixelStore = true; 45407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 45507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 45607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 45707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa} 45807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 45907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawavoid FontRenderer::checkTextureUpdate() { 46007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (!mUploadTexture) { 46107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa return; 46207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 46307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 46407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa Caches& caches = Caches::getInstance(); 46507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa GLuint lastTextureId = 0; 46607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 46707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa bool resetPixelStore = false; 46807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 46907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 47007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa // Iterate over all the cache textures and see which ones need to be updated 47107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa checkTextureUpdateForCache(caches, mACacheTextures, resetPixelStore, lastTextureId); 47207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa checkTextureUpdateForCache(caches, mRGBACacheTextures, resetPixelStore, lastTextureId); 47307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 47407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa // Unbind any PBO we might have used to update textures 47507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa caches.unbindPixelBuffer(); 47607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 47707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa // Reset to default unpack row length to avoid affecting texture 47807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa // uploads in other parts of the renderer 47907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (resetPixelStore) { 48007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 48107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 48207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 48307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa mUploadTexture = false; 48407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa} 48507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 4869b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawavoid FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) { 4879b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa Caches& caches = Caches::getInstance(); 488b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa bool first = true; 489b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa bool force = false; 490b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa for (uint32_t i = 0; i < cacheTextures.size(); i++) { 491b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa CacheTexture* texture = cacheTextures[i]; 492b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa if (texture->canDraw()) { 493b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa if (first) { 494b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa if (mFunctor) { 495b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa TextSetupFunctor::Data functorData(texture->getFormat()); 496b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa (*mFunctor)(0, &functorData); 497b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa } 498b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa 499b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa checkTextureUpdate(); 500b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa caches.bindIndicesBuffer(); 501b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa 5029b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (!mDrawn) { 503b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa // If returns true, a VBO was bound and we must 5049b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa // rebind our vertex attrib pointers even if 5059b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa // they have the same values as the current pointers 5069b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa force = caches.unbindMeshBuffer(); 5079b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 50807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 509d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa caches.activeTexture(0); 5109b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa first = false; 51107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 512d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa 5139b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa caches.bindTexture(texture->getTextureId()); 5149b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa texture->setLinearFiltering(mLinearFiltering, false); 5159b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 516a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa TextureVertex* mesh = texture->mesh(); 517a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa caches.bindPositionVertexPointer(force, &mesh[0].position[0]); 518a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa caches.bindTexCoordsVertexPointer(force, &mesh[0].texture[0]); 519a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa force = false; 52007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 52107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa glDrawElements(GL_TRIANGLES, texture->meshElementCount(), 52207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa GL_UNSIGNED_SHORT, texture->indices()); 523a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 524a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa texture->resetMesh(); 5259b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 5269b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 5279b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa} 5289b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 5299b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawavoid FontRenderer::issueDrawCommand() { 5309b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa issueDrawCommand(mACacheTextures); 5319b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa issueDrawCommand(mRGBACacheTextures); 5329b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 5339b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa mDrawn = true; 5349b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa} 5359b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 5369b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawavoid FontRenderer::appendMeshQuadNoClip(float x1, float y1, float u1, float v1, 5379b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3, 5389b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa float x4, float y4, float u4, float v4, CacheTexture* texture) { 539d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa if (texture != mCurrentCacheTexture) { 540d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa // Now use the new texture id 541d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa mCurrentCacheTexture = texture; 542d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa } 543d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa 544d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa mCurrentCacheTexture->addQuad(x1, y1, u1, v1, x2, y2, u2, v2, 545d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa x3, y3, u3, v3, x4, y4, u4, v4); 5469b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa} 5479b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 5489b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawavoid FontRenderer::appendMeshQuad(float x1, float y1, float u1, float v1, 5499b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3, 5509b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa float x4, float y4, float u4, float v4, CacheTexture* texture) { 5519b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 5525a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa if (mClip && 553d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka (x1 > mClip->right || y1 < mClip->top || x2 < mClip->left || y4 > mClip->bottom)) { 5545a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa return; 5555a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa } 5565a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa 5575a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture); 5585a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa 5595a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa if (mBounds) { 560d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mBounds->left = fmin(mBounds->left, x1); 561d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka mBounds->top = fmin(mBounds->top, y3); 5620297051162193ef2b7d906409868e404f77e4c31Yohei Yukawa mBounds->right = fmax(mBounds->right, x3); 563a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mBounds->bottom = fmax(mBounds->bottom, y1); 564a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 565a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 566a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa if (mCurrentCacheTexture->endOfMesh()) { 567a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa issueDrawCommand(); 568a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 569a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa} 570d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka 571d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokavoid FontRenderer::appendRotatedMeshQuad(float x1, float y1, float u1, float v1, 572d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3, 5735a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa float x4, float y4, float u4, float v4, CacheTexture* texture) { 57407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 575e512f85002379c5949f65daeffdcae3198964dadYohei Yukawa appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture); 576e512f85002379c5949f65daeffdcae3198964dadYohei Yukawa 577d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (mBounds) { 578d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mBounds->left = fmin(mBounds->left, fmin(x1, fmin(x2, fmin(x3, x4)))); 5799b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa mBounds->top = fmin(mBounds->top, fmin(y1, fmin(y2, fmin(y3, y4)))); 580d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa mBounds->right = fmax(mBounds->right, fmax(x1, fmax(x2, fmax(x3, x4)))); 5819b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa mBounds->bottom = fmax(mBounds->bottom, fmax(y1, fmax(y2, fmax(y3, y4)))); 5829b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 5839b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 5849b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (mCurrentCacheTexture->endOfMesh()) { 5859b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa issueDrawCommand(); 5869b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 587d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa} 588d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 589d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokavoid FontRenderer::setFont(SkPaint* paint, const mat4& matrix) { 5905f8e731f18c5cbfd345236c691db0b09aceb7c5dYohei Yukawa mCurrentFont = Font::create(this, paint, matrix); 59114e139179be7daab6ed452105387a3922752c219Seigo Nonaka} 5925a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa 5935f8e731f18c5cbfd345236c691db0b09aceb7c5dYohei YukawaFontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text, 594d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) { 595d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa checkInit(); 596d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa 597d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa DropShadow image; 598d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa image.width = 0; 599d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa image.height = 0; 600d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa image.image = NULL; 601d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa image.penX = 0; 602d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa image.penY = 0; 603d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka 604 if (!mCurrentFont) { 605 return image; 606 } 607 608 mDrawn = false; 609 mClip = NULL; 610 mBounds = NULL; 611 612 Rect bounds; 613 mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds, positions); 614 615 uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius; 616 uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius; 617 618 uint32_t maxSize = Caches::getInstance().maxTextureSize; 619 if (paddedWidth > maxSize || paddedHeight > maxSize) { 620 return image; 621 } 622 623#ifdef ANDROID_ENABLE_RENDERSCRIPT 624 // Align buffers for renderscript usage 625 if (paddedWidth & (RS_CPU_ALLOCATION_ALIGNMENT - 1)) { 626 paddedWidth += RS_CPU_ALLOCATION_ALIGNMENT - paddedWidth % RS_CPU_ALLOCATION_ALIGNMENT; 627 } 628 int size = paddedWidth * paddedHeight; 629 uint8_t* dataBuffer = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, size); 630#else 631 int size = paddedWidth * paddedHeight; 632 uint8_t* dataBuffer = (uint8_t*) malloc(size); 633#endif 634 635 memset(dataBuffer, 0, size); 636 637 int penX = radius - bounds.left; 638 int penY = radius - bounds.bottom; 639 640 if ((bounds.right > bounds.left) && (bounds.top > bounds.bottom)) { 641 // text has non-whitespace, so draw and blur to create the shadow 642 // NOTE: bounds.isEmpty() can't be used here, since vertical coordinates are inverted 643 // TODO: don't draw pure whitespace in the first place, and avoid needing this check 644 mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY, 645 Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions); 646 647 // Unbind any PBO we might have used 648 Caches::getInstance().unbindPixelBuffer(); 649 650 blurImage(&dataBuffer, paddedWidth, paddedHeight, radius); 651 } 652 653 image.width = paddedWidth; 654 image.height = paddedHeight; 655 image.image = dataBuffer; 656 image.penX = penX; 657 image.penY = penY; 658 659 return image; 660} 661 662void FontRenderer::initRender(const Rect* clip, Rect* bounds, Functor* functor) { 663 checkInit(); 664 665 mDrawn = false; 666 mBounds = bounds; 667 mFunctor = functor; 668 mClip = clip; 669} 670 671void FontRenderer::finishRender() { 672 mBounds = NULL; 673 mClip = NULL; 674 675 issueDrawCommand(); 676} 677 678void FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs, const mat4& matrix) { 679 Font* font = Font::create(this, paint, matrix); 680 font->precache(paint, text, numGlyphs); 681} 682 683void FontRenderer::endPrecaching() { 684 checkTextureUpdate(); 685} 686 687bool FontRenderer::renderPosText(SkPaint* paint, const Rect* clip, const char *text, 688 uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, 689 const float* positions, Rect* bounds, Functor* functor, bool forceFinish) { 690 if (!mCurrentFont) { 691 ALOGE("No font set"); 692 return false; 693 } 694 695 initRender(clip, bounds, functor); 696 mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y, positions); 697 698 if (forceFinish) { 699 finishRender(); 700 } 701 702 return mDrawn; 703} 704 705bool FontRenderer::renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, 706 uint32_t startIndex, uint32_t len, int numGlyphs, SkPath* path, 707 float hOffset, float vOffset, Rect* bounds, Functor* functor) { 708 if (!mCurrentFont) { 709 ALOGE("No font set"); 710 return false; 711 } 712 713 initRender(clip, bounds, functor); 714 mCurrentFont->render(paint, text, startIndex, len, numGlyphs, path, hOffset, vOffset); 715 finishRender(); 716 717 return mDrawn; 718} 719 720void FontRenderer::removeFont(const Font* font) { 721 mActiveFonts.remove(font->getDescription()); 722 723 if (mCurrentFont == font) { 724 mCurrentFont = NULL; 725 } 726} 727 728void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, int32_t radius) { 729#ifdef ANDROID_ENABLE_RENDERSCRIPT 730 if (width * height * radius >= RS_MIN_INPUT_CUTOFF) { 731 uint8_t* outImage = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height); 732 733 if (mRs == 0) { 734 mRs = new RSC::RS(); 735 // a null path is OK because there are no custom kernels used 736 // hence nothing gets cached by RS 737 if (!mRs->init("", RSC::RS_INIT_LOW_LATENCY | RSC::RS_INIT_SYNCHRONOUS)) { 738 ALOGE("blur RS failed to init"); 739 } 740 741 mRsElement = RSC::Element::A_8(mRs); 742 mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement); 743 } 744 745 RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0); 746 RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t, 747 RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, 748 *image); 749 RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t, 750 RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, 751 outImage); 752 753 mRsScript->setRadius(radius); 754 mRsScript->setInput(ain); 755 mRsScript->forEach(aout); 756 757 // replace the original image's pointer, avoiding a copy back to the original buffer 758 free(*image); 759 *image = outImage; 760 761 return; 762 } 763#endif 764 765 float *gaussian = new float[2 * radius + 1]; 766 Blur::generateGaussianWeights(gaussian, radius); 767 768 uint8_t* scratch = new uint8_t[width * height]; 769 Blur::horizontal(gaussian, radius, *image, scratch, width, height); 770 Blur::vertical(gaussian, radius, scratch, *image, width, height); 771 772 delete[] gaussian; 773 delete[] scratch; 774} 775 776static uint32_t calculateCacheSize(const Vector<CacheTexture*>& cacheTextures) { 777 uint32_t size = 0; 778 for (uint32_t i = 0; i < cacheTextures.size(); i++) { 779 CacheTexture* cacheTexture = cacheTextures[i]; 780 if (cacheTexture && cacheTexture->getPixelBuffer()) { 781 size += cacheTexture->getPixelBuffer()->getSize(); 782 } 783 } 784 return size; 785} 786 787uint32_t FontRenderer::getCacheSize(GLenum format) const { 788 switch (format) { 789 case GL_ALPHA: { 790 return calculateCacheSize(mACacheTextures); 791 } 792 case GL_RGBA: { 793 return calculateCacheSize(mRGBACacheTextures); 794 } 795 default: { 796 return 0; 797 } 798 } 799} 800 801}; // namespace uirenderer 802}; // namespace android 803