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 31 namespace android { 32 namespace 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_SHIFT 35 75 76 #define PROGRAM_IS_POINT_SHIFT 36 77 78 #define PROGRAM_HAS_AA_SHIFT 37 79 80 #define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38 81 #define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39 82 83 /////////////////////////////////////////////////////////////////////////////// 84 // Types 85 /////////////////////////////////////////////////////////////////////////////// 86 87 typedef uint64_t programid; 88 89 /////////////////////////////////////////////////////////////////////////////// 90 // Cache 91 /////////////////////////////////////////////////////////////////////////////// 92 93 /** 94 * Describe the features required for a given program. The features 95 * determine the generation of both the vertex and fragment shaders. 96 * A ProgramDescription must be used in conjunction with a ProgramCache. 97 */ 98 struct ProgramDescription { 99 enum ColorModifier { 100 kColorNone, 101 kColorMatrix, 102 kColorLighting, 103 kColorBlend 104 }; 105 106 enum Gradient { 107 kGradientLinear, 108 kGradientCircular, 109 kGradientSweep 110 }; 111 ProgramDescriptionProgramDescription112 ProgramDescription() { 113 reset(); 114 } 115 116 // Texturing 117 bool hasTexture; 118 bool hasAlpha8Texture; 119 bool hasExternalTexture; 120 bool hasTextureTransform; 121 122 // Modulate, this should only be set when setColor() return true 123 bool modulate; 124 125 // Shaders 126 bool hasBitmap; 127 bool isBitmapNpot; 128 129 bool isAA; 130 131 bool hasGradient; 132 Gradient gradientType; 133 134 SkXfermode::Mode shadersMode; 135 136 bool isBitmapFirst; 137 GLenum bitmapWrapS; 138 GLenum bitmapWrapT; 139 140 // Color operations 141 ColorModifier colorOp; 142 SkXfermode::Mode colorMode; 143 144 // Framebuffer blending (requires Extensions.hasFramebufferFetch()) 145 // Ignored for all values < SkXfermode::kPlus_Mode 146 SkXfermode::Mode framebufferMode; 147 bool swapSrcDst; 148 149 bool isPoint; 150 float pointSize; 151 152 /** 153 * Resets this description. All fields are reset back to the default 154 * values they hold after building a new instance. 155 */ resetProgramDescription156 void reset() { 157 hasTexture = false; 158 hasAlpha8Texture = false; 159 hasExternalTexture = false; 160 hasTextureTransform = false; 161 162 isAA = false; 163 164 modulate = false; 165 166 hasBitmap = false; 167 isBitmapNpot = false; 168 169 hasGradient = false; 170 gradientType = kGradientLinear; 171 172 shadersMode = SkXfermode::kClear_Mode; 173 174 isBitmapFirst = false; 175 bitmapWrapS = GL_CLAMP_TO_EDGE; 176 bitmapWrapT = GL_CLAMP_TO_EDGE; 177 178 colorOp = kColorNone; 179 colorMode = SkXfermode::kClear_Mode; 180 181 framebufferMode = SkXfermode::kClear_Mode; 182 swapSrcDst = false; 183 184 isPoint = false; 185 pointSize = 0.0f; 186 } 187 188 /** 189 * Indicates, for a given color, whether color modulation is required in 190 * the fragment shader. When this method returns true, the program should 191 * be provided with a modulation color. 192 */ setColorProgramDescription193 bool setColor(const float r, const float g, const float b, const float a) { 194 modulate = a < COLOR_COMPONENT_THRESHOLD || r < COLOR_COMPONENT_THRESHOLD || 195 g < COLOR_COMPONENT_THRESHOLD || b < COLOR_COMPONENT_THRESHOLD; 196 return modulate; 197 } 198 199 /** 200 * Indicates, for a given color, whether color modulation is required in 201 * the fragment shader. When this method returns true, the program should 202 * be provided with a modulation color. 203 */ setAlpha8ColorProgramDescription204 bool setAlpha8Color(const float r, const float g, const float b, const float a) { 205 modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD || 206 g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD; 207 return modulate; 208 } 209 210 /** 211 * Computes the unique key identifying this program. 212 */ keyProgramDescription213 programid key() const { 214 programid key = 0; 215 if (hasTexture) key |= PROGRAM_KEY_TEXTURE; 216 if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE; 217 if (hasBitmap) { 218 key |= PROGRAM_KEY_BITMAP; 219 if (isBitmapNpot) { 220 key |= PROGRAM_KEY_BITMAP_NPOT; 221 key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT; 222 key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT; 223 } 224 } 225 if (hasGradient) key |= PROGRAM_KEY_GRADIENT; 226 key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT; 227 if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST; 228 if (hasBitmap && hasGradient) { 229 key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT; 230 } 231 switch (colorOp) { 232 case kColorMatrix: 233 key |= PROGRAM_KEY_COLOR_MATRIX; 234 break; 235 case kColorLighting: 236 key |= PROGRAM_KEY_COLOR_LIGHTING; 237 break; 238 case kColorBlend: 239 key |= PROGRAM_KEY_COLOR_BLEND; 240 key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT; 241 break; 242 case kColorNone: 243 break; 244 } 245 key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT; 246 if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST; 247 if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT; 248 if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT; 249 if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT; 250 if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT; 251 if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT; 252 return key; 253 } 254 255 /** 256 * Logs the specified message followed by the key identifying this program. 257 */ logProgramDescription258 void log(const char* message) const { 259 #if DEBUG_PROGRAMS 260 programid k = key(); 261 PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32), 262 uint32_t(k & 0xffffffff)); 263 #endif 264 } 265 266 private: getEnumForWrapProgramDescription267 inline uint32_t getEnumForWrap(GLenum wrap) const { 268 switch (wrap) { 269 case GL_CLAMP_TO_EDGE: 270 return 0; 271 case GL_REPEAT: 272 return 1; 273 case GL_MIRRORED_REPEAT: 274 return 2; 275 } 276 return 0; 277 } 278 279 }; // struct ProgramDescription 280 281 /** 282 * Generates and caches program. Programs are generated based on 283 * ProgramDescriptions. 284 */ 285 class ProgramCache { 286 public: 287 ProgramCache(); 288 ~ProgramCache(); 289 290 Program* get(const ProgramDescription& description); 291 292 void clear(); 293 294 private: 295 Program* generateProgram(const ProgramDescription& description, programid key); 296 String8 generateVertexShader(const ProgramDescription& description); 297 String8 generateFragmentShader(const ProgramDescription& description); 298 void generateBlend(String8& shader, const char* name, SkXfermode::Mode mode); 299 void generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT); 300 301 void printLongString(const String8& shader) const; 302 303 KeyedVector<programid, Program*> mCache; 304 }; // class ProgramCache 305 306 }; // namespace uirenderer 307 }; // namespace android 308 309 #endif // ANDROID_HWUI_PROGRAM_CACHE_H 310