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 { None = 0, Matrix, Blend };
    114 
    115     enum Gradient : int8_t { kGradientLinear = 0, kGradientCircular, kGradientSweep };
    116 
    117     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      */
    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         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      */
    224     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      */
    234     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      */
    243     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      */
    297     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:
    305     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      */
    359     inline bool isInUse() const { return mUse; }
    360 
    361     /**
    362      * Indicates whether this program was correctly compiled and linked.
    363      */
    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