CacheTexture.h revision b92d8f7979c29c7c09932578a11b2f8d6eec1d90
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 179f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#ifndef ANDROID_HWUI_CACHE_TEXTURE_H 189f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#define ANDROID_HWUI_CACHE_TEXTURE_H 199f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 209f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#include <GLES2/gl2.h> 219f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 229f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#include <SkScalerContext.h> 239f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 249f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#include <utils/Log.h> 259f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 269f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#include "FontUtil.h" 27b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase#include "Rect.h" 289f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 299f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guynamespace android { 309f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guynamespace uirenderer { 319f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 329f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/** 339f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * CacheBlock is a node in a linked list of current free space areas in a CacheTexture. 349f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * Using CacheBlocks enables us to pack the cache from top to bottom as well as left to right. 359f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * When we add a glyph to the cache, we see if it fits within one of the existing columns that 369f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * have already been started (this is the case if the glyph fits vertically as well as 379f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * horizontally, and if its width is sufficiently close to the column width to avoid 389f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * sub-optimal packing of small glyphs into wide columns). If there is no column in which the 399f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * glyph fits, we check the final node, which is the remaining space in the cache, creating 409f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * a new column as appropriate. 419f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * 429f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * As columns fill up, we remove their CacheBlock from the list to avoid having to check 439f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * small blocks in the future. 449f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy */ 459f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guystruct CacheBlock { 469f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t mX; 479f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t mY; 489f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t mWidth; 499f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t mHeight; 509f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* mNext; 519f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* mPrev; 529f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 539f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height, bool empty = false): 549b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy mX(x), mY(y), mWidth(width), mHeight(height), mNext(NULL), mPrev(NULL) { 559f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 569f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 57e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy static CacheBlock* insertBlock(CacheBlock* head, CacheBlock* newBlock); 589f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 59e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy static CacheBlock* removeBlock(CacheBlock* head, CacheBlock* blockToRemove); 609f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 619f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy void output() { 62e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy CacheBlock* currBlock = this; 639f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy while (currBlock) { 649f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d", 659f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy currBlock, currBlock->mX, currBlock->mY, currBlock->mWidth, currBlock->mHeight); 669f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy currBlock = currBlock->mNext; 679f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 689f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 699f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; 709f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 719f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guyclass CacheTexture { 729f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guypublic: 739f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheTexture(uint16_t width, uint16_t height) : 749f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height), 759f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mLinearFiltering(false), mDirty(false), mNumGlyphs(0) { 769f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, 779f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true); 789f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 799f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 809f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ~CacheTexture() { 819f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (mTexture) { 829f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy delete[] mTexture; 839f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 849f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (mTextureId) { 859f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy glDeleteTextures(1, &mTextureId); 869f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 879f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy reset(); 889f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 899f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 909f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy void reset() { 919f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // Delete existing cache blocks 929f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy while (mCacheBlocks != NULL) { 939f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* tmpBlock = mCacheBlocks; 949f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mCacheBlocks = mCacheBlocks->mNext; 959f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy delete tmpBlock; 969f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 979f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mNumGlyphs = 0; 989f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 999f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 1009f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy void init() { 1019f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // reset, then create a new remainder space to start again 1029f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy reset(); 1039f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, 1049f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true); 1059f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 1069f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 1078087246d9964b11de8ce116bc63b156faa4197e0Romain Guy void releaseTexture() { 1088087246d9964b11de8ce116bc63b156faa4197e0Romain Guy if (mTexture) { 1098087246d9964b11de8ce116bc63b156faa4197e0Romain Guy glDeleteTextures(1, &mTextureId); 1108087246d9964b11de8ce116bc63b156faa4197e0Romain Guy delete[] mTexture; 1118087246d9964b11de8ce116bc63b156faa4197e0Romain Guy mTexture = NULL; 1128087246d9964b11de8ce116bc63b156faa4197e0Romain Guy mTextureId = 0; 1138087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1148087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1158087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1168087246d9964b11de8ce116bc63b156faa4197e0Romain Guy /** 1178087246d9964b11de8ce116bc63b156faa4197e0Romain Guy * This method assumes that the proper texture unit is active. 1188087246d9964b11de8ce116bc63b156faa4197e0Romain Guy */ 1198087246d9964b11de8ce116bc63b156faa4197e0Romain Guy void allocateTexture() { 1208087246d9964b11de8ce116bc63b156faa4197e0Romain Guy int width = mWidth; 1218087246d9964b11de8ce116bc63b156faa4197e0Romain Guy int height = mHeight; 1228087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1238087246d9964b11de8ce116bc63b156faa4197e0Romain Guy mTexture = new uint8_t[width * height]; 1248087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1258087246d9964b11de8ce116bc63b156faa4197e0Romain Guy if (!mTextureId) { 1268087246d9964b11de8ce116bc63b156faa4197e0Romain Guy glGenTextures(1, &mTextureId); 1278087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1288087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1298087246d9964b11de8ce116bc63b156faa4197e0Romain Guy glBindTexture(GL_TEXTURE_2D, mTextureId); 1308087246d9964b11de8ce116bc63b156faa4197e0Romain Guy glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 1318087246d9964b11de8ce116bc63b156faa4197e0Romain Guy // Initialize texture dimensions 1328087246d9964b11de8ce116bc63b156faa4197e0Romain Guy glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, 1338087246d9964b11de8ce116bc63b156faa4197e0Romain Guy GL_ALPHA, GL_UNSIGNED_BYTE, 0); 1348087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1358087246d9964b11de8ce116bc63b156faa4197e0Romain Guy const GLenum filtering = getLinearFiltering() ? GL_LINEAR : GL_NEAREST; 1368087246d9964b11de8ce116bc63b156faa4197e0Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); 1378087246d9964b11de8ce116bc63b156faa4197e0Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); 1388087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1398087246d9964b11de8ce116bc63b156faa4197e0Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1408087246d9964b11de8ce116bc63b156faa4197e0Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1418087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1428087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 143e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy bool fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY); 1449f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 1458087246d9964b11de8ce116bc63b156faa4197e0Romain Guy inline uint16_t getWidth() const { 1468087246d9964b11de8ce116bc63b156faa4197e0Romain Guy return mWidth; 1478087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1488087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1498087246d9964b11de8ce116bc63b156faa4197e0Romain Guy inline uint16_t getHeight() const { 1508087246d9964b11de8ce116bc63b156faa4197e0Romain Guy return mHeight; 1518087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1528087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 153b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase inline const Rect* getDirtyRect() const { 154b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase return &mDirtyRect; 155b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase } 156b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase 1578087246d9964b11de8ce116bc63b156faa4197e0Romain Guy inline uint8_t* getTexture() const { 1588087246d9964b11de8ce116bc63b156faa4197e0Romain Guy return mTexture; 1598087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1608087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1618087246d9964b11de8ce116bc63b156faa4197e0Romain Guy inline GLuint getTextureId() const { 1628087246d9964b11de8ce116bc63b156faa4197e0Romain Guy return mTextureId; 1638087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1648087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1658087246d9964b11de8ce116bc63b156faa4197e0Romain Guy inline bool isDirty() const { 1668087246d9964b11de8ce116bc63b156faa4197e0Romain Guy return mDirty; 1678087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1688087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1698087246d9964b11de8ce116bc63b156faa4197e0Romain Guy inline void setDirty(bool dirty) { 1708087246d9964b11de8ce116bc63b156faa4197e0Romain Guy mDirty = dirty; 171b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase if (!dirty) { 172b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase mDirtyRect.setEmpty(); 173b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase } 1748087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1758087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1768087246d9964b11de8ce116bc63b156faa4197e0Romain Guy inline bool getLinearFiltering() const { 1778087246d9964b11de8ce116bc63b156faa4197e0Romain Guy return mLinearFiltering; 1788087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1798087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1808087246d9964b11de8ce116bc63b156faa4197e0Romain Guy /** 1818087246d9964b11de8ce116bc63b156faa4197e0Romain Guy * This method assumes that the proper texture unit is active. 1828087246d9964b11de8ce116bc63b156faa4197e0Romain Guy */ 1838087246d9964b11de8ce116bc63b156faa4197e0Romain Guy void setLinearFiltering(bool linearFiltering, bool bind = true) { 1848087246d9964b11de8ce116bc63b156faa4197e0Romain Guy if (linearFiltering != mLinearFiltering) { 1858087246d9964b11de8ce116bc63b156faa4197e0Romain Guy mLinearFiltering = linearFiltering; 1868087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1878087246d9964b11de8ce116bc63b156faa4197e0Romain Guy const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST; 1888087246d9964b11de8ce116bc63b156faa4197e0Romain Guy if (bind) glBindTexture(GL_TEXTURE_2D, getTextureId()); 1898087246d9964b11de8ce116bc63b156faa4197e0Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); 1908087246d9964b11de8ce116bc63b156faa4197e0Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); 1918087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1928087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1938087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1948087246d9964b11de8ce116bc63b156faa4197e0Romain Guy inline uint16_t getGlyphCount() const { 1958087246d9964b11de8ce116bc63b156faa4197e0Romain Guy return mNumGlyphs; 1968087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1978087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1988087246d9964b11de8ce116bc63b156faa4197e0Romain Guyprivate: 1999f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint8_t* mTexture; 2009f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy GLuint mTextureId; 2019f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t mWidth; 2029f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t mHeight; 2039f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy bool mLinearFiltering; 2049f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy bool mDirty; 2059f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t mNumGlyphs; 2069f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* mCacheBlocks; 207b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase Rect mDirtyRect; 2089f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; 2099f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 2109f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; // namespace uirenderer 2119f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; // namespace android 2129f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 2139f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif // ANDROID_HWUI_CACHE_TEXTURE_H 214