Home | History | Annotate | Download | only in hwui
      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 {
    114         None = 0,
    115         Matrix,
    116         Blend
    117     };
    118 
    119     enum Gradient : int8_t {
    120         kGradientLinear = 0,
    121         kGradientCircular,
    122         kGradientSweep
    123     };
    124 
    125     ProgramDescription() {
    126         reset();
    127     }
    128 
    129     // Texturing
    130     bool hasTexture;
    131     bool hasAlpha8Texture;
    132     bool hasExternalTexture;
    133     bool hasTextureTransform;
    134 
    135     // Color attribute
    136     bool hasColors;
    137 
    138     // Modulate, this should only be set when setColor() return true
    139     bool modulate;
    140 
    141     // Shaders
    142     bool hasBitmap;
    143     bool isShaderBitmapExternal;
    144     bool useShaderBasedWrap;
    145 
    146     bool hasVertexAlpha;
    147     bool useShadowAlphaInterp;
    148 
    149     bool hasGradient;
    150     Gradient gradientType;
    151     bool isSimpleGradient;
    152 
    153     SkBlendMode shadersMode;
    154 
    155     bool isBitmapFirst;
    156     GLenum bitmapWrapS;
    157     GLenum bitmapWrapT;
    158 
    159     // Color operations
    160     ColorFilterMode colorOp;
    161     SkBlendMode colorMode;
    162 
    163     // Framebuffer blending (requires Extensions.hasFramebufferFetch())
    164     // Ignored for all values < SkBlendMode::kPlus
    165     SkBlendMode framebufferMode;
    166     bool swapSrcDst;
    167 
    168     bool hasDebugHighlight;
    169     bool hasRoundRectClip;
    170 
    171     // Extra gamma correction used for text
    172     bool hasGammaCorrection;
    173     // Set when sampling an image in linear space
    174     bool hasLinearTexture;
    175 
    176     bool hasColorSpaceConversion;
    177     TransferFunctionType transferFunction;
    178     // Indicates whether the bitmap to convert between color spaces is translucent
    179     bool hasTranslucentConversion;
    180 
    181     /**
    182      * Resets this description. All fields are reset back to the default
    183      * values they hold after building a new instance.
    184      */
    185     void reset() {
    186         hasTexture = false;
    187         hasAlpha8Texture = false;
    188         hasExternalTexture = false;
    189         hasTextureTransform = false;
    190 
    191         hasColors = false;
    192 
    193         hasVertexAlpha = false;
    194         useShadowAlphaInterp = false;
    195 
    196         modulate = false;
    197 
    198         hasBitmap = false;
    199         isShaderBitmapExternal = false;
    200         useShaderBasedWrap = false;
    201 
    202         hasGradient = false;
    203         gradientType = kGradientLinear;
    204         isSimpleGradient = false;
    205 
    206         shadersMode = SkBlendMode::kClear;
    207 
    208         isBitmapFirst = false;
    209         bitmapWrapS = GL_CLAMP_TO_EDGE;
    210         bitmapWrapT = GL_CLAMP_TO_EDGE;
    211 
    212         colorOp = ColorFilterMode::None;
    213         colorMode = SkBlendMode::kClear;
    214 
    215         framebufferMode = SkBlendMode::kClear;
    216         swapSrcDst = false;
    217 
    218         hasDebugHighlight = false;
    219         hasRoundRectClip = false;
    220 
    221         hasGammaCorrection = false;
    222         hasLinearTexture = false;
    223 
    224         hasColorSpaceConversion = false;
    225         transferFunction = TransferFunctionType::None;
    226         hasTranslucentConversion = false;
    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      */
    234     bool setColorModulate(const float a) {
    235         modulate = a < COLOR_COMPONENT_THRESHOLD;
    236         return modulate;
    237     }
    238 
    239     /**
    240      * Indicates, for a given color, whether color modulation is required in
    241      * the fragment shader. When this method returns true, the program should
    242      * be provided with a modulation color.
    243      */
    244     bool setAlpha8ColorModulate(const float r, const float g, const float b, const float a) {
    245         modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD ||
    246                 g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD;
    247         return modulate;
    248     }
    249 
    250     /**
    251      * Computes the unique key identifying this program.
    252      */
    253     programid key() const {
    254         programid key = 0;
    255         if (hasTexture) key |= PROGRAM_KEY_TEXTURE;
    256         if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
    257         if (hasBitmap) {
    258             key |= PROGRAM_KEY_BITMAP;
    259             if (useShaderBasedWrap) {
    260                 key |= PROGRAM_KEY_BITMAP_NPOT;
    261                 key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
    262                 key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
    263             }
    264             if (isShaderBitmapExternal) {
    265                 key |= PROGRAM_KEY_BITMAP_EXTERNAL;
    266             }
    267         }
    268         if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
    269         key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
    270         if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
    271         if (hasBitmap && hasGradient) {
    272             key |= ((int)shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
    273         }
    274         switch (colorOp) {
    275             case ColorFilterMode::Matrix:
    276                 key |= PROGRAM_KEY_COLOR_MATRIX;
    277                 break;
    278             case ColorFilterMode::Blend:
    279                 key |= PROGRAM_KEY_COLOR_BLEND;
    280                 key |= ((int) colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
    281                 break;
    282             case ColorFilterMode::None:
    283                 break;
    284         }
    285         key |= ((int) framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
    286         key |= programid(swapSrcDst) << PROGRAM_KEY_SWAP_SRC_DST_SHIFT;
    287         key |= programid(modulate) << PROGRAM_MODULATE_SHIFT;
    288         key |= programid(hasVertexAlpha) << PROGRAM_HAS_VERTEX_ALPHA_SHIFT;
    289         key |= programid(useShadowAlphaInterp) << PROGRAM_USE_SHADOW_ALPHA_INTERP_SHIFT;
    290         key |= programid(hasExternalTexture) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
    291         key |= programid(hasTextureTransform) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
    292         key |= programid(isSimpleGradient) << PROGRAM_IS_SIMPLE_GRADIENT;
    293         key |= programid(hasColors) << PROGRAM_HAS_COLORS;
    294         key |= programid(hasDebugHighlight) << PROGRAM_HAS_DEBUG_HIGHLIGHT;
    295         key |= programid(hasRoundRectClip) << PROGRAM_HAS_ROUND_RECT_CLIP;
    296         key |= programid(hasGammaCorrection) << PROGRAM_HAS_GAMMA_CORRECTION;
    297         key |= programid(hasLinearTexture) << PROGRAM_HAS_LINEAR_TEXTURE;
    298         key |= programid(hasColorSpaceConversion) << PROGRAM_HAS_COLOR_SPACE_CONVERSION;
    299         key |= programid(transferFunction) << PROGRAM_TRANSFER_FUNCTION;
    300         key |= programid(hasTranslucentConversion) << PROGRAM_HAS_TRANSLUCENT_CONVERSION;
    301         return key;
    302     }
    303 
    304     /**
    305      * Logs the specified message followed by the key identifying this program.
    306      */
    307     void log(const char* message) const {
    308 #if DEBUG_PROGRAMS
    309         programid k = key();
    310         PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
    311                 uint32_t(k & 0xffffffff));
    312 #endif
    313     }
    314 
    315 private:
    316     static inline uint32_t getEnumForWrap(GLenum wrap) {
    317         switch (wrap) {
    318             case GL_CLAMP_TO_EDGE:
    319                 return 0;
    320             case GL_REPEAT:
    321                 return 1;
    322             case GL_MIRRORED_REPEAT:
    323                 return 2;
    324         }
    325         return 0;
    326     }
    327 
    328 }; // struct ProgramDescription
    329 
    330 /**
    331  * A program holds a vertex and a fragment shader. It offers several utility
    332  * methods to query attributes and uniforms.
    333  */
    334 class Program {
    335 public:
    336     enum ShaderBindings {
    337         kBindingPosition,
    338         kBindingTexCoords
    339     };
    340 
    341     /**
    342      * Creates a new program with the specified vertex and fragment
    343      * shaders sources.
    344      */
    345     Program(const ProgramDescription& description, const char* vertex, const char* fragment);
    346     virtual ~Program();
    347 
    348     /**
    349      * Binds this program to the GL context.
    350      */
    351     virtual void use();
    352 
    353     /**
    354      * Marks this program as unused. This will not unbind
    355      * the program from the GL context.
    356      */
    357     virtual void remove();
    358 
    359     /**
    360      * Returns the OpenGL name of the specified attribute.
    361      */
    362     int getAttrib(const char* name);
    363 
    364     /**
    365      * Returns the OpenGL name of the specified uniform.
    366      */
    367     int getUniform(const char* name);
    368 
    369     /**
    370      * Indicates whether this program is currently in use with
    371      * the GL context.
    372      */
    373     inline bool isInUse() const {
    374         return mUse;
    375     }
    376 
    377     /**
    378      * Indicates whether this program was correctly compiled and linked.
    379      */
    380     inline bool isInitialized() const {
    381         return mInitialized;
    382     }
    383 
    384     /**
    385      * Binds the program with the specified projection, modelView and
    386      * transform matrices.
    387      */
    388     void set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
    389              const mat4& transformMatrix, bool offset = false);
    390 
    391     /**
    392      * Sets the color associated with this shader.
    393      */
    394     void setColor(FloatColor color);
    395 
    396     /**
    397      * Name of the texCoords attribute if it exists (kBindingTexCoords), -1 otherwise.
    398      */
    399     int texCoords;
    400 
    401     /**
    402      * Name of the transform uniform.
    403      */
    404     int transform;
    405 
    406     /**
    407      * Name of the projection uniform.
    408      */
    409     int projection;
    410 
    411 protected:
    412     /**
    413      * Adds an attribute with the specified name.
    414      *
    415      * @return The OpenGL name of the attribute.
    416      */
    417     int addAttrib(const char* name);
    418 
    419     /**
    420      * Binds the specified attribute name to the specified slot.
    421      */
    422     int bindAttrib(const char* name, ShaderBindings bindingSlot);
    423 
    424     /**
    425      * Adds a uniform with the specified name.
    426      *
    427      * @return The OpenGL name of the uniform.
    428      */
    429     int addUniform(const char* name);
    430 
    431 private:
    432     /**
    433      * Compiles the specified shader of the specified type.
    434      *
    435      * @return The name of the compiled shader.
    436      */
    437     GLuint buildShader(const char* source, GLenum type);
    438 
    439     // Name of the OpenGL program and shaders
    440     GLuint mProgramId;
    441     GLuint mVertexShader;
    442     GLuint mFragmentShader;
    443 
    444     // Keeps track of attributes and uniforms slots
    445     KeyedVector<const char*, int> mAttributes;
    446     KeyedVector<const char*, int> mUniforms;
    447 
    448     bool mUse;
    449     bool mInitialized;
    450 
    451     // Uniforms caching
    452     bool mHasColorUniform;
    453     int mColorUniform;
    454 
    455     bool mHasSampler;
    456 
    457     mat4 mProjection;
    458     bool mOffset;
    459 }; // class Program
    460 
    461 }; // namespace uirenderer
    462 }; // namespace android
    463 
    464 #endif // ANDROID_HWUI_PROGRAM_H
    465