1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "esextcGeometryShaderInput.hpp"
25 
26 #include "gluContextInfo.hpp"
27 #include "glwEnums.hpp"
28 #include "glwFunctions.hpp"
29 #include "tcuTestLog.hpp"
30 #include <cstring>
31 
32 namespace glcts
33 {
34 /* Vertex shader for GeometryShader_gl_in_ArrayContents */
35 const char *const GeometryShader_gl_in_ArrayContentsTest::m_vertex_shader_code =
36     "${VERSION}\n"
37     "\n"
38     "     out  vec2 vs_gs_a;\n"
39     "flat out ivec4 vs_gs_b;\n"
40     "\n"
41     "void main()\n"
42     "{\n"
43     "    vs_gs_a = vec2 (gl_VertexID, 0);\n"
44     "    vs_gs_b = ivec4(0,           gl_VertexID, 0, 1);\n"
45     "}\n";
46 
47 /* Geometry shader for GeometryShader_gl_in_ArrayContents */
48 const char *const GeometryShader_gl_in_ArrayContentsTest::m_geometry_shader_preamble_code =
49     "${VERSION}\n"
50     "\n"
51     "${GEOMETRY_SHADER_REQUIRE}\n"
52     "\n"
53     "layout(triangles)                      in;\n"
54     "layout(triangle_strip, max_vertices=3) out;\n"
55     "\n";
56 
57 const char *const GeometryShader_gl_in_ArrayContentsTest::m_geometry_shader_code =
58     "#ifdef USE_UNSIZED_ARRAYS\n"
59     "         in  vec2 vs_gs_a[];\n"
60     "    flat in ivec4 vs_gs_b[];\n"
61     "#else\n"
62     "         in  vec2 vs_gs_a[3];\n"
63     "    flat in ivec4 vs_gs_b[3];\n"
64     "#endif\n"
65     "\n"
66     "     out  vec2 gs_fs_a;\n"
67     "flat out ivec4 gs_fs_b;\n"
68     "\n"
69     "void main()\n"
70     "{\n"
71     "    gl_Position = vec4(-1, -1, 0, 1);\n"
72     "    gs_fs_a     = vs_gs_a[0];\n"
73     "    gs_fs_b     = vs_gs_b[0];\n"
74     "    EmitVertex();\n"
75     "    \n"
76     "    gl_Position = vec4(-1, 1, 0, 1);\n"
77     "    gs_fs_a     = vs_gs_a[1];\n"
78     "    gs_fs_b     = vs_gs_b[1];\n"
79     "    EmitVertex();\n"
80     "    \n"
81     "    gl_Position = vec4(1, 1, 0, 1);\n"
82     "    gs_fs_a     = vs_gs_a[2];\n"
83     "    gs_fs_b     = vs_gs_b[2];\n"
84     "    EmitVertex();\n"
85     "    \n"
86     "    EndPrimitive();\n"
87     "}\n";
88 
89 /* Fragment shader for GeometryShader_gl_in_ArrayContents */
90 const char *const GeometryShader_gl_in_ArrayContentsTest::m_fragment_shader_code =
91     "${VERSION}\n"
92     "\n"
93     "precision highp float;\n"
94     "\n"
95     "layout(location = 0) out vec4 fs_out_color;\n"
96     "\n"
97     "void main()\n"
98     "{\n"
99     "    fs_out_color = vec4(1, 1, 1, 1);\n"
100     "}\n";
101 
102 /* Vertex Shader for GeometryShader_gl_in_ArrayLengthTest*/
103 const char *const GeometryShader_gl_in_ArrayLengthTest::m_vertex_shader_code =
104     "${VERSION}\n"
105     "\n"
106     "void main()\n"
107     "{\n"
108     "    gl_Position = vec4(gl_VertexID, 0, 0, 1);\n"
109     "}\n";
110 
111 /* Geometry shader body parts for GeometryShader_gl_in_ArrayLengthTest */
112 const char *const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_preamble = "${VERSION}\n"
113                                                                                           "\n"
114                                                                                           "${GEOMETRY_SHADER_REQUIRE}\n"
115                                                                                           "\n";
116 
117 const char *const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_points =
118     "layout(points)                     in;\n";
119 
120 const char *const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_lines =
121     "layout(lines)                      in;\n";
122 
123 const char *const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_lines_with_adjacency =
124     "layout(lines_adjacency)            in;\n";
125 
126 const char *const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_triangles =
127     "layout(triangles)                  in;\n";
128 
129 const char *const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_triangles_with_adjacency =
130     "layout(triangles_adjacency)        in;\n";
131 
132 const char *const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_output_points =
133     "layout(points, max_vertices=1)     out;\n"
134     "\n"
135     "#define N_OUT_VERTICES (1)\n";
136 
137 const char *const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_output_line_strip =
138     "layout(line_strip, max_vertices=2) out;\n"
139     "\n"
140     "#define N_OUT_VERTICES (2)\n";
141 
142 const char *const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_output_triangle_strip =
143     "layout(triangle_strip, max_vertices=3) out;\n"
144     "\n"
145     "#define N_OUT_VERTICES (3)\n";
146 
147 const char *const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_main =
148     "\n"
149     "flat out int in_array_size;\n"
150     "\n"
151     "void main()\n"
152     "{\n"
153     "    for (int n = 0; n < N_OUT_VERTICES; n++)\n"
154     "    {\n"
155     "        in_array_size = gl_in.length();\n"
156     "        EmitVertex();\n"
157     "    }\n"
158     "\n"
159     "    EndPrimitive();\n"
160     "}\n";
161 
162 /* Fragment Shader for GeometryShader_gl_in_ArrayLengthTest */
163 const char *const GeometryShader_gl_in_ArrayLengthTest::m_fragment_shader_code = "${VERSION}\n"
164                                                                                  "\n"
165                                                                                  "precision highp float;\n"
166                                                                                  "\n"
167                                                                                  "void main()\n"
168                                                                                  "{\n"
169                                                                                  "}\n";
170 
171 /* Vertex Shader for GeometryShader_gl_PointSize_ValueTest */
172 const char *const GeometryShader_gl_PointSize_ValueTest::m_vertex_shader_code =
173     "${VERSION}\n"
174     "\n"
175     "void main()\n"
176     "{\n"
177     "    // See test description for explanation of magic numbers\n"
178     "    switch (gl_VertexID)\n"
179     "    {\n"
180     "        case 0:\n"
181     "        {\n"
182     "            gl_Position = vec4(-7.0/8.0, 0, 0, 1);\n"
183     "\n"
184     "            break;\n"
185     "        }\n"
186     "\n"
187     "        case 1:\n"
188     "        {\n"
189     "            gl_Position = vec4(6.0/8.0, 0, 0, 1);\n"
190     "\n"
191     "            break;\n"
192     "        }\n"
193     "    }\n"
194     "\n"
195     "    gl_PointSize = float(2 * (gl_VertexID + 1));\n"
196     "}\n";
197 
198 /* Geometry Shader for GeometryShader_gl_PointSize_ValueTest */
199 const char *const GeometryShader_gl_PointSize_ValueTest::m_geometry_shader_code =
200     "${VERSION}\n"
201     "\n"
202     "${GEOMETRY_SHADER_REQUIRE}\n"
203     "${GEOMETRY_POINT_SIZE_REQUIRE}\n"
204     "\n"
205     "layout(points)                 in;\n"
206     "layout(points, max_vertices=1) out;\n"
207     "\n"
208     "void main()\n"
209     "{\n"
210     "    gl_Position  = gl_in[0].gl_Position;\n"
211     "    gl_PointSize = gl_in[0].gl_PointSize * 2.0;\n"
212     "    EmitVertex();\n"
213     "    \n"
214     "    EndPrimitive();\n"
215     "}\n";
216 
217 /* Fragment Shader for GeometryShader_gl_PointSize_ValueTest */
218 const char *const GeometryShader_gl_PointSize_ValueTest::m_fragment_shader_code =
219     "${VERSION}\n"
220     "\n"
221     "precision highp float;\n"
222     "\n"
223     "layout(location = 0) out vec4 fs_out_color;\n"
224     "\n"
225     "void main()\n"
226     "{\n"
227     "    fs_out_color = vec4(1, 1, 1, 1);\n"
228     "}\n";
229 
230 /* Vertex Shader for GeometryShader_gl_Position_ValueTest */
231 const char *const GeometryShader_gl_Position_ValueTest::m_vertex_shader_code =
232     "${VERSION}\n"
233     "\n"
234     "void main()\n"
235     "{\n"
236     "    gl_Position = vec4(gl_VertexID, gl_VertexID, 0, 1);\n"
237     "\n"
238     "}\n";
239 
240 /* Geometry Shader for GeometryShader_gl_Position_ValueTest */
241 const char *const GeometryShader_gl_Position_ValueTest::m_geometry_shader_code =
242     "${VERSION}\n"
243     "\n"
244     "${GEOMETRY_SHADER_REQUIRE}\n"
245     "${GEOMETRY_POINT_SIZE_REQUIRE}\n"
246     "\n"
247     "layout(points)                 in;\n"
248     "layout(points, max_vertices=1) out;\n"
249     "\n"
250     "void main()\n"
251     "{\n"
252     "    // See test description for discussion on the magic numbers\n"
253     "    gl_Position  = vec4(-1.0 + 4.0/32.0 + gl_in[0].gl_Position.x / 4.0, 0, 0, 1);\n"
254     "    gl_PointSize = 8.0;\n"
255     "    EmitVertex();\n"
256     "\n"
257     "    EndPrimitive();\n"
258     "}\n";
259 
260 /* Fragment Shader for GeometryShader_gl_Position_ValueTest */
261 const char *const GeometryShader_gl_Position_ValueTest::m_fragment_shader_code =
262     "${VERSION}\n"
263     "\n"
264     "precision highp float;\n"
265     "\n"
266     "layout(location = 0) out vec4 fs_out_color;\n"
267     "\n"
268     "void main()\n"
269     "{\n"
270     "    fs_out_color = vec4(1, 1, 1, 1);\n"
271     "}\n";
272 
273 /* Constants for GeometryShader_gl_in_ArrayContentsTest */
274 const unsigned int GeometryShader_gl_in_ArrayContentsTest::m_n_bytes_emitted_per_vertex =
275     2 * sizeof(glw::GLfloat) + 4 * sizeof(glw::GLint);
276 const unsigned int GeometryShader_gl_in_ArrayContentsTest::m_n_emitted_primitives             = 1;
277 const unsigned int GeometryShader_gl_in_ArrayContentsTest::m_n_vertices_emitted_per_primitive = 3;
278 
279 const unsigned int GeometryShader_gl_in_ArrayContentsTest::m_buffer_size =
280     GeometryShader_gl_in_ArrayContentsTest::m_n_bytes_emitted_per_vertex *
281     GeometryShader_gl_in_ArrayContentsTest::m_n_vertices_emitted_per_primitive *
282     GeometryShader_gl_in_ArrayContentsTest::m_n_emitted_primitives;
283 
284 /* Constants for GeometryShader_gl_in_ArrayLengthTest */
285 const glw::GLuint GeometryShader_gl_in_ArrayLengthTest::m_max_primitive_emitted = 6;
286 const glw::GLuint GeometryShader_gl_in_ArrayLengthTest::m_buffer_size = sizeof(glw::GLint) * m_max_primitive_emitted;
287 
288 /* Constants for GeometryShader_gl_PointSize_ValueTest */
289 const glw::GLuint GeometryShader_gl_PointSize_ValueTest::m_texture_height     = 16;
290 const glw::GLuint GeometryShader_gl_PointSize_ValueTest::m_texture_pixel_size = 4;
291 const glw::GLuint GeometryShader_gl_PointSize_ValueTest::m_texture_width      = 16;
292 
293 /* Constants for GeometryShader_gl_Position_ValueTest */
294 const glw::GLuint GeometryShader_gl_Position_ValueTest::m_texture_height     = 64;
295 const glw::GLuint GeometryShader_gl_Position_ValueTest::m_texture_pixel_size = 4;
296 const glw::GLuint GeometryShader_gl_Position_ValueTest::m_texture_width      = 64;
297 
298 /** Constructor
299  *
300  * @param context       Test context
301  * @param name          Test case's name
302  * @param description   Test case's desricption
303  **/
GeometryShader_gl_in_ArrayContentsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)304 GeometryShader_gl_in_ArrayContentsTest::GeometryShader_gl_in_ArrayContentsTest(Context &context,
305                                                                                const ExtParameters &extParams,
306                                                                                const char *name,
307                                                                                const char *description)
308     : TestCaseBase(context, extParams, name, description)
309     , m_fragment_shader_id(0)
310     , m_geometry_shader_sized_arrays_id(0)
311     , m_geometry_shader_unsized_arrays_id(0)
312     , m_program_object_sized_arrays_id(0)
313     , m_program_object_unsized_arrays_id(0)
314     , m_vertex_shader_id(0)
315     , m_buffer_object_id(0)
316     , m_vertex_array_object_id(0)
317 {
318     /* Nothing to be done here */
319 }
320 
321 /** Initializes GLES objects used during the test.
322  *
323  **/
initTest()324 void GeometryShader_gl_in_ArrayContentsTest::initTest()
325 {
326     /* Varing names */
327     const glw::GLchar *const captured_varyings[] = {
328         "gs_fs_a",
329         "gs_fs_b",
330     };
331 
332     /* Number of varings */
333     const glw::GLuint n_captured_varyings_size = sizeof(captured_varyings) / sizeof(captured_varyings[0]);
334 
335     /* GL */
336     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
337 
338     /* Create program and shaders */
339     m_program_object_sized_arrays_id   = gl.createProgram();
340     m_program_object_unsized_arrays_id = gl.createProgram();
341 
342     m_fragment_shader_id                = gl.createShader(GL_FRAGMENT_SHADER);
343     m_geometry_shader_unsized_arrays_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
344     m_geometry_shader_sized_arrays_id   = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
345     m_vertex_shader_id                  = gl.createShader(GL_VERTEX_SHADER);
346 
347     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program");
348 
349     /* Set up transform feedback */
350     gl.transformFeedbackVaryings(m_program_object_sized_arrays_id, n_captured_varyings_size, captured_varyings,
351                                  GL_INTERLEAVED_ATTRIBS);
352     gl.transformFeedbackVaryings(m_program_object_unsized_arrays_id, n_captured_varyings_size, captured_varyings,
353                                  GL_INTERLEAVED_ATTRIBS);
354 
355     /* Build programs */
356     const char *geometry_shader_unsized_arrays_code[] = {m_geometry_shader_preamble_code,
357                                                          "#define USE_UNSIZED_ARRAYS\n", m_geometry_shader_code};
358     const char *geometry_shader_sized_arrays_code[]   = {m_geometry_shader_preamble_code, m_geometry_shader_code};
359 
360     if (false ==
361         buildProgram(m_program_object_unsized_arrays_id, m_fragment_shader_id, 1 /* number of fragment shader parts */,
362                      &m_fragment_shader_code, m_geometry_shader_unsized_arrays_id,
363                      DE_LENGTH_OF_ARRAY(geometry_shader_unsized_arrays_code), geometry_shader_unsized_arrays_code,
364                      m_vertex_shader_id, 1 /* number of vertex shader parts */, &m_vertex_shader_code))
365     {
366         TCU_FAIL("Could not create a program from valid vertex/geometry (unsized arrays version)/fragment shaders");
367     }
368 
369     if (false == buildProgram(m_program_object_sized_arrays_id, m_fragment_shader_id,
370                               1 /* number of fragment shader parts */, &m_fragment_shader_code,
371                               m_geometry_shader_sized_arrays_id, DE_LENGTH_OF_ARRAY(geometry_shader_sized_arrays_code),
372                               geometry_shader_sized_arrays_code, m_vertex_shader_id,
373                               1 /* number of vertex shader parts */, &m_vertex_shader_code))
374     {
375         TCU_FAIL("Could not create a program from valid vertex/geometry (sized arrays version)/fragment shaders");
376     }
377 
378     /* Generate, bind and allocate buffer */
379     gl.genBuffers(1, &m_buffer_object_id);
380     gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_object_id);
381     gl.bufferData(GL_ARRAY_BUFFER, m_buffer_size, 0 /* no start data */, GL_STATIC_DRAW);
382 
383     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create buffer object");
384 
385     /* Generate and bind VAO */
386     gl.genVertexArrays(1, &m_vertex_array_object_id);
387     gl.bindVertexArray(m_vertex_array_object_id);
388 
389     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
390 }
391 
392 /** Executes the test.
393  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
394  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
395  *  Note the function throws exception should an error occur!
396  **/
iterate()397 tcu::TestCase::IterateResult GeometryShader_gl_in_ArrayContentsTest::iterate()
398 {
399     /* This test should only run if EXT_geometry_shader is supported */
400     if (true != m_is_geometry_shader_extension_supported)
401     {
402         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
403     }
404 
405     initTest();
406 
407     const glw::Functions &gl                    = m_context.getRenderContext().getFunctions();
408     unsigned char reference_data[m_buffer_size] = {0};
409     bool result                                 = true;
410 
411     /* Prepare reference data */
412     {
413         glw::GLint *ivec4_data_ptr;
414         glw::GLfloat *vec2_data_ptr;
415 
416         const unsigned int ivec4_offset_from_vertex = 2 * sizeof(glw::GLfloat);
417         const unsigned int vec2_offset_from_vertex  = 0;
418 
419         /* Expected data for vertex:
420          * vec2  = {VertexID, 0.0f}
421          * ivec4 = {0,        VertexID, 0, 1}
422          */
423         for (unsigned int vertex_id = 0; vertex_id < m_n_vertices_emitted_per_primitive * m_n_emitted_primitives;
424              ++vertex_id)
425         {
426             const unsigned int vertex_offset = vertex_id * m_n_bytes_emitted_per_vertex;
427             const unsigned int ivec4_offset  = vertex_offset + ivec4_offset_from_vertex;
428             const unsigned int vec2_offset   = vertex_offset + vec2_offset_from_vertex;
429 
430             ivec4_data_ptr = (glw::GLint *)(reference_data + ivec4_offset);
431             vec2_data_ptr  = (glw::GLfloat *)(reference_data + vec2_offset);
432 
433             ivec4_data_ptr[0] = 0;
434             ivec4_data_ptr[1] = vertex_id;
435             ivec4_data_ptr[2] = 0;
436             ivec4_data_ptr[3] = 1;
437 
438             vec2_data_ptr[0] = (float)vertex_id;
439             vec2_data_ptr[1] = 0.0f;
440         }
441     }
442 
443     /* Setup transform feedback */
444     gl.enable(GL_RASTERIZER_DISCARD);
445     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_object_id);
446 
447     /* Draw the geometry */
448     for (int n_case = 0; n_case < 2 /* unsized/sized array cases */; ++n_case)
449     {
450         glw::GLuint po_id = (n_case == 0) ? m_program_object_unsized_arrays_id : m_program_object_sized_arrays_id;
451 
452         gl.useProgram(po_id);
453         gl.beginTransformFeedback(GL_TRIANGLES);
454         {
455             gl.drawArrays(GL_TRIANGLES, 0 /* first */, 3 /* one triangle */);
456         }
457         gl.endTransformFeedback();
458 
459         GLU_EXPECT_NO_ERROR(gl.getError(), "Error doing a draw call");
460 
461         /* Map buffer object storage holding XFB result into process space. */
462         glw::GLchar *transform_feedback_data = (glw::GLchar *)gl.mapBufferRange(
463             GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, m_buffer_size, GL_MAP_READ_BIT);
464 
465         GLU_EXPECT_NO_ERROR(gl.getError(), "Could not map the buffer object into process space");
466 
467         /* Verify data extracted from transform feedback */
468         if (0 != memcmp(transform_feedback_data, reference_data, m_buffer_size))
469         {
470             m_testCtx.getLog() << tcu::TestLog::Message << "Data extracted from transform feedback is invalid."
471                                << tcu::TestLog::EndMessage;
472 
473             result = false;
474         }
475 
476         /* Unmap the buffer object. */
477         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
478 
479         GLU_EXPECT_NO_ERROR(gl.getError(), "Error unmapping the buffer object");
480 
481         /* Verify results */
482         if (true != result)
483         {
484             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
485             return STOP;
486         }
487     }
488 
489     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
490     return STOP;
491 }
492 
493 /** Deinitializes GLES objects created during the test.
494  *
495  */
deinit()496 void GeometryShader_gl_in_ArrayContentsTest::deinit()
497 {
498     /* GL */
499     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
500 
501     /* Bind default values */
502     gl.useProgram(0);
503     gl.bindVertexArray(0);
504     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, 0 /* id */);
505     gl.bindBuffer(GL_ARRAY_BUFFER, 0);
506 
507     /* Delete everything */
508     if (0 != m_vertex_array_object_id)
509     {
510         gl.deleteVertexArrays(1, &m_vertex_array_object_id);
511     }
512 
513     if (0 != m_buffer_object_id)
514     {
515         gl.deleteBuffers(1, &m_buffer_object_id);
516     }
517 
518     if (0 != m_program_object_sized_arrays_id)
519     {
520         gl.deleteProgram(m_program_object_sized_arrays_id);
521     }
522 
523     if (0 != m_program_object_unsized_arrays_id)
524     {
525         gl.deleteProgram(m_program_object_unsized_arrays_id);
526     }
527 
528     if (0 != m_fragment_shader_id)
529     {
530         gl.deleteShader(m_fragment_shader_id);
531     }
532 
533     if (0 != m_geometry_shader_sized_arrays_id)
534     {
535         gl.deleteShader(m_geometry_shader_sized_arrays_id);
536     }
537 
538     if (0 != m_geometry_shader_unsized_arrays_id)
539     {
540         gl.deleteShader(m_geometry_shader_unsized_arrays_id);
541     }
542 
543     if (0 != m_vertex_shader_id)
544     {
545         gl.deleteShader(m_vertex_shader_id);
546     }
547 
548     /* Deinitialize Base */
549     TestCaseBase::deinit();
550 }
551 
552 /** Constructor
553  *
554  * @param context       Test context
555  * @param name          Test case's name
556  * @param description   Test case's desricption
557  **/
GeometryShader_gl_in_ArrayLengthTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)558 GeometryShader_gl_in_ArrayLengthTest::GeometryShader_gl_in_ArrayLengthTest(Context &context,
559                                                                            const ExtParameters &extParams,
560                                                                            const char *name, const char *description)
561     : TestCaseBase(context, extParams, name, description)
562     , m_buffer_object_id(0)
563     , m_vertex_array_object_id(0)
564 {
565     /* Nothing to be done here */
566 }
567 
568 /** Initialize test case
569  *
570  **/
init()571 void GeometryShader_gl_in_ArrayLengthTest::init()
572 {
573     /* Initialize Base */
574     TestCaseBase::init();
575 
576     /* Captured variables */
577     const char *captured_varyings[] = {"in_array_size"};
578 
579     /* This test should only run if EXT_geometry_shader is supported */
580     if (true != m_is_geometry_shader_extension_supported)
581     {
582         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
583     }
584 
585     /* GL */
586     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
587 
588     /* Set up test descriptors */
589     initCase(m_test_lines, GL_LINES, 2, /* number of vertices */
590              2,                         /* as per spec */
591              GL_POINTS, m_geometry_shader_code_input_lines, m_geometry_shader_code_output_points);
592 
593     m_tests.push_back(&m_test_lines);
594 
595     initCase(m_test_lines_adjacency, m_glExtTokens.LINES_ADJACENCY, 4, /* number of vertices */
596              4,                                                        /* as per spec */
597              GL_POINTS, m_geometry_shader_code_input_lines_with_adjacency, m_geometry_shader_code_output_points);
598 
599     m_tests.push_back(&m_test_lines_adjacency);
600 
601     initCase(m_test_points, GL_POINTS, 1, /* number of vertices */
602              1,                           /* as per spec */
603              GL_POINTS, m_geometry_shader_code_input_points, m_geometry_shader_code_output_points);
604 
605     m_tests.push_back(&m_test_points);
606 
607     initCase(m_test_triangles, GL_TRIANGLES, 3, /* number of vertices */
608              3,                                 /* as per spec */
609              GL_POINTS, m_geometry_shader_code_input_triangles, m_geometry_shader_code_output_points);
610 
611     m_tests.push_back(&m_test_triangles);
612 
613     initCase(m_test_triangles_adjacency, m_glExtTokens.TRIANGLE_STRIP_ADJACENCY, 6, /* number of vertices */
614              6,                                                                     /* as per spec */
615              GL_POINTS, m_geometry_shader_code_input_triangles_with_adjacency, m_geometry_shader_code_output_points);
616 
617     m_tests.push_back(&m_test_triangles_adjacency);
618 
619     initCase(m_test_lines_adjacency_to_line_strip, m_glExtTokens.LINES_ADJACENCY, 4 /* number of vertices */,
620              4 /* expected array length */, GL_LINES, m_geometry_shader_code_input_lines_with_adjacency,
621              m_geometry_shader_code_output_line_strip);
622 
623     m_tests.push_back(&m_test_lines_adjacency_to_line_strip);
624 
625     initCase(m_test_triangles_adjacency_to_triangle_strip, m_glExtTokens.TRIANGLE_STRIP_ADJACENCY,
626              6 /* number of vertices */, 6 /* expected array length */, GL_TRIANGLES,
627              m_geometry_shader_code_input_triangles_with_adjacency, m_geometry_shader_code_output_triangle_strip);
628 
629     m_tests.push_back(&m_test_triangles_adjacency_to_triangle_strip);
630 
631     /* Initialize program objects */
632     for (testContainer::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
633     {
634         /* Case instance */
635         Case *test = *it;
636 
637         /* Init program */
638         initCaseProgram(*test, captured_varyings, sizeof(captured_varyings) / sizeof(captured_varyings[0]));
639     }
640 
641     /* Generate, bind and allocate buffer */
642     gl.genBuffers(1, &m_buffer_object_id);
643     gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_object_id);
644     gl.bufferData(GL_ARRAY_BUFFER, m_buffer_size, 0 /* no start data */, GL_STATIC_DRAW);
645 
646     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create buffer object");
647 
648     /* Generate and bind VAO */
649     gl.genVertexArrays(1, &m_vertex_array_object_id);
650     gl.bindVertexArray(m_vertex_array_object_id);
651 
652     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
653 }
654 
655 /** Executes the test.
656  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
657  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
658  *  Note the function throws exception should an error occur!
659  **/
iterate()660 tcu::TestCase::IterateResult GeometryShader_gl_in_ArrayLengthTest::iterate()
661 {
662     /* GL */
663     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
664 
665     /* This test should only run if EXT_geometry_shader is supported */
666     if (true != m_is_geometry_shader_extension_supported)
667     {
668         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
669     }
670 
671     /* Setup transform feedback */
672     gl.enable(GL_RASTERIZER_DISCARD);
673     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_object_id);
674 
675     /* Execute tests */
676     for (testContainer::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
677     {
678         glw::GLint result_value = 0;
679         Case *test              = *it;
680 
681         /* Execute */
682         gl.useProgram(test->po_id);
683 
684         gl.beginTransformFeedback(test->tf_mode);
685         {
686             gl.drawArrays(test->draw_call_mode, 0, /* first */
687                           test->draw_call_n_vertices);
688         }
689         gl.endTransformFeedback();
690 
691         GLU_EXPECT_NO_ERROR(gl.getError(), "Error doing a draw call");
692 
693         /* Map transform feedback results */
694         glw::GLint *result = (glw::GLint *)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */,
695                                                              sizeof(glw::GLint), GL_MAP_READ_BIT);
696 
697         GLU_EXPECT_NO_ERROR(gl.getError(), "Could not map the buffer object into process space");
698 
699         /* Extract value from transform feedback */
700         result_value = *result;
701 
702         /* Unmap transform feedback buffer */
703         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
704 
705         GLU_EXPECT_NO_ERROR(gl.getError(), "Error unmapping the buffer object");
706 
707         /* Verify results */
708         if (result_value != test->expected_array_length)
709         {
710             m_testCtx.getLog() << tcu::TestLog::Message << "Expected array length: " << test->expected_array_length
711                                << " but found: " << result_value << tcu::TestLog::EndMessage;
712 
713             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
714             return STOP;
715         }
716     }
717 
718     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
719     return STOP;
720 }
721 
722 /** Deinitializes test case
723  *
724  **/
deinit()725 void GeometryShader_gl_in_ArrayLengthTest::deinit()
726 {
727     /* GL */
728     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
729 
730     /* Bind default values */
731     gl.useProgram(0);
732     gl.bindVertexArray(0);
733     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, 0 /* id */);
734     gl.bindBuffer(GL_ARRAY_BUFFER, 0);
735     /* Delete everything */
736     if (0 != m_vertex_array_object_id)
737     {
738         gl.deleteVertexArrays(1, &m_vertex_array_object_id);
739     }
740 
741     if (0 != m_buffer_object_id)
742     {
743         gl.deleteBuffers(1, &m_buffer_object_id);
744     }
745 
746     /* Deinit test cases */
747     for (testContainer::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
748     {
749         Case *test = *it;
750 
751         deinitCase(*test);
752     }
753 
754     m_tests.clear();
755 
756     /* Deinitialize Base */
757     TestCaseBase::deinit();
758 }
759 
760 /** Deinitialize test case instance
761  *
762  * @param info Case instance
763  **/
deinitCase(Case & info)764 void GeometryShader_gl_in_ArrayLengthTest::deinitCase(Case &info)
765 {
766     /* GL */
767     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
768 
769     /* Delete everything */
770     if (0 != info.po_id)
771     {
772         gl.deleteProgram(info.po_id);
773     }
774 
775     if (0 != info.vs_id)
776     {
777         gl.deleteShader(info.vs_id);
778     }
779 
780     if (0 != info.gs_id)
781     {
782         gl.deleteShader(info.gs_id);
783     }
784 
785     if (0 != info.fs_id)
786     {
787         gl.deleteShader(info.fs_id);
788     }
789 
790     /* Clear case */
791     resetCase(info);
792 }
793 
794 /** Initialize test case instance with provided data.
795  *
796  * @param info                  Case instance;
797  * @param draw_call_mode        Primitive type used by a draw call;
798  * @param draw_call_n_vertices  Number of vertices used by a draw call;
799  * @param expected_array_length Expected size of gl_in array;
800  * @param tf_mode               Primitive type used by transform feedback;
801  * @param input_body_part       Part of geometry shader which specifies input layout;
802  * @param output_body_part      Part of geometry shader which specifies output layout;
803  **/
initCase(Case & info,glw::GLenum draw_call_mode,glw::GLint draw_call_n_vertices,glw::GLint expected_array_length,glw::GLenum tf_mode,const glw::GLchar * input_body_part,const glw::GLchar * output_body_part)804 void GeometryShader_gl_in_ArrayLengthTest::initCase(Case &info, glw::GLenum draw_call_mode,
805                                                     glw::GLint draw_call_n_vertices, glw::GLint expected_array_length,
806                                                     glw::GLenum tf_mode, const glw::GLchar *input_body_part,
807                                                     const glw::GLchar *output_body_part)
808 {
809     /* Reset case descriptor */
810     resetCase(info);
811 
812     /* Set fields */
813     info.draw_call_mode        = draw_call_mode;
814     info.draw_call_n_vertices  = draw_call_n_vertices;
815     info.expected_array_length = expected_array_length;
816     info.input_body_part       = input_body_part;
817     info.output_body_part      = output_body_part;
818     info.tf_mode               = tf_mode;
819 }
820 
821 /** Creates and build program for given Case
822  *
823  * @param info                     Case instance
824  * @param captured_varyings        Name of varyings captured by transform feedback
825  * @param n_captured_varyings_size Number of varyings captured by transform feedback
826  **/
initCaseProgram(Case & info,const glw::GLchar ** captured_varyings,glw::GLuint n_captured_varyings_size)827 void GeometryShader_gl_in_ArrayLengthTest::initCaseProgram(Case &info, const glw::GLchar **captured_varyings,
828                                                            glw::GLuint n_captured_varyings_size)
829 {
830     /* GL */
831     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
832 
833     /* Create program and shader objects */
834     info.po_id = gl.createProgram();
835 
836     info.vs_id = gl.createShader(GL_VERTEX_SHADER);
837     info.gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
838     info.fs_id = gl.createShader(GL_FRAGMENT_SHADER);
839 
840     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create program object");
841 
842     /* Prepare geometry shader parts */
843     const char *const geometry_shader_parts[] = {m_geometry_shader_code_preamble, info.input_body_part,
844                                                  info.output_body_part, m_geometry_shader_code_main};
845 
846     /* Set up transform feedback */
847     gl.transformFeedbackVaryings(info.po_id, n_captured_varyings_size, captured_varyings, GL_SEPARATE_ATTRIBS);
848 
849     /* Build program */
850     if (false == buildProgram(info.po_id, info.fs_id, 1 /* number of fragment shader code parts */,
851                               &m_fragment_shader_code, info.gs_id, DE_LENGTH_OF_ARRAY(geometry_shader_parts),
852                               geometry_shader_parts, info.vs_id, 1 /* number of vertex shader code parts */,
853                               &m_vertex_shader_code))
854     {
855         TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
856     }
857 }
858 
859 /** Reset Case instance descriptor's contents.
860  *
861  * @param info Case instance
862  **/
resetCase(Case & info)863 void GeometryShader_gl_in_ArrayLengthTest::resetCase(Case &info)
864 {
865     memset(&info, 0, sizeof(info));
866 }
867 
868 /** Constructor
869  *
870  * @param context     Test context
871  * @param name        Test case's name
872  * @param description Test case's desricption
873  **/
GeometryShader_gl_PointSize_ValueTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)874 GeometryShader_gl_PointSize_ValueTest::GeometryShader_gl_PointSize_ValueTest(Context &context,
875                                                                              const ExtParameters &extParams,
876                                                                              const char *name, const char *description)
877     : TestCaseBase(context, extParams, name, description)
878     , m_fragment_shader_id(0)
879     , m_geometry_shader_id(0)
880     , m_program_object_id(0)
881     , m_vertex_shader_id(0)
882     , m_vertex_array_object_id(0)
883     , m_color_texture_id(0)
884     , m_framebuffer_object_id(0)
885 {
886     /* Nothing to be done here */
887 }
888 
889 /** Initialize test case
890  *
891  **/
init()892 void GeometryShader_gl_PointSize_ValueTest::init()
893 {
894     /* Initialize Base */
895     TestCaseBase::init();
896 
897     /* This test should only run if EXT_geometry_shader and EXT_geometry_point_size both are supported */
898     if (true != m_is_geometry_shader_extension_supported)
899     {
900         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
901     }
902 
903     if (true != m_is_geometry_shader_point_size_supported)
904     {
905         throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
906     }
907 
908     /* GL */
909     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
910 
911     /* Verify that point size range is supported */
912     glw::GLfloat point_size_range[2] = {0};
913 
914     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
915     {
916         gl.getFloatv(GL_POINT_SIZE_RANGE, point_size_range);
917     }
918     else
919     {
920         gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, point_size_range);
921     }
922 
923     if (8.0f > point_size_range[1])
924     {
925         m_testCtx.getLog() << tcu::TestLog::Message
926                            << "Test requires a minimum maximum point size of 8, implementation reports a maximum of : "
927                            << point_size_range[1] << tcu::TestLog::EndMessage;
928 
929         throw tcu::NotSupportedError("Not supported point size", "", __FILE__, __LINE__);
930     }
931 
932     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
933     {
934         gl.enable(GL_PROGRAM_POINT_SIZE);
935     }
936 
937     /* Create program and shaders */
938     m_program_object_id = gl.createProgram();
939 
940     m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
941     m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
942     m_vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
943 
944     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program");
945 
946     /* Build program */
947     if (false == buildProgram(m_program_object_id, m_fragment_shader_id, 1 /* fragment shader parts number */,
948                               &m_fragment_shader_code, m_geometry_shader_id, 1 /* geometry shader parts number */,
949                               &m_geometry_shader_code, m_vertex_shader_id, 1 /* vertex shader parts number */,
950                               &m_vertex_shader_code))
951     {
952         TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
953     }
954 
955     /* Set up texture object and a FBO */
956     gl.genTextures(1, &m_color_texture_id);
957     gl.genFramebuffers(1, &m_framebuffer_object_id);
958 
959     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create framebuffer");
960 
961     if (false == setupFramebufferWithTextureAsAttachment(m_framebuffer_object_id, m_color_texture_id, GL_RGBA8,
962                                                          m_texture_width, m_texture_height))
963     {
964         TCU_FAIL("Failed to setup framebuffer");
965     }
966 
967     /* Set up a vertex array object */
968     gl.genVertexArrays(1, &m_vertex_array_object_id);
969     gl.bindVertexArray(m_vertex_array_object_id);
970 
971     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
972 }
973 
974 /** Executes the test.
975  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
976  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
977  *  Note the function throws exception should an error occur!
978  **/
iterate()979 tcu::TestCase::IterateResult GeometryShader_gl_PointSize_ValueTest::iterate()
980 {
981     /* Buffer to store results of rendering */
982     unsigned char result_image[m_texture_width * m_texture_height * m_texture_pixel_size];
983 
984     /* This test should only run if EXT_geometry_shader is supported */
985     if (true != m_is_geometry_shader_extension_supported)
986     {
987         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
988     }
989 
990     if (true != m_is_geometry_shader_point_size_supported)
991     {
992         throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
993     }
994 
995     /* GL  */
996     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
997 
998     /* Render */
999     gl.useProgram(m_program_object_id);
1000 
1001     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to use program");
1002 
1003     gl.clearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
1004     gl.clear(GL_COLOR_BUFFER_BIT);
1005 
1006     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer");
1007 
1008     gl.drawArrays(GL_POINTS, 0 /* first */, 2 /* count */);
1009 
1010     GLU_EXPECT_NO_ERROR(gl.getError(), "Call drawArrays() failed");
1011 
1012     /* Check if the data was modified during the rendering process */
1013     gl.readPixels(0 /* x */, 0 /* y */, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, result_image);
1014 
1015     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color buffer");
1016 
1017     /* 1) pixel at (2,  8) is (255, 255, 255, 255) */
1018     unsigned int referencePixelCoordinates[2] = {2, 8};
1019 
1020     if (false == comparePixel(result_image, referencePixelCoordinates[0] /* x */, referencePixelCoordinates[1] /* y */,
1021                               m_texture_width, m_texture_height, m_texture_pixel_size, 255 /* red */, 255 /* green */,
1022                               255 /* blue */, 255 /* alpha */))
1023     {
1024         const unsigned int texel_offset = referencePixelCoordinates[1] * m_texture_width * m_texture_pixel_size +
1025                                           referencePixelCoordinates[0] * m_texture_pixel_size;
1026 
1027         m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << result_image[texel_offset + 0] << ", "
1028                            << result_image[texel_offset + 1] << ", " << result_image[texel_offset + 2] << ", "
1029                            << result_image[texel_offset + 3] << "]"
1030                            << " is different from reference data [255, 255, 255, 255]!" << tcu::TestLog::EndMessage;
1031 
1032         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1033         return STOP;
1034     }
1035 
1036     /* 2) pixel at (14, 8) is (255, 255, 255, 255) */
1037     referencePixelCoordinates[0] = 14;
1038     referencePixelCoordinates[1] = 8;
1039 
1040     if (false == comparePixel(result_image, referencePixelCoordinates[0] /* x */, referencePixelCoordinates[1] /* y */,
1041                               m_texture_width, m_texture_height, m_texture_pixel_size, 255 /* red */, 255 /* green */,
1042                               255 /* blue */, 255 /* alpha */))
1043     {
1044         const unsigned int texel_offset = referencePixelCoordinates[1] * m_texture_width * m_texture_pixel_size +
1045                                           referencePixelCoordinates[0] * m_texture_pixel_size;
1046 
1047         m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << result_image[texel_offset + 0] << ", "
1048                            << result_image[texel_offset + 1] << ", " << result_image[texel_offset + 2] << ", "
1049                            << result_image[texel_offset + 3] << "]"
1050                            << " is different from reference data [255, 255, 255, 255]!" << tcu::TestLog::EndMessage;
1051 
1052         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1053         return STOP;
1054     }
1055 
1056     /* 3) pixel at (6,  8) is (0,   0,   0,   0) */
1057     referencePixelCoordinates[0] = 6;
1058     referencePixelCoordinates[1] = 8;
1059 
1060     if (false == comparePixel(result_image, referencePixelCoordinates[0] /* x */, referencePixelCoordinates[1] /* y */,
1061                               m_texture_width, m_texture_height, m_texture_pixel_size, 0 /* red */, 0 /* green */,
1062                               0 /* blue */, 0 /* alpha */))
1063     {
1064         const unsigned int texel_offset = referencePixelCoordinates[1] * m_texture_width * m_texture_pixel_size +
1065                                           referencePixelCoordinates[0] * m_texture_pixel_size;
1066 
1067         m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << result_image[texel_offset + 0] << ", "
1068                            << result_image[texel_offset + 1] << ", " << result_image[texel_offset + 2] << ", "
1069                            << result_image[texel_offset + 3] << "]"
1070                            << "is different from reference data [0, 0, 0, 0]!" << tcu::TestLog::EndMessage;
1071 
1072         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1073         return STOP;
1074     }
1075 
1076     /* Done */
1077     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1078     return STOP;
1079 }
1080 
1081 /** Deinitializes test case
1082  *
1083  **/
deinit()1084 void GeometryShader_gl_PointSize_ValueTest::deinit()
1085 {
1086     /* GL */
1087     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1088 
1089     /* Bind defaults */
1090     gl.useProgram(0);
1091     gl.bindVertexArray(0);
1092     gl.bindTexture(GL_TEXTURE_2D, 0);
1093     gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1094     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1095     {
1096         gl.disable(GL_PROGRAM_POINT_SIZE);
1097     }
1098 
1099     /* Delete everything */
1100     if (m_program_object_id != 0)
1101     {
1102         gl.deleteProgram(m_program_object_id);
1103     }
1104 
1105     if (m_fragment_shader_id != 0)
1106     {
1107         gl.deleteShader(m_fragment_shader_id);
1108     }
1109 
1110     if (m_geometry_shader_id != 0)
1111     {
1112         gl.deleteShader(m_geometry_shader_id);
1113     }
1114 
1115     if (m_vertex_shader_id != 0)
1116     {
1117         gl.deleteShader(m_vertex_shader_id);
1118     }
1119 
1120     if (m_vertex_array_object_id != 0)
1121     {
1122         gl.deleteVertexArrays(1, &m_vertex_array_object_id);
1123     }
1124 
1125     if (m_color_texture_id != 0)
1126     {
1127         gl.deleteTextures(1, &m_color_texture_id);
1128     }
1129 
1130     if (m_framebuffer_object_id != 0)
1131     {
1132         gl.deleteFramebuffers(1, &m_framebuffer_object_id);
1133     }
1134 
1135     /* Release base class */
1136     TestCaseBase::deinit();
1137 }
1138 
1139 /** Constructor
1140  *
1141  * @param context     Test context
1142  * @param name        Test case's name
1143  * @param description Test case's desricption
1144  **/
GeometryShader_gl_Position_ValueTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)1145 GeometryShader_gl_Position_ValueTest::GeometryShader_gl_Position_ValueTest(Context &context,
1146                                                                            const ExtParameters &extParams,
1147                                                                            const char *name, const char *description)
1148     : TestCaseBase(context, extParams, name, description)
1149     , m_fragment_shader_id(0)
1150     , m_geometry_shader_id(0)
1151     , m_program_object_id(0)
1152     , m_vertex_shader_id(0)
1153     , m_vertex_array_object_id(0)
1154     , m_color_texture_id(0)
1155     , m_framebuffer_object_id(0)
1156 {
1157     /* Nothing to be done here */
1158 }
1159 
1160 /** Initialize test case
1161  *
1162  **/
init()1163 void GeometryShader_gl_Position_ValueTest::init()
1164 {
1165     /* Initialize base */
1166     TestCaseBase::init();
1167 
1168     /* This test should only run if EXT_geometry_shader is supported */
1169     if (true != m_is_geometry_shader_extension_supported)
1170     {
1171         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1172     }
1173 
1174     if (true != m_is_geometry_shader_point_size_supported)
1175     {
1176         throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
1177     }
1178 
1179     /* GL */
1180     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1181 
1182     /* Verify that point size range is supported */
1183     glw::GLfloat point_size_range[2] = {0};
1184 
1185     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1186     {
1187         gl.getFloatv(GL_POINT_SIZE_RANGE, point_size_range);
1188     }
1189     else
1190     {
1191         gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, point_size_range);
1192     }
1193 
1194     if (8.0f > point_size_range[1])
1195     {
1196         m_testCtx.getLog() << tcu::TestLog::Message
1197                            << "Test requires a minimum maximum point size of 8, implementation reports a maximum of : "
1198                            << point_size_range[1] << tcu::TestLog::EndMessage;
1199 
1200         throw tcu::NotSupportedError("Not supported point size", "", __FILE__, __LINE__);
1201     }
1202 
1203     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1204     {
1205         gl.enable(GL_PROGRAM_POINT_SIZE);
1206     }
1207 
1208     /* Create program and shaders */
1209     m_program_object_id = gl.createProgram();
1210 
1211     m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
1212     m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
1213     m_vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
1214 
1215     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program");
1216 
1217     /* Build program */
1218     if (false == buildProgram(m_program_object_id, m_fragment_shader_id, 1 /* fragment shader parts number */,
1219                               &m_fragment_shader_code, m_geometry_shader_id, 1 /* geometry shader parts number */,
1220                               &m_geometry_shader_code, m_vertex_shader_id, 1 /* vertex shader parts number */,
1221                               &m_vertex_shader_code))
1222     {
1223         TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
1224     }
1225 
1226     /* Set up a texture object and a FBO */
1227     gl.genTextures(1, &m_color_texture_id);
1228     gl.genFramebuffers(1, &m_framebuffer_object_id);
1229 
1230     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create framebuffer");
1231 
1232     if (false == setupFramebufferWithTextureAsAttachment(m_framebuffer_object_id, m_color_texture_id, GL_RGBA8,
1233                                                          m_texture_width, m_texture_height))
1234     {
1235         TCU_FAIL("Failed to setup framebuffer");
1236     }
1237 
1238     /* Set up a vertex array object */
1239     gl.genVertexArrays(1, &m_vertex_array_object_id);
1240     gl.bindVertexArray(m_vertex_array_object_id);
1241 
1242     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
1243 }
1244 
1245 /** Executes the test.
1246  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1247  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1248  *  Note the function throws exception should an error occur!
1249  **/
iterate()1250 tcu::TestCase::IterateResult GeometryShader_gl_Position_ValueTest::iterate()
1251 {
1252     /* Variables used for image verification purposes */
1253     unsigned char result_image[m_texture_width * m_texture_height * m_texture_pixel_size];
1254 
1255     /* This test should only run if EXT_geometry_shader is supported */
1256     if (true != m_is_geometry_shader_extension_supported)
1257     {
1258         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1259     }
1260 
1261     /* GL  */
1262     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1263 
1264     /* Render */
1265     gl.useProgram(m_program_object_id);
1266 
1267     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to use program");
1268 
1269     gl.clearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
1270     gl.clear(GL_COLOR_BUFFER_BIT);
1271 
1272     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer");
1273 
1274     gl.drawArrays(GL_POINTS, 0 /* first */, 8 /* count */);
1275 
1276     GLU_EXPECT_NO_ERROR(gl.getError(), "Call drawArrays() failed");
1277 
1278     /* Check if the data was modified during the rendering process */
1279     gl.readPixels(0 /* x */, 0 /* y */, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, result_image);
1280 
1281     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color buffer");
1282 
1283     /* The test passes if centers of the rendered points are lit at expected locations. */
1284     for (unsigned int x = 4; x < m_texture_width; x += 8)
1285     {
1286         if (false == comparePixel(result_image, x, 32 /* y */, m_texture_width, m_texture_height, m_texture_pixel_size,
1287                                   255 /* red */, 255 /* green */, 255 /* blue */, 255 /* alpha */))
1288         {
1289             const unsigned int texel_offset = 32 * m_texture_width * m_texture_pixel_size + x * m_texture_pixel_size;
1290 
1291             m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << result_image[texel_offset + 0] << ", "
1292                                << result_image[texel_offset + 1] << ", " << result_image[texel_offset + 2] << ", "
1293                                << result_image[texel_offset + 3] << "]"
1294                                << "is different from reference data [255, 255, 255, 255] !" << tcu::TestLog::EndMessage;
1295 
1296             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1297             return STOP;
1298         }
1299     }
1300 
1301     /* Done */
1302     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1303     return STOP;
1304 }
1305 
1306 /** Deinitializes test case
1307  *
1308  **/
deinit()1309 void GeometryShader_gl_Position_ValueTest::deinit()
1310 {
1311     /* GL */
1312     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1313 
1314     /* Bind default values */
1315     gl.useProgram(0);
1316     gl.bindVertexArray(0);
1317     gl.bindTexture(GL_TEXTURE_2D, 0);
1318     gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1319     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1320     {
1321         gl.disable(GL_PROGRAM_POINT_SIZE);
1322     }
1323 
1324     /* Delete everything */
1325     if (m_program_object_id != 0)
1326     {
1327         gl.deleteProgram(m_program_object_id);
1328     }
1329 
1330     if (m_fragment_shader_id != 0)
1331     {
1332         gl.deleteShader(m_fragment_shader_id);
1333     }
1334 
1335     if (m_geometry_shader_id != 0)
1336     {
1337         gl.deleteShader(m_geometry_shader_id);
1338     }
1339 
1340     if (m_vertex_shader_id != 0)
1341     {
1342         gl.deleteShader(m_vertex_shader_id);
1343     }
1344 
1345     if (m_vertex_array_object_id != 0)
1346     {
1347         gl.deleteVertexArrays(1, &m_vertex_array_object_id);
1348     }
1349 
1350     if (m_color_texture_id != 0)
1351     {
1352         gl.deleteTextures(1, &m_color_texture_id);
1353     }
1354 
1355     if (m_framebuffer_object_id != 0)
1356     {
1357         gl.deleteFramebuffers(1, &m_framebuffer_object_id);
1358     }
1359 
1360     /* Release base class */
1361     TestCaseBase::deinit();
1362 }
1363 
1364 } // namespace glcts
1365