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.
IsExecutable()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.
TexCoordAttributeName()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.
PositionAttributeName()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.
SetBlendEnabled(bool enable)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
SetBlendFunc(int sfactor,int dfactor)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.
BaseTextureUnit()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.
SetBaseTextureUnit(GLuint texture_unit)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 
RGBAColorRGBAColor432       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