• 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 "FloatColor.h"
29 #include "Matrix.h"
30 #include "Properties.h"
31 
32 namespace android {
33 namespace uirenderer {
34 
35 ///////////////////////////////////////////////////////////////////////////////
36 // Defines
37 ///////////////////////////////////////////////////////////////////////////////
38 
39 // Debug
40 #if DEBUG_PROGRAMS
41     #define PROGRAM_LOGD(...) ALOGD(__VA_ARGS__)
42 #else
43     #define PROGRAM_LOGD(...)
44 #endif
45 
46 #define COLOR_COMPONENT_THRESHOLD 1.0f
47 #define COLOR_COMPONENT_INV_THRESHOLD 0.0f
48 
49 #define PROGRAM_KEY_TEXTURE             0x01
50 #define PROGRAM_KEY_A8_TEXTURE          0x02
51 #define PROGRAM_KEY_BITMAP              0x04
52 #define PROGRAM_KEY_GRADIENT            0x08
53 #define PROGRAM_KEY_BITMAP_FIRST        0x10
54 #define PROGRAM_KEY_COLOR_MATRIX        0x20
55 #define PROGRAM_KEY_COLOR_BLEND         0x40
56 #define PROGRAM_KEY_BITMAP_NPOT         0x80
57 
58 #define PROGRAM_KEY_SWAP_SRC_DST      0x2000
59 
60 #define PROGRAM_KEY_BITMAP_WRAPS_MASK  0x600
61 #define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800
62 
63 // Encode the xfermodes on 6 bits
64 #define PROGRAM_MAX_XFERMODE 0x1f
65 #define PROGRAM_XFERMODE_SHADER_SHIFT 26
66 #define PROGRAM_XFERMODE_COLOR_OP_SHIFT 20
67 #define PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT 14
68 
69 #define PROGRAM_BITMAP_WRAPS_SHIFT 9
70 #define PROGRAM_BITMAP_WRAPT_SHIFT 11
71 
72 #define PROGRAM_GRADIENT_TYPE_SHIFT 33 // 2 bits for gradient type
73 #define PROGRAM_MODULATE_SHIFT 35
74 
75 #define PROGRAM_HAS_VERTEX_ALPHA_SHIFT 36
76 #define PROGRAM_USE_SHADOW_ALPHA_INTERP_SHIFT 37
77 
78 #define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
79 #define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 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_HAS_ROUND_RECT_CLIP 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 class ColorFilterMode {
105         None = 0,
106         Matrix,
107         Blend
108     };
109 
110     enum Gradient {
111         kGradientLinear = 0,
112         kGradientCircular,
113         kGradientSweep
114     };
115 
ProgramDescriptionProgramDescription116     ProgramDescription() {
117         reset();
118     }
119 
120     // Texturing
121     bool hasTexture;
122     bool hasAlpha8Texture;
123     bool hasExternalTexture;
124     bool hasTextureTransform;
125 
126     // Color attribute
127     bool hasColors;
128 
129     // Modulate, this should only be set when setColor() return true
130     bool modulate;
131 
132     // Shaders
133     bool hasBitmap;
134     bool isBitmapNpot;
135 
136     bool hasVertexAlpha;
137     bool useShadowAlphaInterp;
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     ColorFilterMode 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 hasDebugHighlight;
159     bool hasRoundRectClip;
160 
161     /**
162      * Resets this description. All fields are reset back to the default
163      * values they hold after building a new instance.
164      */
resetProgramDescription165     void reset() {
166         hasTexture = false;
167         hasAlpha8Texture = false;
168         hasExternalTexture = false;
169         hasTextureTransform = false;
170 
171         hasColors = false;
172 
173         hasVertexAlpha = false;
174         useShadowAlphaInterp = false;
175 
176         modulate = false;
177 
178         hasBitmap = false;
179         isBitmapNpot = false;
180 
181         hasGradient = false;
182         gradientType = kGradientLinear;
183         isSimpleGradient = false;
184 
185         shadersMode = SkXfermode::kClear_Mode;
186 
187         isBitmapFirst = false;
188         bitmapWrapS = GL_CLAMP_TO_EDGE;
189         bitmapWrapT = GL_CLAMP_TO_EDGE;
190 
191         colorOp = ColorFilterMode::None;
192         colorMode = SkXfermode::kClear_Mode;
193 
194         framebufferMode = SkXfermode::kClear_Mode;
195         swapSrcDst = false;
196 
197         hasDebugHighlight = false;
198         hasRoundRectClip = false;
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      */
setColorModulateProgramDescription206     bool setColorModulate(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      */
setAlpha8ColorModulateProgramDescription216     bool setAlpha8ColorModulate(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 ColorFilterMode::Matrix:
245                 key |= PROGRAM_KEY_COLOR_MATRIX;
246                 break;
247             case ColorFilterMode::Blend:
248                 key |= PROGRAM_KEY_COLOR_BLEND;
249                 key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
250                 break;
251             case ColorFilterMode::None:
252                 break;
253         }
254         key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
255         if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
256         if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
257         if (hasVertexAlpha) key |= programid(0x1) << PROGRAM_HAS_VERTEX_ALPHA_SHIFT;
258         if (useShadowAlphaInterp) key |= programid(0x1) << PROGRAM_USE_SHADOW_ALPHA_INTERP_SHIFT;
259         if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
260         if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
261         if (isSimpleGradient) key |= programid(0x1) << PROGRAM_IS_SIMPLE_GRADIENT;
262         if (hasColors) key |= programid(0x1) << PROGRAM_HAS_COLORS;
263         if (hasDebugHighlight) key |= programid(0x1) << PROGRAM_HAS_DEBUG_HIGHLIGHT;
264         if (hasRoundRectClip) key |= programid(0x1) << PROGRAM_HAS_ROUND_RECT_CLIP;
265         return key;
266     }
267 
268     /**
269      * Logs the specified message followed by the key identifying this program.
270      */
logProgramDescription271     void log(const char* message) const {
272 #if DEBUG_PROGRAMS
273         programid k = key();
274         PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
275                 uint32_t(k & 0xffffffff));
276 #endif
277     }
278 
279 private:
getEnumForWrapProgramDescription280     static inline uint32_t getEnumForWrap(GLenum wrap) {
281         switch (wrap) {
282             case GL_CLAMP_TO_EDGE:
283                 return 0;
284             case GL_REPEAT:
285                 return 1;
286             case GL_MIRRORED_REPEAT:
287                 return 2;
288         }
289         return 0;
290     }
291 
292 }; // struct ProgramDescription
293 
294 /**
295  * A program holds a vertex and a fragment shader. It offers several utility
296  * methods to query attributes and uniforms.
297  */
298 class Program {
299 public:
300     enum ShaderBindings {
301         kBindingPosition,
302         kBindingTexCoords
303     };
304 
305     /**
306      * Creates a new program with the specified vertex and fragment
307      * shaders sources.
308      */
309     Program(const ProgramDescription& description, const char* vertex, const char* fragment);
310     virtual ~Program();
311 
312     /**
313      * Binds this program to the GL context.
314      */
315     virtual void use();
316 
317     /**
318      * Marks this program as unused. This will not unbind
319      * the program from the GL context.
320      */
321     virtual void remove();
322 
323     /**
324      * Returns the OpenGL name of the specified attribute.
325      */
326     int getAttrib(const char* name);
327 
328     /**
329      * Returns the OpenGL name of the specified uniform.
330      */
331     int getUniform(const char* name);
332 
333     /**
334      * Indicates whether this program is currently in use with
335      * the GL context.
336      */
isInUse()337     inline bool isInUse() const {
338         return mUse;
339     }
340 
341     /**
342      * Indicates whether this program was correctly compiled and linked.
343      */
isInitialized()344     inline bool isInitialized() const {
345         return mInitialized;
346     }
347 
348     /**
349      * Binds the program with the specified projection, modelView and
350      * transform matrices.
351      */
352     void set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
353              const mat4& transformMatrix, bool offset = false);
354 
355     /**
356      * Sets the color associated with this shader.
357      */
358     void setColor(FloatColor color);
359 
360     /**
361      * Name of the texCoords attribute if it exists (kBindingTexCoords), -1 otherwise.
362      */
363     int texCoords;
364 
365     /**
366      * Name of the transform uniform.
367      */
368     int transform;
369 
370     /**
371      * Name of the projection uniform.
372      */
373     int projection;
374 
375 protected:
376     /**
377      * Adds an attribute with the specified name.
378      *
379      * @return The OpenGL name of the attribute.
380      */
381     int addAttrib(const char* name);
382 
383     /**
384      * Binds the specified attribute name to the specified slot.
385      */
386     int bindAttrib(const char* name, ShaderBindings bindingSlot);
387 
388     /**
389      * Adds a uniform with the specified name.
390      *
391      * @return The OpenGL name of the uniform.
392      */
393     int addUniform(const char* name);
394 
395 private:
396     /**
397      * Compiles the specified shader of the specified type.
398      *
399      * @return The name of the compiled shader.
400      */
401     GLuint buildShader(const char* source, GLenum type);
402 
403     // Name of the OpenGL program and shaders
404     GLuint mProgramId;
405     GLuint mVertexShader;
406     GLuint mFragmentShader;
407 
408     // Keeps track of attributes and uniforms slots
409     KeyedVector<const char*, int> mAttributes;
410     KeyedVector<const char*, int> mUniforms;
411 
412     bool mUse;
413     bool mInitialized;
414 
415     // Uniforms caching
416     bool mHasColorUniform;
417     int mColorUniform;
418 
419     bool mHasSampler;
420 
421     mat4 mProjection;
422     bool mOffset;
423 }; // class Program
424 
425 }; // namespace uirenderer
426 }; // namespace android
427 
428 #endif // ANDROID_HWUI_PROGRAM_H
429