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