• 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
45 #define COLOR_COMPONENT_INV_THRESHOLD 0.0f
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 #define PROGRAM_HAS_GAMMA_CORRECTION 40
81 
82 #define PROGRAM_IS_SIMPLE_GRADIENT 41
83 
84 #define PROGRAM_IS_VERTEX_SHAPE_SHIFT 42
85 
86 ///////////////////////////////////////////////////////////////////////////////
87 // Types
88 ///////////////////////////////////////////////////////////////////////////////
89 
90 typedef uint64_t programid;
91 
92 ///////////////////////////////////////////////////////////////////////////////
93 // Program description
94 ///////////////////////////////////////////////////////////////////////////////
95 
96 /**
97  * Describe the features required for a given program. The features
98  * determine the generation of both the vertex and fragment shaders.
99  * A ProgramDescription must be used in conjunction with a ProgramCache.
100  */
101 struct ProgramDescription {
102     enum ColorModifier {
103         kColorNone = 0,
104         kColorMatrix,
105         kColorLighting,
106         kColorBlend
107     };
108 
109     enum Gradient {
110         kGradientLinear = 0,
111         kGradientCircular,
112         kGradientSweep
113     };
114 
ProgramDescriptionProgramDescription115     ProgramDescription() {
116         reset();
117     }
118 
119     // Texturing
120     bool hasTexture;
121     bool hasAlpha8Texture;
122     bool hasExternalTexture;
123     bool hasTextureTransform;
124 
125     // Modulate, this should only be set when setColor() return true
126     bool modulate;
127 
128     // Shaders
129     bool hasBitmap;
130     bool isBitmapNpot;
131 
132     bool isAA;
133     bool isVertexShape;
134 
135     bool hasGradient;
136     Gradient gradientType;
137     bool isSimpleGradient;
138 
139     SkXfermode::Mode shadersMode;
140 
141     bool isBitmapFirst;
142     GLenum bitmapWrapS;
143     GLenum bitmapWrapT;
144 
145     // Color operations
146     ColorModifier colorOp;
147     SkXfermode::Mode colorMode;
148 
149     // Framebuffer blending (requires Extensions.hasFramebufferFetch())
150     // Ignored for all values < SkXfermode::kPlus_Mode
151     SkXfermode::Mode framebufferMode;
152     bool swapSrcDst;
153 
154     bool isPoint;
155     float pointSize;
156 
157     bool hasGammaCorrection;
158     float gamma;
159 
160     /**
161      * Resets this description. All fields are reset back to the default
162      * values they hold after building a new instance.
163      */
resetProgramDescription164     void reset() {
165         hasTexture = false;
166         hasAlpha8Texture = false;
167         hasExternalTexture = false;
168         hasTextureTransform = false;
169 
170         isAA = false;
171         isVertexShape = false;
172 
173         modulate = false;
174 
175         hasBitmap = false;
176         isBitmapNpot = false;
177 
178         hasGradient = false;
179         gradientType = kGradientLinear;
180         isSimpleGradient = false;
181 
182         shadersMode = SkXfermode::kClear_Mode;
183 
184         isBitmapFirst = false;
185         bitmapWrapS = GL_CLAMP_TO_EDGE;
186         bitmapWrapT = GL_CLAMP_TO_EDGE;
187 
188         colorOp = kColorNone;
189         colorMode = SkXfermode::kClear_Mode;
190 
191         framebufferMode = SkXfermode::kClear_Mode;
192         swapSrcDst = false;
193 
194         isPoint = false;
195         pointSize = 0.0f;
196 
197         hasGammaCorrection = false;
198         gamma = 2.2f;
199     }
200 
201     /**
202      * Indicates, for a given color, whether color modulation is required in
203      * the fragment shader. When this method returns true, the program should
204      * be provided with a modulation color.
205      */
setColorProgramDescription206     bool setColor(const float r, const float g, const float b, const float a) {
207         modulate = a < COLOR_COMPONENT_THRESHOLD;
208         return modulate;
209     }
210 
211     /**
212      * Indicates, for a given color, whether color modulation is required in
213      * the fragment shader. When this method returns true, the program should
214      * be provided with a modulation color.
215      */
setAlpha8ColorProgramDescription216     bool setAlpha8Color(const float r, const float g, const float b, const float a) {
217         modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD ||
218                 g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD;
219         return modulate;
220     }
221 
222     /**
223      * Computes the unique key identifying this program.
224      */
keyProgramDescription225     programid key() const {
226         programid key = 0;
227         if (hasTexture) key |= PROGRAM_KEY_TEXTURE;
228         if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
229         if (hasBitmap) {
230             key |= PROGRAM_KEY_BITMAP;
231             if (isBitmapNpot) {
232                 key |= PROGRAM_KEY_BITMAP_NPOT;
233                 key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
234                 key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
235             }
236         }
237         if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
238         key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
239         if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
240         if (hasBitmap && hasGradient) {
241             key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
242         }
243         switch (colorOp) {
244             case kColorMatrix:
245                 key |= PROGRAM_KEY_COLOR_MATRIX;
246                 break;
247             case kColorLighting:
248                 key |= PROGRAM_KEY_COLOR_LIGHTING;
249                 break;
250             case kColorBlend:
251                 key |= PROGRAM_KEY_COLOR_BLEND;
252                 key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
253                 break;
254             case kColorNone:
255                 break;
256         }
257         key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
258         if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
259         if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
260         if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT;
261         if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT;
262         if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
263         if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
264         if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
265         if (isSimpleGradient) key |= programid(0x1) << PROGRAM_IS_SIMPLE_GRADIENT;
266         if (isVertexShape) key |= programid(0x1) << PROGRAM_IS_VERTEX_SHAPE_SHIFT;
267         return key;
268     }
269 
270     /**
271      * Logs the specified message followed by the key identifying this program.
272      */
logProgramDescription273     void log(const char* message) const {
274 #if DEBUG_PROGRAMS
275         programid k = key();
276         PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
277                 uint32_t(k & 0xffffffff));
278 #endif
279     }
280 
281 private:
getEnumForWrapProgramDescription282     static inline uint32_t getEnumForWrap(GLenum wrap) {
283         switch (wrap) {
284             case GL_CLAMP_TO_EDGE:
285                 return 0;
286             case GL_REPEAT:
287                 return 1;
288             case GL_MIRRORED_REPEAT:
289                 return 2;
290         }
291         return 0;
292     }
293 
294 }; // struct ProgramDescription
295 
296 /**
297  * A program holds a vertex and a fragment shader. It offers several utility
298  * methods to query attributes and uniforms.
299  */
300 class Program {
301 public:
302     enum ShaderBindings {
303         kBindingPosition,
304         kBindingTexCoords
305     };
306 
307     /**
308      * Creates a new program with the specified vertex and fragment
309      * shaders sources.
310      */
311     Program(const ProgramDescription& description, const char* vertex, const char* fragment);
312     virtual ~Program();
313 
314     /**
315      * Binds this program to the GL context.
316      */
317     virtual void use();
318 
319     /**
320      * Marks this program as unused. This will not unbind
321      * the program from the GL context.
322      */
323     virtual void remove();
324 
325     /**
326      * Returns the OpenGL name of the specified attribute.
327      */
328     int getAttrib(const char* name);
329 
330     /**
331      * Returns the OpenGL name of the specified uniform.
332      */
333     int getUniform(const char* name);
334 
335     /**
336      * Indicates whether this program is currently in use with
337      * the GL context.
338      */
isInUse()339     inline bool isInUse() const {
340         return mUse;
341     }
342 
343     /**
344      * Indicates whether this program was correctly compiled and linked.
345      */
isInitialized()346     inline bool isInitialized() const {
347         return mInitialized;
348     }
349 
350     /**
351      * Binds the program with the specified projection, modelView and
352      * transform matrices.
353      */
354     void set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
355              const mat4& transformMatrix, bool offset = false);
356 
357     /**
358      * Sets the color associated with this shader.
359      */
360     void setColor(const float r, const float g, const float b, const float a);
361 
362     /**
363      * Name of the position attribute.
364      */
365     int position;
366 
367     /**
368      * Name of the texCoords attribute if it exists, -1 otherwise.
369      */
370     int texCoords;
371 
372     /**
373      * Name of the transform uniform.
374      */
375     int transform;
376 
377     /**
378      * Name of the projection uniform.
379      */
380     int projection;
381 
382 protected:
383     /**
384      * Adds an attribute with the specified name.
385      *
386      * @return The OpenGL name of the attribute.
387      */
388     int addAttrib(const char* name);
389 
390     /**
391      * Binds the specified attribute name to the specified slot.
392      */
393     int bindAttrib(const char* name, ShaderBindings bindingSlot);
394 
395     /**
396      * Adds a uniform with the specified name.
397      *
398      * @return The OpenGL name of the uniform.
399      */
400     int addUniform(const char* name);
401 
402 private:
403     /**
404      * Compiles the specified shader of the specified type.
405      *
406      * @return The name of the compiled shader.
407      */
408     GLuint buildShader(const char* source, GLenum type);
409 
410     // Name of the OpenGL program and shaders
411     GLuint mProgramId;
412     GLuint mVertexShader;
413     GLuint mFragmentShader;
414 
415     // Keeps track of attributes and uniforms slots
416     KeyedVector<const char*, int> mAttributes;
417     KeyedVector<const char*, int> mUniforms;
418 
419     bool mUse;
420     bool mInitialized;
421 
422     bool mHasColorUniform;
423     int mColorUniform;
424 
425     bool mHasSampler;
426 }; // class Program
427 
428 }; // namespace uirenderer
429 }; // namespace android
430 
431 #endif // ANDROID_HWUI_PROGRAM_H
432