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