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