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