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