| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef ANDROID_FILTERFW_CORE_SHADER_PROGRAM_H |
| #define ANDROID_FILTERFW_CORE_SHADER_PROGRAM_H |
| |
| #include <vector> |
| #include <map> |
| #include <string> |
| |
| #include <GLES2/gl2.h> |
| #include <GLES2/gl2ext.h> |
| #include <EGL/egl.h> |
| |
| #include "core/gl_env.h" |
| #include "core/value.h" |
| |
| namespace android { |
| namespace filterfw { |
| |
| class GLFrame; |
| class GLFrameBufferHandle; |
| class GLTextureHandle; |
| class Quad; |
| class VertexFrame; |
| |
| typedef GLint ProgramVar; |
| |
| // A ShaderProgram is a Program object that holds a GLSL shader implementation. |
| // It provides functionality for compiling, linking, and executing the shader. |
| // On top of that, it provides access to the shaders source code, uniforms, |
| // attributes, and other properties. |
| // By default a ShaderProgram provides its own vertex shader. However, a custom |
| // vertex shader may be passed and used instead. |
| // When implementing a vertex shader, the following attribute names have special |
| // meaning: |
| // |
| // - a_position: The vertex position |
| // - a_texcoord: The texture cooridnates |
| // |
| // The shader program will bind these attributes to the correct values, if they |
| // are present in the vertex shader source code. |
| // |
| // When implementing the fragment shader, the following variable names must be |
| // defined: |
| // |
| // - tex_sampler_<n>: The n'th input texture. For instance, use tex_sampler_0 |
| // for the first input texture. Must be a uniform sampler2D. |
| // - v_texcoord: The current texture coordinate. |
| // |
| // If more input textures are given than the shader can handle, this will result |
| // in an error. |
| // |
| class ShaderProgram { |
| public: |
| // General Functionality /////////////////////////////////////////////////// |
| // Create a new shader program with the given fragment shader source code. |
| // A default vertex shader is used, which renders the input texture to a |
| // rectangular region of the output texture. You can modify the input and |
| // output regions by using the SetSourceRegion(...) and SetTargetRegion(...) |
| // (and related) functions below. |
| // This program will not be executable until you have compiled and linked |
| // it. |
| // Note, that the ShaderProgram does NOT take ownership of the GLEnv. The |
| // caller must make sure the GLEnv stays valid as long as the GLFrame is |
| // alive. |
| explicit ShaderProgram(GLEnv* gl_env, const std::string& fragment_shader); |
| |
| // Create a new shader program with the given fragment and vertex shader |
| // source code. This program will not be executable until you have compiled |
| // and linked it. |
| // Note, that the ShaderProgram does NOT take ownership of the GLEnv. The |
| // caller must make sure the GLEnv stays valid as long as the GLFrame is |
| // alive. |
| ShaderProgram(GLEnv* gl_env, |
| const std::string& vertex_shader, |
| const std::string& fragment_shader); |
| |
| // Destructor. |
| ~ShaderProgram(); |
| |
| // Process the given input frames and write the result to the output frame. |
| // Returns false if there was an error processing. |
| bool Process(const std::vector<const GLFrame*>& inputs, GLFrame* output); |
| |
| // Same as above, but pass GL interfaces rather than frame objects. Use this |
| // only if you are not working on Frame objects, but rather directly on GL |
| // textures and FBOs. |
| bool Process(const std::vector<const GLTextureHandle*>& input, |
| GLFrameBufferHandle* output); |
| |
| // Compile and link the shader source code. Returns true if compilation |
| // and linkage was successful. Compilation and linking error messages are |
| // written to the error log. |
| bool CompileAndLink(); |
| |
| // Returns true if this Program has been compiled and linked successfully. |
| bool IsExecutable() const { |
| return program_ != 0; |
| } |
| |
| // Returns true if the shader program variable is valid. |
| static bool IsVarValid(ProgramVar var); |
| |
| // Special ShaderPrograms ////////////////////////////////////////////////// |
| // A (compiled) shader program which assigns the sampled pixels from the |
| // input to the output. Note that transformations may be applied to achieve |
| // effects such as cropping, scaling or rotation. |
| // The caller takes ownership of the result! |
| static ShaderProgram* CreateIdentity(GLEnv* env); |
| |
| // Geometry //////////////////////////////////////////////////////////////// |
| // These functions modify the source and target regions used during |
| // rasterization. Note, that these functions will ONLY take effect if |
| // the default vertex shader is used, or your custom vertex shader defines |
| // the a_position and a_texcoord attributes. |
| |
| // Set the program to read from a subregion of the input frame, given by |
| // the origin (x, y) and dimensions (width, height). Values are considered |
| // normalized between 0.0 and 1.0. If this region exceeds the input frame |
| // dimensions the results are undefined. |
| void SetSourceRect(float x, float y, float width, float height) ; |
| |
| // Set the program to read from a subregion of the input frame, given by |
| // the passed Quad. Values are considered normalized between 0.0 and 1.0. |
| // The Quad points are expected to be in the order top-left, top-right, |
| // bottom-left, bottom-right. |
| // If this region exceeds the input frame dimensions the results are |
| // undefined. |
| void SetSourceRegion(const Quad& quad); |
| |
| // Set the program to write to a subregion of the output frame, given by |
| // the origin (x, y) and dimensions (width, height). Values are considered |
| // normalized between 0.0 and 1.0. If this region exceeds the output frame |
| // dimensions the image will be clipped. |
| void SetTargetRect(float x, float y, float width, float height); |
| |
| // Set the program to write to a subregion of the output frame, given by |
| // the passed Quad. Values are considered normalized between 0.0 and 1.0. |
| // The Quad points are expected to be in the order top-left, top-right, |
| // bottom-left, bottom-right. |
| // If this region exceeds the output frame dimensions the image will be |
| // clipped. |
| void SetTargetRegion(const Quad& quad); |
| |
| // Uniform Variable access ///////////////////////////////////////////////// |
| // Note: In order to get and set uniforms, the program must have been |
| // successfully compiled and linked. Otherwise, the getters will return an |
| // invalid ProgramVar variable (check with IsVarValid()). |
| // When setting values, the value type must be match the type of the uniform |
| // in the shader. For instance, a vector of 3 elements cannot be assigned to |
| // a vec2. Similarly, an integer value cannot be assigned to a float value. |
| // Such a type mismatch will result in failure to set the value (which will |
| // remain untouched). Check the return value of the setters to determine |
| // success. |
| |
| // Returns the maximum number of uniforms supported by this implementation. |
| static int MaxUniformCount(); |
| |
| // Returns a handle to the uniform with the given name, or invalid if no |
| // such uniform variable exists in the shader. |
| ProgramVar GetUniform(const std::string& name) const; |
| |
| // Set the specified uniform value to the given integer value. Returns true |
| // if the assignment was successful. |
| bool SetUniformValue(ProgramVar var, int value); |
| |
| // Set the specified uniform value to the given float value. Returns true |
| // if the assignment was successful. |
| bool SetUniformValue(ProgramVar var, float value); |
| |
| // Set the specified uniform value to the given values. Returns true |
| // if the assignment was successful. |
| bool SetUniformValue(ProgramVar var, const int* values, int count); |
| |
| // Set the specified uniform value to the given values. Returns true |
| // if the assignment was successful. |
| bool SetUniformValue(ProgramVar var, const float* values, int count); |
| |
| // Set the specified uniform value to the given vector value. Returns true |
| // if the assignment was successful. |
| bool SetUniformValue(ProgramVar var, const std::vector<int>& values); |
| |
| // Set the specified uniform value to the given vector value. Returns true |
| // if the assignment was successful. |
| bool SetUniformValue(ProgramVar var, const std::vector<float>& values); |
| |
| // Generic variable setter, which in the case of GL programs always attempts |
| // to set the value of a uniform variable with the given name. Only values |
| // of type float, float array (or vector), and int are supported. |
| bool SetUniformValue(const std::string& name, const Value& value); |
| |
| // Generic variable getter, which in the case of GL programs always attempts |
| // to get the value of a uniform variable with the given name. |
| Value GetUniformValue(const std::string& name); |
| |
| // Returns the default name of the input texture uniform variable for the |
| // given input index. |
| static std::string InputTextureUniformName(int index); |
| |
| // Attribute access //////////////////////////////////////////////////////// |
| // Note: In order to get and set attributes, the program must have been |
| // successfully compiled and linked. Otherwise, the getters will return an |
| // invalid ProgramVar variable (check with IsVarValid()). Constant attribute |
| // values must be floats. Attribute pointers must be associated with a |
| // specific type, which can be any of the following: |
| // GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT, |
| // GL_FIXED, GL_HALF_FLOAT_OES. |
| // When storing vertex data, it is recommended to use VertexFrames when |
| // possible as these will be kept in GPU memory, and no copying of vertex |
| // attributes between system and GPU memory needs to take place. |
| |
| // Returns the maximum number of attributes supported by this |
| // implementation. |
| static int MaxAttributeCount(); |
| |
| // Returns a handle to the attribute with the given name, or invalid if no |
| // such attribute exists in the vertex shader. |
| ProgramVar GetAttribute(const std::string& name) const; |
| |
| // Set an attribute value that will be constant for each vertex. Returns |
| // true if the assignment was successful. |
| bool SetConstAttributeValue(ProgramVar var, float value); |
| |
| // Set an attribute vector value that will be constant for each vertex. |
| // Returns true if the assignment was successful. |
| bool SetConstAttributeValue(ProgramVar var, const std::vector<float>& value); |
| |
| // Set attribute values that differ across vertexes, using a VertexFrame. |
| // This is the recommended method of specifying vertex data, that does not |
| // change from iteration to iteration. The parameters are as follows: |
| // var: The shader variable to bind the values to. |
| // data: The vertex frame which holds the vertex data. This may be a |
| // superset of the data required for this particular vertex. Use the |
| // offset and stride to select the correct data portion. |
| // type: The type of the data values. This may differ from the type of the |
| // shader variables. See the normalize flag on how values are |
| // converted. |
| // components: The number of components per value. Valid values are 1-4. |
| // stride: The delta of one element to the next in bytes. |
| // offset: The offset of the first element. |
| // normalize: True, if not float values should be normalized to the range |
| // 0-1, when converted to a float. |
| // Returns true, if the assignment was successful. |
| bool SetAttributeValues(ProgramVar var, |
| const VertexFrame* data, |
| GLenum type, |
| int components, |
| int stride, |
| int offset, |
| bool normalize); |
| |
| // Set attribute values that differ across vertexes, using a data buffer. |
| // This is the recommended method of specifying vertex data, if your data |
| // changes often. Note that this data may need to be copied to GPU memory |
| // for each render pass. Please see above for a description of the |
| // parameters. |
| // Note: The data passed here MUST be valid until all executions of this |
| // Program instance have been completed! |
| bool SetAttributeValues(ProgramVar var, |
| const uint8_t* data, |
| GLenum type, |
| int components, |
| int stride, |
| int offset, |
| bool normalize); |
| |
| // Convenience method for setting vertex values using a vector of floats. |
| // The components parameter specifies how many elements per variable should |
| // be assigned (The variable must be able to fit the number of components). |
| // It must be a value between 1 and 4. |
| // While this method is not as flexible as the methods above, this can be |
| // used when more advanced methods are not necessary. Note, that if your |
| // vertex data does not change, it is recommended to use a VertexFrame. |
| bool SetAttributeValues(ProgramVar var, |
| const std::vector<float>& data, |
| int components); |
| |
| // Same as above, but using a float pointer instead of vector. Pass the |
| // total number of elements in total. |
| bool SetAttributeValues(ProgramVar var, |
| const float* data, |
| int total, |
| int components); |
| |
| // By default, rendering only uses the first 4 vertices. You should only |
| // adjust this value if you are providing your own vertex attributes with |
| // a count unequal to 4. Adjust this value before calling Process(). |
| void SetVertexCount(int count); |
| |
| // Returns the default name of the attribute used to hold the texture |
| // coordinates. Use this when you need to access the texture coordinate |
| // attribute of the shader's default vertex shader. |
| static const std::string& TexCoordAttributeName() { |
| static std::string s_texcoord("a_texcoord"); |
| return s_texcoord; |
| } |
| |
| // Returns the default name of the attribute used to hold the output |
| // coordinates. Use this when you need to access the output coordinate |
| // attribute of the shader's default vertex shader. |
| static const std::string& PositionAttributeName() { |
| static std::string s_position("a_position"); |
| return s_position; |
| } |
| |
| // Rendering /////////////////////////////////////////////////////////////// |
| // Set the draw mode, which can be any of GL_POINTS, GL_LINES, |
| // GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES, GL_TRIANGLE_STRIP, |
| // GL_TRIANGLE_FAN. The default is GL_TRIANGLE_STRIP. |
| // Warning: Do NOT change this if you are not specifying your own vertex |
| // data with SetAttributeValues(...). |
| void SetDrawMode(GLenum mode); |
| |
| // If you are doing your own drawing you should call this before beginning |
| // to draw. This will activate the program, push all used attributes, and |
| // clear the frame if requested. You do not need to call this if you are |
| // not doing your own GL drawing! |
| bool BeginDraw(); |
| |
| // Render a single frame with the given input textures. You may override |
| // this, if you need custom rendering behavior. However, you must take |
| // care of the following things when overriding: |
| // - Use the correct program (e.g. by calling UseProgram()). |
| // - Bind the given textures |
| // - Bind vertex attributes |
| // - Draw |
| bool RenderFrame(const std::vector<GLuint>& textures, |
| const std::vector<GLenum>& targets); |
| |
| // Pass true to clear the output frame before rendering. The color used |
| // to clear is set in SetClearColor(). |
| void SetClearsOutput(bool clears); |
| |
| // Set the color used to clear the output frame before rendering. You |
| // must activate clearing by calling SetClearsOutput(true). |
| void SetClearColor(float red, float green, float blue, float alpha); |
| |
| // Set the number of tiles to split rendering into. Higher tile numbers |
| // will affect performance negatively, but will allow other GPU threads |
| // to render more frequently. Defaults to 1, 1. |
| void SetTileCounts(int x_count, int y_count); |
| |
| // Enable or Disable Blending |
| // Set to true to enable, false to disable. |
| void SetBlendEnabled(bool enable) { |
| blending_ = enable; |
| } |
| |
| // Specify pixel arithmetic for blending |
| // The values of sfactor and dfactor can be: |
| // GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, |
| // GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, |
| // GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA_SATURATE |
| // Default values for blending are set to: |
| // sfactor = GL_SRC_ALPHA |
| // dfactor = GL_ONE_MINUS_SRC_ALPHA |
| void SetBlendFunc(int sfactor, int dfactor) { |
| sfactor_ = sfactor; |
| dfactor_ = dfactor; |
| } |
| |
| // Accessing the Compiled Program ////////////////////////////////////////// |
| // Use the compiled and linked program for rendering. You should not need |
| // to call this, unless you are implementing your own rendering method. |
| bool UseProgram(); |
| |
| // Other Properties //////////////////////////////////////////////////////// |
| // Returns the maximum number of varyings supported by this implementation. |
| static int MaxVaryingCount(); |
| |
| // Returns the maximum number of texture units supported by this |
| // implementation. |
| static int MaxTextureUnits(); |
| |
| // Lower level functionality /////////////////////////////////////////////// |
| // Compile the shader with the given source. The shader_type must be either |
| // GL_VERTEX_SHADER or GL_FRAGMENT_SHADER. |
| static GLuint CompileShader(GLenum shader_type, const char* source); |
| |
| // Link the compiled shader objects and return the resulting program. |
| static GLuint LinkProgram(GLuint* shaders, GLuint count); |
| |
| // Returns the lowest texture unit that will be used to bind textures. |
| GLuint BaseTextureUnit() const { |
| return base_texture_unit_; |
| } |
| |
| // Sets the lowest texture unit that will be used to bind textures. The |
| // default value is GL_TEXTURE0. |
| void SetBaseTextureUnit(GLuint texture_unit) { |
| base_texture_unit_ = texture_unit; |
| } |
| |
| private: |
| // Structure to store vertex attribute data. |
| struct VertexAttrib { |
| bool is_const; |
| int index; |
| bool normalized; |
| int stride; |
| int components; |
| int offset; |
| GLenum type; |
| GLuint vbo; |
| const void* values; |
| float* owned_data; |
| |
| VertexAttrib(); |
| }; |
| typedef std::map<ProgramVar, VertexAttrib> VertexAttribMap; |
| |
| struct RGBAColor { |
| float red; |
| float green; |
| float blue; |
| float alpha; |
| |
| RGBAColor() : red(0), green(0), blue(0), alpha(1) { |
| } |
| }; |
| |
| // Scans for all uniforms in the shader and creates index -> id map. |
| void ScanUniforms(); |
| |
| // Returns the index of the given uniform. The caller must make sure |
| // that the variable id passed is valid. |
| GLuint IndexOfUniform(ProgramVar var); |
| |
| // Binds the given input textures. |
| bool BindInputTextures(const std::vector<GLuint>& textures, |
| const std::vector<GLenum>& targets); |
| |
| // Sets the default source and target coordinates. |
| void SetDefaultCoords(); |
| |
| // Pushes the specified coordinates to the shader attribute. |
| bool PushCoords(ProgramVar attr, float* coords); |
| |
| // Pushes the source coordinates. |
| bool PushSourceCoords(float* coords); |
| |
| // Pushes the target coordinates. |
| bool PushTargetCoords(float* coords); |
| |
| // Performs (simple) GL drawing. |
| bool Draw(); |
| |
| // Performs tiled GL drawing. |
| bool DrawTiled(); |
| |
| // Yields to other GPU threads. |
| void Yield(); |
| |
| // Helper method to assert that the variable value passed has the correct |
| // total size. |
| static bool CheckValueCount(const std::string& var_type, |
| const std::string& var_name, |
| int expected_count, |
| int components, |
| int value_size); |
| |
| // Helper method to assert that the variable value passed has a size, that |
| // is compatible with the type size (must be divisible). |
| static bool CheckValueMult(const std::string& var_type, |
| const std::string& var_name, |
| int components, |
| int value_size); |
| |
| // Checks that the variable is valid. Logs an error and returns false if |
| // not. |
| static bool CheckVarValid(ProgramVar var); |
| |
| // Returns true if the uniform specified by var is an active uniform in the |
| // program. |
| bool CheckUniformValid(ProgramVar var); |
| |
| // Store an attribute to use when rendering. |
| bool StoreAttribute(VertexAttrib attrib); |
| |
| // Push all assigned attributes before rendering. |
| bool PushAttributes(); |
| |
| // Pop all assigned attributes after rendering. |
| bool PopAttributes(); |
| |
| // The shader source code |
| std::string fragment_shader_source_; |
| std::string vertex_shader_source_; |
| |
| // The compiled shaders and linked program |
| GLuint fragment_shader_; |
| GLuint vertex_shader_; |
| GLuint program_; |
| |
| // The GL environment this shader lives in. |
| GLEnv* gl_env_; |
| |
| // The lowest texture unit this program will use |
| GLuint base_texture_unit_; |
| |
| // The current source and target coordinates to render from/to. |
| float* source_coords_; |
| float* target_coords_; |
| |
| // True, if the program has control over both source and target coordinates. |
| bool manage_coordinates_; |
| |
| // The number of tiles to split rendering into. |
| int tile_x_count_; |
| int tile_y_count_; |
| |
| // List of attribute data that we need to set before rendering |
| VertexAttribMap attrib_values_; |
| |
| // The number of vertices to render |
| int vertex_count_; |
| |
| // The draw mode used during rendering |
| GLenum draw_mode_; |
| |
| // True, iff the output frame is cleared before rendering |
| bool clears_; |
| |
| // The color used to clear the output frame. |
| RGBAColor clear_color_; |
| |
| // Set to true to enable blending. |
| bool blending_; |
| int sfactor_; |
| int dfactor_; |
| |
| // Map from uniform ids to indices |
| std::map<ProgramVar, GLuint> uniform_indices_; |
| }; |
| |
| } // namespace filterfw |
| } // namespace android |
| |
| #endif // ANDROID_FILTERFW_CORE_SHADER_PROGRAM_H |