blob: 208b1ff0acd805eaf76c213bf4d91350c622cca1 [file] [log] [blame]
Romain Guy9f5dab32012-09-04 12:55:44 -07001/*
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
Romain Guy09087642013-04-04 12:27:54 -070020#include <GLES3/gl3.h>
Romain Guy9f5dab32012-09-04 12:55:44 -070021
22#include <SkScalerContext.h>
23
24#include <utils/Log.h>
25
26#include "FontUtil.h"
Romain Guy661a87e2013-03-19 15:24:36 -070027#include "../Rect.h"
28#include "../Vertex.h"
Romain Guy9f5dab32012-09-04 12:55:44 -070029
30namespace android {
31namespace uirenderer {
32
Romain Guy8aa195d2013-06-04 18:00:09 -070033class Caches;
Romain Guycf51a412013-04-08 19:40:31 -070034class PixelBuffer;
35
Romain Guy9f5dab32012-09-04 12:55:44 -070036/**
37 * CacheBlock is a node in a linked list of current free space areas in a CacheTexture.
38 * Using CacheBlocks enables us to pack the cache from top to bottom as well as left to right.
39 * When we add a glyph to the cache, we see if it fits within one of the existing columns that
40 * have already been started (this is the case if the glyph fits vertically as well as
41 * horizontally, and if its width is sufficiently close to the column width to avoid
42 * sub-optimal packing of small glyphs into wide columns). If there is no column in which the
43 * glyph fits, we check the final node, which is the remaining space in the cache, creating
44 * a new column as appropriate.
45 *
46 * As columns fill up, we remove their CacheBlock from the list to avoid having to check
47 * small blocks in the future.
48 */
49struct CacheBlock {
50 uint16_t mX;
51 uint16_t mY;
52 uint16_t mWidth;
53 uint16_t mHeight;
54 CacheBlock* mNext;
55 CacheBlock* mPrev;
56
57 CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height, bool empty = false):
Romain Guy9b1204b2012-09-04 15:22:57 -070058 mX(x), mY(y), mWidth(width), mHeight(height), mNext(NULL), mPrev(NULL) {
Romain Guy9f5dab32012-09-04 12:55:44 -070059 }
60
Romain Guye43f7852012-09-04 18:58:46 -070061 static CacheBlock* insertBlock(CacheBlock* head, CacheBlock* newBlock);
Romain Guye43f7852012-09-04 18:58:46 -070062 static CacheBlock* removeBlock(CacheBlock* head, CacheBlock* blockToRemove);
Romain Guy9f5dab32012-09-04 12:55:44 -070063
64 void output() {
Romain Guye43f7852012-09-04 18:58:46 -070065 CacheBlock* currBlock = this;
Romain Guy9f5dab32012-09-04 12:55:44 -070066 while (currBlock) {
67 ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d",
Romain Guy661a87e2013-03-19 15:24:36 -070068 currBlock, currBlock->mX, currBlock->mY,
69 currBlock->mWidth, currBlock->mHeight);
Romain Guy9f5dab32012-09-04 12:55:44 -070070 currBlock = currBlock->mNext;
71 }
72 }
73};
74
75class CacheTexture {
76public:
Romain Guy661a87e2013-03-19 15:24:36 -070077 CacheTexture(uint16_t width, uint16_t height, uint32_t maxQuadCount);
78 ~CacheTexture();
Romain Guy9f5dab32012-09-04 12:55:44 -070079
Romain Guy661a87e2013-03-19 15:24:36 -070080 void reset();
81 void init();
Romain Guy9f5dab32012-09-04 12:55:44 -070082
Romain Guy661a87e2013-03-19 15:24:36 -070083 void releaseMesh();
84 void releaseTexture();
Romain Guy9f5dab32012-09-04 12:55:44 -070085
Romain Guy661a87e2013-03-19 15:24:36 -070086 void allocateTexture();
87 void allocateMesh();
Romain Guy80872462012-09-04 16:42:01 -070088
Romain Guycf51a412013-04-08 19:40:31 -070089 // Returns true if glPixelStorei(GL_UNPACK_ROW_LENGTH) must be reset
90 // This method will also call setDirty(false)
91 bool upload();
92
Romain Guye43f7852012-09-04 18:58:46 -070093 bool fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY);
Romain Guy9f5dab32012-09-04 12:55:44 -070094
Romain Guy80872462012-09-04 16:42:01 -070095 inline uint16_t getWidth() const {
96 return mWidth;
97 }
98
99 inline uint16_t getHeight() const {
100 return mHeight;
101 }
102
Chet Haaseb92d8f72012-09-21 08:40:46 -0700103 inline const Rect* getDirtyRect() const {
104 return &mDirtyRect;
105 }
106
Romain Guycf51a412013-04-08 19:40:31 -0700107 inline PixelBuffer* getPixelBuffer() const {
Romain Guy80872462012-09-04 16:42:01 -0700108 return mTexture;
109 }
110
Romain Guy574cf602012-09-23 14:45:31 -0700111 GLuint getTextureId() {
112 allocateTexture();
Romain Guy80872462012-09-04 16:42:01 -0700113 return mTextureId;
114 }
115
116 inline bool isDirty() const {
117 return mDirty;
118 }
119
Romain Guy80872462012-09-04 16:42:01 -0700120 inline bool getLinearFiltering() const {
121 return mLinearFiltering;
122 }
123
124 /**
125 * This method assumes that the proper texture unit is active.
126 */
Romain Guycf51a412013-04-08 19:40:31 -0700127 void setLinearFiltering(bool linearFiltering, bool bind = true);
Romain Guy80872462012-09-04 16:42:01 -0700128
129 inline uint16_t getGlyphCount() const {
130 return mNumGlyphs;
131 }
132
Romain Guy661a87e2013-03-19 15:24:36 -0700133 TextureVertex* mesh() const {
134 return mMesh;
135 }
136
137 uint32_t meshElementCount() const {
138 return mCurrentQuad * 6;
139 }
140
141 uint16_t* indices() const {
142 return (uint16_t*) 0;
143 }
144
145 void resetMesh() {
146 mCurrentQuad = 0;
147 }
148
149 inline void addQuad(float x1, float y1, float u1, float v1,
150 float x2, float y2, float u2, float v2,
151 float x3, float y3, float u3, float v3,
152 float x4, float y4, float u4, float v4) {
153 TextureVertex* mesh = mMesh + mCurrentQuad * 4;
Romain Guy661a87e2013-03-19 15:24:36 -0700154 TextureVertex::set(mesh++, x2, y2, u2, v2);
155 TextureVertex::set(mesh++, x3, y3, u3, v3);
Romain Guy31e08e92013-06-18 15:53:53 -0700156 TextureVertex::set(mesh++, x1, y1, u1, v1);
Romain Guy661a87e2013-03-19 15:24:36 -0700157 TextureVertex::set(mesh++, x4, y4, u4, v4);
158 mCurrentQuad++;
159 }
160
161 bool canDraw() const {
162 return mCurrentQuad > 0;
163 }
164
165 bool endOfMesh() const {
166 return mCurrentQuad == mMaxQuadCount;
167 }
168
Romain Guy80872462012-09-04 16:42:01 -0700169private:
Romain Guycf51a412013-04-08 19:40:31 -0700170 void setDirty(bool dirty);
171
172 PixelBuffer* mTexture;
Romain Guy9f5dab32012-09-04 12:55:44 -0700173 GLuint mTextureId;
174 uint16_t mWidth;
175 uint16_t mHeight;
176 bool mLinearFiltering;
177 bool mDirty;
178 uint16_t mNumGlyphs;
Romain Guy661a87e2013-03-19 15:24:36 -0700179 TextureVertex* mMesh;
180 uint32_t mCurrentQuad;
181 uint32_t mMaxQuadCount;
Romain Guy8aa195d2013-06-04 18:00:09 -0700182 Caches& mCaches;
Romain Guy9f5dab32012-09-04 12:55:44 -0700183 CacheBlock* mCacheBlocks;
Romain Guycf51a412013-04-08 19:40:31 -0700184 bool mHasES3;
Romain Guy8aa195d2013-06-04 18:00:09 -0700185 Rect mDirtyRect;
Romain Guy9f5dab32012-09-04 12:55:44 -0700186};
187
188}; // namespace uirenderer
189}; // namespace android
190
191#endif // ANDROID_HWUI_CACHE_TEXTURE_H