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