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