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