Program.h revision 554ffeb8b7c836da43a637c59eedfc617895b19d
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
32namespace android {
33namespace 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#define PROGRAM_HAS_GAMMA_CORRECTION 44
89
90///////////////////////////////////////////////////////////////////////////////
91// Types
92///////////////////////////////////////////////////////////////////////////////
93
94typedef 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 */
105struct ProgramDescription {
106    enum class ColorFilterMode {
107        None = 0,
108        Matrix,
109        Blend
110    };
111
112    enum Gradient {
113        kGradientLinear = 0,
114        kGradientCircular,
115        kGradientSweep
116    };
117
118    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 useShaderBasedWrap;
137
138    bool hasVertexAlpha;
139    bool useShadowAlphaInterp;
140
141    bool hasGradient;
142    Gradient gradientType;
143    bool isSimpleGradient;
144
145    SkBlendMode shadersMode;
146
147    bool isBitmapFirst;
148    GLenum bitmapWrapS;
149    GLenum bitmapWrapT;
150
151    // Color operations
152    ColorFilterMode colorOp;
153    SkBlendMode colorMode;
154
155    // Framebuffer blending (requires Extensions.hasFramebufferFetch())
156    // Ignored for all values < SkBlendMode::kPlus
157    SkBlendMode framebufferMode;
158    bool swapSrcDst;
159
160    bool hasDebugHighlight;
161    bool hasRoundRectClip;
162
163    bool hasGammaCorrection;
164
165    /**
166     * Resets this description. All fields are reset back to the default
167     * values they hold after building a new instance.
168     */
169    void reset() {
170        hasTexture = false;
171        hasAlpha8Texture = false;
172        hasExternalTexture = false;
173        hasTextureTransform = false;
174
175        hasColors = false;
176
177        hasVertexAlpha = false;
178        useShadowAlphaInterp = false;
179
180        modulate = false;
181
182        hasBitmap = false;
183        useShaderBasedWrap = false;
184
185        hasGradient = false;
186        gradientType = kGradientLinear;
187        isSimpleGradient = false;
188
189        shadersMode = SkBlendMode::kClear;
190
191        isBitmapFirst = false;
192        bitmapWrapS = GL_CLAMP_TO_EDGE;
193        bitmapWrapT = GL_CLAMP_TO_EDGE;
194
195        colorOp = ColorFilterMode::None;
196        colorMode = SkBlendMode::kClear;
197
198        framebufferMode = SkBlendMode::kClear;
199        swapSrcDst = false;
200
201        hasDebugHighlight = false;
202        hasRoundRectClip = false;
203
204        hasGammaCorrection = false;
205    }
206
207    /**
208     * Indicates, for a given color, whether color modulation is required in
209     * the fragment shader. When this method returns true, the program should
210     * be provided with a modulation color.
211     */
212    bool setColorModulate(const float a) {
213        modulate = a < COLOR_COMPONENT_THRESHOLD;
214        return modulate;
215    }
216
217    /**
218     * Indicates, for a given color, whether color modulation is required in
219     * the fragment shader. When this method returns true, the program should
220     * be provided with a modulation color.
221     */
222    bool setAlpha8ColorModulate(const float r, const float g, const float b, const float a) {
223        modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD ||
224                g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD;
225        return modulate;
226    }
227
228    /**
229     * Computes the unique key identifying this program.
230     */
231    programid key() const {
232        programid key = 0;
233        if (hasTexture) key |= PROGRAM_KEY_TEXTURE;
234        if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
235        if (hasBitmap) {
236            key |= PROGRAM_KEY_BITMAP;
237            if (useShaderBasedWrap) {
238                key |= PROGRAM_KEY_BITMAP_NPOT;
239                key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
240                key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
241            }
242        }
243        if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
244        key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
245        if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
246        if (hasBitmap && hasGradient) {
247            key |= ((int)shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
248        }
249        switch (colorOp) {
250            case ColorFilterMode::Matrix:
251                key |= PROGRAM_KEY_COLOR_MATRIX;
252                break;
253            case ColorFilterMode::Blend:
254                key |= PROGRAM_KEY_COLOR_BLEND;
255                key |= ((int)colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
256                break;
257            case ColorFilterMode::None:
258                break;
259        }
260        key |= ((int)framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
261        if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
262        if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
263        if (hasVertexAlpha) key |= programid(0x1) << PROGRAM_HAS_VERTEX_ALPHA_SHIFT;
264        if (useShadowAlphaInterp) key |= programid(0x1) << PROGRAM_USE_SHADOW_ALPHA_INTERP_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 (isSimpleGradient) key |= programid(0x1) << PROGRAM_IS_SIMPLE_GRADIENT;
268        if (hasColors) key |= programid(0x1) << PROGRAM_HAS_COLORS;
269        if (hasDebugHighlight) key |= programid(0x1) << PROGRAM_HAS_DEBUG_HIGHLIGHT;
270        if (hasRoundRectClip) key |= programid(0x1) << PROGRAM_HAS_ROUND_RECT_CLIP;
271        if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
272        return key;
273    }
274
275    /**
276     * Logs the specified message followed by the key identifying this program.
277     */
278    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
286private:
287    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 */
305class Program {
306public:
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     */
344    inline bool isInUse() const {
345        return mUse;
346    }
347
348    /**
349     * Indicates whether this program was correctly compiled and linked.
350     */
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(FloatColor color);
366
367    /**
368     * Name of the texCoords attribute if it exists (kBindingTexCoords), -1 otherwise.
369     */
370    int texCoords;
371
372    /**
373     * Name of the transform uniform.
374     */
375    int transform;
376
377    /**
378     * Name of the projection uniform.
379     */
380    int projection;
381
382protected:
383    /**
384     * Adds an attribute with the specified name.
385     *
386     * @return The OpenGL name of the attribute.
387     */
388    int addAttrib(const char* name);
389
390    /**
391     * Binds the specified attribute name to the specified slot.
392     */
393    int bindAttrib(const char* name, ShaderBindings bindingSlot);
394
395    /**
396     * Adds a uniform with the specified name.
397     *
398     * @return The OpenGL name of the uniform.
399     */
400    int addUniform(const char* name);
401
402private:
403    /**
404     * Compiles the specified shader of the specified type.
405     *
406     * @return The name of the compiled shader.
407     */
408    GLuint buildShader(const char* source, GLenum type);
409
410    // Name of the OpenGL program and shaders
411    GLuint mProgramId;
412    GLuint mVertexShader;
413    GLuint mFragmentShader;
414
415    // Keeps track of attributes and uniforms slots
416    KeyedVector<const char*, int> mAttributes;
417    KeyedVector<const char*, int> mUniforms;
418
419    bool mUse;
420    bool mInitialized;
421
422    // Uniforms caching
423    bool mHasColorUniform;
424    int mColorUniform;
425
426    bool mHasSampler;
427
428    mat4 mProjection;
429    bool mOffset;
430}; // class Program
431
432}; // namespace uirenderer
433}; // namespace android
434
435#endif // ANDROID_HWUI_PROGRAM_H
436