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