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