xref: /aosp_15_r20/external/deqp/external/openglcts/modules/glesext/esextcTestCaseBase.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 "esextcTestCaseBase.hpp"
25 #include "gluContextInfo.hpp"
26 #include "glwEnums.hpp"
27 #include "glwFunctions.hpp"
28 #include "tcuStringTemplate.hpp"
29 #include "tcuTestLog.hpp"
30 #include <algorithm>
31 #include <cstdarg>
32 #include <iostream>
33 
34 namespace glcts
35 {
36 
37 /* Predefined shader source code */
38 const char *TestCaseBase::m_boilerplate_vs_code = "${VERSION}\n"
39                                                   "\n"
40                                                   "precision highp float;\n"
41                                                   "\n"
42                                                   "void main()\n"
43                                                   "{\n"
44                                                   "    gl_Position = vec4(gl_VertexID, 0, 0, 1);\n"
45                                                   "}\n";
46 
47 const float TestCaseBase::m_epsilon_float = 0.0001f;
48 
49 /** Constructor
50  *
51  * @param context       Test context
52  * @param name          Test case's name
53  * @param description   Test case's description
54  **/
TestCaseBase(Context & context,const ExtParameters & extParam,const char * name,const char * description)55 TestCaseBase::TestCaseBase(Context &context, const ExtParameters &extParam, const char *name, const char *description)
56     : tcu::TestCase(context.getTestContext(), name, description)
57     , m_context(context)
58     , m_glslVersion(extParam.glslVersion)
59     , m_extType(extParam.extType)
60     , m_is_framebuffer_no_attachments_supported(false)
61     , m_is_geometry_shader_extension_supported(false)
62     , m_is_geometry_shader_point_size_supported(false)
63     , m_is_gpu_shader5_supported(false)
64     , m_is_program_interface_query_supported(false)
65     , m_is_shader_image_load_store_supported(false)
66     , m_is_shader_image_atomic_supported(false)
67     , m_is_texture_storage_multisample_supported(false)
68     , m_is_texture_storage_multisample_2d_array_supported(false)
69     , m_is_tessellation_shader_supported(false)
70     , m_is_tessellation_shader_point_size_supported(false)
71     , m_is_texture_cube_map_array_supported(false)
72     , m_is_texture_border_clamp_supported(false)
73     , m_is_texture_buffer_supported(false)
74     , m_is_viewport_array_supported(false)
75     , m_is_texture_float_linear_supported(false)
76     , seed_value(1)
77 {
78     m_glExtTokens.init(context.getRenderContext().getType());
79 }
80 
81 /** Initializes base class that all geometry shader test implementations derive from.
82  *
83  **/
init(void)84 void TestCaseBase::init(void)
85 {
86     initExtensions();
87     initGLSLSpecializationMap();
88 }
89 
90 /** Initializes function pointers for ES3.1 extensions, as well as determines
91  *  availability of these extensions.
92  **/
initExtensions()93 void TestCaseBase::initExtensions()
94 {
95     const glu::ContextType &context_type = m_context.getRenderContext().getType();
96 
97     /* OpenGL 4.0 or higher is minimum expectation for any of these tests */
98     if (glu::contextSupports(context_type, glu::ApiType::core(4, 0)))
99     {
100         m_is_geometry_shader_extension_supported      = true;
101         m_is_geometry_shader_point_size_supported     = true;
102         m_is_gpu_shader5_supported                    = true;
103         m_is_tessellation_shader_supported            = true;
104         m_is_tessellation_shader_point_size_supported = true;
105         m_is_texture_cube_map_array_supported         = true;
106         m_is_texture_border_clamp_supported           = true;
107         m_is_texture_buffer_supported                 = true;
108         m_is_texture_float_linear_supported           = true;
109         m_is_shader_image_atomic_supported            = glu::contextSupports(context_type, glu::ApiType::core(4, 2));
110         m_is_texture_storage_multisample_2d_array_supported =
111             glu::contextSupports(context_type, glu::ApiType::core(4, 3));
112         m_is_framebuffer_no_attachments_supported  = glu::contextSupports(context_type, glu::ApiType::core(4, 3));
113         m_is_program_interface_query_supported     = glu::contextSupports(context_type, glu::ApiType::core(4, 3));
114         m_is_texture_storage_multisample_supported = glu::contextSupports(context_type, glu::ApiType::core(4, 3));
115         m_is_shader_image_load_store_supported     = glu::contextSupports(context_type, glu::ApiType::core(4, 2));
116         m_is_viewport_array_supported              = glu::contextSupports(context_type, glu::ApiType::core(4, 1));
117     }
118     else if (glu::contextSupports(context_type, glu::ApiType::es(3, 2)))
119     {
120         m_is_geometry_shader_extension_supported            = true;
121         m_is_gpu_shader5_supported                          = true;
122         m_is_tessellation_shader_supported                  = true;
123         m_is_texture_cube_map_array_supported               = true;
124         m_is_texture_border_clamp_supported                 = true;
125         m_is_texture_buffer_supported                       = true;
126         m_is_shader_image_atomic_supported                  = true;
127         m_is_texture_storage_multisample_2d_array_supported = true;
128         m_is_framebuffer_no_attachments_supported           = true;
129         m_is_program_interface_query_supported              = true;
130         m_is_texture_storage_multisample_supported          = true;
131         m_is_shader_image_load_store_supported              = true;
132         m_is_geometry_shader_point_size_supported =
133             isExtensionSupported("GL_OES_geometry_point_size") || isExtensionSupported("GL_EXT_geometry_point_size");
134         m_is_tessellation_shader_point_size_supported = isExtensionSupported("GL_OES_tessellation_point_size") ||
135                                                         isExtensionSupported("GL_EXT_tessellation_point_size");
136         m_is_viewport_array_supported       = isExtensionSupported("GL_OES_viewport_array");
137         m_is_texture_float_linear_supported = isExtensionSupported("GL_OES_texture_float_linear");
138     }
139     else
140     {
141         /* ES3.1 core functionality is assumed*/
142         DE_ASSERT(isContextTypeES(context_type));
143         DE_ASSERT(glu::contextSupports(context_type, glu::ApiType::es(3, 1)));
144 
145         /* these are part of ES 3.1 */
146         m_is_framebuffer_no_attachments_supported  = true;
147         m_is_program_interface_query_supported     = true;
148         m_is_texture_storage_multisample_supported = true;
149         m_is_shader_image_load_store_supported     = true;
150 
151         /* AEP extensions - either test OES variants or EXT variants */
152         if (m_extType == EXTENSIONTYPE_OES)
153         {
154             /* These are all ES 3.1 extensions */
155             m_is_geometry_shader_extension_supported      = isExtensionSupported("GL_OES_geometry_shader");
156             m_is_geometry_shader_point_size_supported     = isExtensionSupported("GL_OES_geometry_point_size");
157             m_is_gpu_shader5_supported                    = isExtensionSupported("GL_OES_gpu_shader5");
158             m_is_tessellation_shader_supported            = isExtensionSupported("GL_OES_tessellation_shader");
159             m_is_tessellation_shader_point_size_supported = isExtensionSupported("GL_OES_tessellation_point_size");
160             m_is_texture_cube_map_array_supported         = isExtensionSupported("GL_OES_texture_cube_map_array");
161             m_is_texture_border_clamp_supported           = isExtensionSupported("GL_OES_texture_border_clamp");
162             m_is_texture_buffer_supported                 = isExtensionSupported("GL_OES_texture_buffer");
163         }
164         else
165         {
166             DE_ASSERT(m_extType == EXTENSIONTYPE_EXT);
167 
168             /* These are all ES 3.1 extensions */
169             m_is_geometry_shader_extension_supported      = isExtensionSupported("GL_EXT_geometry_shader");
170             m_is_geometry_shader_point_size_supported     = isExtensionSupported("GL_EXT_geometry_point_size");
171             m_is_gpu_shader5_supported                    = isExtensionSupported("GL_EXT_gpu_shader5");
172             m_is_tessellation_shader_supported            = isExtensionSupported("GL_EXT_tessellation_shader");
173             m_is_tessellation_shader_point_size_supported = isExtensionSupported("GL_EXT_tessellation_point_size");
174             m_is_texture_cube_map_array_supported         = isExtensionSupported("GL_EXT_texture_cube_map_array");
175             m_is_texture_border_clamp_supported           = isExtensionSupported("GL_EXT_texture_border_clamp");
176             m_is_texture_buffer_supported                 = isExtensionSupported("GL_EXT_texture_buffer");
177             m_is_fragment_shading_rate_supported          = isExtensionSupported("GL_EXT_fragment_shading_rate");
178             m_is_fragment_shading_rate_primitive_supported =
179                 isExtensionSupported("GL_EXT_fragment_shading_rate_primitive");
180             m_is_fragment_shading_rate_attachment_supported =
181                 isExtensionSupported("GL_EXT_fragment_shading_rate_attachment");
182         }
183 
184         /* other ES 3.1 extensions */
185         m_is_shader_image_atomic_supported = isExtensionSupported("GL_OES_shader_image_atomic");
186         m_is_texture_storage_multisample_2d_array_supported =
187             isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
188         m_is_viewport_array_supported       = isExtensionSupported("GL_OES_viewport_array");
189         m_is_multiview_ovr_supported        = isExtensionSupported("GL_OVR_multiview");
190         m_is_texture_float_linear_supported = isExtensionSupported("GL_OES_texture_float_linear");
191     }
192 }
193 
194 /** Initializes function pointers for ES3.1 extensions, as well as determines
195  *  availability of these extensions.
196  **/
initGLSLSpecializationMap()197 void TestCaseBase::initGLSLSpecializationMap()
198 {
199     m_specializationMap["VERSION"] = glu::getGLSLVersionDeclaration(m_glslVersion);
200     m_specializationMap["SHADER_IO_BLOCKS_ENABLE"] =
201         getGLSLExtDirective(m_extType, EXTENSIONNAME_SHADER_IO_BLOCKS, EXTENSIONBEHAVIOR_ENABLE);
202     m_specializationMap["SHADER_IO_BLOCKS_REQUIRE"] =
203         getGLSLExtDirective(m_extType, EXTENSIONNAME_SHADER_IO_BLOCKS, EXTENSIONBEHAVIOR_REQUIRE);
204     m_specializationMap["GEOMETRY_SHADER_ENABLE"] =
205         getGLSLExtDirective(m_extType, EXTENSIONNAME_GEOMETRY_SHADER, EXTENSIONBEHAVIOR_ENABLE);
206     m_specializationMap["GEOMETRY_SHADER_REQUIRE"] =
207         getGLSLExtDirective(m_extType, EXTENSIONNAME_GEOMETRY_SHADER, EXTENSIONBEHAVIOR_REQUIRE);
208     m_specializationMap["GEOMETRY_POINT_SIZE_ENABLE"] =
209         getGLSLExtDirective(m_extType, EXTENSIONNAME_GEOMETRY_POINT_SIZE, EXTENSIONBEHAVIOR_ENABLE);
210     m_specializationMap["GEOMETRY_POINT_SIZE_REQUIRE"] =
211         getGLSLExtDirective(m_extType, EXTENSIONNAME_GEOMETRY_POINT_SIZE, EXTENSIONBEHAVIOR_REQUIRE);
212     m_specializationMap["TESSELLATION_SHADER_ENABLE"] =
213         getGLSLExtDirective(m_extType, EXTENSIONNAME_TESSELLATION_SHADER, EXTENSIONBEHAVIOR_ENABLE);
214     m_specializationMap["TESSELLATION_SHADER_REQUIRE"] =
215         getGLSLExtDirective(m_extType, EXTENSIONNAME_TESSELLATION_SHADER, EXTENSIONBEHAVIOR_REQUIRE);
216     m_specializationMap["TESSELLATION_POINT_SIZE_ENABLE"] =
217         getGLSLExtDirective(m_extType, EXTENSIONNAME_TESSELLATION_POINT_SIZE, EXTENSIONBEHAVIOR_ENABLE);
218     m_specializationMap["TESSELLATION_POINT_SIZE_REQUIRE"] =
219         getGLSLExtDirective(m_extType, EXTENSIONNAME_TESSELLATION_POINT_SIZE, EXTENSIONBEHAVIOR_REQUIRE);
220     m_specializationMap["GPU_SHADER5_ENABLE"] =
221         getGLSLExtDirective(m_extType, EXTENSIONNAME_GPU_SHADER5, EXTENSIONBEHAVIOR_ENABLE);
222     m_specializationMap["GPU_SHADER5_REQUIRE"] =
223         getGLSLExtDirective(m_extType, EXTENSIONNAME_GPU_SHADER5, EXTENSIONBEHAVIOR_REQUIRE);
224     m_specializationMap["TEXTURE_BUFFER_ENABLE"] =
225         getGLSLExtDirective(m_extType, EXTENSIONNAME_TEXTURE_BUFFER, EXTENSIONBEHAVIOR_ENABLE);
226     m_specializationMap["TEXTURE_BUFFER_REQUIRE"] =
227         getGLSLExtDirective(m_extType, EXTENSIONNAME_TEXTURE_BUFFER, EXTENSIONBEHAVIOR_REQUIRE);
228     m_specializationMap["TEXTURE_CUBE_MAP_ARRAY_ENABLE"] =
229         getGLSLExtDirective(m_extType, EXTENSIONNAME_TEXTURE_CUBE_MAP_ARRAY, EXTENSIONBEHAVIOR_ENABLE);
230     m_specializationMap["TEXTURE_CUBE_MAP_ARRAY_REQUIRE"] =
231         getGLSLExtDirective(m_extType, EXTENSIONNAME_TEXTURE_CUBE_MAP_ARRAY, EXTENSIONBEHAVIOR_REQUIRE);
232     m_specializationMap["SHADER_IMAGE_ATOMIC_ENABLE"] =
233         getGLSLExtDirective(m_extType, EXTENSIONNAME_SHADER_IMAGE_ATOMIC, EXTENSIONBEHAVIOR_ENABLE);
234     m_specializationMap["SHADER_IMAGE_ATOMIC_REQUIRE"] =
235         getGLSLExtDirective(m_extType, EXTENSIONNAME_SHADER_IMAGE_ATOMIC, EXTENSIONBEHAVIOR_REQUIRE);
236     m_specializationMap["VIEWPORT_ARRAY_ENABLE"] =
237         getGLSLExtDirective(m_extType, EXTENSIONNAME_VIEWPORT_ARRAY, EXTENSIONBEHAVIOR_ENABLE);
238     m_specializationMap["VIEWPORT_ARRAY_REQUIRE"] =
239         getGLSLExtDirective(m_extType, EXTENSIONNAME_VIEWPORT_ARRAY, EXTENSIONBEHAVIOR_REQUIRE);
240 
241     if (glu::isContextTypeES(m_context.getRenderContext().getType()))
242     {
243         m_specializationMap["IN_PER_VERTEX_DECL_ARRAY"]             = "\n";
244         m_specializationMap["IN_PER_VERTEX_DECL_ARRAY_POINT_SIZE"]  = "\n";
245         m_specializationMap["OUT_PER_VERTEX_DECL"]                  = "\n";
246         m_specializationMap["OUT_PER_VERTEX_DECL_POINT_SIZE"]       = "\n";
247         m_specializationMap["OUT_PER_VERTEX_DECL_ARRAY"]            = "\n";
248         m_specializationMap["OUT_PER_VERTEX_DECL_ARRAY_POINT_SIZE"] = "\n";
249         m_specializationMap["IN_DATA_DECL"]                         = "\n";
250         m_specializationMap["POSITION_WITH_IN_DATA"]                = "gl_Position = gl_in[0].gl_Position;\n";
251     }
252     else
253     {
254         m_specializationMap["IN_PER_VERTEX_DECL_ARRAY"]             = "in gl_PerVertex {\n"
255                                                                       "    vec4 gl_Position;\n"
256                                                                       "} gl_in[];\n";
257         m_specializationMap["IN_PER_VERTEX_DECL_ARRAY_POINT_SIZE"]  = "in gl_PerVertex {\n"
258                                                                       "    vec4 gl_Position;\n"
259                                                                       "    float gl_PointSize;\n"
260                                                                       "} gl_in[];\n";
261         m_specializationMap["OUT_PER_VERTEX_DECL"]                  = "out gl_PerVertex {\n"
262                                                                       "    vec4 gl_Position;\n"
263                                                                       "};\n";
264         m_specializationMap["OUT_PER_VERTEX_DECL_POINT_SIZE"]       = "out gl_PerVertex {\n"
265                                                                       "    vec4 gl_Position;\n"
266                                                                       "    float gl_PointSize;\n"
267                                                                       "};\n";
268         m_specializationMap["OUT_PER_VERTEX_DECL_ARRAY"]            = "out gl_PerVertex {\n"
269                                                                       "    vec4 gl_Position;\n"
270                                                                       "} gl_out[];\n";
271         m_specializationMap["OUT_PER_VERTEX_DECL_ARRAY_POINT_SIZE"] = "out gl_PerVertex {\n"
272                                                                       "    vec4 gl_Position;\n"
273                                                                       "    float gl_PointSize;\n"
274                                                                       "} gl_out[];\n";
275         m_specializationMap["IN_DATA_DECL"]                         = "in Data {\n"
276                                                                       "    vec4 pos;\n"
277                                                                       "} input_data[1];\n";
278         m_specializationMap["POSITION_WITH_IN_DATA"]                = "gl_Position = input_data[0].pos;\n";
279     }
280 }
281 
282 /** Sets the seed for the random generator
283  *  @param seed - seed for the random generator
284  */
randomSeed(const glw::GLuint seed)285 void TestCaseBase::randomSeed(const glw::GLuint seed)
286 {
287     seed_value = seed;
288 }
289 
290 /** Returns random unsigned integer from the range [0,max)
291  *  @param  max - the value that is the upper boundary for the returned random numbers
292  *  @return random unsigned integer from the range [0,max)
293  */
randomFormula(const glw::GLuint max)294 glw::GLuint TestCaseBase::randomFormula(const glw::GLuint max)
295 {
296     static const glw::GLuint a = 11;
297     static const glw::GLuint b = 17;
298 
299     seed_value = (a * seed_value + b) % max;
300 
301     return seed_value;
302 }
303 
304 /** Executes the test.
305  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
306  *
307  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
308  *
309  *  Note the function throws exception should an error occur!
310  **/
iterate(void)311 tcu::TestNode::IterateResult TestCaseBase::iterate(void)
312 {
313     qpTestResult result = QP_TEST_RESULT_FAIL;
314 
315     m_testCtx.setTestResult(result, "This location should never be called.");
316 
317     return STOP;
318 }
319 
320 /** Deinitializes base class that all test implementations inherit from.
321  *
322  **/
deinit(void)323 void TestCaseBase::deinit(void)
324 {
325     /* Left empty on purpose */
326 }
327 
328 /** Tells whether particular extension is supported.
329  *
330  *  @param extName: The name of the extension
331  *
332  *  @return true   if given extension name is reported as supported, false otherwise.
333  **/
isExtensionSupported(const std::string & extName) const334 bool TestCaseBase::isExtensionSupported(const std::string &extName) const
335 {
336     const std::vector<std::string> &extensions = m_context.getContextInfo().getExtensions();
337 
338     if (std::find(extensions.begin(), extensions.end(), extName) != extensions.end())
339     {
340         return true;
341     }
342 
343     return false;
344 }
345 
346 /** Helper method for specializing a shader */
specializeShader(const unsigned int parts,const char * const * code) const347 std::string TestCaseBase::specializeShader(const unsigned int parts, const char *const *code) const
348 {
349     std::stringstream code_merged;
350     for (unsigned int i = 0; i < parts; i++)
351     {
352         code_merged << code[i];
353     }
354     return tcu::StringTemplate(code_merged.str().c_str()).specialize(m_specializationMap);
355 }
356 
shaderSourceSpecialized(glw::GLuint shader_id,glw::GLsizei shader_count,const glw::GLchar * const * shader_string)357 void TestCaseBase::shaderSourceSpecialized(glw::GLuint shader_id, glw::GLsizei shader_count,
358                                            const glw::GLchar *const *shader_string)
359 {
360     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
361 
362     std::string specialized      = specializeShader(shader_count, shader_string);
363     const char *specialized_cstr = specialized.c_str();
364     gl.shaderSource(shader_id, 1, &specialized_cstr, NULL);
365 }
366 
getShaderTypeName(glw::GLenum shader_type)367 std::string getShaderTypeName(glw::GLenum shader_type)
368 {
369     switch (shader_type)
370     {
371     case GL_VERTEX_SHADER:
372         return "Vertex shader";
373     case GL_TESS_CONTROL_SHADER:
374         return "Tessellation control shader";
375     case GL_TESS_EVALUATION_SHADER:
376         return "Tessellation evaluation shader";
377     case GL_GEOMETRY_SHADER:
378         return "Geometry shader";
379     case GL_FRAGMENT_SHADER:
380         return "Fragment shader";
381     case GL_COMPUTE_SHADER:
382         return "Compute shader";
383     default:
384         DE_ASSERT(0);
385         return "??? shader";
386     }
387 }
388 
389 /** Compiles and links program with variable amount of shaders
390  *
391  * @param po_id                      Program handle
392  * @param out_has_compilation_failed Deref will be set to true, if shader compilation
393  *                                   failed for any of the submitted shaders.
394  *                                   Will be set to false otherwise. Can be NULL.
395  * @param sh_stages                  Shader stages
396  * @for all shader stages
397  * {
398  *   @param sh_id          Shader handle. 0 means "skip"
399  *   @param sh_parts       Number of shader source code parts.
400  *                         0 means that it's already compiled.
401  *   @param sh_code        Shader source code.
402  * }
403  **/
buildProgramVA(glw::GLuint po_id,bool * out_has_compilation_failed,unsigned int sh_stages,...)404 bool TestCaseBase::buildProgramVA(glw::GLuint po_id, bool *out_has_compilation_failed, unsigned int sh_stages, ...)
405 {
406     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
407     std::vector<glw::GLuint> vec_sh_id;
408 
409     va_list values;
410     va_start(values, sh_stages);
411 
412     /* Shaders compilation */
413     glw::GLint compilation_status = GL_FALSE;
414 
415     for (unsigned int stage = 0; stage < sh_stages; ++stage)
416     {
417         glw::GLuint sh_id          = va_arg(values, glw::GLuint);
418         unsigned int sh_parts      = va_arg(values, unsigned int);
419         const char *const *sh_code = va_arg(values, const char *const *);
420 
421         if (sh_id == 0)
422         {
423             continue;
424         }
425 
426         if (sh_parts != 0)
427         {
428             std::string sh_merged_string = specializeShader(sh_parts, sh_code);
429             const char *sh_merged_ptr    = sh_merged_string.c_str();
430 
431             gl.shaderSource(sh_id, 1, &sh_merged_ptr, NULL);
432             GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed!");
433 
434             gl.compileShader(sh_id);
435             GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed!");
436 
437             gl.getShaderiv(sh_id, GL_COMPILE_STATUS, &compilation_status);
438             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed!");
439 
440             if (compilation_status != GL_TRUE)
441             {
442                 glw::GLint shader_type = 0;
443                 std::string info_log   = getCompilationInfoLog(sh_id);
444 
445                 gl.getShaderiv(sh_id, GL_SHADER_TYPE, &shader_type);
446                 std::string shader_type_str = getShaderTypeName(shader_type);
447 
448                 m_testCtx.getLog() << tcu::TestLog::Message << shader_type_str << " compilation failure:\n\n"
449                                    << info_log << "\n\n"
450                                    << shader_type_str << " source:\n\n"
451                                    << sh_merged_string << "\n\n"
452                                    << tcu::TestLog::EndMessage;
453 
454                 break;
455             }
456         }
457 
458         gl.attachShader(po_id, sh_id);
459         GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader(VERTEX_SHADER) call failed");
460 
461         vec_sh_id.push_back(sh_id);
462     }
463 
464     va_end(values);
465 
466     if (out_has_compilation_failed != NULL)
467     {
468         *out_has_compilation_failed = (compilation_status == GL_FALSE);
469     }
470 
471     if (compilation_status != GL_TRUE)
472     {
473         return false;
474     }
475 
476     /* Linking the program */
477 
478     glw::GLint link_status = GL_FALSE;
479     gl.linkProgram(po_id);
480     GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed!");
481 
482     gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
483     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed!");
484 
485     if (link_status != GL_TRUE)
486     {
487         /* Dump link log */
488         std::string link_log = getLinkingInfoLog(po_id);
489         m_testCtx.getLog() << tcu::TestLog::Message << "Link failure:\n\n"
490                            << link_log << "\n\n"
491                            << tcu::TestLog::EndMessage;
492 
493         /* Dump shader source */
494         for (std::vector<glw::GLuint>::iterator it = vec_sh_id.begin(); it != vec_sh_id.end(); ++it)
495         {
496             glw::GLint shader_type = 0;
497             gl.getShaderiv(*it, GL_SHADER_TYPE, &shader_type);
498             std::string shader_type_str = getShaderTypeName(shader_type);
499             std::string shader_source   = getShaderSource(*it);
500             m_testCtx.getLog() << tcu::TestLog::Message << shader_type_str << " source:\n\n"
501                                << shader_source << "\n\n"
502                                << tcu::TestLog::EndMessage;
503         }
504 
505         return false;
506     }
507 
508     return true;
509 }
510 
511 /** Builds an OpenGL ES program by configuring contents of 1 shader object,
512  *  compiling it, attaching to specified program object, and finally
513  *  by linking the program object.
514  *
515  *  Implementation assumes all aforementioned objects have already been
516  *  generated.
517  *
518  *  @param po_id            ID of program object
519  *  @param sh1_shader_id    ID of first shader to configure.
520  *  @param n_sh1_body_parts Number of elements of @param sh1_body_parts array.
521  *  @param sh1_body_parts   Pointer to array of strings to make up first shader's body.
522  *                          Can be NULL.
523  *
524  *  @return GTFtrue if successful, false otherwise.
525  */
buildProgram(glw::GLuint po_id,glw::GLuint sh1_shader_id,unsigned int n_sh1_body_parts,const char * const * sh1_body_parts,bool * out_has_compilation_failed)526 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts,
527                                 const char *const *sh1_body_parts, bool *out_has_compilation_failed)
528 {
529     return buildProgramVA(po_id, out_has_compilation_failed, 1, sh1_shader_id, n_sh1_body_parts, sh1_body_parts);
530 }
531 
532 /** Builds an OpenGL ES program by configuring contents of 2 shader objects,
533  *  compiling them, attaching to specified program object, and finally
534  *  by linking the program object.
535  *
536  *  Implementation assumes all aforementioned objects have already been
537  *  generated.
538  *
539  *  @param po_id            ID of program object
540  *  @param sh1_shader_id    ID of first shader to configure.
541  *  @param n_sh1_body_parts Number of elements of @param sh1_body_parts array.
542  *  @param sh1_body_parts   Pointer to array of strings to make up first shader's body.
543  *                          Can be NULL.
544  *  @param sh2_shader_id    ID of second shader to configure.
545  *  @param n_sh2_body_parts Number of elements of @param sh2_body_parts array.
546  *  @param sh2_body_parts   Pointer to array of strings to make up second shader's body.
547  *                          Can be NULL.
548  *
549  *  @return GTFtrue if successful, false otherwise.
550  */
buildProgram(glw::GLuint po_id,glw::GLuint sh1_shader_id,unsigned int n_sh1_body_parts,const char * const * sh1_body_parts,glw::GLuint sh2_shader_id,unsigned int n_sh2_body_parts,const char * const * sh2_body_parts,bool * out_has_compilation_failed)551 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts,
552                                 const char *const *sh1_body_parts, glw::GLuint sh2_shader_id,
553                                 unsigned int n_sh2_body_parts, const char *const *sh2_body_parts,
554                                 bool *out_has_compilation_failed)
555 {
556     return buildProgramVA(po_id, out_has_compilation_failed, 2, sh1_shader_id, n_sh1_body_parts, sh1_body_parts,
557                           sh2_shader_id, n_sh2_body_parts, sh2_body_parts);
558 }
559 
560 /** Builds an OpenGL ES program by configuring contents of 3 shader objects,
561  *  compiling them, attaching to specified program object, and finally
562  *  by linking the program object.
563  *
564  *  Implementation assumes all aforementioned objects have already been
565  *  generated.
566  *
567  *  @param po_id                  ID of program object
568  *  @param sh1_shader_id          ID of first shader to configure.
569  *  @param n_sh1_body_parts       Number of elements of @param sh1_body_parts array.
570  *  @param sh1_body_parts         Pointer to array of strings to make up first shader's body.
571  *                                Can be NULL.
572  *  @param sh2_shader_id          ID of second shader to configure.
573  *  @param n_sh2_body_parts       Number of elements of @param sh2_body_parts array.
574  *  @param sh2_body_parts         Pointer to array of strings to make up second shader's body.
575  *                                Can be NULL.
576  *  @param sh3_shader_id          ID of third shader to configure.
577  *  @param n_sh3_body_parts       Number of elements of @param sh3_body_parts array.
578  *  @param sh3_body_parts         Pointer to array of strings to make up third shader's body.
579  *                                Can be NULL.
580  *  @param has_compilation_failed Deref will be set to true if shader compilation failed,
581  *                                false if shader compilation was successful. Can be NULL.
582  *
583  *  @return GTFtrue if successful, false otherwise.
584  */
buildProgram(glw::GLuint po_id,glw::GLuint sh1_shader_id,unsigned int n_sh1_body_parts,const char * const * sh1_body_parts,glw::GLuint sh2_shader_id,unsigned int n_sh2_body_parts,const char * const * sh2_body_parts,glw::GLuint sh3_shader_id,unsigned int n_sh3_body_parts,const char * const * sh3_body_parts,bool * out_has_compilation_failed)585 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts,
586                                 const char *const *sh1_body_parts, glw::GLuint sh2_shader_id,
587                                 unsigned int n_sh2_body_parts, const char *const *sh2_body_parts,
588                                 glw::GLuint sh3_shader_id, unsigned int n_sh3_body_parts,
589                                 const char *const *sh3_body_parts, bool *out_has_compilation_failed)
590 {
591     return buildProgramVA(po_id, out_has_compilation_failed, 3, sh1_shader_id, n_sh1_body_parts, sh1_body_parts,
592                           sh2_shader_id, n_sh2_body_parts, sh2_body_parts, sh3_shader_id, n_sh3_body_parts,
593                           sh3_body_parts);
594 }
595 
596 /** Builds an OpenGL ES program by configuring contents of 4 shader objects,
597  *  compiling them, attaching to specified program object, and finally
598  *  by linking the program object.
599  *
600  *  Implementation assumes all aforementioned objects have already been
601  *  generated.
602  *
603  *  @param po_id            ID of program object
604  *  @param sh1_shader_id    ID of first shader to configure.
605  *  @param n_sh1_body_parts Number of elements of @param sh1_body_parts array.
606  *  @param sh1_body_parts   Pointer to array of strings to make up first shader's body.
607  *                          Can be NULL.
608  *  @param sh2_shader_id    ID of second shader to configure.
609  *  @param n_sh2_body_parts Number of elements of @param sh2_body_parts array.
610  *  @param sh2_body_parts   Pointer to array of strings to make up second shader's body.
611  *                          Can be NULL.
612  *  @param sh3_shader_id    ID of third shader to configure.
613  *  @param n_sh3_body_parts Number of elements of @param sh3_body_parts array.
614  *  @param sh3_body_parts   Pointer to array of strings to make up third shader's body.
615  *                          Can be NULL.
616  *  @param sh4_shader_id    ID of fourth shader to configure.
617  *  @param n_sh4_body_parts Number of elements of @param sh4_body_parts array.
618  *  @param sh4_body_parts   Pointer to array of strings to make up fourth shader's body.
619  *                          Can be NULL.
620  *
621  *  @return GTFtrue if successful, false otherwise.
622  */
buildProgram(glw::GLuint po_id,glw::GLuint sh1_shader_id,unsigned int n_sh1_body_parts,const char * const * sh1_body_parts,glw::GLuint sh2_shader_id,unsigned int n_sh2_body_parts,const char * const * sh2_body_parts,glw::GLuint sh3_shader_id,unsigned int n_sh3_body_parts,const char * const * sh3_body_parts,glw::GLuint sh4_shader_id,unsigned int n_sh4_body_parts,const char * const * sh4_body_parts,bool * out_has_compilation_failed)623 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts,
624                                 const char *const *sh1_body_parts, glw::GLuint sh2_shader_id,
625                                 unsigned int n_sh2_body_parts, const char *const *sh2_body_parts,
626                                 glw::GLuint sh3_shader_id, unsigned int n_sh3_body_parts,
627                                 const char *const *sh3_body_parts, glw::GLuint sh4_shader_id,
628                                 unsigned int n_sh4_body_parts, const char *const *sh4_body_parts,
629                                 bool *out_has_compilation_failed)
630 {
631     return buildProgramVA(po_id, out_has_compilation_failed, 4, sh1_shader_id, n_sh1_body_parts, sh1_body_parts,
632                           sh2_shader_id, n_sh2_body_parts, sh2_body_parts, sh3_shader_id, n_sh3_body_parts,
633                           sh3_body_parts, sh4_shader_id, n_sh4_body_parts, sh4_body_parts);
634 }
635 
636 /** Builds an OpenGL ES program by configuring contents of 5 shader objects,
637  *  compiling them, attaching to specified program object, and finally
638  *  by linking the program object.
639  *
640  *  Implementation assumes all aforementioned objects have already been
641  *  generated.
642  *
643  *  @param po_id            ID of program object
644  *  @param sh1_shader_id    ID of first shader to configure.
645  *  @param n_sh1_body_parts Number of elements of @param sh1_body_parts array.
646  *  @param sh1_body_parts   Pointer to array of strings to make up first shader's body.
647  *                          Can be NULL.
648  *  @param sh2_shader_id    ID of second shader to configure.
649  *  @param n_sh2_body_parts Number of elements of @param sh2_body_parts array.
650  *  @param sh2_body_parts   Pointer to array of strings to make up second shader's body.
651  *                          Can be NULL.
652  *  @param sh3_shader_id    ID of third shader to configure.
653  *  @param n_sh3_body_parts Number of elements of @param sh3_body_parts array.
654  *  @param sh3_body_parts   Pointer to array of strings to make up third shader's body.
655  *                          Can be NULL.
656  *  @param sh4_shader_id    ID of fourth shader to configure.
657  *  @param n_sh4_body_parts Number of elements of @param sh4_body_parts array.
658  *  @param sh4_body_parts   Pointer to array of strings to make up fourth shader's body.
659  *                          Can be NULL.
660  *  @param sh5_shader_id    ID of fifth shader to configure.
661  *  @param n_sh5_body_parts Number of elements of @param sh5_body_parts array.
662  *  @param sh5_body_parts   Pointer to array of strings to make up fifth shader's body.
663  *                          Can be NULL.
664  *
665  *  @return GTFtrue if successful, false otherwise.
666  */
buildProgram(glw::GLuint po_id,glw::GLuint sh1_shader_id,unsigned int n_sh1_body_parts,const char * const * sh1_body_parts,glw::GLuint sh2_shader_id,unsigned int n_sh2_body_parts,const char * const * sh2_body_parts,glw::GLuint sh3_shader_id,unsigned int n_sh3_body_parts,const char * const * sh3_body_parts,glw::GLuint sh4_shader_id,unsigned int n_sh4_body_parts,const char * const * sh4_body_parts,glw::GLuint sh5_shader_id,unsigned int n_sh5_body_parts,const char * const * sh5_body_parts,bool * out_has_compilation_failed)667 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts,
668                                 const char *const *sh1_body_parts, glw::GLuint sh2_shader_id,
669                                 unsigned int n_sh2_body_parts, const char *const *sh2_body_parts,
670                                 glw::GLuint sh3_shader_id, unsigned int n_sh3_body_parts,
671                                 const char *const *sh3_body_parts, glw::GLuint sh4_shader_id,
672                                 unsigned int n_sh4_body_parts, const char *const *sh4_body_parts,
673                                 glw::GLuint sh5_shader_id, unsigned int n_sh5_body_parts,
674                                 const char *const *sh5_body_parts, bool *out_has_compilation_failed)
675 {
676     return buildProgramVA(po_id, out_has_compilation_failed, 5, sh1_shader_id, n_sh1_body_parts, sh1_body_parts,
677                           sh2_shader_id, n_sh2_body_parts, sh2_body_parts, sh3_shader_id, n_sh3_body_parts,
678                           sh3_body_parts, sh4_shader_id, n_sh4_body_parts, sh4_body_parts, sh5_shader_id,
679                           n_sh5_body_parts, sh5_body_parts);
680 }
681 
682 /** Compare pixel's color with specified value.
683  *  Assumptions:
684  *  - size of each channel is 1 byte
685  *  - channel order is R G B A
686  *  - lines are stored one after another, without any additional data
687  *
688  * @param buffer            Image data
689  * @param x                 X coordinate of pixel
690  * @param y                 Y coordinate of pixel
691  * @param width             Image width
692  * @param height            Image height
693  * @param pixel_size        Size of single pixel in bytes, eg. for RGBA8 it should be set to 4
694  * @param expected_red      Expected value of red channel, default is 0
695  * @param expected_green    Expected value of green channel, default is 0
696  * @param expected_blue     Expected value of blue channel, default is 0
697  * @param expected_alpha    Expected value of alpha channel, default is 0
698  *
699  * @retrun true    When pixel color matches expected values
700  *         false   When:
701  *                  - buffer is null_ptr
702  *                  - offset of pixel exceeds size of image
703  *                  - pixel_size is not in range <1 ; 4>
704  *                  - pixel color does not match expected values
705  **/
comparePixel(const unsigned char * buffer,unsigned int x,unsigned int y,unsigned int width,unsigned int height,unsigned int pixel_size,unsigned char expected_red,unsigned char expected_green,unsigned char expected_blue,unsigned char expected_alpha) const706 bool TestCaseBase::comparePixel(const unsigned char *buffer, unsigned int x, unsigned int y, unsigned int width,
707                                 unsigned int height, unsigned int pixel_size, unsigned char expected_red,
708                                 unsigned char expected_green, unsigned char expected_blue,
709                                 unsigned char expected_alpha) const
710 {
711     const unsigned int line_size    = width * pixel_size;
712     const unsigned int image_size   = height * line_size;
713     const unsigned int texel_offset = y * line_size + x * pixel_size;
714 
715     bool result = true;
716 
717     /* Quick checks */
718     if (0 == buffer)
719     {
720         return false;
721     }
722 
723     if (image_size < texel_offset)
724     {
725         return false;
726     }
727 
728     switch (pixel_size)
729     {
730     /* Fall through by design */
731     case 4:
732     {
733         result &= (expected_alpha == buffer[texel_offset + 3]);
734     }
735         /* Fallthrough */
736 
737     case 3:
738     {
739         result &= (expected_blue == buffer[texel_offset + 2]);
740     }
741         /* Fallthrough */
742 
743     case 2:
744     {
745         result &= (expected_green == buffer[texel_offset + 1]);
746     }
747         /* Fallthrough */
748 
749     case 1:
750     {
751         result &= (expected_red == buffer[texel_offset + 0]);
752 
753         break;
754     }
755 
756     default:
757     {
758         return false;
759     }
760     } /* switch (pixel_size) */
761 
762     return result;
763 }
764 
765 /** Checks whether a combination of fragment/geometry/vertex shader objects compiles and links into a program
766  *
767  *  @param n_fs_body_parts Number of elements of @param fs_body_parts array.
768  *  @param fs_body_parts   Pointer to array of strings to make up fragment shader's body.
769  *                         Must not be NULL.
770  *
771  *  @param n_gs_body_parts Number of elements of @param gs_body_parts array.
772  *  @param gs_body_parts   Pointer to array of strings to make up geometry shader's body.
773  *                         Can be NULL.
774  *
775  *  @param n_vs_body_parts Number of elements of @param vs_body_parts array.
776  *  @param vs_body_parts   Pointer to array of strings to make up vertex shader's body.
777  *                         Must not be NULL.
778  *
779  *  @return true if program creation was successful, false otherwise.
780  **/
doesProgramBuild(unsigned int n_fs_body_parts,const char * const * fs_body_parts,unsigned int n_gs_body_parts,const char * const * gs_body_parts,unsigned int n_vs_body_parts,const char * const * vs_body_parts)781 bool TestCaseBase::doesProgramBuild(unsigned int n_fs_body_parts, const char *const *fs_body_parts,
782                                     unsigned int n_gs_body_parts, const char *const *gs_body_parts,
783                                     unsigned int n_vs_body_parts, const char *const *vs_body_parts)
784 {
785     /* General variables */
786     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
787     bool result              = false;
788 
789     /* Shaders */
790     glw::GLuint vertex_shader_id   = 0;
791     glw::GLuint geometry_shader_id = 0;
792     glw::GLuint fragment_shader_id = 0;
793 
794     /* Program */
795     glw::GLuint program_object_id = 0;
796 
797     /* Create shaders */
798     vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
799     geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
800     fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
801 
802     /* Create program */
803     program_object_id = gl.createProgram();
804 
805     /* Check createProgram call for errors */
806     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
807 
808     /* Compile and link the program */
809     result = buildProgram(program_object_id, fragment_shader_id, n_fs_body_parts, fs_body_parts, geometry_shader_id,
810                           n_gs_body_parts, gs_body_parts, vertex_shader_id, n_vs_body_parts, vs_body_parts);
811 
812     if (program_object_id != 0)
813         gl.deleteProgram(program_object_id);
814     if (fragment_shader_id != 0)
815         gl.deleteShader(fragment_shader_id);
816     if (geometry_shader_id != 0)
817         gl.deleteShader(geometry_shader_id);
818     if (vertex_shader_id != 0)
819         gl.deleteShader(vertex_shader_id);
820 
821     return result;
822 }
823 
824 /** Retrieves source for a shader object with GLES id @param shader_id.
825  *
826  *  @param shader_id GLES id of a shader object to retrieve source for.
827  *
828  *  @return String instance containing the shader source.
829  **/
getShaderSource(glw::GLuint shader_id)830 std::string TestCaseBase::getShaderSource(glw::GLuint shader_id)
831 {
832     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
833 
834     glw::GLint length = 0;
835 
836     gl.getShaderiv(shader_id, GL_SHADER_SOURCE_LENGTH, &length);
837 
838     std::vector<char> result_vec(length + 1);
839 
840     gl.getShaderSource(shader_id, length + 1, NULL, &result_vec[0]);
841 
842     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve shader source!");
843 
844     return std::string(&result_vec[0]);
845 }
846 
847 /** Retrieves compilation info log for a shader object with GLES id
848  *  @param shader_id.
849  *
850  *  @param shader_id GLES id of a shader object to retrieve compilation
851  *          info log for.
852  *
853  *  @return String instance containing the log.
854  **/
getCompilationInfoLog(glw::GLuint shader_id)855 std::string TestCaseBase::getCompilationInfoLog(glw::GLuint shader_id)
856 {
857     return getInfoLog(LT_SHADER_OBJECT, shader_id);
858 }
859 
860 /** Retrieves linking info log for a program object with GLES id
861  *  @param po_id.
862  *
863  *  @param po_id GLES id of a program object to retrieve linking
864  *               info log for.
865  *
866  *  @return String instance containing the log.
867  **/
getLinkingInfoLog(glw::GLuint po_id)868 std::string TestCaseBase::getLinkingInfoLog(glw::GLuint po_id)
869 {
870     return getInfoLog(LT_PROGRAM_OBJECT, po_id);
871 }
872 
873 /** Retrieves linking info log for a pipeline object with GLES id
874  *  @param ppo_id.
875  *
876  *  @param ppo_id GLES id of a pipeline object to retrieve validation
877  *               info log for.
878  *
879  *  @return String instance containing the log.
880  **/
getPipelineInfoLog(glw::GLuint ppo_id)881 std::string TestCaseBase::getPipelineInfoLog(glw::GLuint ppo_id)
882 {
883     return getInfoLog(LT_PIPELINE_OBJECT, ppo_id);
884 }
885 
886 /** Retrieves compilation OR linking info log for a shader/program object with GLES id
887  *  @param id.
888  *
889  *  @param is_compilation_info_log true if @param id is a GLES id of a shader object;
890  *                                 false if it represents a program object.
891  *  @param id                      GLES id of a shader OR a program object to
892  *                                 retrieve info log for.
893  *
894  *  @return String instance containing the log..
895  **/
getInfoLog(LOG_TYPE log_type,glw::GLuint id)896 std::string TestCaseBase::getInfoLog(LOG_TYPE log_type, glw::GLuint id)
897 {
898     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
899 
900     glw::GLint n_characters = 0;
901     /* Retrieve amount of characters needed to store the info log (terminator-inclusive) */
902     switch (log_type)
903     {
904     case LT_SHADER_OBJECT:
905         gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &n_characters);
906         break;
907     case LT_PROGRAM_OBJECT:
908         gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &n_characters);
909         break;
910     case LT_PIPELINE_OBJECT:
911         gl.getProgramPipelineiv(id, GL_INFO_LOG_LENGTH, &n_characters);
912         break;
913     default:
914         TCU_FAIL("Invalid parameter");
915     }
916 
917     /* Check if everything is fine so far */
918     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query info log length!");
919 
920     /* Allocate buffer */
921     std::vector<char> result_vec(n_characters + 1);
922 
923     /* Retrieve the info log */
924     switch (log_type)
925     {
926     case LT_SHADER_OBJECT:
927         gl.getShaderInfoLog(id, n_characters + 1, 0, &result_vec[0]);
928         break;
929     case LT_PROGRAM_OBJECT:
930         gl.getProgramInfoLog(id, n_characters + 1, 0, &result_vec[0]);
931         break;
932     case LT_PIPELINE_OBJECT:
933         gl.getProgramPipelineInfoLog(id, n_characters + 1, 0, &result_vec[0]);
934         break;
935     }
936 
937     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve info log!");
938 
939     return std::string(&result_vec[0]);
940 }
941 
942 /** Setup frame buffer:
943  * 1 allocate texture storage for specified format and dimensions,
944  * 2 bind framebuffer and attach texture to GL_COLOR_ATTACHMENT0
945  * 3 setup viewport to specified dimensions
946  *
947  * @param framebuffer_object_id FBO handle
948  * @param color_texture_id      Texture handle
949  * @param texture_format        Requested texture format, eg. GL_RGBA8
950  * @param texture_width         Requested texture width
951  * @param texture_height        Requested texture height
952  *
953  * @return true  All operations succeded
954  *         false In case of any error
955  **/
setupFramebufferWithTextureAsAttachment(glw::GLuint framebuffer_object_id,glw::GLuint color_texture_id,glw::GLenum texture_format,glw::GLuint texture_width,glw::GLuint texture_height) const956 bool TestCaseBase::setupFramebufferWithTextureAsAttachment(glw::GLuint framebuffer_object_id,
957                                                            glw::GLuint color_texture_id, glw::GLenum texture_format,
958                                                            glw::GLuint texture_width, glw::GLuint texture_height) const
959 {
960     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
961 
962     /* Allocate texture storage */
963     gl.bindTexture(GL_TEXTURE_2D, color_texture_id);
964     gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, texture_format, texture_width, texture_height);
965 
966     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not allocate texture storage!");
967 
968     /* Setup framebuffer */
969     gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer_object_id);
970     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_texture_id, 0 /* level */);
971 
972     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not setup framebuffer!");
973 
974     /* Setup viewport */
975     gl.viewport(0, 0, texture_width, texture_height);
976 
977     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not setup viewport!");
978 
979     /* Success */
980     return true;
981 }
982 
983 /** Check Framebuffer Status.
984  *   Throws a TestError exception, should the framebuffer be found incomplete.
985  *
986  *  @param framebuffer - GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER
987  *
988  */
checkFramebufferStatus(glw::GLenum framebuffer) const989 void TestCaseBase::checkFramebufferStatus(glw::GLenum framebuffer) const
990 {
991     /* Get GL entry points */
992     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
993 
994     glw::GLenum framebuffer_status = gl.checkFramebufferStatus(framebuffer);
995     GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting framebuffer status!");
996 
997     if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status)
998     {
999         switch (framebuffer_status)
1000         {
1001         case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
1002         {
1003             TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
1004         }
1005 
1006         case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
1007         {
1008             TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
1009         }
1010 
1011         case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
1012         {
1013             TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
1014         }
1015 
1016         case GL_FRAMEBUFFER_UNSUPPORTED:
1017         {
1018             TCU_FAIL("Framebuffer incomplete, status: Error: GL_FRAMEBUFFER_UNSUPPORTED");
1019         }
1020 
1021         default:
1022         {
1023             TCU_FAIL("Framebuffer incomplete, status not recognized");
1024         }
1025         } /* switch (framebuffer_status) */
1026     }     /* if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) */
1027 }
1028 
getGLSLExtDirective(ExtensionType type,ExtensionName name,ExtensionBehavior behavior)1029 std::string TestCaseBase::getGLSLExtDirective(ExtensionType type, ExtensionName name, ExtensionBehavior behavior)
1030 {
1031     if (type == EXTENSIONTYPE_NONE && name != EXTENSIONNAME_GEOMETRY_POINT_SIZE &&
1032         name != EXTENSIONNAME_TESSELLATION_POINT_SIZE)
1033     {
1034         return "";
1035     }
1036 
1037     const char *type_str     = NULL;
1038     const char *name_str     = NULL;
1039     const char *behavior_str = NULL;
1040 
1041     if (name == EXTENSIONNAME_SHADER_IMAGE_ATOMIC)
1042     {
1043         // There is no EXT version of shader_image_atomic; use OES
1044         type = EXTENSIONTYPE_OES;
1045     }
1046 
1047     if (name == EXTENSIONNAME_TESSELLATION_POINT_SIZE)
1048     {
1049         // there is no core version of tessellation_point_size, use OES or EXT
1050         if (isExtensionSupported("GL_OES_tessellation_point_size"))
1051         {
1052             type = EXTENSIONTYPE_OES;
1053         }
1054         else if (isExtensionSupported("GL_EXT_tessellation_point_size"))
1055         {
1056             type = EXTENSIONTYPE_EXT;
1057         }
1058         else
1059         {
1060             return "";
1061         }
1062     }
1063 
1064     if (name == EXTENSIONNAME_GEOMETRY_POINT_SIZE)
1065     {
1066         // there is no core version of geometry_point_size, use OES or EXT
1067         if (isExtensionSupported("GL_OES_geometry_point_size"))
1068         {
1069             type = EXTENSIONTYPE_OES;
1070         }
1071         else if (isExtensionSupported("GL_EXT_geometry_point_size"))
1072         {
1073             type = EXTENSIONTYPE_EXT;
1074         }
1075         else
1076         {
1077             return "";
1078         }
1079     }
1080 
1081     switch (type)
1082     {
1083     case EXTENSIONTYPE_EXT:
1084         type_str = "EXT_";
1085         break;
1086     case EXTENSIONTYPE_OES:
1087         type_str = "OES_";
1088         break;
1089     default:
1090         DE_ASSERT(0);
1091         return "#error unknown extension type\n";
1092     }
1093 
1094     switch (name)
1095     {
1096     case EXTENSIONNAME_SHADER_IMAGE_ATOMIC:
1097         name_str = "shader_image_atomic";
1098         break;
1099     case EXTENSIONNAME_SHADER_IO_BLOCKS:
1100         name_str = "shader_io_blocks";
1101         break;
1102     case EXTENSIONNAME_GEOMETRY_SHADER:
1103         name_str = "geometry_shader";
1104         break;
1105     case EXTENSIONNAME_GEOMETRY_POINT_SIZE:
1106         name_str = "geometry_point_size";
1107         break;
1108     case EXTENSIONNAME_TESSELLATION_SHADER:
1109         name_str = "tessellation_shader";
1110         break;
1111     case EXTENSIONNAME_TESSELLATION_POINT_SIZE:
1112         name_str = "tessellation_point_size";
1113         break;
1114     case EXTENSIONNAME_TEXTURE_BUFFER:
1115         name_str = "texture_buffer";
1116         break;
1117     case EXTENSIONNAME_TEXTURE_CUBE_MAP_ARRAY:
1118         name_str = "texture_cube_map_array";
1119         break;
1120     case EXTENSIONNAME_GPU_SHADER5:
1121         name_str = "gpu_shader5";
1122         break;
1123     case EXTENSIONNAME_VIEWPORT_ARRAY:
1124         name_str = "viewport_array";
1125         break;
1126     default:
1127         DE_ASSERT(0);
1128         return "#error unknown extension name\n";
1129     }
1130 
1131     switch (behavior)
1132     {
1133     case EXTENSIONBEHAVIOR_DISABLE:
1134         behavior_str = "disable";
1135         break;
1136     case EXTENSIONBEHAVIOR_WARN:
1137         behavior_str = "warn";
1138         break;
1139     case EXTENSIONBEHAVIOR_ENABLE:
1140         behavior_str = "enable";
1141         break;
1142     case EXTENSIONBEHAVIOR_REQUIRE:
1143         behavior_str = "require";
1144         break;
1145     default:
1146         DE_ASSERT(0);
1147         return "#error unknown extension behavior";
1148     }
1149 
1150     std::stringstream str;
1151     str << "#extension GL_" << type_str << name_str << " : " << behavior_str;
1152     return str.str();
1153 }
1154 
1155 } // namespace glcts
1156