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_H 18 #define ANDROID_HWUI_PROGRAM_H 19 20 #include <utils/KeyedVector.h> 21 22 #include <GLES2/gl2.h> 23 #include <GLES2/gl2ext.h> 24 25 #include <SkXfermode.h> 26 27 #include "Matrix.h" 28 #include "Properties.h" 29 30 namespace android { 31 namespace uirenderer { 32 33 /////////////////////////////////////////////////////////////////////////////// 34 // Defines 35 /////////////////////////////////////////////////////////////////////////////// 36 37 // Debug 38 #if DEBUG_PROGRAMS 39 #define PROGRAM_LOGD(...) ALOGD(__VA_ARGS__) 40 #else 41 #define PROGRAM_LOGD(...) 42 #endif 43 44 #define COLOR_COMPONENT_THRESHOLD (1.0f - (0.5f / PANEL_BIT_DEPTH)) 45 #define COLOR_COMPONENT_INV_THRESHOLD (0.5f / PANEL_BIT_DEPTH) 46 47 #define PROGRAM_KEY_TEXTURE 0x1 48 #define PROGRAM_KEY_A8_TEXTURE 0x2 49 #define PROGRAM_KEY_BITMAP 0x4 50 #define PROGRAM_KEY_GRADIENT 0x8 51 #define PROGRAM_KEY_BITMAP_FIRST 0x10 52 #define PROGRAM_KEY_COLOR_MATRIX 0x20 53 #define PROGRAM_KEY_COLOR_LIGHTING 0x40 54 #define PROGRAM_KEY_COLOR_BLEND 0x80 55 #define PROGRAM_KEY_BITMAP_NPOT 0x100 56 #define PROGRAM_KEY_SWAP_SRC_DST 0x2000 57 58 #define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600 59 #define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800 60 61 // Encode the xfermodes on 6 bits 62 #define PROGRAM_MAX_XFERMODE 0x1f 63 #define PROGRAM_XFERMODE_SHADER_SHIFT 26 64 #define PROGRAM_XFERMODE_COLOR_OP_SHIFT 20 65 #define PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT 14 66 67 #define PROGRAM_BITMAP_WRAPS_SHIFT 9 68 #define PROGRAM_BITMAP_WRAPT_SHIFT 11 69 70 #define PROGRAM_GRADIENT_TYPE_SHIFT 33 71 #define PROGRAM_MODULATE_SHIFT 35 72 73 #define PROGRAM_IS_POINT_SHIFT 36 74 75 #define PROGRAM_HAS_AA_SHIFT 37 76 77 #define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38 78 #define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39 79 80 /////////////////////////////////////////////////////////////////////////////// 81 // Types 82 /////////////////////////////////////////////////////////////////////////////// 83 84 typedef uint64_t programid; 85 86 /////////////////////////////////////////////////////////////////////////////// 87 // Program description 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 */ 95 struct 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 ProgramDescriptionProgramDescription109 ProgramDescription() { 110 reset(); 111 } 112 113 // Texturing 114 bool hasTexture; 115 bool hasAlpha8Texture; 116 bool hasExternalTexture; 117 bool hasTextureTransform; 118 119 // Modulate, this should only be set when setColor() return true 120 bool modulate; 121 122 // Shaders 123 bool hasBitmap; 124 bool isBitmapNpot; 125 126 bool isAA; 127 128 bool hasGradient; 129 Gradient gradientType; 130 131 SkXfermode::Mode shadersMode; 132 133 bool isBitmapFirst; 134 GLenum bitmapWrapS; 135 GLenum bitmapWrapT; 136 137 // Color operations 138 ColorModifier colorOp; 139 SkXfermode::Mode colorMode; 140 141 // Framebuffer blending (requires Extensions.hasFramebufferFetch()) 142 // Ignored for all values < SkXfermode::kPlus_Mode 143 SkXfermode::Mode framebufferMode; 144 bool swapSrcDst; 145 146 bool isPoint; 147 float pointSize; 148 149 /** 150 * Resets this description. All fields are reset back to the default 151 * values they hold after building a new instance. 152 */ resetProgramDescription153 void reset() { 154 hasTexture = false; 155 hasAlpha8Texture = false; 156 hasExternalTexture = false; 157 hasTextureTransform = false; 158 159 isAA = 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 */ setColorProgramDescription190 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 */ setAlpha8ColorProgramDescription201 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 */ keyProgramDescription210 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 (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT; 247 if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT; 248 if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT; 249 return key; 250 } 251 252 /** 253 * Logs the specified message followed by the key identifying this program. 254 */ logProgramDescription255 void log(const char* message) const { 256 #if DEBUG_PROGRAMS 257 programid k = key(); 258 PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32), 259 uint32_t(k & 0xffffffff)); 260 #endif 261 } 262 263 private: getEnumForWrapProgramDescription264 inline uint32_t getEnumForWrap(GLenum wrap) const { 265 switch (wrap) { 266 case GL_CLAMP_TO_EDGE: 267 return 0; 268 case GL_REPEAT: 269 return 1; 270 case GL_MIRRORED_REPEAT: 271 return 2; 272 } 273 return 0; 274 } 275 276 }; // struct ProgramDescription 277 278 /** 279 * A program holds a vertex and a fragment shader. It offers several utility 280 * methods to query attributes and uniforms. 281 */ 282 class Program { 283 public: 284 enum ShaderBindings { 285 kBindingPosition, 286 kBindingTexCoords 287 }; 288 289 /** 290 * Creates a new program with the specified vertex and fragment 291 * shaders sources. 292 */ 293 Program(const ProgramDescription& description, const char* vertex, const char* fragment); 294 virtual ~Program(); 295 296 /** 297 * Binds this program to the GL context. 298 */ 299 virtual void use(); 300 301 /** 302 * Marks this program as unused. This will not unbind 303 * the program from the GL context. 304 */ 305 virtual void remove(); 306 307 /** 308 * Returns the OpenGL name of the specified attribute. 309 */ 310 int getAttrib(const char* name); 311 312 /** 313 * Returns the OpenGL name of the specified uniform. 314 */ 315 int getUniform(const char* name); 316 317 /** 318 * Indicates whether this program is currently in use with 319 * the GL context. 320 */ isInUse()321 inline bool isInUse() const { 322 return mUse; 323 } 324 325 /** 326 * Indicates whether this program was correctly compiled and linked. 327 */ isInitialized()328 inline bool isInitialized() const { 329 return mInitialized; 330 } 331 332 /** 333 * Binds the program with the specified projection, modelView and 334 * transform matrices. 335 */ 336 void set(const mat4& projectionMatrix, const mat4& modelViewMatrix, 337 const mat4& transformMatrix, bool offset = false); 338 339 /** 340 * Sets the color associated with this shader. 341 */ 342 void setColor(const float r, const float g, const float b, const float a); 343 344 /** 345 * Name of the position attribute. 346 */ 347 int position; 348 349 /** 350 * Name of the texCoords attribute if it exists, -1 otherwise. 351 */ 352 int texCoords; 353 354 /** 355 * Name of the transform uniform. 356 */ 357 int transform; 358 359 protected: 360 /** 361 * Adds an attribute with the specified name. 362 * 363 * @return The OpenGL name of the attribute. 364 */ 365 int addAttrib(const char* name); 366 367 /** 368 * Binds the specified attribute name to the specified slot. 369 */ 370 int bindAttrib(const char* name, ShaderBindings bindingSlot); 371 372 /** 373 * Adds a uniform with the specified name. 374 * 375 * @return The OpenGL name of the uniform. 376 */ 377 int addUniform(const char* name); 378 379 private: 380 /** 381 * Compiles the specified shader of the specified type. 382 * 383 * @return The name of the compiled shader. 384 */ 385 GLuint buildShader(const char* source, GLenum type); 386 387 // Name of the OpenGL program and shaders 388 GLuint mProgramId; 389 GLuint mVertexShader; 390 GLuint mFragmentShader; 391 392 // Keeps track of attributes and uniforms slots 393 KeyedVector<const char*, int> mAttributes; 394 KeyedVector<const char*, int> mUniforms; 395 396 bool mUse; 397 bool mInitialized; 398 399 bool mHasColorUniform; 400 int mColorUniform; 401 402 bool mHasSampler; 403 }; // class Program 404 405 }; // namespace uirenderer 406 }; // namespace android 407 408 #endif // ANDROID_HWUI_PROGRAM_H 409