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