CacheTexture.cpp revision 2dc236b2bae13b9a0ed9b3f7320502aecd7983b3
19f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/* 29f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * Copyright (C) 2012 The Android Open Source Project 39f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * 49f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 59f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * you may not use this file except in compliance with the License. 69f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * You may obtain a copy of the License at 79f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * 89f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * http://www.apache.org/licenses/LICENSE-2.0 99f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * 109f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * Unless required by applicable law or agreed to in writing, software 119f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * distributed under the License is distributed on an "AS IS" BASIS, 129f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * See the License for the specific language governing permissions and 149f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * limitations under the License. 159f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy */ 169f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 17ca79cf69d09efa0c327e9b1237d86a119aea5da7Derek Sollenberger#include <SkGlyph.h> 189f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 199f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#include "CacheTexture.h" 202dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include "FontUtil.h" 218aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy#include "../Caches.h" 220908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy#include "../Debug.h" 23cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy#include "../Extensions.h" 24cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy#include "../PixelBuffer.h" 259f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 269f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guynamespace android { 279f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guynamespace uirenderer { 289f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 299f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/////////////////////////////////////////////////////////////////////////////// 309f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy// CacheBlock 319f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/////////////////////////////////////////////////////////////////////////////// 329f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 339f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/** 349f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * Insert new block into existing linked list of blocks. Blocks are sorted in increasing-width 359f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * order, except for the final block (the remainder space at the right, since we fill from the 369f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * left). 379f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy */ 38e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain GuyCacheBlock* CacheBlock::insertBlock(CacheBlock* head, CacheBlock* newBlock) { 399f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 409f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("insertBlock: this, x, y, w, h = %p, %d, %d, %d, %d", 419f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock, newBlock->mX, newBlock->mY, 429f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mWidth, newBlock->mHeight); 439f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 449b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 45e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy CacheBlock* currBlock = head; 46e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy CacheBlock* prevBlock = NULL; 479b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 489f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy while (currBlock && currBlock->mY != TEXTURE_BORDER_SIZE) { 499f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (newBlock->mWidth < currBlock->mWidth) { 509f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mNext = currBlock; 519f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mPrev = prevBlock; 529f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy currBlock->mPrev = newBlock; 539b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 549f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (prevBlock) { 559f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy prevBlock->mNext = newBlock; 569f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return head; 579f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } else { 589f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return newBlock; 599f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 609f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 619b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 629f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy prevBlock = currBlock; 639f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy currBlock = currBlock->mNext; 649f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 659b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 669f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // new block larger than all others - insert at end (but before the remainder space, if there) 679f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mNext = currBlock; 689f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mPrev = prevBlock; 699b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 709f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (currBlock) { 719f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy currBlock->mPrev = newBlock; 729f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 739b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 749f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (prevBlock) { 759f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy prevBlock->mNext = newBlock; 769f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return head; 779f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } else { 789f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return newBlock; 799f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 809f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy} 819f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 82e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain GuyCacheBlock* CacheBlock::removeBlock(CacheBlock* head, CacheBlock* blockToRemove) { 839f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 849f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("removeBlock: this, x, y, w, h = %p, %d, %d, %d, %d", 859f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy blockToRemove, blockToRemove->mX, blockToRemove->mY, 869f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy blockToRemove->mWidth, blockToRemove->mHeight); 879f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 889b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 899f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* newHead = head; 909f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* nextBlock = blockToRemove->mNext; 919f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* prevBlock = blockToRemove->mPrev; 929b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 939f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (prevBlock) { 949f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy prevBlock->mNext = nextBlock; 959f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } else { 969f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newHead = nextBlock; 979f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 989b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 999f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (nextBlock) { 1009f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy nextBlock->mPrev = prevBlock; 1019f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 1029b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 1039f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy delete blockToRemove; 1049b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 1059f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return newHead; 1069f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy} 1079f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 1089f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/////////////////////////////////////////////////////////////////////////////// 1099f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy// CacheTexture 1109f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/////////////////////////////////////////////////////////////////////////////// 1119f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 1121e546815bbb736c50679a8aefc25f48561026fc5Victoria LeaseCacheTexture::CacheTexture(uint16_t width, uint16_t height, GLenum format, uint32_t maxQuadCount) : 1131e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height), mFormat(format), 114661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mLinearFiltering(false), mDirty(false), mNumGlyphs(0), 1158aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy mMesh(NULL), mCurrentQuad(0), mMaxQuadCount(maxQuadCount), 1168aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy mCaches(Caches::getInstance()) { 117661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, 118e63f7c622a2086aefa80983c6f41b74fb166bb42Chris Craik mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE); 119cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 120cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // OpenGL ES 3.0+ lets us specify the row length for unpack operations such 121cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // as glTexSubImage2D(). This allows us to upload a sub-rectangle of a texture. 122cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // With OpenGL ES 2.0 we have to upload entire stripes instead. 123318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy mHasUnpackRowLength = Extensions::getInstance().hasUnpackRowLength(); 124661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 125661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 126661a87ec28a49458f1faf533783abf2ab9927cabRomain GuyCacheTexture::~CacheTexture() { 127661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy releaseMesh(); 128661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy releaseTexture(); 129661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy reset(); 130661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 131661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 132661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::reset() { 133661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // Delete existing cache blocks 134661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy while (mCacheBlocks != NULL) { 135661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy CacheBlock* tmpBlock = mCacheBlocks; 136661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCacheBlocks = mCacheBlocks->mNext; 137661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy delete tmpBlock; 138661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 139661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mNumGlyphs = 0; 140661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCurrentQuad = 0; 141661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 142661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 143661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::init() { 144661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // reset, then create a new remainder space to start again 145661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy reset(); 146661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, 147e63f7c622a2086aefa80983c6f41b74fb166bb42Chris Craik mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE); 148661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 149661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 150661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::releaseMesh() { 151661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy delete[] mMesh; 152661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 153661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 154661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::releaseTexture() { 155661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (mTexture) { 156cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy delete mTexture; 157661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mTexture = NULL; 158661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 159661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (mTextureId) { 160be1b127c7bec252e0c6ab0e06ed6babed07d496fRomain Guy mCaches.deleteTexture(mTextureId); 161661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mTextureId = 0; 162661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 163661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mDirty = false; 164661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCurrentQuad = 0; 165661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 166661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 167cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid CacheTexture::setLinearFiltering(bool linearFiltering, bool bind) { 168cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (linearFiltering != mLinearFiltering) { 169cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy mLinearFiltering = linearFiltering; 170cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 171cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST; 1728aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy if (bind) mCaches.bindTexture(getTextureId()); 173cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); 174cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); 175cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 176cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 177cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 178661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::allocateMesh() { 179661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (!mMesh) { 180661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mMesh = new TextureVertex[mMaxQuadCount * 4]; 181661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 182661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 183661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 184661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::allocateTexture() { 185661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (!mTexture) { 1861e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mTexture = PixelBuffer::create(mFormat, mWidth, mHeight); 187661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 188661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 189661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (!mTextureId) { 190661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glGenTextures(1, &mTextureId); 191661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 1928aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy mCaches.bindTexture(mTextureId); 193661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 194661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // Initialize texture dimensions 1951e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease glTexImage2D(GL_TEXTURE_2D, 0, mFormat, mWidth, mHeight, 0, 1961e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mFormat, GL_UNSIGNED_BYTE, 0); 197661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 198661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy const GLenum filtering = getLinearFiltering() ? GL_LINEAR : GL_NEAREST; 199661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); 200661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); 201661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 202661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 203661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 204661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 205661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 206661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 207cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guybool CacheTexture::upload() { 208cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy const Rect& dirtyRect = mDirtyRect; 209cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 210318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy uint32_t x = mHasUnpackRowLength ? dirtyRect.left : 0; 211cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint32_t y = dirtyRect.top; 212318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy uint32_t width = mHasUnpackRowLength ? dirtyRect.getWidth() : mWidth; 213cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint32_t height = dirtyRect.getHeight(); 214cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 215cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // The unpack row length only needs to be specified when a new 216cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // texture is bound 217318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy if (mHasUnpackRowLength) { 218cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy glPixelStorei(GL_UNPACK_ROW_LENGTH, mWidth); 219cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 220cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 2211e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mTexture->upload(x, y, width, height); 222cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy setDirty(false); 223cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 224318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy return mHasUnpackRowLength; 225cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 226cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 227cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid CacheTexture::setDirty(bool dirty) { 228cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy mDirty = dirty; 229cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (!dirty) { 230cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy mDirtyRect.setEmpty(); 231cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 232cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 233cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 234e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guybool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY) { 2351e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease switch (glyph.fMaskFormat) { 2361e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kA8_Format: 237723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease case SkMask::kBW_Format: 2381e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (mFormat != GL_ALPHA) { 2391e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#if DEBUG_FONT_RENDERER 240723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease ALOGD("fitBitmap: texture format %x is inappropriate for monochromatic glyphs", 241723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease mFormat); 2421e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#endif 2431e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return false; 2441e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 2451e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 2461e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kARGB32_Format: 2471e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (mFormat != GL_RGBA) { 2481e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#if DEBUG_FONT_RENDERER 249723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease ALOGD("fitBitmap: texture format %x is inappropriate for colour glyphs", mFormat); 2501e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#endif 2511e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return false; 2521e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 2531e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 2541e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease default: 2551e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#if DEBUG_FONT_RENDERER 2561e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease ALOGD("fitBitmap: unknown glyph format %x encountered", glyph.fMaskFormat); 2571e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#endif 2581e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return false; 2591e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 2601e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 261e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > mHeight) { 2629f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return false; 2639f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 2649f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 2659f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t glyphW = glyph.fWidth + TEXTURE_BORDER_SIZE; 2669f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t glyphH = glyph.fHeight + TEXTURE_BORDER_SIZE; 2679b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 2689f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // roundedUpW equals glyphW to the next multiple of CACHE_BLOCK_ROUNDING_SIZE. 2699f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // This columns for glyphs that are close but not necessarily exactly the same size. It trades 2709f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // off the loss of a few pixels for some glyphs against the ability to store more glyphs 2719f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // of varying sizes in one block. 272e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy uint16_t roundedUpW = (glyphW + CACHE_BLOCK_ROUNDING_SIZE - 1) & -CACHE_BLOCK_ROUNDING_SIZE; 2739b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 274e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy CacheBlock* cacheBlock = mCacheBlocks; 2759f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy while (cacheBlock) { 2769f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // Store glyph in this block iff: it fits the block's remaining space and: 2779f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // it's the remainder space (mY == 0) or there's only enough height for this one glyph 2789f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // or it's within ROUNDING_SIZE of the block width 2799f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (roundedUpW <= cacheBlock->mWidth && glyphH <= cacheBlock->mHeight && 2809f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy (cacheBlock->mY == TEXTURE_BORDER_SIZE || 2819f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy (cacheBlock->mWidth - roundedUpW < CACHE_BLOCK_ROUNDING_SIZE))) { 2829f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (cacheBlock->mHeight - glyphH < glyphH) { 2839f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // Only enough space for this glyph - don't bother rounding up the width 2849f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy roundedUpW = glyphW; 2859f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 2869b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 2879f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy *retOriginX = cacheBlock->mX; 2889f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy *retOriginY = cacheBlock->mY; 2899b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 2909f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // If this is the remainder space, create a new cache block for this column. Otherwise, 2919f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // adjust the info about this column. 2929f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (cacheBlock->mY == TEXTURE_BORDER_SIZE) { 2939f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t oldX = cacheBlock->mX; 2949f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // Adjust remainder space dimensions 2959f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mWidth -= roundedUpW; 2969f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mX += roundedUpW; 2979b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 2989f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (mHeight - glyphH >= glyphH) { 2999f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // There's enough height left over to create a new CacheBlock 300e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy CacheBlock* newBlock = new CacheBlock(oldX, glyphH + TEXTURE_BORDER_SIZE, 3019f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy roundedUpW, mHeight - glyphH - TEXTURE_BORDER_SIZE); 3029f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 3039f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("fitBitmap: Created new block: this, x, y, w, h = %p, %d, %d, %d, %d", 3049f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock, newBlock->mX, newBlock->mY, 3059f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mWidth, newBlock->mHeight); 3069f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 3079f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mCacheBlocks = CacheBlock::insertBlock(mCacheBlocks, newBlock); 3089f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3099f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } else { 3109f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // Insert into current column and adjust column dimensions 3119f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mY += glyphH; 3129f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mHeight -= glyphH; 3139f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 3149f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("fitBitmap: Added to existing block: this, x, y, w, h = %p, %d, %d, %d, %d", 3159f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock, cacheBlock->mX, cacheBlock->mY, 3169f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mWidth, cacheBlock->mHeight); 3179f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 3189f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3199b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 3209f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (cacheBlock->mHeight < fmin(glyphH, glyphW)) { 3219f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // If remaining space in this block is too small to be useful, remove it 3229f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mCacheBlocks = CacheBlock::removeBlock(mCacheBlocks, cacheBlock); 3239f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3249b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 3259f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mDirty = true; 326b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase const Rect r(*retOriginX - TEXTURE_BORDER_SIZE, *retOriginY - TEXTURE_BORDER_SIZE, 327b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase *retOriginX + glyphW, *retOriginY + glyphH); 328b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase mDirtyRect.unionWith(r); 3299b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy mNumGlyphs++; 3309b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 3319f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 3329f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("fitBitmap: current block list:"); 3339f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mCacheBlocks->output(); 3349f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 3359b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 3369f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return true; 3379f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3389f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock = cacheBlock->mNext; 3399f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3409f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 3419f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("fitBitmap: returning false for glyph of size %d, %d", glyphW, glyphH); 3429f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 3439f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return false; 3449f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy} 3459f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 3469f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; // namespace uirenderer 3479f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; // namespace android 348