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" 208aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy#include "../Caches.h" 210908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy#include "../Debug.h" 22cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy#include "../Extensions.h" 23cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy#include "../PixelBuffer.h" 249f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 259f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guynamespace android { 269f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guynamespace uirenderer { 279f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 289f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/////////////////////////////////////////////////////////////////////////////// 299f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy// CacheBlock 309f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/////////////////////////////////////////////////////////////////////////////// 319f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 329f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/** 339f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * Insert new block into existing linked list of blocks. Blocks are sorted in increasing-width 349f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * order, except for the final block (the remainder space at the right, since we fill from the 359f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * left). 369f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy */ 37e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain GuyCacheBlock* CacheBlock::insertBlock(CacheBlock* head, CacheBlock* newBlock) { 389f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 399f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("insertBlock: this, x, y, w, h = %p, %d, %d, %d, %d", 409f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock, newBlock->mX, newBlock->mY, 419f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mWidth, newBlock->mHeight); 429f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 439b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 44e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy CacheBlock* currBlock = head; 45e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy CacheBlock* prevBlock = NULL; 469b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 479f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy while (currBlock && currBlock->mY != TEXTURE_BORDER_SIZE) { 489f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (newBlock->mWidth < currBlock->mWidth) { 499f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mNext = currBlock; 509f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mPrev = prevBlock; 519f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy currBlock->mPrev = newBlock; 529b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 539f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (prevBlock) { 549f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy prevBlock->mNext = newBlock; 559f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return head; 569f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } else { 579f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return newBlock; 589f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 599f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 609b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 619f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy prevBlock = currBlock; 629f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy currBlock = currBlock->mNext; 639f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 649b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 659f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // new block larger than all others - insert at end (but before the remainder space, if there) 669f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mNext = currBlock; 679f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mPrev = prevBlock; 689b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 699f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (currBlock) { 709f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy currBlock->mPrev = newBlock; 719f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 729b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 739f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (prevBlock) { 749f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy prevBlock->mNext = newBlock; 759f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return head; 769f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } else { 779f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return newBlock; 789f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 799f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy} 809f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 81e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain GuyCacheBlock* CacheBlock::removeBlock(CacheBlock* head, CacheBlock* blockToRemove) { 829f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 839f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("removeBlock: this, x, y, w, h = %p, %d, %d, %d, %d", 849f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy blockToRemove, blockToRemove->mX, blockToRemove->mY, 859f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy blockToRemove->mWidth, blockToRemove->mHeight); 869f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 879b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 889f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* newHead = head; 899f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* nextBlock = blockToRemove->mNext; 909f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* prevBlock = blockToRemove->mPrev; 919b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 929f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (prevBlock) { 939f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy prevBlock->mNext = nextBlock; 949f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } else { 959f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newHead = nextBlock; 969f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 979b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 989f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (nextBlock) { 999f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy nextBlock->mPrev = prevBlock; 1009f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 1019b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 1029f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy delete blockToRemove; 1039b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 1049f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return newHead; 1059f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy} 1069f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 1079f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/////////////////////////////////////////////////////////////////////////////// 1089f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy// CacheTexture 1099f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/////////////////////////////////////////////////////////////////////////////// 1109f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 1111e546815bbb736c50679a8aefc25f48561026fc5Victoria LeaseCacheTexture::CacheTexture(uint16_t width, uint16_t height, GLenum format, uint32_t maxQuadCount) : 1121e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height), mFormat(format), 113661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mLinearFiltering(false), mDirty(false), mNumGlyphs(0), 1148aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy mMesh(NULL), mCurrentQuad(0), mMaxQuadCount(maxQuadCount), 1158aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy mCaches(Caches::getInstance()) { 116661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, 117e63f7c622a2086aefa80983c6f41b74fb166bb42Chris Craik mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE); 118cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 119cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // OpenGL ES 3.0+ lets us specify the row length for unpack operations such 120cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // as glTexSubImage2D(). This allows us to upload a sub-rectangle of a texture. 121cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // With OpenGL ES 2.0 we have to upload entire stripes instead. 122318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy mHasUnpackRowLength = Extensions::getInstance().hasUnpackRowLength(); 123661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 124661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 125661a87ec28a49458f1faf533783abf2ab9927cabRomain GuyCacheTexture::~CacheTexture() { 126661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy releaseMesh(); 127661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy releaseTexture(); 128661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy reset(); 129661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 130661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 131661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::reset() { 132661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // Delete existing cache blocks 133661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy while (mCacheBlocks != NULL) { 134661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy CacheBlock* tmpBlock = mCacheBlocks; 135661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCacheBlocks = mCacheBlocks->mNext; 136661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy delete tmpBlock; 137661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 138661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mNumGlyphs = 0; 139661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCurrentQuad = 0; 140661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 141661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 142661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::init() { 143661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // reset, then create a new remainder space to start again 144661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy reset(); 145661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, 146e63f7c622a2086aefa80983c6f41b74fb166bb42Chris Craik mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE); 147661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 148661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 149661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::releaseMesh() { 150661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy delete[] mMesh; 151661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 152661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 153661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::releaseTexture() { 154661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (mTexture) { 155cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy delete mTexture; 156661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mTexture = NULL; 157661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 158661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (mTextureId) { 159be1b127c7bec252e0c6ab0e06ed6babed07d496fRomain Guy mCaches.deleteTexture(mTextureId); 160661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mTextureId = 0; 161661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 162661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mDirty = false; 163661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCurrentQuad = 0; 164661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 165661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 166cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid CacheTexture::setLinearFiltering(bool linearFiltering, bool bind) { 167cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (linearFiltering != mLinearFiltering) { 168cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy mLinearFiltering = linearFiltering; 169cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 170cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST; 1718aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy if (bind) mCaches.bindTexture(getTextureId()); 172cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); 173cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); 174cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 175cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 176cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 177661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::allocateMesh() { 178661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (!mMesh) { 179661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mMesh = new TextureVertex[mMaxQuadCount * 4]; 180661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 181661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 182661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 183661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::allocateTexture() { 184661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (!mTexture) { 1851e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mTexture = PixelBuffer::create(mFormat, mWidth, mHeight); 186661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 187661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 188661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (!mTextureId) { 189661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glGenTextures(1, &mTextureId); 190661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 1918aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy mCaches.bindTexture(mTextureId); 192661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 193661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // Initialize texture dimensions 1941e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease glTexImage2D(GL_TEXTURE_2D, 0, mFormat, mWidth, mHeight, 0, 1951e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mFormat, GL_UNSIGNED_BYTE, 0); 196661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 197661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy const GLenum filtering = getLinearFiltering() ? GL_LINEAR : GL_NEAREST; 198661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); 199661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); 200661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 201661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 202661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 203661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 204661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 205661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 206cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guybool CacheTexture::upload() { 207cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy const Rect& dirtyRect = mDirtyRect; 208cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 209318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy uint32_t x = mHasUnpackRowLength ? dirtyRect.left : 0; 210cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint32_t y = dirtyRect.top; 211318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy uint32_t width = mHasUnpackRowLength ? dirtyRect.getWidth() : mWidth; 212cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint32_t height = dirtyRect.getHeight(); 213cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 214cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // The unpack row length only needs to be specified when a new 215cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // texture is bound 216318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy if (mHasUnpackRowLength) { 217cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy glPixelStorei(GL_UNPACK_ROW_LENGTH, mWidth); 218cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 219cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 2201e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mTexture->upload(x, y, width, height); 221cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy setDirty(false); 222cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 223318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy return mHasUnpackRowLength; 224cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 225cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 226cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid CacheTexture::setDirty(bool dirty) { 227cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy mDirty = dirty; 228cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (!dirty) { 229cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy mDirtyRect.setEmpty(); 230cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 231cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 232cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 233e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guybool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY) { 2341e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease switch (glyph.fMaskFormat) { 2351e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kA8_Format: 236723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease case SkMask::kBW_Format: 2371e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (mFormat != GL_ALPHA) { 2381e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#if DEBUG_FONT_RENDERER 239723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease ALOGD("fitBitmap: texture format %x is inappropriate for monochromatic glyphs", 240723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease mFormat); 2411e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#endif 2421e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return false; 2431e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 2441e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 2451e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kARGB32_Format: 2461e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (mFormat != GL_RGBA) { 2471e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#if DEBUG_FONT_RENDERER 248723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease ALOGD("fitBitmap: texture format %x is inappropriate for colour glyphs", mFormat); 2491e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#endif 2501e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return false; 2511e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 2521e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 2531e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease default: 2541e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#if DEBUG_FONT_RENDERER 2551e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease ALOGD("fitBitmap: unknown glyph format %x encountered", glyph.fMaskFormat); 2561e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#endif 2571e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return false; 2581e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 2591e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 260e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > mHeight) { 2619f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return false; 2629f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 2639f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 2649f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t glyphW = glyph.fWidth + TEXTURE_BORDER_SIZE; 2659f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t glyphH = glyph.fHeight + TEXTURE_BORDER_SIZE; 2669b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 2679f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // roundedUpW equals glyphW to the next multiple of CACHE_BLOCK_ROUNDING_SIZE. 2689f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // This columns for glyphs that are close but not necessarily exactly the same size. It trades 2699f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // off the loss of a few pixels for some glyphs against the ability to store more glyphs 2709f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // of varying sizes in one block. 271e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy uint16_t roundedUpW = (glyphW + CACHE_BLOCK_ROUNDING_SIZE - 1) & -CACHE_BLOCK_ROUNDING_SIZE; 2729b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 273e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy CacheBlock* cacheBlock = mCacheBlocks; 2749f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy while (cacheBlock) { 2759f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // Store glyph in this block iff: it fits the block's remaining space and: 2769f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // it's the remainder space (mY == 0) or there's only enough height for this one glyph 2779f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // or it's within ROUNDING_SIZE of the block width 2789f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (roundedUpW <= cacheBlock->mWidth && glyphH <= cacheBlock->mHeight && 2799f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy (cacheBlock->mY == TEXTURE_BORDER_SIZE || 2809f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy (cacheBlock->mWidth - roundedUpW < CACHE_BLOCK_ROUNDING_SIZE))) { 2819f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (cacheBlock->mHeight - glyphH < glyphH) { 2829f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // Only enough space for this glyph - don't bother rounding up the width 2839f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy roundedUpW = glyphW; 2849f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 2859b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 2869f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy *retOriginX = cacheBlock->mX; 2879f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy *retOriginY = cacheBlock->mY; 2889b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 2899f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // If this is the remainder space, create a new cache block for this column. Otherwise, 2909f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // adjust the info about this column. 2919f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (cacheBlock->mY == TEXTURE_BORDER_SIZE) { 2929f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t oldX = cacheBlock->mX; 2939f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // Adjust remainder space dimensions 2949f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mWidth -= roundedUpW; 2959f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mX += roundedUpW; 2969b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 2979f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (mHeight - glyphH >= glyphH) { 2989f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // There's enough height left over to create a new CacheBlock 299e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy CacheBlock* newBlock = new CacheBlock(oldX, glyphH + TEXTURE_BORDER_SIZE, 3009f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy roundedUpW, mHeight - glyphH - TEXTURE_BORDER_SIZE); 3019f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 3029f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("fitBitmap: Created new block: this, x, y, w, h = %p, %d, %d, %d, %d", 3039f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock, newBlock->mX, newBlock->mY, 3049f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mWidth, newBlock->mHeight); 3059f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 3069f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mCacheBlocks = CacheBlock::insertBlock(mCacheBlocks, newBlock); 3079f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3089f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } else { 3099f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // Insert into current column and adjust column dimensions 3109f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mY += glyphH; 3119f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mHeight -= glyphH; 3129f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 3139f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("fitBitmap: Added to existing block: this, x, y, w, h = %p, %d, %d, %d, %d", 3149f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock, cacheBlock->mX, cacheBlock->mY, 3159f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mWidth, cacheBlock->mHeight); 3169f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 3179f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3189b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 3199f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (cacheBlock->mHeight < fmin(glyphH, glyphW)) { 3209f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // If remaining space in this block is too small to be useful, remove it 3219f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mCacheBlocks = CacheBlock::removeBlock(mCacheBlocks, cacheBlock); 3229f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3239b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 3249f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mDirty = true; 325b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase const Rect r(*retOriginX - TEXTURE_BORDER_SIZE, *retOriginY - TEXTURE_BORDER_SIZE, 326b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase *retOriginX + glyphW, *retOriginY + glyphH); 327b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase mDirtyRect.unionWith(r); 3289b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy mNumGlyphs++; 3299b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 3309f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 3319f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("fitBitmap: current block list:"); 3329f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mCacheBlocks->output(); 3339f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 3349b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 3359f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return true; 3369f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3379f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock = cacheBlock->mNext; 3389f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3399f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 3409f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("fitBitmap: returning false for glyph of size %d, %d", glyphW, glyphH); 3419f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 3429f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return false; 3439f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy} 3449f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 3459f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; // namespace uirenderer 3469f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; // namespace android 347