• 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_H
18 #define ANDROID_HWUI_PROGRAM_H
19 
20 #include <utils/KeyedVector.h>
21 
22 #include <GLES2/gl2.h>
23 #include <GLES2/gl2ext.h>
24 
25 #include <SkXfermode.h>
26 
27 #include "Matrix.h"
28 #include "Properties.h"
29 
30 namespace android {
31 namespace uirenderer {
32 
33 ///////////////////////////////////////////////////////////////////////////////
34 // Defines
35 ///////////////////////////////////////////////////////////////////////////////
36 
37 // Debug
38 #if DEBUG_PROGRAMS
39     #define PROGRAM_LOGD(...) ALOGD(__VA_ARGS__)
40 #else
41     #define PROGRAM_LOGD(...)
42 #endif
43 
44 #define COLOR_COMPONENT_THRESHOLD (1.0f - (0.5f / PANEL_BIT_DEPTH))
45 #define COLOR_COMPONENT_INV_THRESHOLD (0.5f / PANEL_BIT_DEPTH)
46 
47 #define PROGRAM_KEY_TEXTURE 0x1
48 #define PROGRAM_KEY_A8_TEXTURE 0x2
49 #define PROGRAM_KEY_BITMAP 0x4
50 #define PROGRAM_KEY_GRADIENT 0x8
51 #define PROGRAM_KEY_BITMAP_FIRST 0x10
52 #define PROGRAM_KEY_COLOR_MATRIX 0x20
53 #define PROGRAM_KEY_COLOR_LIGHTING 0x40
54 #define PROGRAM_KEY_COLOR_BLEND 0x80
55 #define PROGRAM_KEY_BITMAP_NPOT 0x100
56 #define PROGRAM_KEY_SWAP_SRC_DST 0x2000
57 
58 #define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600
59 #define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800
60 
61 // Encode the xfermodes on 6 bits
62 #define PROGRAM_MAX_XFERMODE 0x1f
63 #define PROGRAM_XFERMODE_SHADER_SHIFT 26
64 #define PROGRAM_XFERMODE_COLOR_OP_SHIFT 20
65 #define PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT 14
66 
67 #define PROGRAM_BITMAP_WRAPS_SHIFT 9
68 #define PROGRAM_BITMAP_WRAPT_SHIFT 11
69 
70 #define PROGRAM_GRADIENT_TYPE_SHIFT 33
71 #define PROGRAM_MODULATE_SHIFT 35
72 
73 #define PROGRAM_IS_POINT_SHIFT 36
74 
75 #define PROGRAM_HAS_AA_SHIFT 37
76 
77 #define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
78 #define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39
79 
80 ///////////////////////////////////////////////////////////////////////////////
81 // Types
82 ///////////////////////////////////////////////////////////////////////////////
83 
84 typedef uint64_t programid;
85 
86 ///////////////////////////////////////////////////////////////////////////////
87 // Program description
88 ///////////////////////////////////////////////////////////////////////////////
89 
90 /**
91  * Describe the features required for a given program. The features
92  * determine the generation of both the vertex and fragment shaders.
93  * A ProgramDescription must be used in conjunction with a ProgramCache.
94  */
95 struct ProgramDescription {
96     enum ColorModifier {
97         kColorNone,
98         kColorMatrix,
99         kColorLighting,
100         kColorBlend
101     };
102 
103     enum Gradient {
104         kGradientLinear,
105         kGradientCircular,
106         kGradientSweep
107     };
108 
ProgramDescriptionProgramDescription109     ProgramDescription() {
110         reset();
111     }
112 
113     // Texturing
114     bool hasTexture;
115     bool hasAlpha8Texture;
116     bool hasExternalTexture;
117     bool hasTextureTransform;
118 
119     // Modulate, this should only be set when setColor() return true
120     bool modulate;
121 
122     // Shaders
123     bool hasBitmap;
124     bool isBitmapNpot;
125 
126     bool isAA;
127 
128     bool hasGradient;
129     Gradient gradientType;
130 
131     SkXfermode::Mode shadersMode;
132 
133     bool isBitmapFirst;
134     GLenum bitmapWrapS;
135     GLenum bitmapWrapT;
136 
137     // Color operations
138     ColorModifier colorOp;
139     SkXfermode::Mode colorMode;
140 
141     // Framebuffer blending (requires Extensions.hasFramebufferFetch())
142     // Ignored for all values < SkXfermode::kPlus_Mode
143     SkXfermode::Mode framebufferMode;
144     bool swapSrcDst;
145 
146     bool isPoint;
147     float pointSize;
148 
149     /**
150      * Resets this description. All fields are reset back to the default
151      * values they hold after building a new instance.
152      */
resetProgramDescription153     void reset() {
154         hasTexture = false;
155         hasAlpha8Texture = false;
156         hasExternalTexture = false;
157         hasTextureTransform = false;
158 
159         isAA = false;
160 
161         modulate = false;
162 
163         hasBitmap = false;
164         isBitmapNpot = false;
165 
166         hasGradient = false;
167         gradientType = kGradientLinear;
168 
169         shadersMode = SkXfermode::kClear_Mode;
170 
171         isBitmapFirst = false;
172         bitmapWrapS = GL_CLAMP_TO_EDGE;
173         bitmapWrapT = GL_CLAMP_TO_EDGE;
174 
175         colorOp = kColorNone;
176         colorMode = SkXfermode::kClear_Mode;
177 
178         framebufferMode = SkXfermode::kClear_Mode;
179         swapSrcDst = false;
180 
181         isPoint = false;
182         pointSize = 0.0f;
183     }
184 
185     /**
186      * Indicates, for a given color, whether color modulation is required in
187      * the fragment shader. When this method returns true, the program should
188      * be provided with a modulation color.
189      */
setColorProgramDescription190     bool setColor(const float r, const float g, const float b, const float a) {
191         modulate = a < COLOR_COMPONENT_THRESHOLD || r < COLOR_COMPONENT_THRESHOLD ||
192                 g < COLOR_COMPONENT_THRESHOLD || b < COLOR_COMPONENT_THRESHOLD;
193         return modulate;
194     }
195 
196     /**
197      * Indicates, for a given color, whether color modulation is required in
198      * the fragment shader. When this method returns true, the program should
199      * be provided with a modulation color.
200      */
setAlpha8ColorProgramDescription201     bool setAlpha8Color(const float r, const float g, const float b, const float a) {
202         modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD ||
203                 g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD;
204         return modulate;
205     }
206 
207     /**
208      * Computes the unique key identifying this program.
209      */
keyProgramDescription210     programid key() const {
211         programid key = 0;
212         if (hasTexture) key |= PROGRAM_KEY_TEXTURE;
213         if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
214         if (hasBitmap) {
215             key |= PROGRAM_KEY_BITMAP;
216             if (isBitmapNpot) {
217                 key |= PROGRAM_KEY_BITMAP_NPOT;
218                 key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
219                 key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
220             }
221         }
222         if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
223         key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
224         if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
225         if (hasBitmap && hasGradient) {
226             key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
227         }
228         switch (colorOp) {
229             case kColorMatrix:
230                 key |= PROGRAM_KEY_COLOR_MATRIX;
231                 break;
232             case kColorLighting:
233                 key |= PROGRAM_KEY_COLOR_LIGHTING;
234                 break;
235             case kColorBlend:
236                 key |= PROGRAM_KEY_COLOR_BLEND;
237                 key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
238                 break;
239             case kColorNone:
240                 break;
241         }
242         key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
243         if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
244         if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
245         if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT;
246         if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT;
247         if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
248         if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
249         return key;
250     }
251 
252     /**
253      * Logs the specified message followed by the key identifying this program.
254      */
logProgramDescription255     void log(const char* message) const {
256 #if DEBUG_PROGRAMS
257         programid k = key();
258         PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
259                 uint32_t(k & 0xffffffff));
260 #endif
261     }
262 
263 private:
getEnumForWrapProgramDescription264     inline uint32_t getEnumForWrap(GLenum wrap) const {
265         switch (wrap) {
266             case GL_CLAMP_TO_EDGE:
267                 return 0;
268             case GL_REPEAT:
269                 return 1;
270             case GL_MIRRORED_REPEAT:
271                 return 2;
272         }
273         return 0;
274     }
275 
276 }; // struct ProgramDescription
277 
278 /**
279  * A program holds a vertex and a fragment shader. It offers several utility
280  * methods to query attributes and uniforms.
281  */
282 class Program {
283 public:
284     enum ShaderBindings {
285         kBindingPosition,
286         kBindingTexCoords
287     };
288 
289     /**
290      * Creates a new program with the specified vertex and fragment
291      * shaders sources.
292      */
293     Program(const ProgramDescription& description, const char* vertex, const char* fragment);
294     virtual ~Program();
295 
296     /**
297      * Binds this program to the GL context.
298      */
299     virtual void use();
300 
301     /**
302      * Marks this program as unused. This will not unbind
303      * the program from the GL context.
304      */
305     virtual void remove();
306 
307     /**
308      * Returns the OpenGL name of the specified attribute.
309      */
310     int getAttrib(const char* name);
311 
312     /**
313      * Returns the OpenGL name of the specified uniform.
314      */
315     int getUniform(const char* name);
316 
317     /**
318      * Indicates whether this program is currently in use with
319      * the GL context.
320      */
isInUse()321     inline bool isInUse() const {
322         return mUse;
323     }
324 
325     /**
326      * Indicates whether this program was correctly compiled and linked.
327      */
isInitialized()328     inline bool isInitialized() const {
329         return mInitialized;
330     }
331 
332     /**
333      * Binds the program with the specified projection, modelView and
334      * transform matrices.
335      */
336     void set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
337              const mat4& transformMatrix, bool offset = false);
338 
339     /**
340      * Sets the color associated with this shader.
341      */
342     void setColor(const float r, const float g, const float b, const float a);
343 
344     /**
345      * Name of the position attribute.
346      */
347     int position;
348 
349     /**
350      * Name of the texCoords attribute if it exists, -1 otherwise.
351      */
352     int texCoords;
353 
354     /**
355      * Name of the transform uniform.
356      */
357     int transform;
358 
359 protected:
360     /**
361      * Adds an attribute with the specified name.
362      *
363      * @return The OpenGL name of the attribute.
364      */
365     int addAttrib(const char* name);
366 
367     /**
368      * Binds the specified attribute name to the specified slot.
369      */
370     int bindAttrib(const char* name, ShaderBindings bindingSlot);
371 
372     /**
373      * Adds a uniform with the specified name.
374      *
375      * @return The OpenGL name of the uniform.
376      */
377     int addUniform(const char* name);
378 
379 private:
380     /**
381      * Compiles the specified shader of the specified type.
382      *
383      * @return The name of the compiled shader.
384      */
385     GLuint buildShader(const char* source, GLenum type);
386 
387     // Name of the OpenGL program and shaders
388     GLuint mProgramId;
389     GLuint mVertexShader;
390     GLuint mFragmentShader;
391 
392     // Keeps track of attributes and uniforms slots
393     KeyedVector<const char*, int> mAttributes;
394     KeyedVector<const char*, int> mUniforms;
395 
396     bool mUse;
397     bool mInitialized;
398 
399     bool mHasColorUniform;
400     int mColorUniform;
401 
402     bool mHasSampler;
403 }; // class Program
404 
405 }; // namespace uirenderer
406 }; // namespace android
407 
408 #endif // ANDROID_HWUI_PROGRAM_H
409