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