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