• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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_PROGRAM_CACHE_H
18 #define ANDROID_HWUI_PROGRAM_CACHE_H
19 
20 #include <utils/KeyedVector.h>
21 #include <utils/Log.h>
22 #include <utils/String8.h>
23 
24 #include <GLES2/gl2.h>
25 
26 #include <SkXfermode.h>
27 
28 #include "Debug.h"
29 #include "Program.h"
30 
31 namespace android {
32 namespace uirenderer {
33 
34 ///////////////////////////////////////////////////////////////////////////////
35 // Defines
36 ///////////////////////////////////////////////////////////////////////////////
37 
38 // Debug
39 #if DEBUG_PROGRAMS
40     #define PROGRAM_LOGD(...) LOGD(__VA_ARGS__)
41 #else
42     #define PROGRAM_LOGD(...)
43 #endif
44 
45 // TODO: This should be set in properties
46 #define PANEL_BIT_DEPTH 20
47 #define COLOR_COMPONENT_THRESHOLD (1.0f - (0.5f / PANEL_BIT_DEPTH))
48 #define COLOR_COMPONENT_INV_THRESHOLD (0.5f / PANEL_BIT_DEPTH)
49 
50 #define PROGRAM_KEY_TEXTURE 0x1
51 #define PROGRAM_KEY_A8_TEXTURE 0x2
52 #define PROGRAM_KEY_BITMAP 0x4
53 #define PROGRAM_KEY_GRADIENT 0x8
54 #define PROGRAM_KEY_BITMAP_FIRST 0x10
55 #define PROGRAM_KEY_COLOR_MATRIX 0x20
56 #define PROGRAM_KEY_COLOR_LIGHTING 0x40
57 #define PROGRAM_KEY_COLOR_BLEND 0x80
58 #define PROGRAM_KEY_BITMAP_NPOT 0x100
59 #define PROGRAM_KEY_SWAP_SRC_DST 0x2000
60 
61 #define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600
62 #define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800
63 
64 // Encode the xfermodes on 6 bits
65 #define PROGRAM_MAX_XFERMODE 0x1f
66 #define PROGRAM_XFERMODE_SHADER_SHIFT 26
67 #define PROGRAM_XFERMODE_COLOR_OP_SHIFT 20
68 #define PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT 14
69 
70 #define PROGRAM_BITMAP_WRAPS_SHIFT 9
71 #define PROGRAM_BITMAP_WRAPT_SHIFT 11
72 
73 #define PROGRAM_GRADIENT_TYPE_SHIFT 33
74 #define PROGRAM_MODULATE_SHIFT 35
75 
76 #define PROGRAM_IS_POINT_SHIFT 36
77 
78 #define PROGRAM_HAS_AA_SHIFT 37
79 
80 #define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
81 #define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39
82 
83 ///////////////////////////////////////////////////////////////////////////////
84 // Types
85 ///////////////////////////////////////////////////////////////////////////////
86 
87 typedef uint64_t programid;
88 
89 ///////////////////////////////////////////////////////////////////////////////
90 // Cache
91 ///////////////////////////////////////////////////////////////////////////////
92 
93 /**
94  * Describe the features required for a given program. The features
95  * determine the generation of both the vertex and fragment shaders.
96  * A ProgramDescription must be used in conjunction with a ProgramCache.
97  */
98 struct ProgramDescription {
99     enum ColorModifier {
100         kColorNone,
101         kColorMatrix,
102         kColorLighting,
103         kColorBlend
104     };
105 
106     enum Gradient {
107         kGradientLinear,
108         kGradientCircular,
109         kGradientSweep
110     };
111 
ProgramDescriptionProgramDescription112     ProgramDescription() {
113         reset();
114     }
115 
116     // Texturing
117     bool hasTexture;
118     bool hasAlpha8Texture;
119     bool hasExternalTexture;
120     bool hasTextureTransform;
121 
122     // Modulate, this should only be set when setColor() return true
123     bool modulate;
124 
125     // Shaders
126     bool hasBitmap;
127     bool isBitmapNpot;
128 
129     bool isAA;
130 
131     bool hasGradient;
132     Gradient gradientType;
133 
134     SkXfermode::Mode shadersMode;
135 
136     bool isBitmapFirst;
137     GLenum bitmapWrapS;
138     GLenum bitmapWrapT;
139 
140     // Color operations
141     ColorModifier colorOp;
142     SkXfermode::Mode colorMode;
143 
144     // Framebuffer blending (requires Extensions.hasFramebufferFetch())
145     // Ignored for all values < SkXfermode::kPlus_Mode
146     SkXfermode::Mode framebufferMode;
147     bool swapSrcDst;
148 
149     bool isPoint;
150     float pointSize;
151 
152     /**
153      * Resets this description. All fields are reset back to the default
154      * values they hold after building a new instance.
155      */
resetProgramDescription156     void reset() {
157         hasTexture = false;
158         hasAlpha8Texture = false;
159         hasExternalTexture = false;
160         hasTextureTransform = false;
161 
162         isAA = false;
163 
164         modulate = false;
165 
166         hasBitmap = false;
167         isBitmapNpot = false;
168 
169         hasGradient = false;
170         gradientType = kGradientLinear;
171 
172         shadersMode = SkXfermode::kClear_Mode;
173 
174         isBitmapFirst = false;
175         bitmapWrapS = GL_CLAMP_TO_EDGE;
176         bitmapWrapT = GL_CLAMP_TO_EDGE;
177 
178         colorOp = kColorNone;
179         colorMode = SkXfermode::kClear_Mode;
180 
181         framebufferMode = SkXfermode::kClear_Mode;
182         swapSrcDst = false;
183 
184         isPoint = false;
185         pointSize = 0.0f;
186     }
187 
188     /**
189      * Indicates, for a given color, whether color modulation is required in
190      * the fragment shader. When this method returns true, the program should
191      * be provided with a modulation color.
192      */
setColorProgramDescription193     bool setColor(const float r, const float g, const float b, const float a) {
194         modulate = a < COLOR_COMPONENT_THRESHOLD || r < COLOR_COMPONENT_THRESHOLD ||
195                 g < COLOR_COMPONENT_THRESHOLD || b < COLOR_COMPONENT_THRESHOLD;
196         return modulate;
197     }
198 
199     /**
200      * Indicates, for a given color, whether color modulation is required in
201      * the fragment shader. When this method returns true, the program should
202      * be provided with a modulation color.
203      */
setAlpha8ColorProgramDescription204     bool setAlpha8Color(const float r, const float g, const float b, const float a) {
205         modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD ||
206                 g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD;
207         return modulate;
208     }
209 
210     /**
211      * Computes the unique key identifying this program.
212      */
keyProgramDescription213     programid key() const {
214         programid key = 0;
215         if (hasTexture) key |= PROGRAM_KEY_TEXTURE;
216         if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
217         if (hasBitmap) {
218             key |= PROGRAM_KEY_BITMAP;
219             if (isBitmapNpot) {
220                 key |= PROGRAM_KEY_BITMAP_NPOT;
221                 key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
222                 key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
223             }
224         }
225         if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
226         key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
227         if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
228         if (hasBitmap && hasGradient) {
229             key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
230         }
231         switch (colorOp) {
232             case kColorMatrix:
233                 key |= PROGRAM_KEY_COLOR_MATRIX;
234                 break;
235             case kColorLighting:
236                 key |= PROGRAM_KEY_COLOR_LIGHTING;
237                 break;
238             case kColorBlend:
239                 key |= PROGRAM_KEY_COLOR_BLEND;
240                 key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
241                 break;
242             case kColorNone:
243                 break;
244         }
245         key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
246         if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
247         if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
248         if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT;
249         if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT;
250         if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
251         if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
252         return key;
253     }
254 
255     /**
256      * Logs the specified message followed by the key identifying this program.
257      */
logProgramDescription258     void log(const char* message) const {
259 #if DEBUG_PROGRAMS
260         programid k = key();
261         PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
262                 uint32_t(k & 0xffffffff));
263 #endif
264     }
265 
266 private:
getEnumForWrapProgramDescription267     inline uint32_t getEnumForWrap(GLenum wrap) const {
268         switch (wrap) {
269             case GL_CLAMP_TO_EDGE:
270                 return 0;
271             case GL_REPEAT:
272                 return 1;
273             case GL_MIRRORED_REPEAT:
274                 return 2;
275         }
276         return 0;
277     }
278 
279 }; // struct ProgramDescription
280 
281 /**
282  * Generates and caches program. Programs are generated based on
283  * ProgramDescriptions.
284  */
285 class ProgramCache {
286 public:
287     ProgramCache();
288     ~ProgramCache();
289 
290     Program* get(const ProgramDescription& description);
291 
292     void clear();
293 
294 private:
295     Program* generateProgram(const ProgramDescription& description, programid key);
296     String8 generateVertexShader(const ProgramDescription& description);
297     String8 generateFragmentShader(const ProgramDescription& description);
298     void generateBlend(String8& shader, const char* name, SkXfermode::Mode mode);
299     void generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT);
300 
301     void printLongString(const String8& shader) const;
302 
303     KeyedVector<programid, Program*> mCache;
304 }; // class ProgramCache
305 
306 }; // namespace uirenderer
307 }; // namespace android
308 
309 #endif // ANDROID_HWUI_PROGRAM_CACHE_H
310