2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef ANDROID_HWUI_PROGRAM_H
18 #define ANDROID_HWUI_PROGRAM_H
20 #include <utils/KeyedVector.h>
22 #include <GLES2/gl2.h>
23 #include <GLES2/gl2ext.h>
25 #include <SkXfermode.h>
28 #include "FloatColor.h"
30 #include "Properties.h"
33 namespace uirenderer {
35 ///////////////////////////////////////////////////////////////////////////////
37 ///////////////////////////////////////////////////////////////////////////////
41 #define PROGRAM_LOGD(...) ALOGD(__VA_ARGS__)
43 #define PROGRAM_LOGD(...)
46 #define COLOR_COMPONENT_THRESHOLD 1.0f
47 #define COLOR_COMPONENT_INV_THRESHOLD 0.0f
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
58 #define PROGRAM_KEY_SWAP_SRC_DST 0x2000
60 #define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600
61 #define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800
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
69 #define PROGRAM_BITMAP_WRAPS_SHIFT 9
70 #define PROGRAM_BITMAP_WRAPT_SHIFT 11
72 #define PROGRAM_GRADIENT_TYPE_SHIFT 33 // 2 bits for gradient type
73 #define PROGRAM_MODULATE_SHIFT 35
75 #define PROGRAM_HAS_VERTEX_ALPHA_SHIFT 36
76 #define PROGRAM_USE_SHADOW_ALPHA_INTERP_SHIFT 37
78 #define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
79 #define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39
81 #define PROGRAM_IS_SIMPLE_GRADIENT 40
83 #define PROGRAM_HAS_COLORS 41
85 #define PROGRAM_HAS_DEBUG_HIGHLIGHT 42
86 #define PROGRAM_HAS_ROUND_RECT_CLIP 43
88 ///////////////////////////////////////////////////////////////////////////////
90 ///////////////////////////////////////////////////////////////////////////////
92 typedef uint64_t programid;
94 ///////////////////////////////////////////////////////////////////////////////
95 // Program description
96 ///////////////////////////////////////////////////////////////////////////////
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.
103 struct ProgramDescription {
104 enum class ColorFilterMode {
116 ProgramDescription() {
122 bool hasAlpha8Texture;
123 bool hasExternalTexture;
124 bool hasTextureTransform;
129 // Modulate, this should only be set when setColor() return true
137 bool useShadowAlphaInterp;
140 Gradient gradientType;
141 bool isSimpleGradient;
143 SkXfermode::Mode shadersMode;
150 ColorFilterMode colorOp;
151 SkXfermode::Mode colorMode;
153 // Framebuffer blending (requires Extensions.hasFramebufferFetch())
154 // Ignored for all values < SkXfermode::kPlus_Mode
155 SkXfermode::Mode framebufferMode;
158 bool hasDebugHighlight;
159 bool hasRoundRectClip;
162 * Resets this description. All fields are reset back to the default
163 * values they hold after building a new instance.
167 hasAlpha8Texture = false;
168 hasExternalTexture = false;
169 hasTextureTransform = false;
173 hasVertexAlpha = false;
174 useShadowAlphaInterp = false;
179 isBitmapNpot = false;
182 gradientType = kGradientLinear;
183 isSimpleGradient = false;
185 shadersMode = SkXfermode::kClear_Mode;
187 isBitmapFirst = false;
188 bitmapWrapS = GL_CLAMP_TO_EDGE;
189 bitmapWrapT = GL_CLAMP_TO_EDGE;
191 colorOp = ColorFilterMode::None;
192 colorMode = SkXfermode::kClear_Mode;
194 framebufferMode = SkXfermode::kClear_Mode;
197 hasDebugHighlight = false;
198 hasRoundRectClip = false;
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.
206 bool setColorModulate(const float a) {
207 modulate = a < COLOR_COMPONENT_THRESHOLD;
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.
216 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;
223 * Computes the unique key identifying this program.
225 programid key() const {
227 if (hasTexture) key |= PROGRAM_KEY_TEXTURE;
228 if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
230 key |= PROGRAM_KEY_BITMAP;
232 key |= PROGRAM_KEY_BITMAP_NPOT;
233 key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
234 key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
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;
244 case ColorFilterMode::Matrix:
245 key |= PROGRAM_KEY_COLOR_MATRIX;
247 case ColorFilterMode::Blend:
248 key |= PROGRAM_KEY_COLOR_BLEND;
249 key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
251 case ColorFilterMode::None:
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;
269 * Logs the specified message followed by the key identifying this program.
271 void log(const char* message) const {
274 PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
275 uint32_t(k & 0xffffffff));
280 static inline uint32_t getEnumForWrap(GLenum wrap) {
282 case GL_CLAMP_TO_EDGE:
286 case GL_MIRRORED_REPEAT:
292 }; // struct ProgramDescription
295 * A program holds a vertex and a fragment shader. It offers several utility
296 * methods to query attributes and uniforms.
300 enum ShaderBindings {
306 * Creates a new program with the specified vertex and fragment
309 Program(const ProgramDescription& description, const char* vertex, const char* fragment);
313 * Binds this program to the GL context.
318 * Marks this program as unused. This will not unbind
319 * the program from the GL context.
321 virtual void remove();
324 * Returns the OpenGL name of the specified attribute.
326 int getAttrib(const char* name);
329 * Returns the OpenGL name of the specified uniform.
331 int getUniform(const char* name);
334 * Indicates whether this program is currently in use with
337 inline bool isInUse() const {
342 * Indicates whether this program was correctly compiled and linked.
344 inline bool isInitialized() const {
349 * Binds the program with the specified projection, modelView and
350 * transform matrices.
352 void set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
353 const mat4& transformMatrix, bool offset = false);
356 * Sets the color associated with this shader.
358 void setColor(FloatColor color);
361 * Name of the texCoords attribute if it exists (kBindingTexCoords), -1 otherwise.
366 * Name of the transform uniform.
371 * Name of the projection uniform.
377 * Adds an attribute with the specified name.
379 * @return The OpenGL name of the attribute.
381 int addAttrib(const char* name);
384 * Binds the specified attribute name to the specified slot.
386 int bindAttrib(const char* name, ShaderBindings bindingSlot);
389 * Adds a uniform with the specified name.
391 * @return The OpenGL name of the uniform.
393 int addUniform(const char* name);
397 * Compiles the specified shader of the specified type.
399 * @return The name of the compiled shader.
401 GLuint buildShader(const char* source, GLenum type);
403 // Name of the OpenGL program and shaders
405 GLuint mVertexShader;
406 GLuint mFragmentShader;
408 // Keeps track of attributes and uniforms slots
409 KeyedVector<const char*, int> mAttributes;
410 KeyedVector<const char*, int> mUniforms;
416 bool mHasColorUniform;
425 }; // namespace uirenderer
426 }; // namespace android
428 #endif // ANDROID_HWUI_PROGRAM_H