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