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 20e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik#include "PixelBuffer.h" 21e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik#include "Rect.h" 22e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik#include "Texture.h" 23e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik#include "Vertex.h" 249f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 25e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik#include <GLES3/gl3.h> 26c46813d72464f950b6f945f46a979caeaa05d21bLeon Scroggins III#include <SkGlyph.h> 279f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#include <utils/Log.h> 289f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 299f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 309f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guynamespace android { 319f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guynamespace uirenderer { 329f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 338aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guyclass Caches; 34cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 359f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/** 369f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * CacheBlock is a node in a linked list of current free space areas in a CacheTexture. 379f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * Using CacheBlocks enables us to pack the cache from top to bottom as well as left to right. 389f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * When we add a glyph to the cache, we see if it fits within one of the existing columns that 399f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * have already been started (this is the case if the glyph fits vertically as well as 409f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * horizontally, and if its width is sufficiently close to the column width to avoid 419f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * sub-optimal packing of small glyphs into wide columns). If there is no column in which the 429f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * glyph fits, we check the final node, which is the remaining space in the cache, creating 439f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * a new column as appropriate. 449f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * 459f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * As columns fill up, we remove their CacheBlock from the list to avoid having to check 469f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * small blocks in the future. 479f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy */ 489f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guystruct CacheBlock { 499f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t mX; 509f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t mY; 519f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t mWidth; 529f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t mHeight; 539f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* mNext; 549f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* mPrev; 559f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 56e63f7c622a2086aefa80983c6f41b74fb166bb42Chris Craik CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height): 57e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik mX(x), mY(y), mWidth(width), mHeight(height), mNext(nullptr), mPrev(nullptr) { 589f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 599f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 60e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy static CacheBlock* insertBlock(CacheBlock* head, CacheBlock* newBlock); 61e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy static CacheBlock* removeBlock(CacheBlock* head, CacheBlock* blockToRemove); 629f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 639f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy void output() { 64e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy CacheBlock* currBlock = this; 659f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy while (currBlock) { 669f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d", 67661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy currBlock, currBlock->mX, currBlock->mY, 68661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy currBlock->mWidth, currBlock->mHeight); 699f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy currBlock = currBlock->mNext; 709f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 719f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 729f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; 739f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 749f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guyclass CacheTexture { 759f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guypublic: 761e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture(uint16_t width, uint16_t height, GLenum format, uint32_t maxQuadCount); 77661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy ~CacheTexture(); 789f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 79661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy void reset(); 80661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy void init(); 819f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 82661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy void releaseMesh(); 83e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik void releasePixelBuffer(); 849f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 85e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik void allocatePixelBuffer(); 86661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy void allocateMesh(); 878087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 88cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // Returns true if glPixelStorei(GL_UNPACK_ROW_LENGTH) must be reset 89cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // This method will also call setDirty(false) 90cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy bool upload(); 91cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 92e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy bool fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY); 939f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 948087246d9964b11de8ce116bc63b156faa4197e0Romain Guy inline uint16_t getWidth() const { 9538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck return mWidth; 968087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 978087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 988087246d9964b11de8ce116bc63b156faa4197e0Romain Guy inline uint16_t getHeight() const { 9938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck return mHeight; 1008087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1018087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1021e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease inline GLenum getFormat() const { 1031e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return mFormat; 1041e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 1051e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 1061e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease inline uint32_t getOffset(uint16_t x, uint16_t y) const { 107e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik return (y * getWidth() + x) * PixelBuffer::formatSize(mFormat); 1081e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 1091e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 110b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase inline const Rect* getDirtyRect() const { 111b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase return &mDirtyRect; 112b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase } 113b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase 114cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy inline PixelBuffer* getPixelBuffer() const { 115e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik return mPixelBuffer; 116e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik } 117e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik 118e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik Texture& getTexture() { 119e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik allocatePixelBuffer(); 1208087246d9964b11de8ce116bc63b156faa4197e0Romain Guy return mTexture; 1218087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1228087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 123574cf6070d34e66dfd6f2006937986eddd1f09e7Romain Guy GLuint getTextureId() { 124e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik allocatePixelBuffer(); 12538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck return mTexture.id(); 1268087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1278087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1288087246d9964b11de8ce116bc63b156faa4197e0Romain Guy inline bool isDirty() const { 1298087246d9964b11de8ce116bc63b156faa4197e0Romain Guy return mDirty; 1308087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1318087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1328087246d9964b11de8ce116bc63b156faa4197e0Romain Guy inline bool getLinearFiltering() const { 1338087246d9964b11de8ce116bc63b156faa4197e0Romain Guy return mLinearFiltering; 1348087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1358087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1368087246d9964b11de8ce116bc63b156faa4197e0Romain Guy /** 1378087246d9964b11de8ce116bc63b156faa4197e0Romain Guy * This method assumes that the proper texture unit is active. 1388087246d9964b11de8ce116bc63b156faa4197e0Romain Guy */ 139e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik void setLinearFiltering(bool linearFiltering); 1408087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 1418087246d9964b11de8ce116bc63b156faa4197e0Romain Guy inline uint16_t getGlyphCount() const { 1428087246d9964b11de8ce116bc63b156faa4197e0Romain Guy return mNumGlyphs; 1438087246d9964b11de8ce116bc63b156faa4197e0Romain Guy } 1448087246d9964b11de8ce116bc63b156faa4197e0Romain Guy 145661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy TextureVertex* mesh() const { 146661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy return mMesh; 147661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 148661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 149661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy uint32_t meshElementCount() const { 150661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy return mCurrentQuad * 6; 151661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 152661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 153661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy uint16_t* indices() const { 154e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik return (uint16_t*) nullptr; 155661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 156661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 157661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy void resetMesh() { 158661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCurrentQuad = 0; 159661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 160661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 161661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy inline void addQuad(float x1, float y1, float u1, float v1, 162661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy float x2, float y2, float u2, float v2, 163661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy float x3, float y3, float u3, float v3, 164661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy float x4, float y4, float u4, float v4) { 165661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy TextureVertex* mesh = mMesh + mCurrentQuad * 4; 166661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy TextureVertex::set(mesh++, x2, y2, u2, v2); 167661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy TextureVertex::set(mesh++, x3, y3, u3, v3); 16831e08e953fe7bdb1b1cbc247156cb6a19917a2f1Romain Guy TextureVertex::set(mesh++, x1, y1, u1, v1); 169661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy TextureVertex::set(mesh++, x4, y4, u4, v4); 170661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCurrentQuad++; 171661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 172661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 173661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy bool canDraw() const { 174661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy return mCurrentQuad > 0; 175661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 176661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 177661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy bool endOfMesh() const { 178661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy return mCurrentQuad == mMaxQuadCount; 179661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 180661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 181baf29e7cf433624687c9d6b3bac180d33add8e0fsergeyv uint32_t calculateFreeMemory() const; 182baf29e7cf433624687c9d6b3bac180d33add8e0fsergeyv 1838087246d9964b11de8ce116bc63b156faa4197e0Romain Guyprivate: 184cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy void setDirty(bool dirty); 185cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 186e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik PixelBuffer* mPixelBuffer = nullptr; 187e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik Texture mTexture; 18838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck uint32_t mWidth, mHeight; 1891e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GLenum mFormat; 190e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik bool mLinearFiltering = false; 191e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik bool mDirty = false; 192e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik uint16_t mNumGlyphs = 0; 193e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik TextureVertex* mMesh = nullptr; 194e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik uint32_t mCurrentQuad = 0; 195661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy uint32_t mMaxQuadCount; 1968aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy Caches& mCaches; 1979f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* mCacheBlocks; 198318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy bool mHasUnpackRowLength; 1998aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy Rect mDirtyRect; 2009f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; 2019f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 2029f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; // namespace uirenderer 2039f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; // namespace android 2049f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 2059f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif // ANDROID_HWUI_CACHE_TEXTURE_H 206