ProgramCache.h revision 70ca14e08ae197547ac412e8a1210e1ebdfb2eb1
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_CACHE_H
18#define ANDROID_HWUI_PROGRAM_CACHE_H
19
20#include <utils/KeyedVector.h>
21#include <utils/Log.h>
22#include <utils/String8.h>
23
24#include <GLES2/gl2.h>
25
26#include <SkXfermode.h>
27
28#include "Debug.h"
29#include "Program.h"
30
31namespace android {
32namespace uirenderer {
33
34///////////////////////////////////////////////////////////////////////////////
35// Defines
36///////////////////////////////////////////////////////////////////////////////
37
38// Debug
39#if DEBUG_PROGRAMS
40    #define PROGRAM_LOGD(...) LOGD(__VA_ARGS__)
41#else
42    #define PROGRAM_LOGD(...)
43#endif
44
45// TODO: This should be set in properties
46#define PANEL_BIT_DEPTH 20
47#define COLOR_COMPONENT_THRESHOLD (1.0f - (0.5f / PANEL_BIT_DEPTH))
48#define COLOR_COMPONENT_INV_THRESHOLD (0.5f / PANEL_BIT_DEPTH)
49
50#define PROGRAM_KEY_TEXTURE 0x1
51#define PROGRAM_KEY_A8_TEXTURE 0x2
52#define PROGRAM_KEY_BITMAP 0x4
53#define PROGRAM_KEY_GRADIENT 0x8
54#define PROGRAM_KEY_BITMAP_FIRST 0x10
55#define PROGRAM_KEY_COLOR_MATRIX 0x20
56#define PROGRAM_KEY_COLOR_LIGHTING 0x40
57#define PROGRAM_KEY_COLOR_BLEND 0x80
58#define PROGRAM_KEY_BITMAP_NPOT 0x100
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
74#define PROGRAM_MODULATE 35
75
76///////////////////////////////////////////////////////////////////////////////
77// Types
78///////////////////////////////////////////////////////////////////////////////
79
80typedef uint64_t programid;
81
82///////////////////////////////////////////////////////////////////////////////
83// Cache
84///////////////////////////////////////////////////////////////////////////////
85
86/**
87 * Describe the features required for a given program. The features
88 * determine the generation of both the vertex and fragment shaders.
89 * A ProgramDescription must be used in conjunction with a ProgramCache.
90 */
91struct ProgramDescription {
92    enum ColorModifier {
93        kColorNone,
94        kColorMatrix,
95        kColorLighting,
96        kColorBlend
97    };
98
99    enum Gradient {
100        kGradientLinear,
101        kGradientCircular,
102        kGradientSweep
103    };
104
105    ProgramDescription() {
106        reset();
107    }
108
109    // Texturing
110    bool hasTexture;
111    bool hasAlpha8Texture;
112
113    // Modulate, this should only be set when setColor() return true
114    bool modulate;
115
116    // Shaders
117    bool hasBitmap;
118    bool isBitmapNpot;
119
120    bool hasGradient;
121    Gradient gradientType;
122
123    SkXfermode::Mode shadersMode;
124
125    bool isBitmapFirst;
126    GLenum bitmapWrapS;
127    GLenum bitmapWrapT;
128
129    // Color operations
130    ColorModifier colorOp;
131    SkXfermode::Mode colorMode;
132
133    // Framebuffer blending (requires Extensions.hasFramebufferFetch())
134    // Ignored for all values < SkXfermode::kPlus_Mode
135    SkXfermode::Mode framebufferMode;
136    bool swapSrcDst;
137
138    /**
139     * Resets this description. All fields are reset back to the default
140     * values they hold after building a new instance.
141     */
142    void reset() {
143        hasTexture = false;
144        hasAlpha8Texture = false;
145
146        modulate = false;
147
148        hasBitmap = false;
149        isBitmapNpot = false;
150
151        hasGradient = false;
152        gradientType = kGradientLinear;
153
154        shadersMode = SkXfermode::kClear_Mode;
155
156        isBitmapFirst = false;
157        bitmapWrapS = GL_CLAMP_TO_EDGE;
158        bitmapWrapT = GL_CLAMP_TO_EDGE;
159
160        colorOp = kColorNone;
161        colorMode = SkXfermode::kClear_Mode;
162
163        framebufferMode = SkXfermode::kClear_Mode;
164        swapSrcDst = false;
165    }
166
167    /**
168     * Indicates, for a given color, whether color modulation is required in
169     * the fragment shader. When this method returns true, the program should
170     * be provided with a modulation color.
171     */
172    bool setColor(const float r, const float g, const float b, const float a) {
173        modulate = a < COLOR_COMPONENT_THRESHOLD || r < COLOR_COMPONENT_THRESHOLD ||
174                g < COLOR_COMPONENT_THRESHOLD || b < COLOR_COMPONENT_THRESHOLD;
175        return modulate;
176    }
177
178    /**
179     * Indicates, for a given color, whether color modulation is required in
180     * the fragment shader. When this method returns true, the program should
181     * be provided with a modulation color.
182     */
183    bool setAlpha8Color(const float r, const float g, const float b, const float a) {
184        modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD ||
185                g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD;
186        return modulate;
187    }
188
189    /**
190     * Computes the unique key identifying this program.
191     */
192    programid key() const {
193        programid key = 0;
194        if (hasTexture) key |= PROGRAM_KEY_TEXTURE;
195        if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
196        if (hasBitmap) {
197            key |= PROGRAM_KEY_BITMAP;
198            if (isBitmapNpot) {
199                key |= PROGRAM_KEY_BITMAP_NPOT;
200                key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
201                key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
202            }
203        }
204        if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
205        key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
206        if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
207        if (hasBitmap && hasGradient) {
208            key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
209        }
210        switch (colorOp) {
211            case kColorMatrix:
212                key |= PROGRAM_KEY_COLOR_MATRIX;
213                break;
214            case kColorLighting:
215                key |= PROGRAM_KEY_COLOR_LIGHTING;
216                break;
217            case kColorBlend:
218                key |= PROGRAM_KEY_COLOR_BLEND;
219                key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
220                break;
221            case kColorNone:
222                break;
223        }
224        key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
225        if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
226        if (modulate) key |= programid(0x1) << PROGRAM_MODULATE;
227        return key;
228    }
229
230    /**
231     * Logs the specified message followed by the key identifying this program.
232     */
233    void log(const char* message) const {
234        programid k = key();
235        PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
236                uint32_t(k & 0xffffffff));
237    }
238
239private:
240    inline uint32_t getEnumForWrap(GLenum wrap) const {
241        switch (wrap) {
242            case GL_CLAMP_TO_EDGE:
243                return 0;
244            case GL_REPEAT:
245                return 1;
246            case GL_MIRRORED_REPEAT:
247                return 2;
248        }
249        return 0;
250    }
251
252}; // struct ProgramDescription
253
254/**
255 * Generates and caches program. Programs are generated based on
256 * ProgramDescriptions.
257 */
258class ProgramCache {
259public:
260    ProgramCache();
261    ~ProgramCache();
262
263    Program* get(const ProgramDescription& description);
264
265    void clear();
266
267private:
268    Program* generateProgram(const ProgramDescription& description, programid key);
269    String8 generateVertexShader(const ProgramDescription& description);
270    String8 generateFragmentShader(const ProgramDescription& description);
271    void generateBlend(String8& shader, const char* name, SkXfermode::Mode mode);
272    void generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT);
273
274    void printLongString(const String8& shader) const;
275
276    KeyedVector<programid, Program*> mCache;
277}; // class ProgramCache
278
279}; // namespace uirenderer
280}; // namespace android
281
282#endif // ANDROID_HWUI_PROGRAM_CACHE_H
283