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
31namespace android {
32namespace filterfw {
33
34class GLFrame;
35class GLFrameBufferHandle;
36class GLTextureHandle;
37class Quad;
38class VertexFrame;
39
40typedef 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//
67class 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