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