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
200908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy#include <GLES3/gl3.h>
219f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
229f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#include <SkScalerContext.h>
239f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
249f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#include <utils/Log.h>
259f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
269f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#include "FontUtil.h"
271e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#include "../PixelBuffer.h"
28661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy#include "../Rect.h"
29661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy#include "../Vertex.h"
309f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
319f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guynamespace android {
329f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guynamespace uirenderer {
339f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
348aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guyclass Caches;
35cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
369f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/**
379f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * CacheBlock is a node in a linked list of current free space areas in a CacheTexture.
389f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * Using CacheBlocks enables us to pack the cache from top to bottom as well as left to right.
399f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * When we add a glyph to the cache, we see if it fits within one of the existing columns that
409f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * have already been started (this is the case if the glyph fits vertically as well as
419f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * horizontally, and if its width is sufficiently close to the column width to avoid
429f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * sub-optimal packing of small glyphs into wide columns). If there is no column in which the
439f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * glyph fits, we check the final node, which is the remaining space in the cache, creating
449f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * a new column as appropriate.
459f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy *
469f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * As columns fill up, we remove their CacheBlock from the list to avoid having to check
479f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * small blocks in the future.
489f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy */
499f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guystruct CacheBlock {
509f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    uint16_t mX;
519f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    uint16_t mY;
529f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    uint16_t mWidth;
539f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    uint16_t mHeight;
549f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    CacheBlock* mNext;
559f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    CacheBlock* mPrev;
569f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
57e63f7c622a2086aefa80983c6f41b74fb166bb42Chris Craik    CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height):
589b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy            mX(x), mY(y), mWidth(width), mHeight(height), mNext(NULL), mPrev(NULL) {
599f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    }
609f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
61e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy    static CacheBlock* insertBlock(CacheBlock* head, CacheBlock* newBlock);
62e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy    static CacheBlock* removeBlock(CacheBlock* head, CacheBlock* blockToRemove);
639f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
649f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    void output() {
65e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy        CacheBlock* currBlock = this;
669f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy        while (currBlock) {
679f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy            ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d",
68661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy                    currBlock, currBlock->mX, currBlock->mY,
69661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy                    currBlock->mWidth, currBlock->mHeight);
709f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy            currBlock = currBlock->mNext;
719f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy        }
729f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    }
739f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy};
749f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
759f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guyclass CacheTexture {
769f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guypublic:
771e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease    CacheTexture(uint16_t width, uint16_t height, GLenum format, uint32_t maxQuadCount);
78661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    ~CacheTexture();
799f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
80661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    void reset();
81661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    void init();
829f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
83661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    void releaseMesh();
84661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    void releaseTexture();
859f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
86661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    void allocateTexture();
87661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    void allocateMesh();
888087246d9964b11de8ce116bc63b156faa4197e0Romain Guy
89cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    // Returns true if glPixelStorei(GL_UNPACK_ROW_LENGTH) must be reset
90cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    // This method will also call setDirty(false)
91cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    bool upload();
92cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
93e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy    bool fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY);
949f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
958087246d9964b11de8ce116bc63b156faa4197e0Romain Guy    inline uint16_t getWidth() const {
968087246d9964b11de8ce116bc63b156faa4197e0Romain Guy        return mWidth;
978087246d9964b11de8ce116bc63b156faa4197e0Romain Guy    }
988087246d9964b11de8ce116bc63b156faa4197e0Romain Guy
998087246d9964b11de8ce116bc63b156faa4197e0Romain Guy    inline uint16_t getHeight() const {
1008087246d9964b11de8ce116bc63b156faa4197e0Romain Guy        return mHeight;
1018087246d9964b11de8ce116bc63b156faa4197e0Romain Guy    }
1028087246d9964b11de8ce116bc63b156faa4197e0Romain Guy
1031e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease    inline GLenum getFormat() const {
1041e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease        return mFormat;
1051e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease    }
1061e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease
1071e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease    inline uint32_t getOffset(uint16_t x, uint16_t y) const {
1081e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease        return (y * mWidth + x) * PixelBuffer::formatSize(mFormat);
1091e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease    }
1101e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease
111b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase    inline const Rect* getDirtyRect() const {
112b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase        return &mDirtyRect;
113b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase    }
114b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase
115cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    inline PixelBuffer* getPixelBuffer() const {
1168087246d9964b11de8ce116bc63b156faa4197e0Romain Guy        return mTexture;
1178087246d9964b11de8ce116bc63b156faa4197e0Romain Guy    }
1188087246d9964b11de8ce116bc63b156faa4197e0Romain Guy
119574cf6070d34e66dfd6f2006937986eddd1f09e7Romain Guy    GLuint getTextureId() {
120574cf6070d34e66dfd6f2006937986eddd1f09e7Romain Guy        allocateTexture();
1218087246d9964b11de8ce116bc63b156faa4197e0Romain Guy        return mTextureId;
1228087246d9964b11de8ce116bc63b156faa4197e0Romain Guy    }
1238087246d9964b11de8ce116bc63b156faa4197e0Romain Guy
1248087246d9964b11de8ce116bc63b156faa4197e0Romain Guy    inline bool isDirty() const {
1258087246d9964b11de8ce116bc63b156faa4197e0Romain Guy        return mDirty;
1268087246d9964b11de8ce116bc63b156faa4197e0Romain Guy    }
1278087246d9964b11de8ce116bc63b156faa4197e0Romain Guy
1288087246d9964b11de8ce116bc63b156faa4197e0Romain Guy    inline bool getLinearFiltering() const {
1298087246d9964b11de8ce116bc63b156faa4197e0Romain Guy        return mLinearFiltering;
1308087246d9964b11de8ce116bc63b156faa4197e0Romain Guy    }
1318087246d9964b11de8ce116bc63b156faa4197e0Romain Guy
1328087246d9964b11de8ce116bc63b156faa4197e0Romain Guy    /**
1338087246d9964b11de8ce116bc63b156faa4197e0Romain Guy     * This method assumes that the proper texture unit is active.
1348087246d9964b11de8ce116bc63b156faa4197e0Romain Guy     */
135cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    void setLinearFiltering(bool linearFiltering, bool bind = true);
1368087246d9964b11de8ce116bc63b156faa4197e0Romain Guy
1378087246d9964b11de8ce116bc63b156faa4197e0Romain Guy    inline uint16_t getGlyphCount() const {
1388087246d9964b11de8ce116bc63b156faa4197e0Romain Guy        return mNumGlyphs;
1398087246d9964b11de8ce116bc63b156faa4197e0Romain Guy    }
1408087246d9964b11de8ce116bc63b156faa4197e0Romain Guy
141661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    TextureVertex* mesh() const {
142661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy        return mMesh;
143661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    }
144661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy
145661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    uint32_t meshElementCount() const {
146661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy        return mCurrentQuad * 6;
147661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    }
148661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy
149661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    uint16_t* indices() const {
150661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy        return (uint16_t*) 0;
151661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    }
152661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy
153661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    void resetMesh() {
154661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy        mCurrentQuad = 0;
155661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    }
156661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy
157661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    inline void addQuad(float x1, float y1, float u1, float v1,
158661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy            float x2, float y2, float u2, float v2,
159661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy            float x3, float y3, float u3, float v3,
160661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy            float x4, float y4, float u4, float v4) {
161661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy        TextureVertex* mesh = mMesh + mCurrentQuad * 4;
162661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy        TextureVertex::set(mesh++, x2, y2, u2, v2);
163661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy        TextureVertex::set(mesh++, x3, y3, u3, v3);
16431e08e953fe7bdb1b1cbc247156cb6a19917a2f1Romain Guy        TextureVertex::set(mesh++, x1, y1, u1, v1);
165661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy        TextureVertex::set(mesh++, x4, y4, u4, v4);
166661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy        mCurrentQuad++;
167661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    }
168661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy
169661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    bool canDraw() const {
170661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy        return mCurrentQuad > 0;
171661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    }
172661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy
173661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    bool endOfMesh() const {
174661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy        return mCurrentQuad == mMaxQuadCount;
175661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    }
176661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy
1778087246d9964b11de8ce116bc63b156faa4197e0Romain Guyprivate:
178cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    void setDirty(bool dirty);
179cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy
180cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy    PixelBuffer* mTexture;
1819f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    GLuint mTextureId;
1829f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    uint16_t mWidth;
1839f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    uint16_t mHeight;
1841e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease    GLenum mFormat;
1859f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    bool mLinearFiltering;
1869f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    bool mDirty;
1879f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    uint16_t mNumGlyphs;
188661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    TextureVertex* mMesh;
189661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    uint32_t mCurrentQuad;
190661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy    uint32_t mMaxQuadCount;
1918aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy    Caches& mCaches;
1929f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy    CacheBlock* mCacheBlocks;
193318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy    bool mHasUnpackRowLength;
1948aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy    Rect mDirtyRect;
1959f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy};
1969f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
1979f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; // namespace uirenderer
1989f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; // namespace android
1999f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy
2009f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif // ANDROID_HWUI_CACHE_TEXTURE_H
201