Home | History | Annotate | Download | only in geometry_shader
      1 #ifndef _ESEXTCGEOMETRYSHADERLIMITS_HPP
      2 #define _ESEXTCGEOMETRYSHADERLIMITS_HPP
      3 /*-------------------------------------------------------------------------
      4  * OpenGL Conformance Test Suite
      5  * -----------------------------
      6  *
      7  * Copyright (c) 2014-2016 The Khronos Group Inc.
      8  *
      9  * Licensed under the Apache License, Version 2.0 (the "License");
     10  * you may not use this file except in compliance with the License.
     11  * You may obtain a copy of the License at
     12  *
     13  *      http://www.apache.org/licenses/LICENSE-2.0
     14  *
     15  * Unless required by applicable law or agreed to in writing, software
     16  * distributed under the License is distributed on an "AS IS" BASIS,
     17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     18  * See the License for the specific language governing permissions and
     19  * limitations under the License.
     20  *
     21  */ /*!
     22  * \file
     23  * \brief
     24  */ /*-------------------------------------------------------------------*/
     25 
     26 /*!
     27  * \file esextcGeometryShaderLimits.hpp
     28  * \brief Geometry Shader Limits (Test Group 16)
     29  */ /*-------------------------------------------------------------------*/
     30 
     31 #include "../esextcTestCaseBase.hpp"
     32 
     33 #include <vector>
     34 
     35 namespace glcts
     36 {
     37 /** Parent class for geometry shader Test Group 16 tests
     38  *  based on fetching result via transfrom feedback.
     39  **/
     40 class GeometryShaderLimitsTransformFeedbackBase : public TestCaseBase
     41 {
     42 public:
     43 	/* Public methods */
     44 	virtual void		  deinit(void);
     45 	virtual IterateResult iterate(void);
     46 
     47 protected:
     48 	/* Protected methods */
     49 	GeometryShaderLimitsTransformFeedbackBase(Context& context, const ExtParameters& extParams, const char* name,
     50 											  const char* description);
     51 
     52 	virtual ~GeometryShaderLimitsTransformFeedbackBase()
     53 	{
     54 	}
     55 
     56 	void initTest(void);
     57 
     58 	/* Methods to be overriden by inheriting test cases */
     59 	virtual void clean() = 0;
     60 
     61 	virtual void getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names,
     62 									 glw::GLuint&				out_n_captured_varyings) = 0;
     63 
     64 	virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
     65 								glw::GLuint&			   out_n_fragment_shader_parts,
     66 								const glw::GLchar* const*& out_geometry_shader_parts,
     67 								glw::GLuint&			   out_n_geometry_shader_parts,
     68 								const glw::GLchar* const*& out_vertex_shader_parts,
     69 								glw::GLuint&			   out_n_vertex_shader_parts) = 0;
     70 
     71 	virtual void getTransformFeedbackBufferSize(glw::GLuint& out_buffer_size) = 0;
     72 	virtual void prepareProgramInput()										  = 0;
     73 	virtual bool verifyResult(const void* data)								  = 0;
     74 
     75 	/* Protected fields */
     76 	/* Program and shader ids */
     77 	glw::GLuint m_fragment_shader_id;
     78 	glw::GLuint m_geometry_shader_id;
     79 	glw::GLuint m_program_object_id;
     80 	glw::GLuint m_vertex_shader_id;
     81 
     82 	/* Buffer object used in transform feedback */
     83 	glw::GLuint m_buffer_object_id;
     84 
     85 	/* Vertex array object */
     86 	glw::GLuint m_vertex_array_object_id;
     87 
     88 private:
     89 	/* Private fields */
     90 	/* Shaders' code */
     91 	const glw::GLchar* const* m_fragment_shader_parts;
     92 	const glw::GLchar* const* m_geometry_shader_parts;
     93 	const glw::GLchar* const* m_vertex_shader_parts;
     94 
     95 	glw::GLuint m_n_fragment_shader_parts;
     96 	glw::GLuint m_n_geometry_shader_parts;
     97 	glw::GLuint m_n_vertex_shader_parts;
     98 
     99 	/* Names of varyings */
    100 	const glw::GLchar* const* m_captured_varyings_names;
    101 	glw::GLuint				  m_n_captured_varyings;
    102 
    103 	/* Size of buffer used by transform feedback */
    104 	glw::GLuint m_buffer_size;
    105 };
    106 
    107 /** Parent class for geometry shader Test Group 16 tests
    108  *  based on fetching result via rendering to texture.
    109  **/
    110 class GeometryShaderLimitsRenderingBase : public TestCaseBase
    111 {
    112 public:
    113 	/* Public methods */
    114 	virtual void		  deinit(void);
    115 	virtual IterateResult iterate(void);
    116 
    117 protected:
    118 	/* Protected methods */
    119 	GeometryShaderLimitsRenderingBase(Context& context, const ExtParameters& extParams, const char* name,
    120 									  const char* description);
    121 
    122 	virtual ~GeometryShaderLimitsRenderingBase()
    123 	{
    124 	}
    125 
    126 	void initTest(void);
    127 
    128 	/* Methods to be overriden by child test cases */
    129 	virtual void clean() = 0;
    130 
    131 	virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices) = 0;
    132 
    133 	virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format,
    134 									   glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width,
    135 									   glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size) = 0;
    136 
    137 	virtual void getRequiredPointSize(glw::GLfloat& out_point_size) = 0;
    138 
    139 	virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
    140 								glw::GLuint&			   out_n_fragment_shader_parts,
    141 								const glw::GLchar* const*& out_geometry_shader_parts,
    142 								glw::GLuint&			   out_n_geometry_shader_parts,
    143 								const glw::GLchar* const*& out_vertex_shader_parts,
    144 								glw::GLuint&			   out_n_vertex_shader_parts) = 0;
    145 
    146 	virtual void prepareProgramInput()			= 0;
    147 	virtual bool verifyResult(const void* data) = 0;
    148 
    149 	/* Protected fields */
    150 	/* Program and shader ids */
    151 	glw::GLuint m_fragment_shader_id;
    152 	glw::GLuint m_geometry_shader_id;
    153 	glw::GLuint m_program_object_id;
    154 	glw::GLuint m_vertex_shader_id;
    155 
    156 	/* Framebuffer object id */
    157 	glw::GLuint m_framebuffer_object_id;
    158 	glw::GLuint m_color_texture_id;
    159 
    160 	/* Vertex array object */
    161 	glw::GLuint m_vertex_array_object_id;
    162 
    163 private:
    164 	/* Private fields */
    165 	/* Shaders' code */
    166 	const glw::GLchar* const* m_fragment_shader_parts;
    167 	const glw::GLchar* const* m_geometry_shader_parts;
    168 	const glw::GLchar* const* m_vertex_shader_parts;
    169 
    170 	glw::GLuint m_n_fragment_shader_parts;
    171 	glw::GLuint m_n_geometry_shader_parts;
    172 	glw::GLuint m_n_vertex_shader_parts;
    173 
    174 	/* Framebuffer dimensions */
    175 	glw::GLenum m_texture_format;
    176 	glw::GLuint m_texture_height;
    177 	glw::GLuint m_texture_pixel_size;
    178 	glw::GLenum m_texture_read_format;
    179 	glw::GLenum m_texture_read_type;
    180 	glw::GLuint m_texture_width;
    181 };
    182 
    183 /** Implementation of test case 16.1. Test description follows:
    184  *
    185  *  Make sure it is possible to use as many uniform components as defined
    186  *  by GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT
    187  *
    188  *  Category: API;
    189  *            Functional Test.
    190  *
    191  *  1. Create a fragment, geometry and vertex shader objects:
    192  *
    193  *  - Vertex shader code can be boilerplate;
    194  *  - Geometry shader code should define
    195  *    floor(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT / 4) uniform ivec4
    196  *    variables. It should take points as input and output, a maximum of
    197  *    1 vertex will be written by the shader. In main(), the shader should
    198  *    set output int variable named result to a sum of all the vectors'
    199  *    components and emit a vertex.
    200  *  - Fragment shader code can be boilerplate.
    201  *
    202  *  2. The program object consisting of these shader objects is expected to
    203  *  link successfully.
    204  *
    205  *  3. Configure the uniforms to use subsequently increasing values, starting
    206  *  from 1 for R component of first vector, 2 for G component of that vector,
    207  *  5 for first component of second vector, and so on.
    208  *
    209  *  4. Configure transform feedback object to capture output from result.
    210  *  Draw a single point. The test succeeds if first component of the result
    211  *  vector contains a valid value (bearing potentially minor precision issues
    212  *  in mind)
    213  **/
    214 class GeometryShaderMaxUniformComponentsTest : public GeometryShaderLimitsTransformFeedbackBase
    215 {
    216 public:
    217 	/* Public methods */
    218 	GeometryShaderMaxUniformComponentsTest(Context& context, const ExtParameters& extParams, const char* name,
    219 										   const char* description);
    220 
    221 	virtual ~GeometryShaderMaxUniformComponentsTest()
    222 	{
    223 	}
    224 
    225 protected:
    226 	/* Overriden from GeometryShaderLimitsTransformFeedbackBase */
    227 	virtual void clean();
    228 
    229 	virtual void getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names,
    230 									 glw::GLuint&				out_n_captured_varyings);
    231 
    232 	virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
    233 								glw::GLuint&			   out_n_fragment_shader_parts,
    234 								const glw::GLchar* const*& out_geometry_shader_parts,
    235 								glw::GLuint&			   out_n_geometry_shader_parts,
    236 								const glw::GLchar* const*& out_vertex_shader_parts,
    237 								glw::GLuint&			   out_n_vertex_shader_parts);
    238 
    239 	virtual void getTransformFeedbackBufferSize(glw::GLuint& out_buffer_size);
    240 	virtual void prepareProgramInput();
    241 	virtual bool verifyResult(const void* data);
    242 
    243 private:
    244 	/* Private fields */
    245 	/* Shaders' code */
    246 	static const glw::GLchar* const m_fragment_shader_code;
    247 	static const glw::GLchar* const m_geometry_shader_code_preamble;
    248 	static const glw::GLchar* const m_geometry_shader_code_number_of_uniforms;
    249 	static const glw::GLchar* const m_geometry_shader_code_body;
    250 	static const glw::GLchar* const m_vertex_shader_code;
    251 
    252 	const glw::GLchar* m_geometry_shader_parts[4];
    253 
    254 	/* String used to store number of uniform vectors */
    255 	std::string m_max_uniform_vectors_string;
    256 
    257 	/* Varying names */
    258 	static const glw::GLchar* const m_captured_varyings_names;
    259 
    260 	/* Buffer size */
    261 	static const glw::GLuint m_buffer_size;
    262 
    263 	/* Max uniform components and vectors */
    264 	glw::GLint m_max_uniform_components;
    265 	glw::GLint m_max_uniform_vectors;
    266 
    267 	/* Uniform location */
    268 	glw::GLint m_uniform_location;
    269 
    270 	/* Uniform data */
    271 	std::vector<glw::GLint> m_uniform_data;
    272 };
    273 
    274 /** Implementation of test case 16.2. Test description follows:
    275  *
    276  *  Make sure it is possible to use as many uniform blocks as defined by
    277  *  GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT
    278  *
    279  *  Category: API;
    280  *            Functional Test.
    281  *
    282  *  Slightly modify test case 16.1 to use a similar idea to test if the
    283  *  value reported for the property by the implementation is reliable:
    284  *
    285  *  - Test case 16.1's ivec4s take form of as many uniform blocks as needed,
    286  *    each hosting a single int.
    287  *  - The result value to be calculated in the geometry shader is a sum of
    288  *    all ints, stored in output int result variable.
    289  **/
    290 class GeometryShaderMaxUniformBlocksTest : public GeometryShaderLimitsTransformFeedbackBase
    291 {
    292 public:
    293 	/* Public methods */
    294 	GeometryShaderMaxUniformBlocksTest(Context& context, const ExtParameters& extParams, const char* name,
    295 									   const char* description);
    296 
    297 	virtual ~GeometryShaderMaxUniformBlocksTest()
    298 	{
    299 	}
    300 
    301 protected:
    302 	/* Overriden from GeometryShaderLimitsTransformFeedbackBase */
    303 	virtual void clean();
    304 
    305 	virtual void getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names,
    306 									 glw::GLuint&				out_n_captured_varyings);
    307 
    308 	virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
    309 								glw::GLuint&			   out_n_fragment_shader_parts,
    310 								const glw::GLchar* const*& out_geometry_shader_parts,
    311 								glw::GLuint&			   out_n_geometry_shader_parts,
    312 								const glw::GLchar* const*& out_vertex_shader_parts,
    313 								glw::GLuint&			   out_n_vertex_shader_parts);
    314 
    315 	virtual void getTransformFeedbackBufferSize(glw::GLuint& out_buffer_size);
    316 	virtual void prepareProgramInput();
    317 	virtual bool verifyResult(const void* data);
    318 
    319 private:
    320 	/* Private type */
    321 	struct _uniform_block
    322 	{
    323 		glw::GLuint buffer_object_id;
    324 		glw::GLint  data;
    325 	};
    326 
    327 	/* Private fields */
    328 	/* Shaders' code */
    329 	static const glw::GLchar* const m_fragment_shader_code;
    330 	static const glw::GLchar* const m_geometry_shader_code_preamble;
    331 	static const glw::GLchar* const m_geometry_shader_code_number_of_uniforms;
    332 	static const glw::GLchar* const m_geometry_shader_code_body_str;
    333 	static const glw::GLchar* const m_geometry_shader_code_body_end;
    334 	static const glw::GLchar* const m_vertex_shader_code;
    335 
    336 	const glw::GLchar* m_geometry_shader_parts[6];
    337 
    338 	/* String used to store uniform blocks accesses */
    339 	std::string m_uniform_block_access_string;
    340 
    341 	/* String used to store number of uniform blocks */
    342 	std::string m_max_uniform_blocks_string;
    343 
    344 	/* Varying names */
    345 	static const glw::GLchar* const m_captured_varyings_names;
    346 
    347 	/* Buffer size */
    348 	static const glw::GLuint m_buffer_size;
    349 
    350 	/* Max uniform blocks */
    351 	glw::GLint m_max_uniform_blocks;
    352 
    353 	/* Uniform blocks data */
    354 	std::vector<_uniform_block> m_uniform_blocks;
    355 };
    356 
    357 /** Implementation of test case 16.3. Test description follows:
    358  *
    359  *  Make sure it is possible to use as many input components as defined by
    360  *  GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT
    361  *
    362  *  Category: API.
    363  *
    364  *  Create a program object, attach a fragment, geometry and a vertex shader to it:
    365  *
    366  *  - Fragment shader can be boilerplate;
    367  *  - Vertex shader should define exactly
    368  *    (GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT / 4) ivec4 output variables.
    369  *    Each of the variables should be assigned a vector value of
    370  *    (n, n+1, n+2, n+3) where n corresponds to "index" of the variable,
    371  *    assuming the very first output variable has an "index" of 1.
    372  *  - Geometry shader should define exactly
    373  *    (GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT / 4) vec4 input variables. It
    374  *    should accept input point geometry and output a maximum of 1 point.
    375  *    It should sum up all components read from input variables and store them
    376  *    in output int variable called result..
    377  *
    378  *  The test should then configure the program object to capture values of
    379  *  "result" variable using transform feedback and link the program object.
    380  *
    381  *  The test should now generate and bind a vertex array object, and then
    382  *  draw a single point. Test succeeds if the value stored in a buffer object
    383  *  configured for transform feedback storage is valid.
    384  **/
    385 class GeometryShaderMaxInputComponentsTest : public GeometryShaderLimitsTransformFeedbackBase
    386 {
    387 public:
    388 	/* Public methods */
    389 	GeometryShaderMaxInputComponentsTest(Context& context, const ExtParameters& extParams, const char* name,
    390 										 const char* description);
    391 
    392 	virtual ~GeometryShaderMaxInputComponentsTest()
    393 	{
    394 	}
    395 
    396 protected:
    397 	/* Overriden from GeometryShaderLimitsTransformFeedbackBase */
    398 	virtual void clean();
    399 
    400 	virtual void getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names,
    401 									 glw::GLuint&				out_n_captured_varyings);
    402 
    403 	virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
    404 								glw::GLuint&			   out_n_fragment_shader_parts,
    405 								const glw::GLchar* const*& out_geometry_shader_parts,
    406 								glw::GLuint&			   out_n_geometry_shader_parts,
    407 								const glw::GLchar* const*& out_vertex_shader_parts,
    408 								glw::GLuint&			   out_n_vertex_shader_parts);
    409 
    410 	virtual void getTransformFeedbackBufferSize(glw::GLuint& out_buffer_size);
    411 	virtual void prepareProgramInput();
    412 	virtual bool verifyResult(const void* data);
    413 
    414 private:
    415 	/* Private fields */
    416 	/* Shaders' code */
    417 	static const glw::GLchar* const m_fragment_shader_code;
    418 	static const glw::GLchar* const m_geometry_shader_code_preamble;
    419 	static const glw::GLchar* const m_geometry_shader_code_number_of_uniforms;
    420 	static const glw::GLchar* const m_geometry_shader_code_body;
    421 	static const glw::GLchar* const m_vertex_shader_code_preamble;
    422 	static const glw::GLchar* const m_vertex_shader_code_number_of_uniforms;
    423 	static const glw::GLchar* const m_vertex_shader_code_body;
    424 
    425 	const glw::GLchar* m_geometry_shader_parts[4];
    426 	const glw::GLchar* m_vertex_shader_parts[4];
    427 
    428 	/* Max input components and vectors */
    429 	glw::GLint m_max_geometry_input_components;
    430 	glw::GLint m_max_geometry_input_vectors;
    431 
    432 	/* String used to store number of geometry input vectors */
    433 	std::string m_max_geometry_input_vectors_string;
    434 
    435 	/* Varying names */
    436 	static const glw::GLchar* const m_captured_varyings_names;
    437 
    438 	/* Buffer size */
    439 	static const glw::GLuint m_buffer_size;
    440 };
    441 
    442 /** Implementation of test case 16.4. Test description follows:
    443  *
    444  *  Make sure it is possible to use as many total output components as
    445  *  defined by GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT.
    446  *
    447  *  Category: API.
    448  *
    449  *  Let n_points be equal to:
    450  *
    451  *  (GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT / GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT)
    452  *
    453  *  Create a fragment, geometry and vertex shader objects:
    454  *
    455  *  - Vertex shader code can be boilerplate;
    456  *  - Geometry shader code should define:
    457  *
    458  *             floor(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT / 4)
    459  *
    460  *   output ivec4 variables. It should take points as input and output,
    461  *   a maximum of n_points vertices will be written. In main(), for each
    462  *   vertex, the shader should set gl_Position to:
    463  *
    464  *         (-1 + (2 * vertex id + 1) / (2 * max vertices) * 2, 0, 0, 1)
    465  *
    466  *   where (vertex id) corresponds to index of about-to-be-emitted vertices,
    467  *   assuming the indexing starts from 0.
    468  *   Each vertex should store subsequently increasing, unique values to
    469  *   components of the output variables.
    470  *   Geometry shader should emit as many vertices as specified. For each
    471  *   output point, point size should be set to 2.
    472  *  - Fragment shader code should take all aforementioned varyings as input
    473  *   variables, read them, and store result int fragment as sum of all
    474  *   components for all vectors passed from the geometry shader.
    475  *
    476  *  For rendering, the test should use a framebuffer object, to which
    477  *  a GL_R32I-based 2D texture object of resolution:
    478  *
    479  *                              (2*n_points, 2)
    480  *
    481  *  has been attached to color attachment 0.
    482  *
    483  *  The test should link the program (no linking error should be reported)
    484  *  and then activate it. Having bound a vertex array object, it should then
    485  *  draw n_points points.
    486  *
    487  *  The test passes, if the texture attached to color attachment 0 consists
    488  *  of 2x2 quads filled with the same value, that can be considered valid in
    489  *  light of the description above.
    490  *  The program object consisting of these shader objects is expected to link
    491  *  successfully.
    492  **/
    493 class GeometryShaderMaxOutputComponentsTest : public GeometryShaderLimitsRenderingBase
    494 {
    495 public:
    496 	/* Public methods */
    497 	GeometryShaderMaxOutputComponentsTest(Context& context, const ExtParameters& extParams, const char* name,
    498 										  const char* description);
    499 
    500 	virtual ~GeometryShaderMaxOutputComponentsTest()
    501 	{
    502 	}
    503 
    504 protected:
    505 	/* Methods overriden from GeometryShaderLimitsRenderingBase */
    506 	virtual void clean();
    507 
    508 	virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices);
    509 
    510 	virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format,
    511 									   glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width,
    512 									   glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size);
    513 
    514 	virtual void getRequiredPointSize(glw::GLfloat& out_point_size);
    515 
    516 	virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
    517 								glw::GLuint&			   out_n_fragment_shader_parts,
    518 								const glw::GLchar* const*& out_geometry_shader_parts,
    519 								glw::GLuint&			   out_n_geometry_shader_parts,
    520 								const glw::GLchar* const*& out_vertex_shader_parts,
    521 								glw::GLuint&			   out_n_vertex_shader_parts);
    522 
    523 	virtual void prepareProgramInput();
    524 	virtual bool verifyResult(const void* data);
    525 
    526 private:
    527 	/* Private methods */
    528 	void prepareFragmentShader(std::string& out_shader_code) const;
    529 	void prepareGeometryShader(std::string& out_shader_code) const;
    530 
    531 	/* Private fields */
    532 	/* Shaders' code */
    533 	static const glw::GLchar* const m_common_shader_code_gs_fs_out;
    534 	static const glw::GLchar* const m_common_shader_code_number_of_points;
    535 	static const glw::GLchar* const m_common_shader_code_gs_fs_out_definitions;
    536 	static const glw::GLchar* const m_fragment_shader_code_preamble;
    537 	static const glw::GLchar* const m_fragment_shader_code_flat_in_ivec4;
    538 	static const glw::GLchar* const m_fragment_shader_code_sum;
    539 	static const glw::GLchar* const m_fragment_shader_code_body_begin;
    540 	static const glw::GLchar* const m_fragment_shader_code_body_end;
    541 	static const glw::GLchar* const m_geometry_shader_code_preamble;
    542 	static const glw::GLchar* const m_geometry_shader_code_layout;
    543 	static const glw::GLchar* const m_geometry_shader_code_flat_out_ivec4;
    544 	static const glw::GLchar* const m_geometry_shader_code_assignment;
    545 	static const glw::GLchar* const m_geometry_shader_code_body_begin;
    546 	static const glw::GLchar* const m_geometry_shader_code_body_end;
    547 	static const glw::GLchar* const m_vertex_shader_code;
    548 
    549 	/* Storage for prepared fragment and geometry shader */
    550 	std::string		   m_fragment_shader_code;
    551 	const glw::GLchar* m_fragment_shader_code_c_str;
    552 	std::string		   m_geometry_shader_code;
    553 	const glw::GLchar* m_geometry_shader_code_c_str;
    554 
    555 	/* Framebuffer dimensions */
    556 	glw::GLuint				 m_texture_width;
    557 	static const glw::GLuint m_texture_height;
    558 	static const glw::GLuint m_texture_pixel_size;
    559 	static const glw::GLuint m_point_size;
    560 
    561 	/* Max number of output components */
    562 	glw::GLint m_max_output_components;
    563 	glw::GLint m_max_output_vectors;
    564 	glw::GLint m_max_total_output_components;
    565 	glw::GLint m_n_available_vectors;
    566 	glw::GLint m_n_output_points;
    567 };
    568 
    569 /** Implementation of test case 16.5. Test description follows:
    570  *
    571  *  Make sure it possible to request as many output vertices as report for
    572  *  GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT. Requesting support for larger amount
    573  *  of output vertices should cause the linking process to fail.
    574  *
    575  *  Category: API;
    576  *           Negative Test.
    577  *
    578  *  Create two program objects and one boilerplate fragment & one boilerplate
    579  *  vertex shader objects.
    580  *  Also create two boilerplate geometry shader objects where:
    581  *
    582  *  a) The first geometry shader object can output up to
    583  *    GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT vertices.
    584  *  b) The other geometry shader object can output up to
    585  *    (GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT+1) vertices.
    586  *
    587  *  1) Program object A should be attached fragment and vertex shader
    588  *    objects, as well as geometry shader A. This program object should
    589  *    link successfully.
    590  *  2) Program object B should be attached fragment and vertex shader objects,
    591  *    as well as geometry shader B. This program object should fail to link.
    592  **/
    593 class GeometryShaderMaxOutputVerticesTest : public TestCaseBase
    594 {
    595 public:
    596 	/* Public methods */
    597 	GeometryShaderMaxOutputVerticesTest(Context& context, const ExtParameters& extParams, const char* name,
    598 										const char* description);
    599 
    600 	virtual ~GeometryShaderMaxOutputVerticesTest()
    601 	{
    602 	}
    603 
    604 	virtual IterateResult iterate(void);
    605 
    606 private:
    607 	/* Private fields */
    608 	/* Shaders' code */
    609 	static const glw::GLchar* const m_fragment_shader_code;
    610 	static const glw::GLchar* const m_geometry_shader_code_preamble;
    611 	static const glw::GLchar* const m_geometry_shader_code_body;
    612 	static const glw::GLchar* const m_vertex_shader_code;
    613 };
    614 
    615 /** Implementation of test case 16.6. Test description follows:
    616  *
    617  *  Make sure it is possible to use as many output components as defined by
    618  *  GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT
    619  *
    620  *  Category: API.
    621  *
    622  *  Modify test case 16.4, so that:
    623  *
    624  *  * n_points is always 1;
    625  **/
    626 class GeometryShaderMaxOutputComponentsSinglePointTest : public GeometryShaderLimitsRenderingBase
    627 {
    628 public:
    629 	/* Public methods */
    630 	GeometryShaderMaxOutputComponentsSinglePointTest(Context& context, const ExtParameters& extParams, const char* name,
    631 													 const char* description);
    632 
    633 	virtual ~GeometryShaderMaxOutputComponentsSinglePointTest()
    634 	{
    635 	}
    636 
    637 protected:
    638 	/* Methods overriden from GeometryShaderLimitsRenderingBase */
    639 	virtual void clean();
    640 
    641 	virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices);
    642 
    643 	virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format,
    644 									   glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width,
    645 									   glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size);
    646 
    647 	virtual void getRequiredPointSize(glw::GLfloat& out_point_size);
    648 
    649 	virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
    650 								glw::GLuint&			   out_n_fragment_shader_parts,
    651 								const glw::GLchar* const*& out_geometry_shader_parts,
    652 								glw::GLuint&			   out_n_geometry_shader_parts,
    653 								const glw::GLchar* const*& out_vertex_shader_parts,
    654 								glw::GLuint&			   out_n_vertex_shader_parts);
    655 
    656 	virtual void prepareProgramInput();
    657 	virtual bool verifyResult(const void* data);
    658 
    659 private:
    660 	/* Private methods */
    661 	void prepareFragmentShader(std::string& out_shader_code) const;
    662 	void prepareGeometryShader(std::string& out_shader_code) const;
    663 
    664 	/* Private fields */
    665 	/* Shaders' code */
    666 	static const glw::GLchar* const m_common_shader_code_gs_fs_out;
    667 	static const glw::GLchar* const m_common_shader_code_gs_fs_out_definitions;
    668 	static const glw::GLchar* const m_fragment_shader_code_preamble;
    669 	static const glw::GLchar* const m_fragment_shader_code_flat_in_ivec4;
    670 	static const glw::GLchar* const m_fragment_shader_code_sum;
    671 	static const glw::GLchar* const m_fragment_shader_code_body_begin;
    672 	static const glw::GLchar* const m_fragment_shader_code_body_end;
    673 	static const glw::GLchar* const m_geometry_shader_code_preamble;
    674 	static const glw::GLchar* const m_geometry_shader_code_flat_out_ivec4;
    675 	static const glw::GLchar* const m_geometry_shader_code_assignment;
    676 	static const glw::GLchar* const m_geometry_shader_code_body_begin;
    677 	static const glw::GLchar* const m_geometry_shader_code_body_end;
    678 	static const glw::GLchar* const m_vertex_shader_code;
    679 
    680 	/* Storage for prepared fragment and geometry shader */
    681 	std::string m_fragment_shader_code;
    682 	std::string m_geometry_shader_code;
    683 
    684 	const glw::GLchar* m_fragment_shader_code_c_str;
    685 	const glw::GLchar* m_geometry_shader_code_c_str;
    686 
    687 	/* Framebuffer dimensions */
    688 	static const glw::GLuint m_texture_width;
    689 	static const glw::GLuint m_texture_height;
    690 	static const glw::GLuint m_texture_pixel_size;
    691 	static const glw::GLuint m_point_size;
    692 
    693 	/* Max number of output components */
    694 	glw::GLint m_max_output_components;
    695 	glw::GLint m_max_output_vectors;
    696 	glw::GLint m_n_available_vectors;
    697 };
    698 
    699 /** Implementation of test case 16.7. Test description follows:
    700  *
    701  *  Make sure that it is possible to access as many texture image units from
    702  *  a geometry shader as reported by GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT
    703  *
    704  *  Category: API;
    705  *            Functional Test.
    706  *
    707  *  Create as many texture objects as reported by
    708  *  GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT. Each texture should be made an
    709  *  immutable GL_R32I 2D texture, have 1x1 resolution and be filled with
    710  *  subsequently increasing intensities (starting from 1, delta: 2). Let's
    711  *  name these textures "source textures" for the purpose of this test case.
    712  *
    713  *  Create a program object and a fragment/geometry/vertex shader object.
    714  *  Behavior of the shaders should be as follows:
    715  *
    716  *  1) Vertex shader should take gl_VertexID and calculate an unique 2D
    717  *  location, that will later be used to render a 2x2 quad. The calculations
    718  *  should take quad size into account, note the quads must not overlap. The
    719  *  result location should be passed to geometry shader by storing it in an
    720  *  output variable. The shader should also store the vertex id in a
    721  *  flat-interpolated int output variable called vertex_id.
    722  *
    723  *  2) Geometry shader should accept points as input types and should emit
    724  *  triangle strips with a maximum of 4 output vertices. For each output
    725  *  geometry's vertex, two values should be written:
    726  *
    727  *  * gl_Position obviously;
    728  *  * color (stored as flat-interpolated integer);
    729  *
    730  *  The shader should define as many 2D samplers as reported for the tested
    731  *  property. In geometry shader's entry-point, the aforementioned 2D
    732  *  location should be used to calculate vertices of a quad the shader will
    733  *  emit (built using a triangle strip). Geometry shader should also write
    734  *  a result of the following computation to an output color variable:
    735  *
    736  *  sum(i=0..n_samplers)( (vertex_id == i) * (result of sampling 2D texture
    737  *  at (0,0) using a sampler bound to texture unit i) );
    738  *
    739  *  3) Fragment shader should take the color as passed by geometry shader
    740  *  and write it to output result variable.
    741  *
    742  *  These shader objects should then be compiled, attached to the program
    743  *  object. The program object should be linked. Each sampler uniform should
    744  *  be assigned a consecutive texture unit index, starting from 0.
    745  *
    746  *  A framebuffer object should then be created, as well as a 2D GL_R32I
    747  *  texture of resolution:
    748  *
    749  *            (GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT*2, 2)
    750  *
    751  *  The texture should be attached to the FBO's color attachment.
    752  *
    753  *  A vertex array object should be created and bound.
    754  *
    755  *  "Source textures" are next bound to corresponding texture units, and the
    756  *  FBO should be made a draw framebuffer. The program object should be made
    757  *  current and exactly GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT points should
    758  *  be drawn.
    759  *
    760  *  Next, bind the FBO to GL_READ_FRAMEBUFFER target, read the data, and make
    761  *  sure that consequent 2x2 quads are of expected intensities (epsilon to
    762  *  consider: +-1).
    763  **/
    764 class GeometryShaderMaxTextureUnitsTest : public GeometryShaderLimitsRenderingBase
    765 {
    766 public:
    767 	/* Public methods */
    768 	GeometryShaderMaxTextureUnitsTest(Context& context, const ExtParameters& extParams, const char* name,
    769 									  const char* description);
    770 
    771 	virtual ~GeometryShaderMaxTextureUnitsTest()
    772 	{
    773 	}
    774 
    775 protected:
    776 	/* Methods overriden from GeometryShaderLimitsRenderingBase */
    777 	virtual void clean();
    778 
    779 	virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices);
    780 
    781 	virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format,
    782 									   glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width,
    783 									   glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size);
    784 
    785 	virtual void getRequiredPointSize(glw::GLfloat& out_point_size);
    786 
    787 	virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
    788 								glw::GLuint&			   out_n_fragment_shader_parts,
    789 								const glw::GLchar* const*& out_geometry_shader_parts,
    790 								glw::GLuint&			   out_n_geometry_shader_parts,
    791 								const glw::GLchar* const*& out_vertex_shader_parts,
    792 								glw::GLuint&			   out_n_vertex_shader_parts);
    793 
    794 	virtual void prepareProgramInput();
    795 	virtual bool verifyResult(const void* data);
    796 
    797 private:
    798 	/* Private types */
    799 	struct _texture_data
    800 	{
    801 		glw::GLuint texture_id;
    802 		glw::GLint  data;
    803 	};
    804 	typedef std::vector<_texture_data> textureContainer;
    805 
    806 	/* Private fields */
    807 	/* Shaders' code */
    808 	static const glw::GLchar* const m_fragment_shader_code;
    809 	static const glw::GLchar* const m_geometry_shader_code_preamble;
    810 	static const glw::GLchar* const m_geometry_shader_code_body;
    811 	static const glw::GLchar* const m_vertex_shader_code_preamble;
    812 	static const glw::GLchar* const m_vertex_shader_code_body;
    813 
    814 	/* Storage for vertex and geometry shader parts */
    815 	const glw::GLchar* m_geometry_shader_parts[3];
    816 	const glw::GLchar* m_vertex_shader_parts[3];
    817 
    818 	/* Framebuffer dimensions */
    819 	glw::GLuint				 m_texture_width;
    820 	static const glw::GLuint m_texture_height;
    821 	static const glw::GLuint m_texture_pixel_size;
    822 	static const glw::GLuint m_point_size;
    823 
    824 	/* Max number of texture units */
    825 	glw::GLint  m_max_texture_units;
    826 	std::string m_max_texture_units_string;
    827 
    828 	/* Texture units */
    829 	textureContainer m_textures;
    830 };
    831 
    832 /** Implementation of test case 16.8. Test description follows:
    833  *
    834  *  Make sure it is possible to use as many geometry shader invocations as
    835  *  defined by GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT. Verify invocation
    836  *  count defaults to 1 if no number of invocations is defined in the
    837  *  geometry shader.
    838  *
    839  *  Category: API.
    840  *
    841  *  Create a program object and:
    842  *
    843  *  - A boilerplate vertex shader object;
    844  *  - A geometry shader object that:
    845  *
    846  *  1) takes points on input;
    847  *  2) outputs a maximum of 3 vertices making up triangles;
    848  *  3) uses exactly GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT invocations;
    849  *  4) let:
    850  *
    851  *              dx = 2.0 / GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT.
    852  *
    853  *    Emit 3 vertices:
    854  *
    855  *    4a) (-1+dx*(gl_InvocationID),  -1.001, 0, 1)
    856  *    4b) (-1+dx*(gl_InvocationID),   1.001, 0, 1)
    857  *    4c) (-1+dx*(gl_InvocationID+1), 1.001, 0, 1)
    858  *
    859  *  - A fragment shader object that always sets green color for rasterized
    860  *   fragments.
    861  *
    862  *  Compile the shaders, attach them to the program object, link the program
    863  *  object.
    864  *
    865  *  Generate a texture object of type GL_RGBA8 type and of resolution:
    866  *
    867  *                     (GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT*9)x9
    868  *
    869  *  Generate a FBO and attach the texture object to its color attachment.
    870  *
    871  *  Bind the FBO to GL_FRAMEBUFFER target and clear the attachments with red
    872  *  color.
    873  *
    874  *  Generate a vertex array object, bind it.
    875  *
    876  *  Use the program object and issue a draw call for a single point.
    877  *
    878  *  Read back texture object data. The test succeeds if correct amount of
    879  *  triangles was rendered at expected locations. To test this: :
    880  *
    881  *  * Let n = (GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT - 1);
    882  *  * Let (x1, y1) = ((n)     * 9,     0);
    883  *  * Let (x2, y2) = ((n)     * 9,     0);
    884  *  * Let (x3, y3) = ((n + 1) * 9 - 1, 9 - 1);
    885  *  * Triangle rendered in last invocation is described by vertices at
    886  *   coordinates (x_i, y_i) where i e {1, 2, 3}.
    887  *  * Centroid of this triangle is defined by (x', y') where:
    888  *
    889  *                      x' = floor( (x1 + x2 + x3) / 3);
    890  *                      y' = floor( (y1 + y2 + y3) / 3);
    891  *
    892  *  * Pixel at (x',    y') should be set to (0, 255, 0, 0) (allowed epsilon: 0)
    893  *  * Pixel at (n*9-1, 9)  should be set to red color      (allowed epsilon: 0)
    894  *
    895  *  Repeat this test for a geometry shader with no number of invocations
    896  *  defined, in which case only one triangle should be rendered.
    897  **/
    898 class GeometryShaderMaxInvocationsTest : public TestCaseBase
    899 {
    900 public:
    901 	/* Public methods */
    902 	GeometryShaderMaxInvocationsTest(Context& context, const ExtParameters& extParams, const char* name,
    903 									 const char* description);
    904 
    905 	virtual ~GeometryShaderMaxInvocationsTest()
    906 	{
    907 	}
    908 
    909 	virtual void		  deinit(void);
    910 	virtual IterateResult iterate(void);
    911 
    912 private:
    913 	/* Private methods */
    914 	void initTest(void);
    915 
    916 	/* Verification of results */
    917 	bool verifyResultOfMultipleInvocationsPass(unsigned char* result_image);
    918 	bool verifyResultOfSingleInvocationPass(unsigned char* result_image);
    919 
    920 	/* Private fields */
    921 	/* Program and shader ids for multiple GS invocations */
    922 	glw::GLuint m_fragment_shader_id_for_multiple_invocations_pass;
    923 	glw::GLuint m_geometry_shader_id_for_multiple_invocations_pass;
    924 	glw::GLuint m_program_object_id_for_multiple_invocations_pass;
    925 	glw::GLuint m_vertex_shader_id_for_multiple_invocations_pass;
    926 
    927 	/* Program and shader ids for single GS invocation */
    928 	glw::GLuint m_fragment_shader_id_for_single_invocation_pass;
    929 	glw::GLuint m_geometry_shader_id_for_single_invocation_pass;
    930 	glw::GLuint m_program_object_id_for_single_invocation_pass;
    931 	glw::GLuint m_vertex_shader_id_for_single_invocation_pass;
    932 
    933 	/* Shaders' code */
    934 	static const glw::GLchar* const m_fragment_shader_code;
    935 	static const glw::GLchar* const m_geometry_shader_code_preamble;
    936 	static const glw::GLchar* const m_geometry_shader_code_layout;
    937 	static const glw::GLchar* const m_geometry_shader_code_layout_invocations;
    938 	static const glw::GLchar* const m_geometry_shader_code_body;
    939 	static const glw::GLchar* const m_vertex_shader_code;
    940 
    941 	const glw::GLchar* m_geometry_shader_parts_for_multiple_invocations_pass[16];
    942 	const glw::GLchar* m_geometry_shader_parts_for_single_invocation_pass[16];
    943 
    944 	/* Max GS invocations */
    945 	glw::GLint m_max_geometry_shader_invocations;
    946 
    947 	/* String used to store maximum number of GS invocations */
    948 	std::string m_max_geometry_shader_invocations_string;
    949 
    950 	/* Framebuffer */
    951 	glw::GLuint m_framebuffer_object_id;
    952 	glw::GLuint m_color_texture_id;
    953 
    954 	/* Framebuffer dimensions */
    955 	glw::GLuint				 m_texture_width;
    956 	static const glw::GLuint m_triangle_edge_length;
    957 	static const glw::GLuint m_texture_height;
    958 	static const glw::GLuint m_texture_pixel_size;
    959 
    960 	/* Vertex array object */
    961 	glw::GLuint m_vertex_array_object_id;
    962 };
    963 
    964 /** Implementation of test case 16.9. Test description follows:
    965  *
    966  *  Make sure it is possible to use up to GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
    967  *  texture image units in three different stages, with an assumption that
    968  *  each access to the same texture unit from a different stage counts as
    969  *  a separate texture unit access.
    970  *
    971  *  Category: API;
    972  *           Functional Test.
    973  *
    974  *  Create max(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
    975  *  GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT, GL_MAX_TEXTURE_IMAGE_UNITS)
    976  *  immutable texture objects. Each texture should use GL_R32UI internal
    977  *  format, have 1x1 resolution and contain an unique intensity equal to
    978  *  index of the texture, where first texture object created is considered
    979  *  to have index equal to 1.
    980  *
    981  *  We want each stage to use at least one texture unit. Use the following
    982  *  calculations to determine how many samplers should be defined for each
    983  *  stage:
    984  *
    985  *  1) Vertex stage: n_vertex_smpl = max(1,
    986  *    min(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - 2,
    987  *        GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS) ).
    988  *  2) Fragment stage: n_frag_smpl = max(1,
    989  *    min(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - n_vertex_smpl - 1,
    990  *        GL_MAX_TEXTURE_IMAGE_UNITS) )
    991  *  3) Geometry shader: n_geom_smpl = max(1,
    992  *    min(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - n_vertex_smpl - n_frag_smpl,
    993  *        GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT) )
    994  *
    995  *  Create a program object and fragment, geometry and vertex shader objects:
    996  *
    997  *  - Vertex shader object should define exactly n_vertex_smpl 2D texture
    998  *   samplers named samplerX where X stands for texture unit index that
    999  *   will be accessed. It should set gl_Position to:
   1000  *
   1001  *     (-1 + gl_VertexID / GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, -1, 0, 1)
   1002  *
   1003  *  Vertex shader should define int output variable out_vs_vertexid storing
   1004  *  gl_VertexID value, and an output integer variable out_vs_vertex that
   1005  *  should be written result of the following computation:
   1006  *
   1007  *  sum(i=0..n_vertex_smpl)( (gl_VertexID == i) * (value sampled from the
   1008  *  texture sampler samplerX)) where: X = i;
   1009  *
   1010  *  - Geometry shader object should define exactly n_geom_smpl 2D texture
   1011  *   samplers named samplerX where X stands for texture unit index that
   1012  *   will be accessed. The geometry shader should define int input variables
   1013  *   out_vs_vertexid, out_vs_vertex and int output variables:
   1014  *
   1015  *  * out_gs_vertexid - set to the value of out_vs_vertexid;
   1016  *  * out_gs_vertex   - set to the value of out_vs_vertex;
   1017  *  * out_geometry that should be written result of the following computation:
   1018  *
   1019  *  sum(i=0..n_geom_smpl)( (out_vs_vertexid == i) * (value sampled from the
   1020  *  texture sampler samplerX)) where: X = i;
   1021  *
   1022  *  The geometry shader should emit exactly one point at position configured
   1023  *  by vertex shader. The geometry shader should take points as input.
   1024  *
   1025  *  - Fragment shader object should define exactly n_frag_smpl 2D texture
   1026  *   samplers named samplerX where X stands for texture unit index that
   1027  *   will be accessed. The fragment shader should define int input variables
   1028  *   out_gs_vertexid, out_gs_vertex and out_geometry. It should define
   1029  *   a single int output variable result which should be written result of
   1030  *   the following computation:
   1031  *
   1032  *  if (out_gs_vertex == out_geometry)
   1033  *  {
   1034  *     set to sum(i=0..n_frag_smpl)(out_gs_vertex_id == i) * (value sampled
   1035  *     from the texture sampler samplerX)) where: X = i;
   1036  *  }
   1037  *  else
   1038  *  {
   1039  *     set to 0.
   1040  *  }
   1041  *
   1042  *  The shaders should be attached to the program object and compiled. The
   1043  *  program object should be linked.
   1044  *
   1045  *  Assume:
   1046  *
   1047  *  min_texture_image_units = min(
   1048  *  GL_MAX_TEXTURE_IMAGE_UNITS, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
   1049  *  GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT);
   1050  *
   1051  *  A framebuffer object should be created, along with a 2D texture object of
   1052  *  min_texture_image_units x 1 resolution. The texture object should be
   1053  *  attached to color attachment point of the FBO. Bind the framebuffer object
   1054  *  to GL_DRAW_FRAMEBUFFER target.
   1055  *
   1056  *  A vertex array object should be created and bound.
   1057  *
   1058  *  Configure the program object's uniform samplers to use consecutive texture
   1059  *  image units. Bind the texture objects we created at the beginning to these
   1060  *  texture units. Draw exactly min_texture_image_units points.
   1061  *
   1062  *  Bind the FBO to GL_READ_FRAMEBUFFER. Read the rendered data and make sure
   1063  *  the result values form a (1, 2, ... min_texture_image_units) set.
   1064  **/
   1065 class GeometryShaderMaxCombinedTextureUnitsTest : public GeometryShaderLimitsRenderingBase
   1066 {
   1067 public:
   1068 	/* Public methods */
   1069 	GeometryShaderMaxCombinedTextureUnitsTest(Context& context, const ExtParameters& extParams, const char* name,
   1070 											  const char* description);
   1071 
   1072 	virtual ~GeometryShaderMaxCombinedTextureUnitsTest()
   1073 	{
   1074 	}
   1075 
   1076 protected:
   1077 	/* Methods overriden from GeometryShaderLimitsRenderingBase */
   1078 	virtual void clean();
   1079 
   1080 	virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices);
   1081 
   1082 	virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format,
   1083 									   glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width,
   1084 									   glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size);
   1085 
   1086 	virtual void getRequiredPointSize(glw::GLfloat& out_point_size);
   1087 
   1088 	virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
   1089 								glw::GLuint&			   out_n_fragment_shader_parts,
   1090 								const glw::GLchar* const*& out_geometry_shader_parts,
   1091 								glw::GLuint&			   out_n_geometry_shader_parts,
   1092 								const glw::GLchar* const*& out_vertex_shader_parts,
   1093 								glw::GLuint&			   out_n_vertex_shader_parts);
   1094 
   1095 	virtual void prepareProgramInput();
   1096 	virtual bool verifyResult(const void* data);
   1097 
   1098 private:
   1099 	/* Private types */
   1100 	struct _texture_data
   1101 	{
   1102 		glw::GLuint texture_id;
   1103 		glw::GLuint data;
   1104 	};
   1105 	typedef std::vector<_texture_data> textureContainer;
   1106 
   1107 	/* Private fields */
   1108 	/* Shaders' code */
   1109 	static const glw::GLchar* const m_fragment_shader_code_preamble;
   1110 	static const glw::GLchar* const m_fragment_shader_code_body;
   1111 	static const glw::GLchar* const m_geometry_shader_code_preamble;
   1112 	static const glw::GLchar* const m_geometry_shader_code_body;
   1113 	static const glw::GLchar* const m_vertex_shader_code_preamble;
   1114 	static const glw::GLchar* const m_vertex_shader_code_body;
   1115 
   1116 	/* Storage for vertex and geometry shader parts */
   1117 	const glw::GLchar* m_fragment_shader_parts[3];
   1118 	const glw::GLchar* m_geometry_shader_parts[3];
   1119 	const glw::GLchar* m_vertex_shader_parts[3];
   1120 
   1121 	/* Framebuffer dimensions */
   1122 	glw::GLuint				 m_texture_width;
   1123 	static const glw::GLuint m_texture_height;
   1124 	static const glw::GLuint m_texture_pixel_size;
   1125 	static const glw::GLuint m_point_size;
   1126 
   1127 	/* Max number of texture units */
   1128 	glw::GLint  m_max_combined_texture_units;
   1129 	glw::GLint  m_max_fragment_texture_units;
   1130 	glw::GLint  m_max_geometry_texture_units;
   1131 	glw::GLint  m_max_vertex_texture_units;
   1132 	glw::GLint  m_min_texture_units;
   1133 	glw::GLint  m_n_fragment_texture_units;
   1134 	glw::GLint  m_n_geometry_texture_units;
   1135 	glw::GLint  m_n_texture_units;
   1136 	glw::GLint  m_n_vertex_texture_units;
   1137 	std::string m_n_fragment_texture_units_string;
   1138 	std::string m_n_geometry_texture_units_string;
   1139 	std::string m_n_vertex_texture_units_string;
   1140 
   1141 	/* Texture units */
   1142 	textureContainer m_textures;
   1143 };
   1144 
   1145 } /* glcts */
   1146 
   1147 #endif // _ESEXTCGEOMETRYSHADERLIMITS_HPP
   1148