blob: 9cb13b391f63d42a3d5c8427fd1a396977c06806 [file] [log] [blame]
Romain Guyac670c02010-07-27 17:39:27 -07001/*
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_UI_PROGRAM_CACHE_H
18#define ANDROID_UI_PROGRAM_CACHE_H
19
20#include <utils/KeyedVector.h>
21#include <utils/Log.h>
Romain Guy06f96e22010-07-30 19:18:16 -070022#include <utils/String8.h>
Romain Guyac670c02010-07-27 17:39:27 -070023
Romain Guy889f8d12010-07-29 14:37:42 -070024#include <GLES2/gl2.h>
25
Romain Guyac670c02010-07-27 17:39:27 -070026#include <SkXfermode.h>
27
28#include "Program.h"
29
30namespace android {
31namespace uirenderer {
32
33///////////////////////////////////////////////////////////////////////////////
34// Defines
35///////////////////////////////////////////////////////////////////////////////
36
37// Debug
Romain Guyf607bdc2010-09-10 19:20:06 -070038#define DEBUG_PROGRAM_CACHE 0
Romain Guyac670c02010-07-27 17:39:27 -070039
40// Debug
41#if DEBUG_PROGRAM_CACHE
42 #define PROGRAM_LOGD(...) LOGD(__VA_ARGS__)
43#else
44 #define PROGRAM_LOGD(...)
45#endif
46
Romain Guy707b2f72010-10-11 16:34:59 -070047// TODO: This should be set in properties
Romain Guydbc26d22010-10-11 17:58:29 -070048#define PANEL_BIT_DEPTH 20
Romain Guy707b2f72010-10-11 16:34:59 -070049#define COLOR_COMPONENT_THRESHOLD (1.0f - (0.5f / PANEL_BIT_DEPTH))
50#define COLOR_COMPONENT_INV_THRESHOLD (0.5f / PANEL_BIT_DEPTH)
51
Romain Guyac670c02010-07-27 17:39:27 -070052#define PROGRAM_KEY_TEXTURE 0x1
53#define PROGRAM_KEY_A8_TEXTURE 0x2
54#define PROGRAM_KEY_BITMAP 0x4
55#define PROGRAM_KEY_GRADIENT 0x8
56#define PROGRAM_KEY_BITMAP_FIRST 0x10
57#define PROGRAM_KEY_COLOR_MATRIX 0x20
58#define PROGRAM_KEY_COLOR_LIGHTING 0x40
59#define PROGRAM_KEY_COLOR_BLEND 0x80
Romain Guy889f8d12010-07-29 14:37:42 -070060#define PROGRAM_KEY_BITMAP_NPOT 0x100
Romain Guyf607bdc2010-09-10 19:20:06 -070061#define PROGRAM_KEY_SWAP_SRC_DST 0x2000
Romain Guy889f8d12010-07-29 14:37:42 -070062
63#define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600
64#define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800
Romain Guyac670c02010-07-27 17:39:27 -070065
Romain Guy48daa542010-08-10 19:21:34 -070066// Encode the xfermodes on 6 bits
67#define PROGRAM_MAX_XFERMODE 0x1f
68#define PROGRAM_XFERMODE_SHADER_SHIFT 26
Romain Guyac670c02010-07-27 17:39:27 -070069#define PROGRAM_XFERMODE_COLOR_OP_SHIFT 20
Romain Guya5aed0d2010-09-09 14:42:43 -070070#define PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT 14
Romain Guyac670c02010-07-27 17:39:27 -070071
Romain Guy889f8d12010-07-29 14:37:42 -070072#define PROGRAM_BITMAP_WRAPS_SHIFT 9
73#define PROGRAM_BITMAP_WRAPT_SHIFT 11
74
Romain Guyee916f12010-09-20 17:53:08 -070075#define PROGRAM_GRADIENT_TYPE_SHIFT 33
Romain Guy707b2f72010-10-11 16:34:59 -070076#define PROGRAM_MODULATE 35
Romain Guyee916f12010-09-20 17:53:08 -070077
Romain Guyac670c02010-07-27 17:39:27 -070078///////////////////////////////////////////////////////////////////////////////
79// Types
80///////////////////////////////////////////////////////////////////////////////
81
Romain Guyee916f12010-09-20 17:53:08 -070082typedef uint64_t programid;
Romain Guyac670c02010-07-27 17:39:27 -070083
84///////////////////////////////////////////////////////////////////////////////
85// Cache
86///////////////////////////////////////////////////////////////////////////////
87
88/**
89 * Describe the features required for a given program. The features
90 * determine the generation of both the vertex and fragment shaders.
91 * A ProgramDescription must be used in conjunction with a ProgramCache.
92 */
93struct ProgramDescription {
94 enum ColorModifier {
95 kColorNone,
96 kColorMatrix,
97 kColorLighting,
98 kColorBlend
99 };
100
Romain Guyee916f12010-09-20 17:53:08 -0700101 enum Gradient {
102 kGradientLinear,
103 kGradientCircular,
104 kGradientSweep
105 };
106
Romain Guyac670c02010-07-27 17:39:27 -0700107 ProgramDescription():
Romain Guy707b2f72010-10-11 16:34:59 -0700108 hasTexture(false), hasAlpha8Texture(false), modulate(false),
Romain Guy889f8d12010-07-29 14:37:42 -0700109 hasBitmap(false), isBitmapNpot(false), hasGradient(false),
Romain Guyee916f12010-09-20 17:53:08 -0700110 gradientType(kGradientLinear),
Romain Guy889f8d12010-07-29 14:37:42 -0700111 shadersMode(SkXfermode::kClear_Mode), isBitmapFirst(false),
112 bitmapWrapS(GL_CLAMP_TO_EDGE), bitmapWrapT(GL_CLAMP_TO_EDGE),
Romain Guya5aed0d2010-09-09 14:42:43 -0700113 colorOp(kColorNone), colorMode(SkXfermode::kClear_Mode),
Romain Guyf607bdc2010-09-10 19:20:06 -0700114 framebufferMode(SkXfermode::kClear_Mode), swapSrcDst(false) {
Romain Guyac670c02010-07-27 17:39:27 -0700115 }
116
117 // Texturing
118 bool hasTexture;
119 bool hasAlpha8Texture;
120
Romain Guy707b2f72010-10-11 16:34:59 -0700121 // Modulate, this should only be set when setColor() return true
122 bool modulate;
123
Romain Guyac670c02010-07-27 17:39:27 -0700124 // Shaders
125 bool hasBitmap;
Romain Guy889f8d12010-07-29 14:37:42 -0700126 bool isBitmapNpot;
Romain Guyee916f12010-09-20 17:53:08 -0700127
Romain Guyac670c02010-07-27 17:39:27 -0700128 bool hasGradient;
Romain Guyee916f12010-09-20 17:53:08 -0700129 Gradient gradientType;
130
Romain Guyac670c02010-07-27 17:39:27 -0700131 SkXfermode::Mode shadersMode;
Romain Guyee916f12010-09-20 17:53:08 -0700132
Romain Guyac670c02010-07-27 17:39:27 -0700133 bool isBitmapFirst;
Romain Guy889f8d12010-07-29 14:37:42 -0700134 GLenum bitmapWrapS;
135 GLenum bitmapWrapT;
Romain Guyac670c02010-07-27 17:39:27 -0700136
137 // Color operations
Romain Guy4afdf662010-10-13 21:31:28 -0700138 ColorModifier colorOp;
Romain Guyac670c02010-07-27 17:39:27 -0700139 SkXfermode::Mode colorMode;
140
Romain Guya5aed0d2010-09-09 14:42:43 -0700141 // Framebuffer blending (requires Extensions.hasFramebufferFetch())
142 // Ignored for all values < SkXfermode::kPlus_Mode
143 SkXfermode::Mode framebufferMode;
Romain Guyf607bdc2010-09-10 19:20:06 -0700144 bool swapSrcDst;
Romain Guya5aed0d2010-09-09 14:42:43 -0700145
Romain Guy707b2f72010-10-11 16:34:59 -0700146 /**
147 * Indicates, for a given color, whether color modulation is required in
148 * the fragment shader. When this method returns true, the program should
149 * be provided with a modulation color.
150 */
151 bool setColor(const float r, const float g, const float b, const float a) {
152 modulate = a < COLOR_COMPONENT_THRESHOLD || r < COLOR_COMPONENT_THRESHOLD ||
153 g < COLOR_COMPONENT_THRESHOLD || b < COLOR_COMPONENT_THRESHOLD;
154 return modulate;
Romain Guy889f8d12010-07-29 14:37:42 -0700155 }
156
Romain Guy707b2f72010-10-11 16:34:59 -0700157 /**
158 * Indicates, for a given color, whether color modulation is required in
159 * the fragment shader. When this method returns true, the program should
160 * be provided with a modulation color.
161 */
162 bool setAlpha8Color(const float r, const float g, const float b, const float a) {
163 modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD ||
164 g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD;
165 return modulate;
166 }
167
168 /**
169 * Computes the unique key identifying this program.
170 */
Romain Guyac670c02010-07-27 17:39:27 -0700171 programid key() const {
172 programid key = 0;
173 if (hasTexture) key |= PROGRAM_KEY_TEXTURE;
174 if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
Romain Guy889f8d12010-07-29 14:37:42 -0700175 if (hasBitmap) {
176 key |= PROGRAM_KEY_BITMAP;
177 if (isBitmapNpot) {
178 key |= PROGRAM_KEY_BITMAP_NPOT;
179 key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
180 key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
181 }
182 }
Romain Guyac670c02010-07-27 17:39:27 -0700183 if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
Romain Guyee916f12010-09-20 17:53:08 -0700184 key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
185 if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
Romain Guyac670c02010-07-27 17:39:27 -0700186 if (hasBitmap && hasGradient) {
187 key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
188 }
189 switch (colorOp) {
190 case kColorMatrix:
191 key |= PROGRAM_KEY_COLOR_MATRIX;
192 break;
193 case kColorLighting:
194 key |= PROGRAM_KEY_COLOR_LIGHTING;
195 break;
196 case kColorBlend:
197 key |= PROGRAM_KEY_COLOR_BLEND;
198 key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
199 break;
200 case kColorNone:
201 break;
202 }
Romain Guya5aed0d2010-09-09 14:42:43 -0700203 key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
Romain Guyf607bdc2010-09-10 19:20:06 -0700204 if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
Romain Guy707b2f72010-10-11 16:34:59 -0700205 if (modulate) key |= programid(0x1) << PROGRAM_MODULATE;
Romain Guyac670c02010-07-27 17:39:27 -0700206 return key;
207 }
Romain Guyee916f12010-09-20 17:53:08 -0700208
Romain Guy707b2f72010-10-11 16:34:59 -0700209 /**
210 * Logs the specified message followed by the key identifying this program.
211 */
Romain Guyee916f12010-09-20 17:53:08 -0700212 void log(const char* message) const {
213 programid k = key();
214 PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
215 uint32_t(k & 0xffffffff));
216 }
Romain Guy707b2f72010-10-11 16:34:59 -0700217
218private:
219 inline uint32_t getEnumForWrap(GLenum wrap) const {
220 switch (wrap) {
221 case GL_CLAMP_TO_EDGE:
222 return 0;
223 case GL_REPEAT:
224 return 1;
225 case GL_MIRRORED_REPEAT:
226 return 2;
227 }
228 return 0;
229 }
230
Romain Guyac670c02010-07-27 17:39:27 -0700231}; // struct ProgramDescription
232
233/**
234 * Generates and caches program. Programs are generated based on
235 * ProgramDescriptions.
236 */
237class ProgramCache {
238public:
239 ProgramCache();
240 ~ProgramCache();
241
242 Program* get(const ProgramDescription& description);
243
244 void clear();
245
246private:
247 Program* generateProgram(const ProgramDescription& description, programid key);
248 String8 generateVertexShader(const ProgramDescription& description);
249 String8 generateFragmentShader(const ProgramDescription& description);
Romain Guy48daa542010-08-10 19:21:34 -0700250 void generateBlend(String8& shader, const char* name, SkXfermode::Mode mode);
Romain Guy889f8d12010-07-29 14:37:42 -0700251 void generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT);
Romain Guyac670c02010-07-27 17:39:27 -0700252
Romain Guydb1938e2010-08-02 18:50:22 -0700253 void printLongString(const String8& shader) const;
254
Romain Guyac670c02010-07-27 17:39:27 -0700255 KeyedVector<programid, Program*> mCache;
Romain Guyac670c02010-07-27 17:39:27 -0700256}; // class ProgramCache
257
258}; // namespace uirenderer
259}; // namespace android
260
261#endif // ANDROID_UI_PROGRAM_CACHE_H