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 "esextcGeometryShaderLayeredFramebuffer.hpp"
25 
26 #include "gluContextInfo.hpp"
27 #include "gluDefs.hpp"
28 #include "glwEnums.hpp"
29 #include "glwFunctions.hpp"
30 #include "tcuTestLog.hpp"
31 #include <cstring>
32 
33 namespace glcts
34 {
35 /** Constructor
36  *
37  * @param context       Test context
38  * @param name          Test case's name
39  * @param description   Test case's desricption
40  **/
GeometryShaderLayeredFramebufferBlending(Context & context,const ExtParameters & extParams,const char * name,const char * description)41 GeometryShaderLayeredFramebufferBlending::GeometryShaderLayeredFramebufferBlending(Context &context,
42                                                                                    const ExtParameters &extParams,
43                                                                                    const char *name,
44                                                                                    const char *description)
45     : TestCaseBase(context, extParams, name, description)
46     , m_fbo_id(0)
47     , m_fs_id(0)
48     , m_gs_id(0)
49     , m_po_id(0)
50     , m_read_fbo_id(0)
51     , m_to_id(0)
52     , m_vao_id(0)
53     , m_vs_id(0)
54 {
55     /* Left blank on purpose */
56 }
57 
58 /** Deinitializes GLES objects created during the test. */
deinit(void)59 void GeometryShaderLayeredFramebufferBlending::deinit(void)
60 {
61     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
62 
63     /* Clean up */
64     if (m_fbo_id != 0)
65     {
66         gl.deleteFramebuffers(1, &m_fbo_id);
67     }
68 
69     if (m_fs_id != 0)
70     {
71         gl.deleteShader(m_fs_id);
72     }
73 
74     if (m_gs_id != 0)
75     {
76         gl.deleteShader(m_gs_id);
77     }
78 
79     if (m_po_id != 0)
80     {
81         gl.deleteProgram(m_po_id);
82     }
83 
84     if (m_read_fbo_id != 0)
85     {
86         gl.deleteFramebuffers(1, &m_read_fbo_id);
87     }
88 
89     if (m_to_id != 0)
90     {
91         gl.deleteTextures(1, &m_to_id);
92     }
93 
94     if (m_vao_id != 0)
95     {
96         gl.deleteVertexArrays(1, &m_vao_id);
97     }
98 
99     if (m_vs_id != 0)
100     {
101         gl.deleteShader(m_vs_id);
102     }
103 
104     /* Release base class */
105     TestCaseBase::deinit();
106 }
107 
108 /** Executes the test.
109  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
110  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
111  *  Note the function throws exception should an error occur!
112  **/
iterate(void)113 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferBlending::iterate(void)
114 {
115 /* Test-wide constants */
116 #define N_TEXTURE_COMPONENTS (4)
117 #define TEXTURE_DEPTH (4)
118 #define TEXTURE_HEIGHT (4)
119 #define TEXTURE_WIDTH (4)
120 
121     /* Fragment shader code */
122     const char *fs_code = "${VERSION}\n"
123                           "\n"
124                           "precision highp float;\n"
125                           "\n"
126                           "out vec4 result;\n"
127                           "\n"
128                           "void main()\n"
129                           "{\n"
130                           "    result = vec4(0.2);\n"
131                           "}\n";
132 
133     /* Geometry shader code */
134     const char *gs_code = "${VERSION}\n"
135                           "${GEOMETRY_SHADER_REQUIRE}\n"
136                           "\n"
137                           "layout(points)                          in;\n"
138                           "layout(triangle_strip, max_vertices=64) out;\n"
139                           "\n"
140                           "void main()\n"
141                           "{\n"
142                           "    for (int n = 0; n < 4; ++n)\n"
143                           "    {\n"
144                           "        gl_Layer    = n;\n"
145                           "        gl_Position = vec4(1, 1, 0, 1);\n"
146                           "        EmitVertex();\n"
147                           "\n"
148                           "        gl_Layer    = n;\n"
149                           "        gl_Position = vec4(1, -1, 0, 1);\n"
150                           "        EmitVertex();\n"
151                           "\n"
152                           "        gl_Layer    = n;\n"
153                           "        gl_Position = vec4(-1, 1, 0, 1);\n"
154                           "        EmitVertex();\n"
155                           "\n"
156                           "        gl_Layer    = n;\n"
157                           "        gl_Position = vec4(-1, -1, 0, 1);\n"
158                           "        EmitVertex();\n"
159                           "\n"
160                           "        EndPrimitive();\n"
161                           "    }\n"
162                           "}\n";
163 
164     /* General variables */
165     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
166     unsigned int n           = 0;
167     unsigned int n_component = 0;
168     unsigned int n_layer     = 0;
169     unsigned int n_slice     = 0;
170     unsigned int x           = 0;
171     unsigned int y           = 0;
172 
173     unsigned char buffer[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
174     unsigned char buffer_slice1[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
175     unsigned char buffer_slice2[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
176     unsigned char buffer_slice3[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
177     unsigned char buffer_slice4[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
178     unsigned char ref_buffer_slice1[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
179     unsigned char ref_buffer_slice2[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
180     unsigned char ref_buffer_slice3[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
181     unsigned char ref_buffer_slice4[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
182 
183     if (!m_is_geometry_shader_extension_supported)
184     {
185         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
186     }
187 
188     /* Set up shader objects */
189     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
190     m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
191     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
192 
193     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate shader objects");
194 
195     /* Set up program objects */
196     m_po_id = gl.createProgram();
197 
198     if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fs_code, m_gs_id, 1 /* part */, &gs_code, m_vs_id, 1 /* part */,
199                       &m_boilerplate_vs_code))
200     {
201         TCU_FAIL("Could not build program object");
202     }
203 
204     /* Prepare texture data we will use for each slice */
205     for (n = 0; n < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++n)
206     {
207         unsigned char *slice_pixels_ptr[] = {
208             buffer_slice1 + n * N_TEXTURE_COMPONENTS, buffer_slice2 + n * N_TEXTURE_COMPONENTS,
209             buffer_slice3 + n * N_TEXTURE_COMPONENTS, buffer_slice4 + n * N_TEXTURE_COMPONENTS};
210 
211         for (n_slice = 0; n_slice < sizeof(slice_pixels_ptr) / sizeof(slice_pixels_ptr[0]); ++n_slice)
212         {
213             slice_pixels_ptr[n_slice][0] = 0;
214             slice_pixels_ptr[n_slice][1] = (unsigned char)(n_slice * 255 / 4);
215             slice_pixels_ptr[n_slice][2] = (unsigned char)(n_slice * 255 / 8);
216             slice_pixels_ptr[n_slice][3] = (unsigned char)(n_slice * 255 / 12);
217         } /* for (all slices) */
218     }     /* for (all pixels) */
219 
220     /* Calculate reference texture data we will later use when verifying the rendered data */
221     for (n = 0; n < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++n)
222     {
223         unsigned char *ref_slice_pixels_ptr[] = {
224             ref_buffer_slice1 + n * N_TEXTURE_COMPONENTS, ref_buffer_slice2 + n * N_TEXTURE_COMPONENTS,
225             ref_buffer_slice3 + n * N_TEXTURE_COMPONENTS, ref_buffer_slice4 + n * N_TEXTURE_COMPONENTS};
226 
227         unsigned char *slice_pixels_ptr[] = {
228             buffer_slice1 + n * N_TEXTURE_COMPONENTS, buffer_slice2 + n * N_TEXTURE_COMPONENTS,
229             buffer_slice3 + n * N_TEXTURE_COMPONENTS, buffer_slice4 + n * N_TEXTURE_COMPONENTS};
230 
231         for (n_slice = 0; n_slice < sizeof(slice_pixels_ptr) / sizeof(slice_pixels_ptr[0]); ++n_slice)
232         {
233             unsigned char *ref_slice_ptr = ref_slice_pixels_ptr[n_slice];
234             unsigned char *slice_ptr     = slice_pixels_ptr[n_slice];
235             float slice_rgba[]           = {
236                 float(slice_ptr[0]) / 255.0f, /* convert to FP representation */
237                 float(slice_ptr[1]) / 255.0f, /* convert to FP representation */
238                 float(slice_ptr[2]) / 255.0f, /* convert to FP representation */
239                 float(slice_ptr[3]) / 255.0f  /* convert to FP representation */
240             };
241 
242             for (n_component = 0; n_component < N_TEXTURE_COMPONENTS; ++n_component)
243             {
244                 float temp_component = slice_rgba[n_component] /* dst_color */ * slice_rgba[n_component] /* dst_color */
245                                        + 0.8f /* 1-src_color */ * 0.2f /* src_color */;
246 
247                 /* Clamp if necessary */
248                 if (temp_component < 0)
249                 {
250                     temp_component = 0.0f;
251                 }
252                 else if (temp_component > 1)
253                 {
254                     temp_component = 1.0f;
255                 }
256 
257                 /* Convert back to GL_RGBA8 */
258                 ref_slice_ptr[n_component] = (unsigned char)(temp_component * 255.0f);
259             } /* for (all components) */
260         }     /* for (all slices) */
261     }         /* for (all pixels) */
262 
263     /* Set up texture object used for the test */
264     gl.genTextures(1, &m_to_id);
265     gl.bindTexture(GL_TEXTURE_3D, m_to_id);
266     gl.texStorage3D(GL_TEXTURE_3D, 1 /* levels */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH);
267     gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH,
268                      TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice1);
269     gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH,
270                      TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice2);
271     gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH,
272                      TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice3);
273     gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH,
274                      TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice4);
275 
276     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object");
277 
278     /* Set up framebuffer object used for the test */
279     gl.genFramebuffers(1, &m_fbo_id);
280     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
281 
282     gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_id, 0 /* level */);
283 
284     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer");
285 
286     /* Generate and bind a vertex array object */
287     gl.genVertexArrays(1, &m_vao_id);
288     gl.bindVertexArray(m_vao_id);
289 
290     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up vertex array object");
291 
292     /* Set up blending */
293     gl.blendFunc(GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR);
294     gl.enable(GL_BLEND);
295 
296     /* Render */
297     gl.useProgram(m_po_id);
298     gl.viewport(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT);
299 
300     gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
301 
302     GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed");
303 
304     /* Verify rendered data in the layers */
305     gl.genFramebuffers(1, &m_read_fbo_id);
306     gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
307 
308     for (n_layer = 0; n_layer < TEXTURE_DEPTH; ++n_layer)
309     {
310         bool has_layer_failed = false;
311 
312         const unsigned char *ref_buffer = (n_layer == 0) ? ref_buffer_slice1 :
313                                           (n_layer == 1) ? ref_buffer_slice2 :
314                                           (n_layer == 2) ? ref_buffer_slice3 :
315                                                            ref_buffer_slice4;
316 
317         gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_id, 0 /* level */, n_layer);
318         gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
319 
320         GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixel data!");
321 
322         for (y = 0; y < TEXTURE_HEIGHT; ++y)
323         {
324             const unsigned int pixel_size = N_TEXTURE_COMPONENTS;
325             const unsigned char *ref_row  = ref_buffer + y * pixel_size;
326             const unsigned char *row      = buffer + y * pixel_size;
327 
328             for (x = 0; x < TEXTURE_WIDTH; ++x)
329             {
330 #define EPSILON (1)
331 
332                 const unsigned char *data     = row + x * pixel_size;
333                 const unsigned char *ref_data = ref_row + x * pixel_size;
334 
335                 if (de::abs((int)data[0] - (int)ref_data[0]) > EPSILON ||
336                     de::abs((int)data[1] - (int)ref_data[1]) > EPSILON ||
337                     de::abs((int)data[2] - (int)ref_data[2]) > EPSILON ||
338                     de::abs((int)data[3] - (int)ref_data[3]) > EPSILON)
339                 {
340                     m_testCtx.getLog() << tcu::TestLog::Message << "(layer=" << n_layer << " x=" << x << " y=" << y
341                                        << ") "
342                                        << "Reference value is different than the rendered data (epsilon > " << EPSILON
343                                        << "): "
344                                        << "(" << (unsigned int)ref_data[0] << ", " << (unsigned int)ref_data[1] << ", "
345                                        << (unsigned int)ref_data[2] << ", " << (unsigned int)ref_data[3] << ") vs "
346                                        << "(" << (unsigned int)data[0] << ", " << (unsigned int)data[1] << ", "
347                                        << (unsigned int)data[2] << ", " << (unsigned int)data[3] << ")."
348                                        << tcu::TestLog::EndMessage;
349 
350                     has_layer_failed = true;
351                 } /* if (regions are different) */
352 
353 #undef EPSILON
354             } /* for (all pixels in a row) */
355         }     /* for (all rows) */
356 
357         if (has_layer_failed)
358         {
359             TCU_FAIL("Pixel data comparison failed");
360         }
361     } /* for (all layers) */
362 
363     /* Done */
364     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
365     return STOP;
366 
367 #undef N_TEXTURE_COMPONENTS
368 #undef TEXTURE_DEPTH
369 #undef TEXTURE_HEIGHT
370 #undef TEXTURE_WIDTH
371 }
372 
373 /** Constructor
374  *
375  * @param context       Test context
376  * @param name          Test case's name
377  * @param description   Test case's description
378  **/
GeometryShaderLayeredFramebufferClear(Context & context,const ExtParameters & extParams,const char * name,const char * description)379 GeometryShaderLayeredFramebufferClear::GeometryShaderLayeredFramebufferClear(Context &context,
380                                                                              const ExtParameters &extParams,
381                                                                              const char *name, const char *description)
382     : TestCaseBase(context, extParams, name, description)
383     , m_fbo_char_id(0)
384     , m_fbo_int_id(0)
385     , m_fbo_uint_id(0)
386     , m_read_fbo_id(0)
387     , m_to_rgba32i_id(0)
388     , m_to_rgba32ui_id(0)
389     , m_to_rgba8_id(0)
390 {
391     /* Left blank on purpose */
392 }
393 
394 /** Executes the test.
395  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
396  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
397  *  Note the function throws exception should an error occur!
398  **/
iterate(void)399 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferClear::iterate(void)
400 {
401     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
402 
403 /* Test-wide definitions */
404 #define N_TEXTURE_COMPONENTS (4)
405 #define TEXTURE_DEPTH (4)
406 #define TEXTURE_HEIGHT (4)
407 #define TEXTURE_WIDTH (4)
408 
409     /* Type definitions */
410     typedef enum
411     {
412         /* Always first */
413         CLEAR_FIRST = 0,
414 
415         /* glClear() */
416         CLEAR_PLAIN = CLEAR_FIRST,
417         /* glClearBufferfv() */
418         CLEAR_BUFFERFV,
419         /* glClearBufferiv() */
420         CLEAR_BUFFERIV,
421         /* glClearBufferuiv() */
422         CLEAR_BUFFERUIV,
423 
424         /* Always last */
425         CLEAR_COUNT
426     } _clear_type;
427 
428     /* General variables */
429     const glw::GLenum fbo_draw_buffer = GL_COLOR_ATTACHMENT0;
430 
431     int n       = 0;
432     int n_layer = 0;
433     int x       = 0;
434     int y       = 0;
435 
436     unsigned char buffer_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
437     int buffer_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
438     unsigned int buffer_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
439     unsigned char slice_1_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
440     int slice_1_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
441     unsigned int slice_1_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
442     unsigned char slice_2_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
443     int slice_2_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
444     unsigned int slice_2_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
445     unsigned char slice_3_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
446     int slice_3_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
447     unsigned int slice_3_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
448     unsigned char slice_4_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
449     int slice_4_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
450     unsigned int slice_4_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
451 
452     /* Only carry on if geometry shaders are supported */
453     if (!m_is_geometry_shader_extension_supported)
454     {
455         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
456     }
457 
458     /* Set up slice data */
459     memset(slice_1_data_char, 0, sizeof(slice_1_data_char));
460     memset(slice_1_data_int, 0, sizeof(slice_1_data_int));
461     memset(slice_1_data_uint, 0, sizeof(slice_1_data_uint));
462     memset(slice_2_data_char, 0, sizeof(slice_2_data_char));
463     memset(slice_2_data_int, 0, sizeof(slice_2_data_int));
464     memset(slice_2_data_uint, 0, sizeof(slice_2_data_uint));
465     memset(slice_3_data_char, 0, sizeof(slice_3_data_char));
466     memset(slice_3_data_int, 0, sizeof(slice_3_data_int));
467     memset(slice_3_data_uint, 0, sizeof(slice_3_data_uint));
468     memset(slice_4_data_char, 0, sizeof(slice_4_data_char));
469     memset(slice_4_data_int, 0, sizeof(slice_4_data_int));
470     memset(slice_4_data_uint, 0, sizeof(slice_4_data_uint));
471 
472     for (n = 0; n < 4 /* width */ * 4 /* height */; ++n)
473     {
474         slice_1_data_char[4 * n + 0] = 255;
475         slice_1_data_int[4 * n + 0]  = 255;
476         slice_1_data_uint[4 * n + 0] = 255;
477 
478         slice_2_data_char[4 * n + 1] = 255;
479         slice_2_data_int[4 * n + 1]  = 255;
480         slice_2_data_uint[4 * n + 1] = 255;
481 
482         slice_3_data_char[4 * n + 2] = 255;
483         slice_3_data_int[4 * n + 2]  = 255;
484         slice_3_data_uint[4 * n + 2] = 255;
485 
486         slice_4_data_char[4 * n + 0] = 255;
487         slice_4_data_char[4 * n + 1] = 255;
488         slice_4_data_int[4 * n + 0]  = 255;
489         slice_4_data_int[4 * n + 1]  = 255;
490         slice_4_data_uint[4 * n + 0] = 255;
491         slice_4_data_uint[4 * n + 1] = 255;
492     } /* for (all pixels) */
493 
494     /* Set up texture objects */
495     gl.genTextures(1, &m_to_rgba8_id);
496     gl.genTextures(1, &m_to_rgba32i_id);
497     gl.genTextures(1, &m_to_rgba32ui_id);
498 
499     for (n = 0; n < 3 /* textures */; ++n)
500     {
501         void *to_data_1 = (n == 0) ? (void *)slice_1_data_char :
502                           (n == 1) ? (void *)slice_1_data_int :
503                                      (void *)slice_1_data_uint;
504 
505         void *to_data_2 = (n == 0) ? (void *)slice_2_data_char :
506                           (n == 1) ? (void *)slice_2_data_int :
507                                      (void *)slice_2_data_uint;
508 
509         void *to_data_3 = (n == 0) ? (void *)slice_3_data_char :
510                           (n == 1) ? (void *)slice_3_data_int :
511                                      (void *)slice_3_data_uint;
512 
513         void *to_data_4 = (n == 0) ? (void *)slice_4_data_char :
514                           (n == 1) ? (void *)slice_4_data_int :
515                                      (void *)slice_4_data_uint;
516 
517         glw::GLenum to_format = (n == 0) ? GL_RGBA : (n == 1) ? GL_RGBA_INTEGER : GL_RGBA_INTEGER;
518 
519         glw::GLenum to_internalformat = (n == 0) ? GL_RGBA8 : (n == 1) ? GL_RGBA32I : GL_RGBA32UI;
520 
521         glw::GLuint to_id = (n == 0) ? m_to_rgba8_id : (n == 1) ? m_to_rgba32i_id : m_to_rgba32ui_id;
522 
523         glw::GLenum to_type = (n == 0) ? GL_UNSIGNED_BYTE : (n == 1) ? GL_INT : GL_UNSIGNED_INT;
524 
525         gl.bindTexture(GL_TEXTURE_3D, to_id);
526 
527         gl.texStorage3D(GL_TEXTURE_3D, 1 /* levels */, to_internalformat, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH);
528 
529         gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH,
530                          TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_1);
531         gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH,
532                          TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_2);
533         gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH,
534                          TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_3);
535         gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH,
536                          TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_4);
537 
538         gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
539         gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0);
540         gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
541 
542         GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize texture object");
543     } /* for (all texture objects) */
544 
545     /* Set up framebuffer object */
546     gl.genFramebuffers(1, &m_fbo_char_id);
547     gl.genFramebuffers(1, &m_fbo_int_id);
548     gl.genFramebuffers(1, &m_fbo_uint_id);
549     gl.genFramebuffers(1, &m_read_fbo_id);
550 
551     for (n = 0; n < 3 /* framebuffers */; ++n)
552     {
553         glw::GLuint fbo_id = (n == 0) ? m_fbo_char_id : (n == 1) ? m_fbo_int_id : m_fbo_uint_id;
554 
555         glw::GLuint to_id = (n == 0) ? m_to_rgba8_id : (n == 1) ? m_to_rgba32i_id : m_to_rgba32ui_id;
556 
557         gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
558         gl.drawBuffers(1, &fbo_draw_buffer);
559         gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, to_id, 0 /* level */);
560 
561         GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize framebuffer object");
562     } /* for (all framebuffers) */
563 
564     /* Try reading from the layered framebuffer. */
565     gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_char_id);
566     gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer_char);
567 
568     /* Is the returned data an exact copy of what we've uploaded for layer zero? */
569     if (memcmp(buffer_char, slice_1_data_char, sizeof(slice_1_data_char)) != 0)
570     {
571         TCU_FAIL("Retrieved data is different from data uploaded for layer 0 of a layered framebuffer.");
572     }
573 
574     /* Iterate through all clear calls supported */
575 
576     for (int current_test = static_cast<int>(CLEAR_FIRST); current_test < static_cast<int>(CLEAR_COUNT); current_test++)
577     {
578         void *buffer                    = NULL;
579         const float clear_color_float[] = {0.25f, 0.5f, 1.0f, 32.0f / 255.0f};
580         const int clear_color_int[]     = {64, 128, 255, 32};
581         glw::GLuint fbo_id              = 0;
582         int pixel_size                  = 0;
583         void *slice_1_data              = NULL;
584         void *slice_2_data              = NULL;
585         void *slice_3_data              = NULL;
586         void *slice_4_data              = NULL;
587         glw::GLenum to_format           = GL_NONE;
588         glw::GLuint to_id               = 0;
589         glw::GLenum to_type             = GL_NONE;
590 
591         switch (static_cast<_clear_type>(current_test))
592         {
593         case CLEAR_BUFFERFV:
594         case CLEAR_PLAIN:
595         {
596             buffer       = buffer_char;
597             fbo_id       = m_fbo_char_id;
598             pixel_size   = N_TEXTURE_COMPONENTS;
599             slice_1_data = slice_1_data_char;
600             slice_2_data = slice_2_data_char;
601             slice_3_data = slice_3_data_char;
602             slice_4_data = slice_4_data_char;
603             to_format    = GL_RGBA;
604             to_id        = m_to_rgba8_id;
605             to_type      = GL_UNSIGNED_BYTE;
606 
607             break;
608         }
609 
610         case CLEAR_BUFFERIV:
611         {
612             buffer       = (void *)buffer_int;
613             fbo_id       = m_fbo_int_id;
614             pixel_size   = N_TEXTURE_COMPONENTS * sizeof(int);
615             slice_1_data = slice_1_data_int;
616             slice_2_data = slice_2_data_int;
617             slice_3_data = slice_3_data_int;
618             slice_4_data = slice_4_data_int;
619             to_format    = GL_RGBA_INTEGER;
620             to_id        = m_to_rgba32i_id;
621             to_type      = GL_INT;
622 
623             break;
624         }
625 
626         case CLEAR_BUFFERUIV:
627         {
628             buffer       = (void *)buffer_uint;
629             fbo_id       = m_fbo_uint_id;
630             pixel_size   = N_TEXTURE_COMPONENTS * sizeof(unsigned int);
631             slice_1_data = slice_1_data_uint;
632             slice_2_data = slice_2_data_uint;
633             slice_3_data = slice_3_data_uint;
634             slice_4_data = slice_4_data_uint;
635             to_format    = GL_RGBA_INTEGER;
636             to_id        = m_to_rgba32ui_id;
637             to_type      = GL_UNSIGNED_INT;
638 
639             break;
640         }
641 
642         default:
643         {
644             /* This location should never be reached */
645             TCU_FAIL("Execution flow failure");
646         }
647         } /* switch (current_test)*/
648 
649         /* Restore layer data just in case */
650         gl.bindTexture(GL_TEXTURE_3D, to_id);
651         gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH,
652                          TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_1_data);
653         gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH,
654                          TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_2_data);
655         gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH,
656                          TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_3_data);
657         gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH,
658                          TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_4_data);
659 
660         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage3D() call failed.");
661 
662         /* Issue requested clear call */
663         gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id);
664 
665         switch (current_test)
666         {
667         case CLEAR_PLAIN:
668         {
669             gl.clearColor(clear_color_float[0], clear_color_float[1], clear_color_float[2], clear_color_float[3]);
670             gl.clear(GL_COLOR_BUFFER_BIT);
671 
672             break;
673         }
674 
675         case CLEAR_BUFFERIV:
676         {
677             gl.clearBufferiv(GL_COLOR, 0 /* draw buffer index */, clear_color_int);
678 
679             break;
680         }
681 
682         case CLEAR_BUFFERUIV:
683         {
684             gl.clearBufferuiv(GL_COLOR, 0 /* draw buffer index */, (const glw::GLuint *)clear_color_int);
685 
686             break;
687         }
688 
689         case CLEAR_BUFFERFV:
690         {
691             gl.clearBufferfv(GL_COLOR, 0 /* draw buffer index */, clear_color_float);
692 
693             break;
694         }
695 
696         default:
697         {
698             /* This location should never be reached */
699             TCU_FAIL("Execution flow failure");
700         }
701         } /* switch (current_test) */
702 
703         /* Make sure no error was generated */
704         GLU_EXPECT_NO_ERROR(gl.getError(), "Clear call failed.");
705 
706         gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
707         GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create read framebuffer object!");
708 
709         /* Check the layer data after a clear call */
710         for (n_layer = 0; n_layer < TEXTURE_DEPTH; ++n_layer)
711         {
712             gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, to_id, 0 /* level */, n_layer);
713             gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, to_format, to_type, buffer);
714 
715             GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
716 
717             /* If we requested an integer clear, the pixels we obtained should be reset to specific values.
718              * If we asked for a FP-based clear, consider an epsilon. */
719             for (y = 0; y < TEXTURE_HEIGHT; ++y)
720             {
721                 const int row_size = TEXTURE_WIDTH * pixel_size;
722                 unsigned char *row = (unsigned char *)buffer + y * row_size;
723 
724                 for (x = 0; x < TEXTURE_WIDTH; ++x)
725                 {
726                     if (current_test == CLEAR_BUFFERIV || current_test == CLEAR_BUFFERUIV)
727                     {
728                         unsigned int *pixel = (unsigned int *)(row + x * pixel_size);
729                         if (memcmp(pixel, clear_color_int, sizeof(clear_color_int)) != 0)
730                         {
731                             /* Test fails at this point */
732                             m_testCtx.getLog()
733                                 << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") Reference pixel ["
734                                 << clear_color_int[0] << ", " << clear_color_int[1] << ", " << clear_color_int[2]
735                                 << ", " << clear_color_int[3] << "] is different from the one retrieved ["
736                                 << (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << ", "
737                                 << (int)pixel[3] << "]" << tcu::TestLog::EndMessage;
738 
739                             TCU_FAIL("Data comparison failure");
740                         } /* if (memcmp(pixel, clear_color_int, sizeof(clear_color_int) ) != 0) */
741                     }     /* if (current_test == CLEAR_BUFFERIV || current_test == CLEAR_BUFFERUIV) */
742                     else
743                     {
744 #define EPSILON (1)
745 
746                         unsigned char *pixel = (unsigned char *)(row + x * pixel_size);
747 
748                         if (de::abs((int)pixel[0] - clear_color_int[0]) > EPSILON ||
749                             de::abs((int)pixel[1] - clear_color_int[1]) > EPSILON ||
750                             de::abs((int)pixel[2] - clear_color_int[2]) > EPSILON ||
751                             de::abs((int)pixel[3] - clear_color_int[3]) > EPSILON)
752                         {
753                             /* Test fails at this point */
754                             m_testCtx.getLog()
755                                 << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") Reference pixel ["
756                                 << clear_color_int[0] << ", " << clear_color_int[1] << ", " << clear_color_int[2]
757                                 << ", " << clear_color_int[3] << "] is different from the one retrieved ["
758                                 << (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << ", "
759                                 << (int)pixel[3] << "]" << tcu::TestLog::EndMessage;
760 
761                             TCU_FAIL("Data comparison failure");
762                         } /* if (pixel component has exceeded an allowed epsilon) */
763 
764 #undef EPSILON
765                     }
766                 } /* for (all pixels) */
767             }     /* for (all rows) */
768         }         /* for (all layers) */
769     }             /* for (all clear call types) */
770 
771     /* Done */
772     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
773     return STOP;
774 
775 #undef TEXTURE_DEPTH
776 #undef TEXTURE_HEIGHT
777 #undef TEXTURE_WIDTH
778 }
779 
780 /** Deinitializes GLES objects created during the test. */
deinit(void)781 void GeometryShaderLayeredFramebufferClear::deinit(void)
782 {
783     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
784 
785     if (m_fbo_char_id != 0)
786     {
787         gl.deleteFramebuffers(1, &m_fbo_char_id);
788     }
789 
790     if (m_fbo_int_id != 0)
791     {
792         gl.deleteFramebuffers(1, &m_fbo_int_id);
793     }
794 
795     if (m_fbo_uint_id != 0)
796     {
797         gl.deleteFramebuffers(1, &m_fbo_uint_id);
798     }
799 
800     if (m_to_rgba32i_id != 0)
801     {
802         gl.deleteTextures(1, &m_to_rgba32i_id);
803     }
804 
805     if (m_to_rgba32ui_id != 0)
806     {
807         gl.deleteTextures(1, &m_to_rgba32ui_id);
808     }
809 
810     if (m_to_rgba8_id != 0)
811     {
812         gl.deleteTextures(1, &m_to_rgba8_id);
813     }
814 
815     if (m_read_fbo_id != 0)
816     {
817         gl.deleteFramebuffers(1, &m_read_fbo_id);
818     }
819 
820     /* Release base class */
821     TestCaseBase::deinit();
822 }
823 
824 /** Constructor
825  *
826  * @param context       Test context
827  * @param name          Test case's name
828  * @param description   Test case's desricption
829  **/
GeometryShaderLayeredFramebufferDepth(Context & context,const ExtParameters & extParams,const char * name,const char * description)830 GeometryShaderLayeredFramebufferDepth::GeometryShaderLayeredFramebufferDepth(Context &context,
831                                                                              const ExtParameters &extParams,
832                                                                              const char *name, const char *description)
833     : TestCaseBase(context, extParams, name, description)
834     , m_fbo_id(0)
835     , m_fs_id(0)
836     , m_gs_id(0)
837     , m_po_id(0)
838     , m_read_fbo_id(0)
839     , m_to_a_id(0)
840     , m_to_b_id(0)
841     , m_vao_id(0)
842     , m_vs_id(0)
843 {
844     /* Left blank on purpose */
845 }
846 
847 /** Deinitializes GLES objects created during the test. */
deinit(void)848 void GeometryShaderLayeredFramebufferDepth::deinit(void)
849 {
850     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
851 
852     /* Clean up */
853     if (m_fbo_id != 0)
854     {
855         gl.deleteFramebuffers(1, &m_fbo_id);
856     }
857 
858     if (m_fs_id != 0)
859     {
860         gl.deleteShader(m_fs_id);
861     }
862 
863     if (m_gs_id != 0)
864     {
865         gl.deleteShader(m_gs_id);
866     }
867 
868     if (m_po_id != 0)
869     {
870         gl.deleteProgram(m_po_id);
871     }
872 
873     if (m_read_fbo_id != 0)
874     {
875         gl.deleteFramebuffers(1, &m_read_fbo_id);
876     }
877 
878     if (m_to_a_id != 0)
879     {
880         gl.deleteTextures(1, &m_to_a_id);
881     }
882 
883     if (m_to_b_id != 0)
884     {
885         gl.deleteTextures(1, &m_to_b_id);
886     }
887 
888     if (m_vao_id != 0)
889     {
890         gl.deleteVertexArrays(1, &m_vao_id);
891     }
892 
893     if (m_vs_id != 0)
894     {
895         gl.deleteShader(m_vs_id);
896     }
897 
898     /* Release base class */
899     TestCaseBase::deinit();
900 }
901 
902 /** Executes the test.
903  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
904  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
905  *  Note the function throws exception should an error occur!
906  **/
iterate(void)907 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferDepth::iterate(void)
908 {
909     /* General variables */
910     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
911     unsigned int n           = 0;
912     unsigned int x           = 0;
913     unsigned int y           = 0;
914 
915 /* Test-wide definitions */
916 #define N_TEXTURE_COMPONENTS (4)
917 #define TEXTURE_DEPTH (4)
918 #define TEXTURE_HEIGHT (4)
919 #define TEXTURE_WIDTH (4)
920 
921     /* Fragment shader code */
922     const char *fs_code = "${VERSION}\n"
923                           "\n"
924                           "precision highp float;\n"
925                           "\n"
926                           "out vec4 result;\n"
927                           "\n"
928                           "void main()\n"
929                           "{\n"
930                           "    result = vec4(1.0);\n"
931                           "}\n";
932 
933     const char *gs_code = "${VERSION}\n"
934                           "${GEOMETRY_SHADER_REQUIRE}\n"
935                           "\n"
936                           "layout(points)                          in;\n"
937                           "layout(triangle_strip, max_vertices=64) out;\n"
938                           "\n"
939                           "void main()\n"
940                           "{\n"
941                           "    for (int n = 0; n < 4; ++n)\n"
942                           "    {\n"
943                           "        float depth = -1.0 + float(n) * 0.5;\n"
944                           "\n"
945                           "        gl_Layer    = n;\n"
946                           "        gl_Position = vec4(1, 1, depth, 1);\n"
947                           "        EmitVertex();\n"
948                           "\n"
949                           "        gl_Layer    = n;\n"
950                           "        gl_Position = vec4(1, -1, depth, 1);\n"
951                           "        EmitVertex();\n"
952                           "\n"
953                           "        gl_Layer    = n;\n"
954                           "        gl_Position = vec4(-1, 1, depth, 1);\n"
955                           "        EmitVertex();\n"
956                           "\n"
957                           "        gl_Layer    = n;\n"
958                           "        gl_Position = vec4(-1, -1, depth, 1);\n"
959                           "        EmitVertex();\n"
960                           "\n"
961                           "        EndPrimitive();\n"
962                           "    }\n"
963                           "}\n";
964 
965     /* This test should only run if EXT_geometry_shader is supported */
966     if (!m_is_geometry_shader_extension_supported)
967     {
968         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
969     }
970 
971     /* Set up texture objects we will be using for the test */
972     gl.genTextures(1, &m_to_a_id);
973     gl.genTextures(1, &m_to_b_id);
974 
975     gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_a_id);
976     gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH);
977     gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_b_id);
978     gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_DEPTH_COMPONENT32F, TEXTURE_WIDTH, TEXTURE_HEIGHT,
979                     TEXTURE_DEPTH);
980 
981     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize texture objects");
982 
983     /* Set up framebuffer object we will use for the test */
984     gl.genFramebuffers(1, &m_fbo_id);
985     gl.genFramebuffers(1, &m_read_fbo_id);
986 
987     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
988 
989     gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */);
990     gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_to_b_id, 0 /* level */);
991 
992     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize framebuffer object");
993 
994     if (gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
995     {
996         m_testCtx.getLog() << tcu::TestLog::Message
997                            << "Draw framebuffer is incomplete: " << gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER)
998                            << tcu::TestLog::EndMessage;
999 
1000         TCU_FAIL("Draw framebuffer is incomplete.");
1001     }
1002 
1003     /* Set up shader objects */
1004     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1005     m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
1006     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1007 
1008     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize shader objects");
1009 
1010     /* Set up program object */
1011     m_po_id = gl.createProgram();
1012 
1013     if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fs_code, m_gs_id, 1 /* part */, &gs_code, m_vs_id, 1 /* part */,
1014                       &m_boilerplate_vs_code))
1015     {
1016         TCU_FAIL("Could not build program object");
1017     }
1018 
1019     /* Set up vertex array object */
1020     gl.genVertexArrays(1, &m_vao_id);
1021     gl.bindVertexArray(m_vao_id);
1022 
1023     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind vertex array object");
1024 
1025     /* Clear the depth attachment before we continue */
1026     gl.clearColor(0.0f /* red */, 0.0f /* green */, 0.0f /* blue */, 0.0f /* alpha */);
1027     gl.clearDepthf(0.5f);
1028     gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1029 
1030     GLU_EXPECT_NO_ERROR(gl.getError(), "Depth buffer clear operation failed");
1031 
1032     /* Render */
1033     gl.useProgram(m_po_id);
1034     gl.viewport(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT);
1035 
1036     gl.enable(GL_DEPTH_TEST);
1037     gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1038 
1039     GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
1040 
1041     /* Verify the output */
1042     gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
1043 
1044     for (n = 0; n < TEXTURE_DEPTH; ++n)
1045     {
1046         unsigned char buffer[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
1047         unsigned char ref_color[4];
1048 
1049         /* Determine reference color */
1050         if (n < 2)
1051         {
1052             memset(ref_color, 0xFF, sizeof(ref_color));
1053         }
1054         else
1055         {
1056             memset(ref_color, 0, sizeof(ref_color));
1057         }
1058 
1059         /* Read the rendered layer data */
1060         gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */, n);
1061         gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
1062 
1063         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
1064 
1065         /* Compare all pixels against the reference value */
1066         for (y = 0; y < TEXTURE_HEIGHT; ++y)
1067         {
1068             const unsigned int pixel_size = N_TEXTURE_COMPONENTS;
1069             const unsigned int row_width  = TEXTURE_WIDTH * pixel_size;
1070             const unsigned char *row_data = buffer + y * row_width;
1071 
1072             for (x = 0; x < TEXTURE_WIDTH; ++x)
1073             {
1074                 const unsigned char *result = row_data + x * pixel_size;
1075 
1076                 if (memcmp(result, ref_color, sizeof(ref_color)) != 0)
1077                 {
1078                     m_testCtx.getLog() << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") "
1079                                        << "Reference value is different than the rendered data: "
1080                                        << "(" << (unsigned int)ref_color[0] << ", " << (unsigned int)ref_color[1]
1081                                        << ", " << (unsigned int)ref_color[2] << ", " << (unsigned int)ref_color[3]
1082                                        << ") vs "
1083                                        << "(" << (unsigned int)result[0] << ", " << (unsigned int)result[1] << ", "
1084                                        << (unsigned int)result[2] << ", " << (unsigned int)result[3] << ")."
1085                                        << tcu::TestLog::EndMessage;
1086 
1087                     TCU_FAIL("Rendered data mismatch");
1088                 } /* if (memcmp(row_data + x * pixel_size, ref_color, sizeof(ref_color) ) != 0)*/
1089             }     /* for (all pixels in a row) */
1090         }         /* for (all rows) */
1091     }             /* for (all layers) */
1092 
1093     /* Done */
1094     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1095     return STOP;
1096 
1097 #undef N_TEXTURE_COMPONENTS
1098 #undef TEXTURE_DEPTH
1099 #undef TEXTURE_HEIGHT
1100 #undef TEXTURE_WIDTH
1101 }
1102 
1103 /** Constructor
1104  *
1105  * @param context       Test context
1106  * @param name          Test case's name
1107  * @param description   Test case's desricption
1108  **/
GeometryShaderLayeredFramebufferStencil(Context & context,const ExtParameters & extParams,const char * name,const char * description)1109 GeometryShaderLayeredFramebufferStencil::GeometryShaderLayeredFramebufferStencil(Context &context,
1110                                                                                  const ExtParameters &extParams,
1111                                                                                  const char *name,
1112                                                                                  const char *description)
1113     : TestCaseBase(context, extParams, name, description)
1114     , m_fbo_id(0)
1115     , m_fs_id(0)
1116     , m_gs_id(0)
1117     , m_po_id(0)
1118     , m_to_a_id(0)
1119     , m_to_b_id(0)
1120     , m_vao_id(0)
1121     , m_vs_id(0)
1122 {
1123     /* Left blank on purpose */
1124 }
1125 
1126 /** Deinitializes GLES objects created during the test. */
deinit(void)1127 void GeometryShaderLayeredFramebufferStencil::deinit(void)
1128 {
1129     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1130 
1131     /* Clean up */
1132     if (m_fbo_id != 0)
1133     {
1134         gl.deleteFramebuffers(1, &m_fbo_id);
1135     }
1136 
1137     if (m_fs_id != 0)
1138     {
1139         gl.deleteShader(m_fs_id);
1140     }
1141 
1142     if (m_gs_id != 0)
1143     {
1144         gl.deleteShader(m_gs_id);
1145     }
1146 
1147     if (m_po_id != 0)
1148     {
1149         gl.deleteProgram(m_po_id);
1150     }
1151 
1152     if (m_to_a_id != 0)
1153     {
1154         gl.deleteTextures(1, &m_to_a_id);
1155     }
1156 
1157     if (m_to_b_id != 0)
1158     {
1159         gl.deleteTextures(1, &m_to_b_id);
1160     }
1161 
1162     if (m_vao_id != 0)
1163     {
1164         gl.deleteVertexArrays(1, &m_vao_id);
1165     }
1166 
1167     if (m_vs_id != 0)
1168     {
1169         gl.deleteShader(m_vs_id);
1170     }
1171 
1172     /* Release base class */
1173     TestCaseBase::deinit();
1174 }
1175 
1176 /** Executes the test.
1177  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1178  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1179  *  Note the function throws exception should an error occur!
1180  **/
iterate(void)1181 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferStencil::iterate(void)
1182 {
1183     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1184 
1185 /* Test-wide definitions */
1186 #define N_TEXTURE_COMPONENTS (4)
1187 #define TEXTURE_DEPTH (4)
1188 #define TEXTURE_HEIGHT (4)
1189 #define TEXTURE_WIDTH (8)
1190 
1191     /* Fragment shader code */
1192     const char *fs_code = "${VERSION}\n"
1193                           "\n"
1194                           "precision highp float;\n"
1195                           "\n"
1196                           "out vec4 result;\n"
1197                           "\n"
1198                           "void main()\n"
1199                           "{\n"
1200                           "    result = vec4(1, 1, 1, 1);\n"
1201                           "}\n";
1202 
1203     /* Geometry shader code */
1204     const char *gs_code = "${VERSION}\n"
1205                           "${GEOMETRY_SHADER_REQUIRE}\n"
1206                           "\n"
1207                           "precision highp float;\n"
1208                           "\n"
1209                           "layout (points)                            in;\n"
1210                           "layout (triangle_strip, max_vertices = 16) out;\n"
1211                           "\n"
1212                           "void main()\n"
1213                           "{\n"
1214                           "    for (int n = 0; n < 4; ++n)\n"
1215                           "    {\n"
1216                           "        gl_Position = vec4(1, -1, 0, 1);\n"
1217                           "        gl_Layer    = n;\n"
1218                           "        EmitVertex();\n"
1219                           "\n"
1220                           "        gl_Position = vec4(1,  1, 0, 1);\n"
1221                           "        gl_Layer    = n;\n"
1222                           "        EmitVertex();\n"
1223                           "\n"
1224                           "        gl_Position = vec4(-1, -1, 0, 1);\n"
1225                           "        gl_Layer    = n;\n"
1226                           "        EmitVertex();\n"
1227                           "\n"
1228                           "        gl_Position = vec4(-1,  1, 0, 1);\n"
1229                           "        gl_Layer    = n;\n"
1230                           "        EmitVertex();\n"
1231                           "\n"
1232                           "        EndPrimitive();\n"
1233                           "    }\n"
1234                           "\n"
1235                           "}\n";
1236 
1237     /* General variables */
1238     int n = 0;
1239 
1240     unsigned char slice_null_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 1 /* byte  per texel */] = {0};
1241     unsigned char slice_1_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */]    = {0};
1242     unsigned char slice_2_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */]    = {0};
1243     unsigned char slice_3_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */]    = {0};
1244     unsigned char slice_4_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */]    = {0};
1245 
1246     /* This test should only run if EXT_geometry_shader is supported */
1247     if (!m_is_geometry_shader_extension_supported)
1248     {
1249         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1250     }
1251 
1252     /* Create shader & program objects */
1253     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1254     m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
1255     m_po_id = gl.createProgram();
1256     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1257 
1258     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader or program objects");
1259 
1260     /* Build test program object */
1261     if (!buildProgram(m_po_id, m_fs_id, 1 /* parts */, &fs_code, m_gs_id, 1 /* parts */, &gs_code, m_vs_id,
1262                       1 /* parts */, &m_boilerplate_vs_code))
1263     {
1264         TCU_FAIL("Could not build test program object");
1265     }
1266 
1267     /* Generate and bind a vertex array object */
1268     gl.genVertexArrays(1, &m_vao_id);
1269     gl.bindVertexArray(m_vao_id);
1270 
1271     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create & bind a vertex array object.");
1272 
1273     /* Configure slice data */
1274     for (n = 0; n < TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */; ++n)
1275     {
1276         /* We are okay with depth data being filled with glitch, but need the stencil data to be
1277          * as per test spec. To keep code simple, we do not differentiate between floating-point and
1278          * stencil part.
1279          */
1280         slice_1_data[n] = 2;
1281         slice_2_data[n] = 1;
1282 
1283         /* Slices 3 and 4 should be filled with 0s */
1284         slice_3_data[n] = 0;
1285         slice_4_data[n] = 0;
1286     } /* for (all pixels making up slices) */
1287 
1288     /* Set up texture objects */
1289     gl.genTextures(1, &m_to_a_id);
1290     gl.genTextures(1, &m_to_b_id);
1291 
1292     gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_a_id);
1293     gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH,
1294                   0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1295 
1296     gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */,
1297                      TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
1298     gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */,
1299                      TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
1300     gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */,
1301                      TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
1302     gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */,
1303                      TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
1304 
1305     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object A.");
1306 
1307     gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_b_id);
1308     gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, GL_DEPTH32F_STENCIL8, TEXTURE_WIDTH, TEXTURE_HEIGHT,
1309                   TEXTURE_DEPTH, 0 /* border */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL);
1310 
1311     gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */,
1312                      TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
1313                      slice_1_data);
1314     gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */,
1315                      TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
1316                      slice_2_data);
1317     gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */,
1318                      TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
1319                      slice_3_data);
1320     gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */,
1321                      TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
1322                      slice_4_data);
1323 
1324     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object B.");
1325 
1326     /* Set up depth tests */
1327     gl.disable(GL_DEPTH_TEST);
1328 
1329     /* Set up stencil tests */
1330     gl.enable(GL_STENCIL_TEST);
1331     gl.stencilFunc(GL_LESS, 0, /* reference value */ 0xFFFFFFFF /* mask */);
1332 
1333     /* Set up framebuffer objects */
1334     gl.genFramebuffers(1, &m_fbo_id);
1335     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
1336 
1337     gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */);
1338     gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, m_to_b_id, 0 /* level */);
1339 
1340     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer.");
1341 
1342     /* Issue the draw call. */
1343     gl.useProgram(m_po_id);
1344     gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1345 
1346     GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed.");
1347 
1348     /* Check the results */
1349     for (n = 0; n < 4 /* layers */; ++n)
1350     {
1351         glw::GLenum fbo_completeness                                                     = GL_NONE;
1352         int m                                                                            = 0;
1353         unsigned char ref_data[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]    = {0};
1354         unsigned char result_data[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS] = {0};
1355         int x                                                                            = 0;
1356         int y                                                                            = 0;
1357 
1358         /* Configure the read framebuffer */
1359         gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id);
1360 
1361         gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */, n);
1362         gl.framebufferTexture(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0 /* texture */, 0 /* level */);
1363 
1364         GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up read framebuffer.");
1365 
1366         /* Verify read framebuffer is considered complete */
1367         fbo_completeness = gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER);
1368 
1369         if (fbo_completeness != GL_FRAMEBUFFER_COMPLETE)
1370         {
1371             m_testCtx.getLog() << tcu::TestLog::Message << "Read FBO is incomplete: "
1372                                << "[" << fbo_completeness << "]" << tcu::TestLog::EndMessage;
1373 
1374             TCU_FAIL("Read FBO is incomplete.");
1375         }
1376 
1377         /* Build reference data */
1378         for (m = 0; m < TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS; ++m)
1379         {
1380             if (n < 2)
1381             {
1382                 ref_data[m] = 255;
1383             }
1384             else
1385             {
1386                 ref_data[m] = 0;
1387             }
1388         } /* for (all reference pixels) */
1389 
1390         /* Read the rendered data */
1391         gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, result_data);
1392 
1393         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed");
1394 
1395         for (y = 0; y < TEXTURE_HEIGHT; ++y)
1396         {
1397             int pixel_size            = N_TEXTURE_COMPONENTS;
1398             int row_size              = pixel_size * TEXTURE_WIDTH;
1399             unsigned char *ref_row    = ref_data + y * row_size;
1400             unsigned char *result_row = result_data + y * row_size;
1401 
1402             for (x = 0; x < TEXTURE_WIDTH; ++x)
1403             {
1404                 if (memcmp(ref_row, result_row, pixel_size) != 0)
1405                 {
1406                     m_testCtx.getLog() << tcu::TestLog::Message << "(x=" << x << " y=" << y << "): Rendered data "
1407                                        << "(" << result_row[0] << ", " << result_row[1] << ", " << result_row[2] << ", "
1408                                        << result_row[3] << ")"
1409                                        << " is different from reference data "
1410                                        << "(" << ref_row[0] << ", " << ref_row[1] << ", " << ref_row[2] << ", "
1411                                        << ref_row[3] << ")" << tcu::TestLog::EndMessage;
1412 
1413                     TCU_FAIL("Data comparison failed");
1414                 } /* if (memcmp(ref_row, result_row, pixel_size) != 0) */
1415 
1416                 ref_row += pixel_size;
1417                 result_row += pixel_size;
1418             } /* for (all pixels in a row) */
1419         }     /* for (all pixels) */
1420     }         /* for (all layers) */
1421 
1422     /* Done */
1423     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1424     return STOP;
1425 
1426 #undef N_TEXTURE_COMPONENTS
1427 #undef TEXTURE_DEPTH
1428 #undef TEXTURE_HEIGHT
1429 #undef TEXTURE_WIDTH
1430 }
1431 
1432 } // namespace glcts
1433