Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2011 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_FILTERFW_CORE_SHADER_PROGRAM_H
     18 #define ANDROID_FILTERFW_CORE_SHADER_PROGRAM_H
     19 
     20 #include <vector>
     21 #include <map>
     22 #include <string>
     23 
     24 #include <GLES2/gl2.h>
     25 #include <GLES2/gl2ext.h>
     26 #include <EGL/egl.h>
     27 
     28 #include "core/gl_env.h"
     29 #include "core/value.h"
     30 
     31 namespace android {
     32 namespace filterfw {
     33 
     34 class GLFrame;
     35 class GLFrameBufferHandle;
     36 class GLTextureHandle;
     37 class Quad;
     38 class VertexFrame;
     39 
     40 typedef GLint ProgramVar;
     41 
     42 // A ShaderProgram is a Program object that holds a GLSL shader implementation.
     43 // It provides functionality for compiling, linking, and executing the shader.
     44 // On top of that, it provides access to the shaders source code, uniforms,
     45 // attributes, and other properties.
     46 // By default a ShaderProgram provides its own vertex shader. However, a custom
     47 // vertex shader may be passed and used instead.
     48 // When implementing a vertex shader, the following attribute names have special
     49 // meaning:
     50 //
     51 //  - a_position: The vertex position
     52 //  - a_texcoord: The texture cooridnates
     53 //
     54 // The shader program will bind these attributes to the correct values, if they
     55 // are present in the vertex shader source code.
     56 //
     57 // When implementing the fragment shader, the following variable names must be
     58 // defined:
     59 //
     60 //  - tex_sampler_<n>: The n'th input texture. For instance, use tex_sampler_0
     61 //                     for the first input texture. Must be a uniform sampler2D.
     62 //  - v_texcoord: The current texture coordinate.
     63 //
     64 // If more input textures are given than the shader can handle, this will result
     65 // in an error.
     66 //
     67 class ShaderProgram {
     68   public:
     69     // General Functionality ///////////////////////////////////////////////////
     70     // Create a new shader program with the given fragment shader source code.
     71     // A default vertex shader is used, which renders the input texture to a
     72     // rectangular region of the output texture. You can modify the input and
     73     // output regions by using the SetSourceRegion(...) and SetTargetRegion(...)
     74     // (and related) functions below.
     75     // This program will not be executable until you have compiled and linked
     76     // it.
     77     // Note, that the ShaderProgram does NOT take ownership of the GLEnv. The
     78     // caller must make sure the GLEnv stays valid as long as the GLFrame is
     79     // alive.
     80     explicit ShaderProgram(GLEnv* gl_env, const std::string& fragment_shader);
     81 
     82     // Create a new shader program with the given fragment and vertex shader
     83     // source code. This program will not be executable until you have compiled
     84     // and linked it.
     85     // Note, that the ShaderProgram does NOT take ownership of the GLEnv. The
     86     // caller must make sure the GLEnv stays valid as long as the GLFrame is
     87     // alive.
     88     ShaderProgram(GLEnv* gl_env,
     89                   const std::string& vertex_shader,
     90                   const std::string& fragment_shader);
     91 
     92     // Destructor.
     93     ~ShaderProgram();
     94 
     95     // Process the given input frames and write the result to the output frame.
     96     // Returns false if there was an error processing.
     97     bool Process(const std::vector<const GLFrame*>& inputs, GLFrame* output);
     98 
     99     // Same as above, but pass GL interfaces rather than frame objects. Use this
    100     // only if you are not working on Frame objects, but rather directly on GL
    101     // textures and FBOs.
    102     bool Process(const std::vector<const GLTextureHandle*>& input,
    103                  GLFrameBufferHandle* output);
    104 
    105     // Compile and link the shader source code. Returns true if compilation
    106     // and linkage was successful. Compilation and linking error messages are
    107     // written to the error log.
    108     bool CompileAndLink();
    109 
    110     // Returns true if this Program has been compiled and linked successfully.
    111     bool IsExecutable() const {
    112       return program_ != 0;
    113     }
    114 
    115     // Returns true if the shader program variable is valid.
    116     static bool IsVarValid(ProgramVar var);
    117 
    118     // Special ShaderPrograms //////////////////////////////////////////////////
    119     // A (compiled) shader program which assigns the sampled pixels from the
    120     // input to the output. Note that transformations may be applied to achieve
    121     // effects such as cropping, scaling or rotation.
    122     // The caller takes ownership of the result!
    123     static ShaderProgram* CreateIdentity(GLEnv* env);
    124 
    125     // Geometry ////////////////////////////////////////////////////////////////
    126     // These functions modify the source and target regions used during
    127     // rasterization. Note, that these functions will ONLY take effect if
    128     // the default vertex shader is used, or your custom vertex shader defines
    129     // the a_position and a_texcoord attributes.
    130 
    131     // Set the program to read from a subregion of the input frame, given by
    132     // the origin (x, y) and dimensions (width, height). Values are considered
    133     // normalized between 0.0 and 1.0. If this region exceeds the input frame
    134     // dimensions the results are undefined.
    135     void SetSourceRect(float x, float y, float width, float height) ;
    136 
    137     // Set the program to read from a subregion of the input frame, given by
    138     // the passed Quad. Values are considered normalized between 0.0 and 1.0.
    139     // The Quad points are expected to be in the order top-left, top-right,
    140     // bottom-left, bottom-right.
    141     // If this region exceeds the input frame dimensions the results are
    142     // undefined.
    143     void SetSourceRegion(const Quad& quad);
    144 
    145     // Set the program to write to a subregion of the output frame, given by
    146     // the origin (x, y) and dimensions (width, height). Values are considered
    147     // normalized between 0.0 and 1.0. If this region exceeds the output frame
    148     // dimensions the image will be clipped.
    149     void SetTargetRect(float x, float y, float width, float height);
    150 
    151     // Set the program to write to a subregion of the output frame, given by
    152     // the passed Quad. Values are considered normalized between 0.0 and 1.0.
    153     // The Quad points are expected to be in the order top-left, top-right,
    154     // bottom-left, bottom-right.
    155     // If this region exceeds the output frame dimensions the image will be
    156     // clipped.
    157     void SetTargetRegion(const Quad& quad);
    158 
    159     // Uniform Variable access /////////////////////////////////////////////////
    160     // Note: In order to get and set uniforms, the program must have been
    161     // successfully compiled and linked. Otherwise, the getters will return an
    162     // invalid ProgramVar variable (check with IsVarValid()).
    163     // When setting values, the value type must be match the type of the uniform
    164     // in the shader. For instance, a vector of 3 elements cannot be assigned to
    165     // a vec2. Similarly, an integer value cannot be assigned to a float value.
    166     // Such a type mismatch will result in failure to set the value (which will
    167     // remain untouched). Check the return value of the setters to determine
    168     // success.
    169 
    170     // Returns the maximum number of uniforms supported by this implementation.
    171     static int MaxUniformCount();
    172 
    173     // Returns a handle to the uniform with the given name, or invalid if no
    174     // such uniform variable exists in the shader.
    175     ProgramVar GetUniform(const std::string& name) const;
    176 
    177     // Set the specified uniform value to the given integer value. Returns true
    178     // if the assignment was successful.
    179     bool SetUniformValue(ProgramVar var, int value);
    180 
    181     // Set the specified uniform value to the given float value. Returns true
    182     // if the assignment was successful.
    183     bool SetUniformValue(ProgramVar var, float value);
    184 
    185     // Set the specified uniform value to the given values. Returns true
    186     // if the assignment was successful.
    187     bool SetUniformValue(ProgramVar var, const int* values, int count);
    188 
    189     // Set the specified uniform value to the given values. Returns true
    190     // if the assignment was successful.
    191     bool SetUniformValue(ProgramVar var, const float* values, int count);
    192 
    193     // Set the specified uniform value to the given vector value. Returns true
    194     // if the assignment was successful.
    195     bool SetUniformValue(ProgramVar var, const std::vector<int>& values);
    196 
    197     // Set the specified uniform value to the given vector value. Returns true
    198     // if the assignment was successful.
    199     bool SetUniformValue(ProgramVar var, const std::vector<float>& values);
    200 
    201     // Generic variable setter, which in the case of GL programs always attempts
    202     // to set the value of a uniform variable with the given name. Only values
    203     // of type float, float array (or vector), and int are supported.
    204     bool SetUniformValue(const std::string& name, const Value& value);
    205 
    206     // Generic variable getter, which in the case of GL programs always attempts
    207     // to get the value of a uniform variable with the given name.
    208     Value GetUniformValue(const std::string& name);
    209 
    210     // Returns the default name of the input texture uniform variable for the
    211     // given input index.
    212     static std::string InputTextureUniformName(int index);
    213 
    214     // Attribute access ////////////////////////////////////////////////////////
    215     // Note: In order to get and set attributes, the program must have been
    216     // successfully compiled and linked. Otherwise, the getters will return an
    217     // invalid ProgramVar variable (check with IsVarValid()). Constant attribute
    218     // values must be floats. Attribute pointers must be associated with a
    219     // specific type, which can be any of the following:
    220     //   GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT,
    221     //   GL_FIXED, GL_HALF_FLOAT_OES.
    222     // When storing vertex data, it is recommended to use VertexFrames when
    223     // possible as these will be kept in GPU memory, and no copying of vertex
    224     // attributes between system and GPU memory needs to take place.
    225 
    226     // Returns the maximum number of attributes supported by this
    227     // implementation.
    228     static int MaxAttributeCount();
    229 
    230     // Returns a handle to the attribute with the given name, or invalid if no
    231     // such attribute exists in the vertex shader.
    232     ProgramVar GetAttribute(const std::string& name) const;
    233 
    234     // Set an attribute value that will be constant for each vertex. Returns
    235     // true if the assignment was successful.
    236     bool SetConstAttributeValue(ProgramVar var, float value);
    237 
    238     // Set an attribute vector value that will be constant for each vertex.
    239     // Returns true if the assignment was successful.
    240     bool SetConstAttributeValue(ProgramVar var, const std::vector<float>& value);
    241 
    242     // Set attribute values that differ across vertexes, using a VertexFrame.
    243     // This is the recommended method of specifying vertex data, that does not
    244     // change from iteration to iteration. The parameters are as follows:
    245     //   var: The shader variable to bind the values to.
    246     //   data: The vertex frame which holds the vertex data. This may be a
    247     //         superset of the data required for this particular vertex. Use the
    248     //         offset and stride to select the correct data portion.
    249     //   type: The type of the data values. This may differ from the type of the
    250     //         shader variables. See the normalize flag on how values are
    251     //         converted.
    252     //   components: The number of components per value. Valid values are 1-4.
    253     //   stride: The delta of one element to the next in bytes.
    254     //   offset: The offset of the first element.
    255     //   normalize: True, if not float values should be normalized to the range
    256     //              0-1, when converted to a float.
    257     // Returns true, if the assignment was successful.
    258     bool SetAttributeValues(ProgramVar var,
    259                             const VertexFrame* data,
    260                             GLenum type,
    261                             int components,
    262                             int stride,
    263                             int offset,
    264                             bool normalize);
    265 
    266     // Set attribute values that differ across vertexes, using a data buffer.
    267     // This is the recommended method of specifying vertex data, if your data
    268     // changes often. Note that this data may need to be copied to GPU memory
    269     // for each render pass. Please see above for a description of the
    270     // parameters.
    271     // Note: The data passed here MUST be valid until all executions of this
    272     // Program instance have been completed!
    273     bool SetAttributeValues(ProgramVar var,
    274                             const uint8_t* data,
    275                             GLenum type,
    276                             int components,
    277                             int stride,
    278                             int offset,
    279                             bool normalize);
    280 
    281     // Convenience method for setting vertex values using a vector of floats.
    282     // The components parameter specifies how many elements per variable should
    283     // be assigned (The variable must be able to fit the number of components).
    284     // It must be a value between 1 and 4.
    285     // While this method is not as flexible as the methods above, this can be
    286     // used when more advanced methods are not necessary. Note, that if your
    287     // vertex data does not change, it is recommended to use a VertexFrame.
    288     bool SetAttributeValues(ProgramVar var,
    289                             const std::vector<float>& data,
    290                             int components);
    291 
    292     // Same as above, but using a float pointer instead of vector. Pass the
    293     // total number of elements in total.
    294     bool SetAttributeValues(ProgramVar var,
    295                             const float* data,
    296                             int total,
    297                             int components);
    298 
    299     // By default, rendering only uses the first 4 vertices. You should only
    300     // adjust this value if you are providing your own vertex attributes with
    301     // a count unequal to 4. Adjust this value before calling Process().
    302     void SetVertexCount(int count);
    303 
    304     // Returns the default name of the attribute used to hold the texture
    305     // coordinates. Use this when you need to access the texture coordinate
    306     // attribute of the shader's default vertex shader.
    307     static const std::string& TexCoordAttributeName() {
    308       static std::string s_texcoord("a_texcoord");
    309       return s_texcoord;
    310     }
    311 
    312     // Returns the default name of the attribute used to hold the output
    313     // coordinates. Use this when you need to access the output coordinate
    314     // attribute of the shader's default vertex shader.
    315     static const std::string& PositionAttributeName() {
    316       static std::string s_position("a_position");
    317       return s_position;
    318     }
    319 
    320     // Rendering ///////////////////////////////////////////////////////////////
    321     // Set the draw mode, which can be any of GL_POINTS, GL_LINES,
    322     // GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES, GL_TRIANGLE_STRIP,
    323     // GL_TRIANGLE_FAN. The default is GL_TRIANGLE_STRIP.
    324     // Warning: Do NOT change this if you are not specifying your own vertex
    325     // data with SetAttributeValues(...).
    326     void SetDrawMode(GLenum mode);
    327 
    328     // If you are doing your own drawing you should call this before beginning
    329     // to draw. This will activate the program, push all used attributes, and
    330     // clear the frame if requested. You do not need to call this if you are
    331     // not doing your own GL drawing!
    332     bool BeginDraw();
    333 
    334     // Render a single frame with the given input textures. You may override
    335     // this, if you need custom rendering behavior. However, you must take
    336     // care of the following things when overriding:
    337     //   - Use the correct program (e.g. by calling UseProgram()).
    338     //   - Bind the given textures
    339     //   - Bind vertex attributes
    340     //   - Draw
    341     bool RenderFrame(const std::vector<GLuint>& textures,
    342                      const std::vector<GLenum>& targets);
    343 
    344     // Pass true to clear the output frame before rendering. The color used
    345     // to clear is set in SetClearColor().
    346     void SetClearsOutput(bool clears);
    347 
    348     // Set the color used to clear the output frame before rendering. You
    349     // must activate clearing by calling SetClearsOutput(true).
    350     void SetClearColor(float red, float green, float blue, float alpha);
    351 
    352     // Set the number of tiles to split rendering into. Higher tile numbers
    353     // will affect performance negatively, but will allow other GPU threads
    354     // to render more frequently. Defaults to 1, 1.
    355     void SetTileCounts(int x_count, int y_count);
    356 
    357     // Enable or Disable Blending
    358     // Set to true to enable, false to disable.
    359     void SetBlendEnabled(bool enable) {
    360       blending_ = enable;
    361     }
    362 
    363     // Specify pixel arithmetic for blending
    364     // The values of sfactor and dfactor can be:
    365     //  GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA,
    366     //  GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA,
    367     //  GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA_SATURATE
    368     // Default values for blending are set to:
    369     //  sfactor = GL_SRC_ALPHA
    370     //  dfactor = GL_ONE_MINUS_SRC_ALPHA
    371     void SetBlendFunc(int sfactor, int dfactor) {
    372       sfactor_ = sfactor;
    373       dfactor_ = dfactor;
    374     }
    375 
    376     // Accessing the Compiled Program //////////////////////////////////////////
    377     // Use the compiled and linked program for rendering. You should not need
    378     // to call this, unless you are implementing your own rendering method.
    379     bool UseProgram();
    380 
    381     // Other Properties ////////////////////////////////////////////////////////
    382     // Returns the maximum number of varyings supported by this implementation.
    383     static int MaxVaryingCount();
    384 
    385     // Returns the maximum number of texture units supported by this
    386     // implementation.
    387     static int MaxTextureUnits();
    388 
    389     // Lower level functionality ///////////////////////////////////////////////
    390     // Compile the shader with the given source. The shader_type must be either
    391     // GL_VERTEX_SHADER or GL_FRAGMENT_SHADER.
    392     static GLuint CompileShader(GLenum shader_type, const char* source);
    393 
    394     // Link the compiled shader objects and return the resulting program.
    395     static GLuint LinkProgram(GLuint* shaders, GLuint count);
    396 
    397     // Returns the lowest texture unit that will be used to bind textures.
    398     GLuint BaseTextureUnit() const {
    399       return base_texture_unit_;
    400     }
    401 
    402     // Sets the lowest texture unit that will be used to bind textures. The
    403     // default value is GL_TEXTURE0.
    404     void SetBaseTextureUnit(GLuint texture_unit) {
    405       base_texture_unit_ = texture_unit;
    406     }
    407 
    408   private:
    409     // Structure to store vertex attribute data.
    410     struct VertexAttrib {
    411       bool          is_const;
    412       int           index;
    413       bool          normalized;
    414       int           stride;
    415       int           components;
    416       int           offset;
    417       GLenum        type;
    418       GLuint        vbo;
    419       const void*   values;
    420       float*        owned_data;
    421 
    422       VertexAttrib();
    423     };
    424     typedef std::map<ProgramVar, VertexAttrib> VertexAttribMap;
    425 
    426     struct RGBAColor {
    427       float red;
    428       float green;
    429       float blue;
    430       float alpha;
    431 
    432       RGBAColor() : red(0), green(0), blue(0), alpha(1) {
    433       }
    434     };
    435 
    436     // Scans for all uniforms in the shader and creates index -> id map.
    437     void ScanUniforms();
    438 
    439     // Returns the index of the given uniform. The caller must make sure
    440     // that the variable id passed is valid.
    441     GLuint IndexOfUniform(ProgramVar var);
    442 
    443     // Binds the given input textures.
    444     bool BindInputTextures(const std::vector<GLuint>& textures,
    445                            const std::vector<GLenum>& targets);
    446 
    447     // Sets the default source and target coordinates.
    448     void SetDefaultCoords();
    449 
    450     // Pushes the specified coordinates to the shader attribute.
    451     bool PushCoords(ProgramVar attr, float* coords);
    452 
    453     // Pushes the source coordinates.
    454     bool PushSourceCoords(float* coords);
    455 
    456     // Pushes the target coordinates.
    457     bool PushTargetCoords(float* coords);
    458 
    459     // Performs (simple) GL drawing.
    460     bool Draw();
    461 
    462     // Performs tiled GL drawing.
    463     bool DrawTiled();
    464 
    465     // Yields to other GPU threads.
    466     void Yield();
    467 
    468     // Helper method to assert that the variable value passed has the correct
    469     // total size.
    470     static bool CheckValueCount(const std::string& var_type,
    471                                 const std::string& var_name,
    472                                 int expected_count,
    473                                 int components,
    474                                 int value_size);
    475 
    476     // Helper method to assert that the variable value passed has a size, that
    477     // is compatible with the type size (must be divisible).
    478     static bool CheckValueMult(const std::string& var_type,
    479                                const std::string& var_name,
    480                                int components,
    481                                int value_size);
    482 
    483     // Checks that the variable is valid. Logs an error and returns false if
    484     // not.
    485     static bool CheckVarValid(ProgramVar var);
    486 
    487     // Returns true if the uniform specified by var is an active uniform in the
    488     // program.
    489     bool CheckUniformValid(ProgramVar var);
    490 
    491     // Store an attribute to use when rendering.
    492     bool StoreAttribute(VertexAttrib attrib);
    493 
    494     // Push all assigned attributes before rendering.
    495     bool PushAttributes();
    496 
    497     // Pop all assigned attributes after rendering.
    498     bool PopAttributes();
    499 
    500     // The shader source code
    501     std::string fragment_shader_source_;
    502     std::string vertex_shader_source_;
    503 
    504     // The compiled shaders and linked program
    505     GLuint fragment_shader_;
    506     GLuint vertex_shader_;
    507     GLuint program_;
    508 
    509     // The GL environment this shader lives in.
    510     GLEnv* gl_env_;
    511 
    512     // The lowest texture unit this program will use
    513     GLuint base_texture_unit_;
    514 
    515     // The current source and target coordinates to render from/to.
    516     float* source_coords_;
    517     float* target_coords_;
    518 
    519     // True, if the program has control over both source and target coordinates.
    520     bool manage_coordinates_;
    521 
    522     // The number of tiles to split rendering into.
    523     int tile_x_count_;
    524     int tile_y_count_;
    525 
    526     // List of attribute data that we need to set before rendering
    527     VertexAttribMap attrib_values_;
    528 
    529     // The number of vertices to render
    530     int vertex_count_;
    531 
    532     // The draw mode used during rendering
    533     GLenum draw_mode_;
    534 
    535     // True, iff the output frame is cleared before rendering
    536     bool clears_;
    537 
    538     // The color used to clear the output frame.
    539     RGBAColor clear_color_;
    540 
    541     // Set to true to enable blending.
    542     bool blending_;
    543     int sfactor_;
    544     int dfactor_;
    545 
    546     // Map from uniform ids to indices
    547     std::map<ProgramVar, GLuint> uniform_indices_;
    548 };
    549 
    550 } // namespace filterfw
    551 } // namespace android
    552 
    553 #endif  // ANDROID_FILTERFW_CORE_SHADER_PROGRAM_H
    554