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