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 <SkBlendMode.h> 26 27 #include "Debug.h" 28 #include "FloatColor.h" 29 #include "Matrix.h" 30 #include "Properties.h" 31 #include "utils/Color.h" 32 33 namespace android { 34 namespace uirenderer { 35 36 /////////////////////////////////////////////////////////////////////////////// 37 // Defines 38 /////////////////////////////////////////////////////////////////////////////// 39 40 // Debug 41 #if DEBUG_PROGRAMS 42 #define PROGRAM_LOGD(...) ALOGD(__VA_ARGS__) 43 #else 44 #define PROGRAM_LOGD(...) 45 #endif 46 47 #define COLOR_COMPONENT_THRESHOLD 1.0f 48 #define COLOR_COMPONENT_INV_THRESHOLD 0.0f 49 50 #define PROGRAM_KEY_TEXTURE 0x01 51 #define PROGRAM_KEY_A8_TEXTURE 0x02 52 #define PROGRAM_KEY_BITMAP 0x04 53 #define PROGRAM_KEY_GRADIENT 0x08 54 #define PROGRAM_KEY_BITMAP_FIRST 0x10 55 #define PROGRAM_KEY_COLOR_MATRIX 0x20 56 #define PROGRAM_KEY_COLOR_BLEND 0x40 57 #define PROGRAM_KEY_BITMAP_NPOT 0x80 58 #define PROGRAM_KEY_BITMAP_EXTERNAL 0x100 59 60 #define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600 61 #define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800 62 63 #define PROGRAM_KEY_SWAP_SRC_DST_SHIFT 13 64 65 // Encode the xfermodes on 6 bits 66 #define PROGRAM_MAX_XFERMODE 0x1f 67 #define PROGRAM_XFERMODE_SHADER_SHIFT 26 68 #define PROGRAM_XFERMODE_COLOR_OP_SHIFT 20 69 #define PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT 14 70 71 #define PROGRAM_BITMAP_WRAPS_SHIFT 9 72 #define PROGRAM_BITMAP_WRAPT_SHIFT 11 73 74 #define PROGRAM_GRADIENT_TYPE_SHIFT 33 // 2 bits for gradient type 75 #define PROGRAM_MODULATE_SHIFT 35 76 77 #define PROGRAM_HAS_VERTEX_ALPHA_SHIFT 36 78 #define PROGRAM_USE_SHADOW_ALPHA_INTERP_SHIFT 37 79 80 #define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38 81 #define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39 82 83 #define PROGRAM_IS_SIMPLE_GRADIENT 40 84 85 #define PROGRAM_HAS_COLORS 41 86 87 #define PROGRAM_HAS_DEBUG_HIGHLIGHT 42 88 #define PROGRAM_HAS_ROUND_RECT_CLIP 43 89 90 #define PROGRAM_HAS_GAMMA_CORRECTION 44 91 #define PROGRAM_HAS_LINEAR_TEXTURE 45 92 93 #define PROGRAM_HAS_COLOR_SPACE_CONVERSION 46 94 #define PROGRAM_TRANSFER_FUNCTION 47 // 2 bits for transfer function 95 #define PROGRAM_HAS_TRANSLUCENT_CONVERSION 49 96 97 /////////////////////////////////////////////////////////////////////////////// 98 // Types 99 /////////////////////////////////////////////////////////////////////////////// 100 101 typedef uint64_t programid; 102 103 /////////////////////////////////////////////////////////////////////////////// 104 // Program description 105 /////////////////////////////////////////////////////////////////////////////// 106 107 /** 108 * Describe the features required for a given program. The features 109 * determine the generation of both the vertex and fragment shaders. 110 * A ProgramDescription must be used in conjunction with a ProgramCache. 111 */ 112 struct ProgramDescription { 113 enum class ColorFilterMode : int8_t { None = 0, Matrix, Blend }; 114 115 enum Gradient : int8_t { kGradientLinear = 0, kGradientCircular, kGradientSweep }; 116 ProgramDescriptionProgramDescription117 ProgramDescription() { reset(); } 118 119 // Texturing 120 bool hasTexture; 121 bool hasAlpha8Texture; 122 bool hasExternalTexture; 123 bool hasTextureTransform; 124 125 // Color attribute 126 bool hasColors; 127 128 // Modulate, this should only be set when setColor() return true 129 bool modulate; 130 131 // Shaders 132 bool hasBitmap; 133 bool isShaderBitmapExternal; 134 bool useShaderBasedWrap; 135 136 bool hasVertexAlpha; 137 bool useShadowAlphaInterp; 138 139 bool hasGradient; 140 Gradient gradientType; 141 bool isSimpleGradient; 142 143 SkBlendMode shadersMode; 144 145 bool isBitmapFirst; 146 GLenum bitmapWrapS; 147 GLenum bitmapWrapT; 148 149 // Color operations 150 ColorFilterMode colorOp; 151 SkBlendMode colorMode; 152 153 // Framebuffer blending (requires Extensions.hasFramebufferFetch()) 154 // Ignored for all values < SkBlendMode::kPlus 155 SkBlendMode framebufferMode; 156 bool swapSrcDst; 157 158 bool hasDebugHighlight; 159 bool hasRoundRectClip; 160 161 // Extra gamma correction used for text 162 bool hasGammaCorrection; 163 // Set when sampling an image in linear space 164 bool hasLinearTexture; 165 166 bool hasColorSpaceConversion; 167 TransferFunctionType transferFunction; 168 // Indicates whether the bitmap to convert between color spaces is translucent 169 bool hasTranslucentConversion; 170 171 /** 172 * Resets this description. All fields are reset back to the default 173 * values they hold after building a new instance. 174 */ resetProgramDescription175 void reset() { 176 hasTexture = false; 177 hasAlpha8Texture = false; 178 hasExternalTexture = false; 179 hasTextureTransform = false; 180 181 hasColors = false; 182 183 hasVertexAlpha = false; 184 useShadowAlphaInterp = false; 185 186 modulate = false; 187 188 hasBitmap = false; 189 isShaderBitmapExternal = false; 190 useShaderBasedWrap = false; 191 192 hasGradient = false; 193 gradientType = kGradientLinear; 194 isSimpleGradient = false; 195 196 shadersMode = SkBlendMode::kClear; 197 198 isBitmapFirst = false; 199 bitmapWrapS = GL_CLAMP_TO_EDGE; 200 bitmapWrapT = GL_CLAMP_TO_EDGE; 201 202 colorOp = ColorFilterMode::None; 203 colorMode = SkBlendMode::kClear; 204 205 framebufferMode = SkBlendMode::kClear; 206 swapSrcDst = false; 207 208 hasDebugHighlight = false; 209 hasRoundRectClip = false; 210 211 hasGammaCorrection = false; 212 hasLinearTexture = false; 213 214 hasColorSpaceConversion = false; 215 transferFunction = TransferFunctionType::None; 216 hasTranslucentConversion = false; 217 } 218 219 /** 220 * Indicates, for a given color, whether color modulation is required in 221 * the fragment shader. When this method returns true, the program should 222 * be provided with a modulation color. 223 */ setColorModulateProgramDescription224 bool setColorModulate(const float a) { 225 modulate = a < COLOR_COMPONENT_THRESHOLD; 226 return modulate; 227 } 228 229 /** 230 * Indicates, for a given color, whether color modulation is required in 231 * the fragment shader. When this method returns true, the program should 232 * be provided with a modulation color. 233 */ setAlpha8ColorModulateProgramDescription234 bool setAlpha8ColorModulate(const float r, const float g, const float b, const float a) { 235 modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD || 236 g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD; 237 return modulate; 238 } 239 240 /** 241 * Computes the unique key identifying this program. 242 */ keyProgramDescription243 programid key() const { 244 programid key = 0; 245 if (hasTexture) key |= PROGRAM_KEY_TEXTURE; 246 if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE; 247 if (hasBitmap) { 248 key |= PROGRAM_KEY_BITMAP; 249 if (useShaderBasedWrap) { 250 key |= PROGRAM_KEY_BITMAP_NPOT; 251 key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT; 252 key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT; 253 } 254 if (isShaderBitmapExternal) { 255 key |= PROGRAM_KEY_BITMAP_EXTERNAL; 256 } 257 } 258 if (hasGradient) key |= PROGRAM_KEY_GRADIENT; 259 key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT; 260 if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST; 261 if (hasBitmap && hasGradient) { 262 key |= ((int)shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT; 263 } 264 switch (colorOp) { 265 case ColorFilterMode::Matrix: 266 key |= PROGRAM_KEY_COLOR_MATRIX; 267 break; 268 case ColorFilterMode::Blend: 269 key |= PROGRAM_KEY_COLOR_BLEND; 270 key |= ((int)colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT; 271 break; 272 case ColorFilterMode::None: 273 break; 274 } 275 key |= ((int)framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT; 276 key |= programid(swapSrcDst) << PROGRAM_KEY_SWAP_SRC_DST_SHIFT; 277 key |= programid(modulate) << PROGRAM_MODULATE_SHIFT; 278 key |= programid(hasVertexAlpha) << PROGRAM_HAS_VERTEX_ALPHA_SHIFT; 279 key |= programid(useShadowAlphaInterp) << PROGRAM_USE_SHADOW_ALPHA_INTERP_SHIFT; 280 key |= programid(hasExternalTexture) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT; 281 key |= programid(hasTextureTransform) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT; 282 key |= programid(isSimpleGradient) << PROGRAM_IS_SIMPLE_GRADIENT; 283 key |= programid(hasColors) << PROGRAM_HAS_COLORS; 284 key |= programid(hasDebugHighlight) << PROGRAM_HAS_DEBUG_HIGHLIGHT; 285 key |= programid(hasRoundRectClip) << PROGRAM_HAS_ROUND_RECT_CLIP; 286 key |= programid(hasGammaCorrection) << PROGRAM_HAS_GAMMA_CORRECTION; 287 key |= programid(hasLinearTexture) << PROGRAM_HAS_LINEAR_TEXTURE; 288 key |= programid(hasColorSpaceConversion) << PROGRAM_HAS_COLOR_SPACE_CONVERSION; 289 key |= programid(transferFunction) << PROGRAM_TRANSFER_FUNCTION; 290 key |= programid(hasTranslucentConversion) << PROGRAM_HAS_TRANSLUCENT_CONVERSION; 291 return key; 292 } 293 294 /** 295 * Logs the specified message followed by the key identifying this program. 296 */ logProgramDescription297 void log(const char* message) const { 298 #if DEBUG_PROGRAMS 299 programid k = key(); 300 PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32), uint32_t(k & 0xffffffff)); 301 #endif 302 } 303 304 private: getEnumForWrapProgramDescription305 static inline uint32_t getEnumForWrap(GLenum wrap) { 306 switch (wrap) { 307 case GL_CLAMP_TO_EDGE: 308 return 0; 309 case GL_REPEAT: 310 return 1; 311 case GL_MIRRORED_REPEAT: 312 return 2; 313 } 314 return 0; 315 } 316 317 }; // struct ProgramDescription 318 319 /** 320 * A program holds a vertex and a fragment shader. It offers several utility 321 * methods to query attributes and uniforms. 322 */ 323 class Program { 324 public: 325 enum ShaderBindings { kBindingPosition, kBindingTexCoords }; 326 327 /** 328 * Creates a new program with the specified vertex and fragment 329 * shaders sources. 330 */ 331 Program(const ProgramDescription& description, const char* vertex, const char* fragment); 332 virtual ~Program(); 333 334 /** 335 * Binds this program to the GL context. 336 */ 337 virtual void use(); 338 339 /** 340 * Marks this program as unused. This will not unbind 341 * the program from the GL context. 342 */ 343 virtual void remove(); 344 345 /** 346 * Returns the OpenGL name of the specified attribute. 347 */ 348 int getAttrib(const char* name); 349 350 /** 351 * Returns the OpenGL name of the specified uniform. 352 */ 353 int getUniform(const char* name); 354 355 /** 356 * Indicates whether this program is currently in use with 357 * the GL context. 358 */ isInUse()359 inline bool isInUse() const { return mUse; } 360 361 /** 362 * Indicates whether this program was correctly compiled and linked. 363 */ isInitialized()364 inline bool isInitialized() const { return mInitialized; } 365 366 /** 367 * Binds the program with the specified projection, modelView and 368 * transform matrices. 369 */ 370 void set(const mat4& projectionMatrix, const mat4& modelViewMatrix, const mat4& transformMatrix, 371 bool offset = false); 372 373 /** 374 * Sets the color associated with this shader. 375 */ 376 void setColor(FloatColor color); 377 378 /** 379 * Name of the texCoords attribute if it exists (kBindingTexCoords), -1 otherwise. 380 */ 381 int texCoords; 382 383 /** 384 * Name of the transform uniform. 385 */ 386 int transform; 387 388 /** 389 * Name of the projection uniform. 390 */ 391 int projection; 392 393 protected: 394 /** 395 * Adds an attribute with the specified name. 396 * 397 * @return The OpenGL name of the attribute. 398 */ 399 int addAttrib(const char* name); 400 401 /** 402 * Binds the specified attribute name to the specified slot. 403 */ 404 int bindAttrib(const char* name, ShaderBindings bindingSlot); 405 406 /** 407 * Adds a uniform with the specified name. 408 * 409 * @return The OpenGL name of the uniform. 410 */ 411 int addUniform(const char* name); 412 413 private: 414 /** 415 * Compiles the specified shader of the specified type. 416 * 417 * @return The name of the compiled shader. 418 */ 419 GLuint buildShader(const char* source, GLenum type); 420 421 // Name of the OpenGL program and shaders 422 GLuint mProgramId; 423 GLuint mVertexShader; 424 GLuint mFragmentShader; 425 426 // Keeps track of attributes and uniforms slots 427 KeyedVector<const char*, int> mAttributes; 428 KeyedVector<const char*, int> mUniforms; 429 430 bool mUse; 431 bool mInitialized; 432 433 // Uniforms caching 434 bool mHasColorUniform; 435 int mColorUniform; 436 437 bool mHasSampler; 438 439 mat4 mProjection; 440 bool mOffset; 441 }; // class Program 442 443 }; // namespace uirenderer 444 }; // namespace android 445 446 #endif // ANDROID_HWUI_PROGRAM_H 447