CacheTexture.h revision 0908764b2b3cf5075df4178a5f0a8547dcb7b317
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ANDROID_HWUI_CACHE_TEXTURE_H 18#define ANDROID_HWUI_CACHE_TEXTURE_H 19 20#include <GLES3/gl3.h> 21 22#include <SkScalerContext.h> 23 24#include <utils/Log.h> 25 26#include "FontUtil.h" 27#include "../Rect.h" 28#include "../Vertex.h" 29 30namespace android { 31namespace uirenderer { 32 33/** 34 * CacheBlock is a node in a linked list of current free space areas in a CacheTexture. 35 * Using CacheBlocks enables us to pack the cache from top to bottom as well as left to right. 36 * When we add a glyph to the cache, we see if it fits within one of the existing columns that 37 * have already been started (this is the case if the glyph fits vertically as well as 38 * horizontally, and if its width is sufficiently close to the column width to avoid 39 * sub-optimal packing of small glyphs into wide columns). If there is no column in which the 40 * glyph fits, we check the final node, which is the remaining space in the cache, creating 41 * a new column as appropriate. 42 * 43 * As columns fill up, we remove their CacheBlock from the list to avoid having to check 44 * small blocks in the future. 45 */ 46struct CacheBlock { 47 uint16_t mX; 48 uint16_t mY; 49 uint16_t mWidth; 50 uint16_t mHeight; 51 CacheBlock* mNext; 52 CacheBlock* mPrev; 53 54 CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height, bool empty = false): 55 mX(x), mY(y), mWidth(width), mHeight(height), mNext(NULL), mPrev(NULL) { 56 } 57 58 static CacheBlock* insertBlock(CacheBlock* head, CacheBlock* newBlock); 59 static CacheBlock* removeBlock(CacheBlock* head, CacheBlock* blockToRemove); 60 61 void output() { 62 CacheBlock* currBlock = this; 63 while (currBlock) { 64 ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d", 65 currBlock, currBlock->mX, currBlock->mY, 66 currBlock->mWidth, currBlock->mHeight); 67 currBlock = currBlock->mNext; 68 } 69 } 70}; 71 72class CacheTexture { 73public: 74 CacheTexture(uint16_t width, uint16_t height, uint32_t maxQuadCount); 75 ~CacheTexture(); 76 77 void reset(); 78 void init(); 79 80 void releaseMesh(); 81 void releaseTexture(); 82 83 void allocateTexture(); 84 void allocateMesh(); 85 86 bool fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY); 87 88 inline uint16_t getWidth() const { 89 return mWidth; 90 } 91 92 inline uint16_t getHeight() const { 93 return mHeight; 94 } 95 96 inline const Rect* getDirtyRect() const { 97 return &mDirtyRect; 98 } 99 100 inline uint8_t* getTexture() const { 101 return mTexture; 102 } 103 104 GLuint getTextureId() { 105 allocateTexture(); 106 return mTextureId; 107 } 108 109 inline bool isDirty() const { 110 return mDirty; 111 } 112 113 inline void setDirty(bool dirty) { 114 mDirty = dirty; 115 if (!dirty) { 116 mDirtyRect.setEmpty(); 117 } 118 } 119 120 inline bool getLinearFiltering() const { 121 return mLinearFiltering; 122 } 123 124 /** 125 * This method assumes that the proper texture unit is active. 126 */ 127 void setLinearFiltering(bool linearFiltering, bool bind = true) { 128 if (linearFiltering != mLinearFiltering) { 129 mLinearFiltering = linearFiltering; 130 131 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST; 132 if (bind) glBindTexture(GL_TEXTURE_2D, getTextureId()); 133 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); 134 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); 135 } 136 } 137 138 inline uint16_t getGlyphCount() const { 139 return mNumGlyphs; 140 } 141 142 TextureVertex* mesh() const { 143 return mMesh; 144 } 145 146 uint32_t meshElementCount() const { 147 return mCurrentQuad * 6; 148 } 149 150 uint16_t* indices() const { 151 return (uint16_t*) 0; 152 } 153 154 void resetMesh() { 155 mCurrentQuad = 0; 156 } 157 158 inline void addQuad(float x1, float y1, float u1, float v1, 159 float x2, float y2, float u2, float v2, 160 float x3, float y3, float u3, float v3, 161 float x4, float y4, float u4, float v4) { 162 TextureVertex* mesh = mMesh + mCurrentQuad * 4; 163 TextureVertex::set(mesh++, x1, y1, u1, v1); 164 TextureVertex::set(mesh++, x2, y2, u2, v2); 165 TextureVertex::set(mesh++, x3, y3, u3, v3); 166 TextureVertex::set(mesh++, x4, y4, u4, v4); 167 mCurrentQuad++; 168 } 169 170 bool canDraw() const { 171 return mCurrentQuad > 0; 172 } 173 174 bool endOfMesh() const { 175 return mCurrentQuad == mMaxQuadCount; 176 } 177 178private: 179 uint8_t* mTexture; 180 GLuint mTextureId; 181 uint16_t mWidth; 182 uint16_t mHeight; 183 bool mLinearFiltering; 184 bool mDirty; 185 uint16_t mNumGlyphs; 186 TextureVertex* mMesh; 187 uint32_t mCurrentQuad; 188 uint32_t mMaxQuadCount; 189 CacheBlock* mCacheBlocks; 190 Rect mDirtyRect; 191}; 192 193}; // namespace uirenderer 194}; // namespace android 195 196#endif // ANDROID_HWUI_CACHE_TEXTURE_H 197