Home | History | Annotate | Download | only in font
      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 
     30 namespace android {
     31 namespace uirenderer {
     32 
     33 class PixelBuffer;
     34 
     35 /**
     36  * CacheBlock is a node in a linked list of current free space areas in a CacheTexture.
     37  * Using CacheBlocks enables us to pack the cache from top to bottom as well as left to right.
     38  * When we add a glyph to the cache, we see if it fits within one of the existing columns that
     39  * have already been started (this is the case if the glyph fits vertically as well as
     40  * horizontally, and if its width is sufficiently close to the column width to avoid
     41  * sub-optimal packing of small glyphs into wide columns). If there is no column in which the
     42  * glyph fits, we check the final node, which is the remaining space in the cache, creating
     43  * a new column as appropriate.
     44  *
     45  * As columns fill up, we remove their CacheBlock from the list to avoid having to check
     46  * small blocks in the future.
     47  */
     48 struct CacheBlock {
     49     uint16_t mX;
     50     uint16_t mY;
     51     uint16_t mWidth;
     52     uint16_t mHeight;
     53     CacheBlock* mNext;
     54     CacheBlock* mPrev;
     55 
     56     CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height, bool empty = false):
     57             mX(x), mY(y), mWidth(width), mHeight(height), mNext(NULL), mPrev(NULL) {
     58     }
     59 
     60     static CacheBlock* insertBlock(CacheBlock* head, CacheBlock* newBlock);
     61     static CacheBlock* removeBlock(CacheBlock* head, CacheBlock* blockToRemove);
     62 
     63     void output() {
     64         CacheBlock* currBlock = this;
     65         while (currBlock) {
     66             ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d",
     67                     currBlock, currBlock->mX, currBlock->mY,
     68                     currBlock->mWidth, currBlock->mHeight);
     69             currBlock = currBlock->mNext;
     70         }
     71     }
     72 };
     73 
     74 class CacheTexture {
     75 public:
     76     CacheTexture(uint16_t width, uint16_t height, uint32_t maxQuadCount);
     77     ~CacheTexture();
     78 
     79     void reset();
     80     void init();
     81 
     82     void releaseMesh();
     83     void releaseTexture();
     84 
     85     void allocateTexture();
     86     void allocateMesh();
     87 
     88     // Returns true if glPixelStorei(GL_UNPACK_ROW_LENGTH) must be reset
     89     // This method will also call setDirty(false)
     90     bool upload();
     91 
     92     bool fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY);
     93 
     94     inline uint16_t getWidth() const {
     95         return mWidth;
     96     }
     97 
     98     inline uint16_t getHeight() const {
     99         return mHeight;
    100     }
    101 
    102     inline const Rect* getDirtyRect() const {
    103         return &mDirtyRect;
    104     }
    105 
    106     inline PixelBuffer* getPixelBuffer() const {
    107         return mTexture;
    108     }
    109 
    110     GLuint getTextureId() {
    111         allocateTexture();
    112         return mTextureId;
    113     }
    114 
    115     inline bool isDirty() const {
    116         return mDirty;
    117     }
    118 
    119     inline bool getLinearFiltering() const {
    120         return mLinearFiltering;
    121     }
    122 
    123     /**
    124      * This method assumes that the proper texture unit is active.
    125      */
    126     void setLinearFiltering(bool linearFiltering, bool bind = true);
    127 
    128     inline uint16_t getGlyphCount() const {
    129         return mNumGlyphs;
    130     }
    131 
    132     TextureVertex* mesh() const {
    133         return mMesh;
    134     }
    135 
    136     uint32_t meshElementCount() const {
    137         return mCurrentQuad * 6;
    138     }
    139 
    140     uint16_t* indices() const {
    141         return (uint16_t*) 0;
    142     }
    143 
    144     void resetMesh() {
    145         mCurrentQuad = 0;
    146     }
    147 
    148     inline void addQuad(float x1, float y1, float u1, float v1,
    149             float x2, float y2, float u2, float v2,
    150             float x3, float y3, float u3, float v3,
    151             float x4, float y4, float u4, float v4) {
    152         TextureVertex* mesh = mMesh + mCurrentQuad * 4;
    153         TextureVertex::set(mesh++, x1, y1, u1, v1);
    154         TextureVertex::set(mesh++, x2, y2, u2, v2);
    155         TextureVertex::set(mesh++, x3, y3, u3, v3);
    156         TextureVertex::set(mesh++, x4, y4, u4, v4);
    157         mCurrentQuad++;
    158     }
    159 
    160     bool canDraw() const {
    161         return mCurrentQuad > 0;
    162     }
    163 
    164     bool endOfMesh() const {
    165         return mCurrentQuad == mMaxQuadCount;
    166     }
    167 
    168 private:
    169     void setDirty(bool dirty);
    170 
    171     PixelBuffer* mTexture;
    172     GLuint mTextureId;
    173     uint16_t mWidth;
    174     uint16_t mHeight;
    175     bool mLinearFiltering;
    176     bool mDirty;
    177     uint16_t mNumGlyphs;
    178     TextureVertex* mMesh;
    179     uint32_t mCurrentQuad;
    180     uint32_t mMaxQuadCount;
    181     CacheBlock* mCacheBlocks;
    182     Rect mDirtyRect;
    183     bool mHasES3;
    184 };
    185 
    186 }; // namespace uirenderer
    187 }; // namespace android
    188 
    189 #endif // ANDROID_HWUI_CACHE_TEXTURE_H
    190