CacheTexture.h revision 661a87ec28a49458f1faf533783abf2ab9927cab
18182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood/*
28182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * Copyright (C) 2012 The Android Open Source Project
38182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood *
48182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
58182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * you may not use this file except in compliance with the License.
68182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * You may obtain a copy of the License at
78182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood *
88182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
98182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood *
108182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * Unless required by applicable law or agreed to in writing, software
118182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
128182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * See the License for the specific language governing permissions and
148182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * limitations under the License.
158182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood */
168182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
178182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood#ifndef ANDROID_HWUI_CACHE_TEXTURE_H
188182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood#define ANDROID_HWUI_CACHE_TEXTURE_H
19c4308f01c965571dc2354107c3574df113e397eeMike Lockwood
20acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood#include <GLES2/gl2.h>
218182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
228182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood#include <SkScalerContext.h>
230cdd9f7def708a71a0d0722361f52c0416370dc6Scott Main
240cdd9f7def708a71a0d0722361f52c0416370dc6Scott Main#include <utils/Log.h>
250cdd9f7def708a71a0d0722361f52c0416370dc6Scott Main
260cdd9f7def708a71a0d0722361f52c0416370dc6Scott Main#include "FontUtil.h"
278182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood#include "../Rect.h"
288182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood#include "../Vertex.h"
298182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
308182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwoodnamespace android {
318182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwoodnamespace uirenderer {
328182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
338182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood/**
348182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * CacheBlock is a node in a linked list of current free space areas in a CacheTexture.
358182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * Using CacheBlocks enables us to pack the cache from top to bottom as well as left to right.
368182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * When we add a glyph to the cache, we see if it fits within one of the existing columns that
378182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * have already been started (this is the case if the glyph fits vertically as well as
38540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood * horizontally, and if its width is sufficiently close to the column width to avoid
39540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood * sub-optimal packing of small glyphs into wide columns). If there is no column in which the
40540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood * glyph fits, we check the final node, which is the remaining space in the cache, creating
41c4308f01c965571dc2354107c3574df113e397eeMike Lockwood * a new column as appropriate.
42540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood *
438182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * As columns fill up, we remove their CacheBlock from the list to avoid having to check
448182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood * small blocks in the future.
458182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood */
468182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwoodstruct CacheBlock {
47540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    uint16_t mX;
48acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    uint16_t mY;
49acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    uint16_t mWidth;
50acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    uint16_t mHeight;
51acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    CacheBlock* mNext;
52540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    CacheBlock* mPrev;
53acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood
54540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height, bool empty = false):
55540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood            mX(x), mY(y), mWidth(width), mHeight(height), mNext(NULL), mPrev(NULL) {
56acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    }
57acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood
58acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    static CacheBlock* insertBlock(CacheBlock* head, CacheBlock* newBlock);
59acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    static CacheBlock* removeBlock(CacheBlock* head, CacheBlock* blockToRemove);
608182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
61acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    void output() {
628182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood        CacheBlock* currBlock = this;
638182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood        while (currBlock) {
64540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood            ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d",
6511dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood                    currBlock, currBlock->mX, currBlock->mY,
6611dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood                    currBlock->mWidth, currBlock->mHeight);
6711dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood            currBlock = currBlock->mNext;
68540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        }
698182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    }
708182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood};
718182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
728182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwoodclass CacheTexture {
738182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwoodpublic:
748182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    CacheTexture(uint16_t width, uint16_t height, uint32_t maxQuadCount);
758182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    ~CacheTexture();
768182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
778182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    void reset();
788182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    void init();
798182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
808182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    void releaseMesh();
818182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    void releaseTexture();
82540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood
83540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    void allocateTexture();
8411dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood    void allocateMesh();
8511dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood
86540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    bool fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY);
87540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood
88540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    inline uint16_t getWidth() const {
898182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood        return mWidth;
908182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    }
918182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
928182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    inline uint16_t getHeight() const {
93540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        return mHeight;
9411dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood    }
9511dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood
9611dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood    inline const Rect* getDirtyRect() const {
97540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        return &mDirtyRect;
98540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    }
99540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood
1008182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    inline uint8_t* getTexture() const {
1018182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood        return mTexture;
1028182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    }
1038182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
1048182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    GLuint getTextureId() {
1058182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood        allocateTexture();
1068182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood        return mTextureId;
1078182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    }
1088182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
109540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    inline bool isDirty() const {
11011dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood        return mDirty;
111540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    }
112540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood
113540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    inline void setDirty(bool dirty) {
1148182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood        mDirty = dirty;
1158182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood        if (!dirty) {
1168182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood            mDirtyRect.setEmpty();
1178182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood        }
118540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    }
119540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood
12011dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood    inline bool getLinearFiltering() const {
121540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        return mLinearFiltering;
12211dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood    }
123540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood
1248182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    /**
1258182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood     * This method assumes that the proper texture unit is active.
1268182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood     */
1278182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    void setLinearFiltering(bool linearFiltering, bool bind = true) {
128540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        if (linearFiltering != mLinearFiltering) {
129540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood            mLinearFiltering = linearFiltering;
130540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood
13111dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood            const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
132540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood            if (bind) glBindTexture(GL_TEXTURE_2D, getTextureId());
133540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
134540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
135540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        }
136540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    }
137540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood
1388182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    inline uint16_t getGlyphCount() const {
1398182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood        return mNumGlyphs;
1408182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    }
1418182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
142540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    TextureVertex* mesh() const {
143540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        return mMesh;
14411dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood    }
14511dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood
146540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    uint32_t meshElementCount() const {
147540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        return mCurrentQuad * 6;
148540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    }
14911dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood
150540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    uint16_t* indices() const {
151540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        return (uint16_t*) 0;
1528182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    }
1538182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
1548182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    void resetMesh() {
1558182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood        mCurrentQuad = 0;
156540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    }
157540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood
15811dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood    inline void addQuad(float x1, float y1, float u1, float v1,
15911dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood            float x2, float y2, float u2, float v2,
16011dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood            float x3, float y3, float u3, float v3,
16111dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood            float x4, float y4, float u4, float v4) {
162540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        TextureVertex* mesh = mMesh + mCurrentQuad * 4;
163540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        TextureVertex::set(mesh++, x1, y1, u1, v1);
164540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        TextureVertex::set(mesh++, x2, y2, u2, v2);
165540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        TextureVertex::set(mesh++, x3, y3, u3, v3);
1668182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood        TextureVertex::set(mesh++, x4, y4, u4, v4);
1678182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood        mCurrentQuad++;
1688182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    }
1698182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
170540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    bool canDraw() const {
17111dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood        return mCurrentQuad > 0;
172540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    }
173540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood
174540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    bool endOfMesh() const {
175540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood        return mCurrentQuad == mMaxQuadCount;
1768182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    }
1778182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood
1788182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwoodprivate:
1798182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    uint8_t* mTexture;
180540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    GLuint mTextureId;
18111dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood    uint16_t mWidth;
182540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    uint16_t mHeight;
183540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    bool mLinearFiltering;
184540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    bool mDirty;
185540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    uint16_t mNumGlyphs;
1868182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    TextureVertex* mMesh;
1878182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    uint32_t mCurrentQuad;
1888182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    uint32_t mMaxQuadCount;
1898182e72479a8b0d832df9c392890b25bfa6f97b5Mike Lockwood    CacheBlock* mCacheBlocks;
190540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood    Rect mDirtyRect;
19111dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood};
19211dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood
19311dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood}; // namespace uirenderer
194540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood}; // namespace android
195540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood
196540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood#endif // ANDROID_HWUI_CACHE_TEXTURE_H
197540380fb0a45b12af3970f9ea1ed041607451f46Mike Lockwood