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