Fix texture_size_promotion snorm/RGB10_A2UI issue
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / gl / gl3cTextureSizePromotion.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2015-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 /**
25  * \file  gl3cTextureSizePromotionTests.hpp
26  * \brief Implements test classes for testing of texture internal format
27  promotion mechanism.
28  */ /*-------------------------------------------------------------------*/
29
30 #include "gl3cTextureSizePromotion.hpp"
31
32 #include "deMath.h"
33 #include "gluContextInfo.hpp"
34 #include "gluStrUtil.hpp"
35 #include "glwFunctions.hpp"
36 #include "tcuTestLog.hpp"
37
38 /* Stringify macro. */
39 #define _STR(s) STR(s)
40 #define STR(s) #s
41
42 namespace gl3cts
43 {
44 namespace TextureSizePromotion
45 {
46 Tests::Tests(deqp::Context& context)
47         : TestCaseGroup(context, "texture_size_promotion", "Verifies texture internal format size promotion mechanism.")
48 {
49         /* Left blank on purpose */
50 }
51
52 void Tests::init(void)
53 {
54         addChild(new TextureSizePromotion::FunctionalTest(m_context));
55 }
56
57 /*===========================================================================================================*/
58
59 FunctionalTest::FunctionalTest(deqp::Context& context)
60         : TestCase(context, "functional", "Verifies that texture internal format size promotion mechanism can be used.")
61         , m_vao(0)
62         , m_source_texture(0)
63         , m_destination_texture(0)
64         , m_framebuffer(0)
65         , m_program(0)
66         , m_max_samples(0)
67 {
68         /* Left blank on purpose */
69 }
70
71 tcu::TestNode::IterateResult FunctionalTest::iterate()
72 {
73         /* Get context setup. */
74         glu::ContextType context_type = m_context.getRenderContext().getType();
75         bool                     is_arb_texture_storage_multisample =
76                 m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_storage_multisample");
77
78         /* Prepare initial results. */
79         bool is_ok       = true;
80         bool was_error = false;
81
82         /* Iterate over test cases. */
83         try
84         {
85                 /* Only for OpenGL 3.1 context. */
86                 if (glu::contextSupports(context_type, glu::ApiType::core(3, 1)))
87                 {
88                         /* Generate and bind VAO. */
89                         prepareVertexArrayObject();
90
91                         /* For every required format */
92                         for (glw::GLuint i = 0; i < s_formats_size; ++i)
93                         {
94                                 /* Test only if format is required by context. */
95                                 if (glu::contextSupports(context_type, s_formats[i].required_by_context.getAPI()))
96                                 {
97                                         /* For every target. */
98                                         for (glw::GLuint j = 0; j < s_source_texture_targets_count; ++j)
99                                         {
100                                                 /* Test if it is supported by context or internal format. */
101                                                 if (isTargetMultisampled(s_source_texture_targets[j]))
102                                                 {
103                                                         if ((!is_arb_texture_storage_multisample) &&
104                                                                 (!glu::contextSupports(context_type, glu::ApiType::core(4, 3))))
105                                                         {
106                                                                 continue;
107                                                         }
108
109                                                         if (!s_formats[i]
110                                                                          .is_color_renderable) /* Multisampled textures need to be set using rendering. */
111                                                         {
112                                                                 continue;
113                                                         }
114
115                                                         if (isDepthType(s_formats[i]) || isStencilType(s_formats[i]))
116                                                         {
117                                                                 continue;
118                                                         }
119                                                 }
120
121                                                 if ((isDepthType(s_formats[i]) || isStencilType(s_formats[i])) &&
122                                                         (GL_TEXTURE_3D == s_source_texture_targets[j]))
123                                                 {
124                                                         continue;
125                                                 }
126
127                                                 /* Prepare source texture to be tested. */
128                                                 prepareSourceTexture(s_formats[i], s_source_texture_targets[j]);
129
130                                                 /* Check basic API queries for source texture. */
131                                                 is_ok = is_ok & checkSourceTextureSizeAndType(s_formats[i], s_source_texture_targets[j]);
132
133                                                 /* For every [R, G, B, A] component. */
134                                                 for (glw::GLuint k = 0; k < COMPONENTS_COUNT; ++k)
135                                                 {
136                                                         /* Prepare destination texture. */
137                                                         prepareDestinationTextureAndFramebuffer(s_formats[i], GL_TEXTURE_2D);
138
139                                                         /* Building program (throws on failure). */
140                                                         m_program =
141                                                                 prepareProgram(s_source_texture_targets[j], s_formats[i], ColorChannelSelector(k));
142
143                                                         /* Setup GL and draw. */
144                                                         makeProgramAndSourceTextureActive(s_source_texture_targets[j]);
145
146                                                         drawQuad();
147
148                                                         /* Check results. */
149                                                         is_ok = is_ok & checkDestinationTexture(s_formats[i], ColorChannelSelector(k),
150                                                                                                                                         s_source_texture_targets[j],
151                                                                                                                                         s_source_texture_targets_names[j]);
152
153                                                         /* Cleanup. */
154                                                         cleanDestinationTexture();
155                                                         cleanFramebuffer();
156                                                         cleanProgram();
157                                                 }
158
159                                                 cleanSourceTexture();
160                                         }
161                                 }
162                         }
163                 }
164         }
165         catch (...)
166         {
167                 /* Error have occured. */
168                 is_ok    = false;
169                 was_error = true;
170         }
171
172         /* Clean all. */
173
174         cleanSourceTexture();
175         cleanDestinationTexture();
176         cleanFramebuffer();
177         cleanProgram();
178         cleanVertexArrayObject();
179
180         /* Result's setup. */
181         if (is_ok)
182         {
183                 /* Log success. */
184                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture Size Promotion Test have passed."
185                                                                                         << tcu::TestLog::EndMessage;
186
187                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
188         }
189         else
190         {
191                 if (was_error)
192                 {
193                         /* Log error. */
194                         m_context.getTestContext().getLog() << tcu::TestLog::Message
195                                                                                                 << "Texture Size Promotion Test have approached error."
196                                                                                                 << tcu::TestLog::EndMessage;
197
198                         m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
199                 }
200                 else
201                 {
202                         /* Log fail. */
203                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture Size Promotion Test have failed."
204                                                                                                 << tcu::TestLog::EndMessage;
205
206                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
207                 }
208         }
209
210         /* End test. */
211         return tcu::TestNode::STOP;
212 }
213
214 void FunctionalTest::prepareVertexArrayObject()
215 {
216         /* GL functions object. */
217         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
218
219         gl.genVertexArrays(1, &m_vao);
220         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays have failed");
221
222         gl.bindVertexArray(m_vao);
223         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray have failed");
224 }
225
226 void FunctionalTest::prepareSourceTexture(TextureInternalFormatDescriptor descriptor, glw::GLenum target)
227 {
228         /* GL functions object. */
229         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
230
231         /* Create and bind texture object. */
232         gl.genTextures(1, &m_source_texture);
233         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
234
235         gl.bindTexture(target, m_source_texture);
236         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
237
238         /* Select proper data set. */
239         glw::GLvoid* source_data   = DE_NULL;
240         glw::GLenum  source_type   = GL_NONE;
241         glw::GLenum  source_format = GL_RGBA;
242
243         if (isFloatType(descriptor)) /* For floating type. */
244         {
245                 source_data   = (glw::GLvoid*)s_source_texture_data_f;
246                 source_type   = GL_FLOAT;
247                 source_format = GL_RGBA;
248         }
249         else
250         {
251                 if (isFixedSignedType(descriptor)) /* For fixed signed type. */
252                 {
253                         source_data   = (glw::GLvoid*)s_source_texture_data_sn;
254                         source_type   = GL_FLOAT;
255                         source_format = GL_RGBA;
256                 }
257                 else
258                 {
259                         if (isFixedUnsignedType(descriptor)) /* For fixed unsigned type. */
260                         {
261                                 source_data   = (glw::GLvoid*)s_source_texture_data_n;
262                                 source_type   = GL_FLOAT;
263                                 source_format = GL_RGBA;
264                         }
265                         else
266                         {
267                                 if (isIntegerSignedType(descriptor)) /* For integral signed type. */
268                                 {
269                                         source_data   = (glw::GLvoid*)s_source_texture_data_i;
270                                         source_type   = GL_INT;
271                                         source_format = GL_RGBA_INTEGER;
272                                 }
273                                 else
274                                 {
275                                         if (isIntegerUnsignedType(descriptor)) /* For integral unsigned type. */
276                                         {
277                                                 source_data   = (glw::GLvoid*)s_source_texture_data_ui;
278                                                 source_type   = GL_UNSIGNED_INT;
279                                                 source_format = GL_RGBA_INTEGER;
280                                         }
281                                         else
282                                         {
283                                                 if (isDepthType(descriptor)) /* For depth type. */
284                                                 {
285                                                         source_data   = NULL;
286                                                         source_type   = GL_UNSIGNED_INT;
287                                                         source_format = GL_DEPTH_COMPONENT;
288                                                 }
289                                                 else
290                                                 {
291                                                         if (isStencilType(descriptor)) /* For stencil type. */
292                                                         {
293                                                                 source_data   = NULL;
294                                                                 source_type   = GL_UNSIGNED_INT;
295                                                                 source_format = GL_STENCIL_INDEX;
296                                                         }
297                                                 }
298                                         }
299                                 }
300                         }
301                 }
302         }
303
304         /* Prepare texture storage depending on the target. */
305         switch (target)
306         {
307         case GL_TEXTURE_1D:
308                 gl.texImage1D(target, 0, descriptor.internal_format, s_source_texture_size, 0, source_format, source_type,
309                                           source_data);
310                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
311                 break;
312         case GL_TEXTURE_1D_ARRAY:
313         case GL_TEXTURE_2D:
314         case GL_TEXTURE_RECTANGLE:
315                 gl.texImage2D(target, 0, descriptor.internal_format, s_source_texture_size, s_source_texture_size, 0,
316                                           source_format, source_type, source_data);
317                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
318                 break;
319         case GL_TEXTURE_2D_ARRAY:
320         case GL_TEXTURE_3D:
321                 gl.texImage3D(target, 0, descriptor.internal_format, s_source_texture_size, s_source_texture_size,
322                                           s_source_texture_size, 0, source_format, source_type, source_data);
323                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
324                 break;
325         case GL_TEXTURE_2D_MULTISAMPLE:
326         case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
327                 renderDataIntoMultisampledTexture(descriptor, target);
328                 break;
329         default:
330                 throw 0;
331         }
332 }
333
334 void FunctionalTest::renderDataIntoMultisampledTexture(TextureInternalFormatDescriptor descriptor, glw::GLenum target)
335 {
336         /* GL functions object. */
337         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
338
339         /* Fetch limits. */
340         gl.getIntegerv(GL_MAX_SAMPLES, &m_max_samples);
341         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv have failed");
342
343         if (m_max_samples == 0)
344         {
345                 m_max_samples = 1;
346         }
347
348         /* Setup target. */
349         glw::GLenum non_ms_target = (target == GL_TEXTURE_2D_MULTISAMPLE) ? GL_TEXTURE_2D : GL_TEXTURE_2D_ARRAY;
350
351         /* Cleanup required by prepareSourceTexture(...). */
352         cleanSourceTexture();
353
354         /* Prepare textures and program. */
355         prepareSourceTexture(descriptor, non_ms_target);
356
357         prepareDestinationTextureAndFramebuffer(descriptor, target);
358
359         m_program = prepareProgram(non_ms_target, descriptor, COMPONENTS_COUNT);
360
361         /* Setup GL and render texture. */
362         makeProgramAndSourceTextureActive(non_ms_target);
363
364         drawQuad();
365
366         /* Cleanup. */
367         cleanFramebuffer();
368         cleanSourceTexture();
369
370         /* Swpaing destination texture to source texture. */
371         m_source_texture = m_destination_texture;
372
373         m_destination_texture = 0;
374
375         /* Clean program. */
376         cleanProgram();
377 }
378
379 void FunctionalTest::prepareDestinationTextureAndFramebuffer(TextureInternalFormatDescriptor descriptor,
380                                                                                                                          glw::GLenum                                     target)
381 {
382         /* GL functions object. */
383         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
384
385         /* Get internal format. */
386         glw::GLenum internal_format = getDestinationFormatForChannel(descriptor);
387
388         /* Create framebuffer object. */
389         gl.genFramebuffers(1, &m_framebuffer);
390         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
391
392         gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
393         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
394
395         /* Create framebuffer's destination texture. */
396         gl.genTextures(1, &m_destination_texture);
397         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
398
399         gl.bindTexture(target, m_destination_texture);
400         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
401
402         /* Allocate texture storage and upload data for test rendering. */
403         if (target == GL_TEXTURE_2D)
404         {
405                 glw::GLenum  destination_format = GL_RED;
406                 glw::GLenum  destination_type   = GL_FLOAT;
407                 glw::GLvoid* destination_data   = (glw::GLvoid*)s_destination_texture_data_f;
408
409                 if (isIntegerSignedType(descriptor))
410                 {
411                         destination_format = GL_RED_INTEGER;
412                         destination_type   = GL_INT;
413                         destination_data   = (glw::GLvoid*)s_destination_texture_data_i;
414                 }
415
416                 if (isIntegerUnsignedType(descriptor))
417                 {
418                         destination_format = GL_RED_INTEGER;
419                         destination_type   = GL_UNSIGNED_INT;
420                         destination_data   = (glw::GLvoid*)s_destination_texture_data_ui;
421                 }
422
423                 gl.texImage2D(target, 0, internal_format, s_source_texture_size, s_source_texture_size, 0, destination_format,
424                                           destination_type, destination_data);
425                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
426
427                 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_destination_texture, 0);
428                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D have failed");
429         }
430         else /* Allocate texture storage for uploading datat for multisampled targets (upload must be done via shader). */
431         {
432                 if (target == GL_TEXTURE_2D_MULTISAMPLE)
433                 {
434                         gl.texImage2DMultisample(target, m_max_samples - 1, descriptor.internal_format, s_source_texture_size,
435                                                                          s_source_texture_size, GL_TRUE);
436                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
437
438                         gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, m_destination_texture, 0);
439                         GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D have failed");
440                 }
441                 else
442                 {
443                         gl.texImage3DMultisample(target, m_max_samples - 1, descriptor.internal_format, s_source_texture_size,
444                                                                          s_source_texture_size, s_source_texture_size, GL_TRUE);
445                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
446
447                         gl.framebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_destination_texture, 0, 0);
448                         GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D have failed");
449                 }
450         }
451
452         /* Check framebuffer completness. */
453         if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
454         {
455                 throw 0;
456         }
457
458         /* Setup viewport. */
459         gl.viewport(0, 0, s_source_texture_size, s_source_texture_size);
460         GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
461 }
462
463 void FunctionalTest::makeProgramAndSourceTextureActive(glw::GLenum target)
464 {
465         /* GL functions object. */
466         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
467
468         /* Use GLSL program. */
469         gl.useProgram(m_program);
470         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram have failed");
471
472         /* Setup source texture. */
473         gl.activeTexture(GL_TEXTURE0);
474         GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture have failed");
475
476         gl.bindTexture(target, m_source_texture);
477         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
478
479         glw::GLint location = gl.getUniformLocation(m_program, "data");
480         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation have failed");
481
482         gl.uniform1i(location, 0);
483         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i have failed");
484 }
485
486 bool FunctionalTest::checkSourceTextureSizeAndType(TextureInternalFormatDescriptor descriptor, glw::GLenum target)
487 {
488         /* GL functions object. */
489         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
490
491         /* query result storage */
492         glw::GLint red_size             = 0;
493         glw::GLint blue_size    = 0;
494         glw::GLint green_size   = 0;
495         glw::GLint alpha_size   = 0;
496         glw::GLint depth_size   = 0;
497         glw::GLint stencil_size = 0;
498
499         glw::GLint red_type   = 0;
500         glw::GLint green_type = 0;
501         glw::GLint blue_type  = 0;
502         glw::GLint alpha_type = 0;
503         glw::GLint depth_type = 0;
504
505         /* Bind texture */
506         gl.bindTexture(target, m_source_texture);
507         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
508
509         /* queries */
510         gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_RED_SIZE, &red_size);
511         gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_GREEN_SIZE, &green_size);
512         gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_BLUE_SIZE, &blue_size);
513         gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size);
514         gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_DEPTH_SIZE, &depth_size);
515         gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_STENCIL_SIZE, &stencil_size);
516
517         gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_RED_TYPE, &red_type);
518         gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_GREEN_TYPE, &green_type);
519         gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_BLUE_TYPE, &blue_type);
520         gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_ALPHA_TYPE, &alpha_type);
521         gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_DEPTH_TYPE, &depth_type);
522
523         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
524
525         /* check expected values */
526         bool is_ok = true;
527
528         is_ok = is_ok && (red_size >= descriptor.min_red_size);
529         is_ok = is_ok && (green_size >= descriptor.min_green_size);
530         is_ok = is_ok && (blue_size >= descriptor.min_blue_size);
531         is_ok = is_ok && (alpha_size >= descriptor.min_alpha_size);
532         is_ok = is_ok && (depth_size >= descriptor.min_depth_size);
533         is_ok = is_ok && (stencil_size >= descriptor.min_stencil_size);
534
535         is_ok = is_ok && ((glw::GLenum)red_type == descriptor.expected_red_type);
536         is_ok = is_ok && ((glw::GLenum)green_type == descriptor.expected_green_type);
537         is_ok = is_ok && ((glw::GLenum)blue_type == descriptor.expected_blue_type);
538         is_ok = is_ok && ((glw::GLenum)alpha_type == descriptor.expected_alpha_type);
539         is_ok = is_ok && ((glw::GLenum)depth_type == descriptor.expected_depth_type);
540
541         /* Log on failure. */
542         if (!is_ok)
543         {
544                 m_context.getTestContext().getLog()
545                         << tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
546                         << " have failed during glGetTexLevelParameteriv query. "
547                         << "Expected red size = " << descriptor.min_red_size
548                         << ", expected green size = " << descriptor.min_green_size
549                         << ", expected blue size = " << descriptor.min_blue_size
550                         << ", expected alpha size = " << descriptor.min_alpha_size
551                         << ", expected depth size = " << descriptor.min_depth_size
552                         << ", expected stencil size = " << descriptor.min_stencil_size << ". Queried red size = " << red_size
553                         << ", queried green size = " << green_size << ", queried blue size = " << blue_size
554                         << ", queried alpha size = " << alpha_size << ", queried depth size = " << depth_size
555                         << ", queried stencil size = " << stencil_size << ". "
556                         << "Expected red type = " << glu::getTypeStr(descriptor.expected_red_type)
557                         << ", expected green type = " << glu::getTypeStr(descriptor.expected_green_type)
558                         << ", expected blue type = " << glu::getTypeStr(descriptor.expected_blue_type)
559                         << ", expected alpha type = " << glu::getTypeStr(descriptor.expected_alpha_type)
560                         << ", expected depth type = " << glu::getTypeStr(descriptor.expected_depth_type)
561                         << ". Queried red type = " << glu::getTypeStr(red_type)
562                         << ", queried green type = " << glu::getTypeStr(green_type)
563                         << ", queried blue type = " << glu::getTypeStr(blue_type)
564                         << ", queried alpha type = " << glu::getTypeStr(alpha_type)
565                         << ", queried depth type = " << glu::getTypeStr(depth_type) << "." << tcu::TestLog::EndMessage;
566         }
567
568         /* return results. */
569         return is_ok;
570 }
571
572 glw::GLenum FunctionalTest::getDestinationFormatForChannel(TextureInternalFormatDescriptor descriptor)
573 {
574         if (isFloatType(descriptor))
575         {
576                 return GL_R32F;
577         }
578
579         if (isFixedUnsignedType(descriptor))
580         {
581                 return GL_R16;
582         }
583
584         if (isFixedSignedType(descriptor))
585         {
586                 return GL_R16_SNORM;
587         }
588
589         if (isIntegerUnsignedType(descriptor))
590         {
591                 return GL_R32UI;
592         }
593
594         if (isIntegerSignedType(descriptor))
595         {
596                 return GL_R32I;
597         }
598
599         return GL_R32F;
600 }
601
602 glw::GLuint FunctionalTest::prepareProgram(glw::GLenum target, TextureInternalFormatDescriptor descriptor,
603                                                                                    ColorChannelSelector channel)
604 {
605         /* GL functions object. */
606         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
607
608         /* Preparing sampler name and textelFetch arguments */
609         std::string sampler_name                           = "";
610         std::string texel_fetch_arguments_tail = "";
611
612         switch (target)
613         {
614         case GL_TEXTURE_1D:
615                 sampler_name                       = "sampler1D";
616                 texel_fetch_arguments_tail = "0, 0";
617                 break;
618         case GL_TEXTURE_2D:
619                 sampler_name                       = "sampler2D";
620                 texel_fetch_arguments_tail = "ivec2(0), 0";
621                 break;
622         case GL_TEXTURE_1D_ARRAY:
623                 sampler_name                       = "sampler1DArray";
624                 texel_fetch_arguments_tail = "ivec2(0), 0";
625                 break;
626         case GL_TEXTURE_RECTANGLE:
627                 sampler_name                       = "sampler2DRect";
628                 texel_fetch_arguments_tail = "ivec2(0)";
629                 break;
630         case GL_TEXTURE_2D_ARRAY:
631                 sampler_name                       = "sampler2DArray";
632                 texel_fetch_arguments_tail = "ivec3(0), 0";
633                 break;
634         case GL_TEXTURE_3D:
635                 sampler_name                       = "sampler3D";
636                 texel_fetch_arguments_tail = "ivec3(0), 0";
637                 break;
638         case GL_TEXTURE_2D_MULTISAMPLE:
639                 sampler_name                       = "sampler2DMS";
640                 texel_fetch_arguments_tail = "ivec2(0), ";
641                 texel_fetch_arguments_tail.append(Utilities::itoa(m_max_samples - 1));
642                 break;
643         case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
644                 sampler_name                       = "sampler2DMSArray";
645                 texel_fetch_arguments_tail = "ivec3(0), ";
646                 texel_fetch_arguments_tail.append(Utilities::itoa(m_max_samples - 1));
647                 break;
648         default:
649                 throw 0;
650         }
651
652         /* Preparing component selector name */
653         std::string component_name = "";
654
655         switch (channel)
656         {
657         case RED_COMPONENT:
658                 component_name = ".r";
659                 break;
660         case GREEN_COMPONENT:
661                 component_name = ".g";
662                 break;
663         case BLUE_COMPONENT:
664                 component_name = ".b";
665                 break;
666         case ALPHA_COMPONENT:
667                 component_name = ".a";
668                 break;
669         case COMPONENTS_COUNT:
670                 break;
671         default:
672                 throw 0;
673         }
674
675         /* Preparing output type name and sampler prefix */
676         std::string type_name     = "";
677         std::string sampler_prefix = "";
678
679         if (isFloatType(descriptor) || isFixedSignedType(descriptor) || isFixedUnsignedType(descriptor) ||
680                 isDepthType(descriptor) || isStencilType(descriptor))
681         {
682                 if (channel == COMPONENTS_COUNT)
683                 {
684                         type_name = "vec4";
685                 }
686                 else
687                 {
688                         type_name = "float";
689                 }
690                 sampler_prefix = "";
691         }
692         else
693         {
694                 if (isIntegerSignedType(descriptor))
695                 {
696                         if (channel == COMPONENTS_COUNT)
697                         {
698                                 type_name = "ivec4";
699                         }
700                         else
701                         {
702                                 type_name = "int";
703                         }
704                         sampler_prefix = "i";
705                 }
706                 else
707                 {
708                         if (channel == COMPONENTS_COUNT)
709                         {
710                                 type_name = "uvec4";
711                         }
712                         else
713                         {
714                                 type_name = "uint";
715                         }
716                         sampler_prefix = "u";
717                 }
718         }
719
720         std::string template_verison = "#version 150";
721
722         /* Preprocessing fragment shader source code. */
723         std::string fragment_shader = s_fragment_shader_template;
724
725         fragment_shader = Utilities::preprocessString(fragment_shader, "TEMPLATE_TYPE", type_name);
726         fragment_shader =
727                 Utilities::preprocessString(fragment_shader, "TEMPLATE_SAMPLER", sampler_prefix.append(sampler_name));
728         fragment_shader =
729                 Utilities::preprocessString(fragment_shader, "TEMPLATE_TEXEL_FETCH_ARGUMENTS", texel_fetch_arguments_tail);
730         fragment_shader = Utilities::preprocessString(fragment_shader, "TEMPLATE_COMPONENT", component_name);
731
732         /* Building program. */
733         glw::GLuint program =
734                 Utilities::buildProgram(gl, m_context.getTestContext().getLog(), s_vertex_shader_code, fragment_shader.c_str());
735
736         if (0 == program)
737         {
738                 throw 0;
739         }
740
741         /* Return program name. */
742         return program;
743 }
744
745 void FunctionalTest::drawQuad()
746 {
747         /* GL functions object. */
748         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
749
750         /* Draw quad. */
751         gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
752         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays have failed");
753 }
754
755 void FunctionalTest::cleanSourceTexture()
756 {
757         /* GL functions object. */
758         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
759
760         /* Delete object. */
761         if (m_source_texture)
762         {
763                 gl.deleteTextures(1, &m_source_texture);
764                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures have failed");
765
766                 m_source_texture = 0;
767         }
768 }
769
770 void FunctionalTest::cleanDestinationTexture()
771 {
772         /* GL functions object. */
773         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
774
775         /* Delete object. */
776         if (m_destination_texture)
777         {
778                 gl.deleteTextures(1, &m_destination_texture);
779
780                 m_destination_texture = 0;
781         }
782 }
783
784 void FunctionalTest::cleanFramebuffer()
785 {
786         /* GL functions object. */
787         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
788
789         /* Delete object. */
790         if (m_framebuffer)
791         {
792                 gl.deleteFramebuffers(1, &m_framebuffer);
793
794                 m_framebuffer = 0;
795         }
796 }
797
798 void FunctionalTest::cleanProgram()
799 {
800         /* GL functions object. */
801         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
802
803         /* Delete object. */
804         if (m_program)
805         {
806                 gl.useProgram(0);
807
808                 gl.deleteProgram(m_program);
809
810                 m_program = 0;
811         }
812 }
813
814 void FunctionalTest::cleanVertexArrayObject()
815 {
816         /* GL functions object. */
817         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
818
819         /* Delete object. */
820         if (m_vao)
821         {
822                 gl.deleteVertexArrays(1, &m_vao);
823
824                 m_vao = 0;
825         }
826 }
827
828 bool FunctionalTest::checkDestinationTexture(TextureInternalFormatDescriptor descriptor, ColorChannelSelector channel,
829                                                                                          glw::GLenum target, const glw::GLchar* target_name)
830 {
831         /* GL functions object. */
832         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
833
834         /* Check depending on format. */
835         if (isFloatType(descriptor) || isDepthType(descriptor) || isStencilType(descriptor))
836         {
837                 /* Fetch results from destination texture (attached to current framebuffer). */
838                 glw::GLfloat pixel = 3.1415927f;
839                 gl.readPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &pixel);
840                 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
841
842                 /* Setup expected value. */
843                 glw::GLfloat expected_value = isChannelTypeNone(descriptor, channel) ?
844                                                                                   ((channel == ALPHA_COMPONENT) ? 1.f : 0.f) :
845                                                                                   s_source_texture_data_f[channel];
846
847                 /* Compare expected and fetched values. */
848                 if (fabs(pixel - expected_value) <= getMinPrecision(descriptor, channel))
849                 {
850                         /* Test succeeded*/
851                         return true;
852                 }
853                 else
854                 {
855                         /* Log failure. */
856                         m_context.getTestContext().getLog()
857                                 << tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
858                                 << " have failed during functional test of " << s_color_channel_names[channel]
859                                 << " channel with target " << target_name << ". Expected value = " << expected_value
860                                 << " read value = " << pixel << "." << tcu::TestLog::EndMessage;
861                 }
862         }
863         else
864         {
865                 if (isFixedSignedType(descriptor))
866                 {
867                         /* Fetch results from destination texture (attached to current framebuffer). */
868                         glw::GLfloat pixel = 3.1415927f;
869                         gl.readPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &pixel);
870                         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
871
872                         /* Setup expected value. */
873                         /* Signed fixed-point read color are clamped to [0, 1] by default */
874                         glw::GLfloat expected_value = isChannelTypeNone(descriptor, channel) ?
875                                                                                           ((channel == ALPHA_COMPONENT) ? 1.f : 0.f) :
876                                                                                           deFloatClamp(s_source_texture_data_sn[channel], 0, 1);
877
878                         /* Compare expected and fetched values. */
879                         if (fabs(pixel - expected_value) <= getMinPrecision(descriptor, channel))
880                         {
881                                 /* Test succeeded*/
882                                 return true;
883                         }
884                         else
885                         {
886                                 /* Log failure. */
887                                 m_context.getTestContext().getLog()
888                                         << tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
889                                         << " have failed during functional test of " << s_color_channel_names[channel]
890                                         << " channel with target " << target_name << ". Expected value = " << expected_value
891                                         << " read value = " << pixel << "." << tcu::TestLog::EndMessage;
892                         }
893                 }
894                 else
895                 {
896                         if (isFixedUnsignedType(descriptor))
897                         {
898                                 /* Fetch results from destination texture (attached to current framebuffer). */
899                                 glw::GLfloat pixel = 3.1415927f;
900                                 gl.readPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &pixel);
901                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
902
903                                 /* Setup expected value. */
904                                 glw::GLfloat expected_value = isChannelTypeNone(descriptor, channel) ?
905                                                                                                   ((channel == ALPHA_COMPONENT) ? 1.f : 0.f) :
906                                                                                                   s_source_texture_data_n[channel];
907
908                                 /* For sRGB internal formats convert value to linear space. */
909                                 if (descriptor.is_sRGB && (channel < ALPHA_COMPONENT))
910                                 {
911                                         expected_value = convert_from_sRGB(expected_value);
912
913                                         if (isTargetMultisampled(
914                                                         target)) /* In multisampled targets two conversions are made (in upload and in shader) */
915                                         {
916                                                 expected_value = convert_from_sRGB(expected_value);
917                                         }
918                                 }
919
920                                 /* Compare expected and fetched values. */
921                                 if (fabs(pixel - expected_value) <= getMinPrecision(descriptor, channel))
922                                 {
923                                         /* Test succeeded*/
924                                         return true;
925                                 }
926                                 else
927                                 {
928                                         /* Log failure. */
929                                         m_context.getTestContext().getLog()
930                                                 << tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
931                                                 << " have failed during functional test of " << s_color_channel_names[channel]
932                                                 << " channel with target " << target_name << ". Expected value = " << expected_value
933                                                 << " read value = " << pixel << "." << tcu::TestLog::EndMessage;
934                                 }
935                         }
936                         else
937                         {
938                                 if (isIntegerSignedType(descriptor))
939                                 {
940                                         /* Fetch results from destination texture (attached to current framebuffer). */
941                                         glw::GLint pixel = 5;
942                                         gl.readPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_INT, &pixel);
943                                         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
944
945                                         /* Setup expected value. */
946                                         glw::GLint expected_value = isChannelTypeNone(descriptor, channel) ?
947                                                                                                         ((channel == ALPHA_COMPONENT) ? 1 : 0) :
948                                                                                                         s_source_texture_data_i[channel];
949
950                                         /* Compare expected and fetched values. */
951                                         if (pixel == expected_value)
952                                         {
953                                                 /* Test succeeded*/
954                                                 return true;
955                                         }
956                                         else
957                                         {
958                                                 /* Log failure. */
959                                                 m_context.getTestContext().getLog()
960                                                         << tcu::TestLog::Message << "Promotion from internal format "
961                                                         << descriptor.internal_format_name << " have failed during functional test of "
962                                                         << s_color_channel_names[channel] << " channel with target " << target_name
963                                                         << ". Expected value = " << expected_value << " read value = " << pixel << "."
964                                                         << tcu::TestLog::EndMessage;
965                                         }
966                                 }
967                                 else
968                                 {
969                                         if (isIntegerUnsignedType(descriptor))
970                                         {
971                                                 /* Fetch results from destination texture (attached to current framebuffer). */
972                                                 glw::GLuint pixel = 5;
973                                                 gl.readPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixel);
974                                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
975
976                                                 /* Setup expected value. */
977                                                 glw::GLuint expected_value = isChannelTypeNone(descriptor, channel) ?
978                                                                                                                  ((channel == ALPHA_COMPONENT) ? 1 : 0) :
979                                                                                                                  s_source_texture_data_ui[channel];
980
981                                                 /* Compare expected and fetched values. */
982                                                 if (pixel == expected_value)
983                                                 {
984                                                         /* Test succeeded*/
985                                                         return true;
986                                                 }
987                                                 else
988                                                 {
989                                                         /* Log failure. */
990                                                         m_context.getTestContext().getLog()
991                                                                 << tcu::TestLog::Message << "Promotion from internal format "
992                                                                 << descriptor.internal_format_name << " have failed during functional test of "
993                                                                 << s_color_channel_names[channel] << " channel with target " << target_name
994                                                                 << ". Expected value = " << expected_value << " read value = " << pixel << "."
995                                                                 << tcu::TestLog::EndMessage;
996                                                 }
997                                         }
998                                 }
999                         }
1000                 }
1001         }
1002
1003         /* Test failed. */
1004         return false;
1005 }
1006
1007 bool FunctionalTest::isFloatType(TextureInternalFormatDescriptor descriptor)
1008 {
1009         return (GL_FLOAT == descriptor.expected_red_type) || (GL_FLOAT == descriptor.expected_green_type) ||
1010                    (GL_FLOAT == descriptor.expected_blue_type) || (GL_FLOAT == descriptor.expected_alpha_type);
1011 }
1012
1013 bool FunctionalTest::isFixedSignedType(TextureInternalFormatDescriptor descriptor)
1014 {
1015         return (GL_SIGNED_NORMALIZED == descriptor.expected_red_type) ||
1016                    (GL_SIGNED_NORMALIZED == descriptor.expected_green_type) ||
1017                    (GL_SIGNED_NORMALIZED == descriptor.expected_blue_type) ||
1018                    (GL_SIGNED_NORMALIZED == descriptor.expected_alpha_type);
1019 }
1020
1021 bool FunctionalTest::isFixedUnsignedType(TextureInternalFormatDescriptor descriptor)
1022 {
1023         return (GL_UNSIGNED_NORMALIZED == descriptor.expected_red_type) ||
1024                    (GL_UNSIGNED_NORMALIZED == descriptor.expected_green_type) ||
1025                    (GL_UNSIGNED_NORMALIZED == descriptor.expected_blue_type) ||
1026                    (GL_UNSIGNED_NORMALIZED == descriptor.expected_alpha_type);
1027 }
1028
1029 bool FunctionalTest::isIntegerSignedType(TextureInternalFormatDescriptor descriptor)
1030 {
1031         return (GL_INT == descriptor.expected_red_type) || (GL_INT == descriptor.expected_green_type) ||
1032                    (GL_INT == descriptor.expected_blue_type) || (GL_INT == descriptor.expected_alpha_type);
1033 }
1034
1035 bool FunctionalTest::isIntegerUnsignedType(TextureInternalFormatDescriptor descriptor)
1036 {
1037         return (GL_UNSIGNED_INT == descriptor.expected_red_type) || (GL_UNSIGNED_INT == descriptor.expected_green_type) ||
1038                    (GL_UNSIGNED_INT == descriptor.expected_blue_type) || (GL_UNSIGNED_INT == descriptor.expected_alpha_type);
1039 }
1040
1041 bool FunctionalTest::isDepthType(TextureInternalFormatDescriptor descriptor)
1042 {
1043         return (GL_NONE != descriptor.expected_depth_type);
1044 }
1045
1046 bool FunctionalTest::isStencilType(TextureInternalFormatDescriptor descriptor)
1047 {
1048         return (descriptor.min_stencil_size > 0);
1049 }
1050
1051 bool FunctionalTest::isChannelTypeNone(TextureInternalFormatDescriptor descriptor, ColorChannelSelector channel)
1052 {
1053         switch (channel)
1054         {
1055         case RED_COMPONENT:
1056                 return (GL_NONE == descriptor.expected_red_type);
1057         case GREEN_COMPONENT:
1058                 return (GL_NONE == descriptor.expected_green_type);
1059         case BLUE_COMPONENT:
1060                 return (GL_NONE == descriptor.expected_blue_type);
1061         case ALPHA_COMPONENT:
1062                 return (GL_NONE == descriptor.expected_alpha_type);
1063         default:
1064                 throw 0;
1065         }
1066
1067         return false;
1068 }
1069
1070 glw::GLfloat FunctionalTest::getMinPrecision(TextureInternalFormatDescriptor descriptor, ColorChannelSelector channel)
1071 {
1072         /* Select channel data. */
1073         glw::GLenum type = GL_NONE;
1074         glw::GLuint size = 0;
1075
1076         switch (channel)
1077         {
1078         case RED_COMPONENT:
1079                 type = descriptor.expected_red_type;
1080                 size = descriptor.min_red_size;
1081                 break;
1082         case GREEN_COMPONENT:
1083                 type = descriptor.expected_green_type;
1084                 size = descriptor.min_green_size;
1085                 break;
1086         case BLUE_COMPONENT:
1087                 type = descriptor.expected_blue_type;
1088                 size = descriptor.min_blue_size;
1089                 break;
1090         case ALPHA_COMPONENT:
1091                 type = descriptor.expected_alpha_type;
1092                 size = descriptor.min_alpha_size;
1093                 break;
1094         default:
1095                 throw 0;
1096         }
1097
1098         /* If it is empty channel. */
1099         if ((type == GL_NONE) || (size == 0))
1100         {
1101                 return 0.1f;
1102         }
1103
1104         /* If float type. */
1105         if (isFloatType(descriptor))
1106         {
1107                 switch (size)
1108                 {
1109                 case 32:
1110                         return 0.00001f; /* specification GL4.5 core constant */
1111                 case 16:
1112                         return 1.f / 1024.f; /* specification GL4.5 core 10 bit mantisa constant */
1113                 case 11:
1114                         return 1.f / 64.f; /* specification GL4.5 core 6 bit mantisa constant */
1115                 case 10:
1116                         return 1.f / 32.f; /* specification GL4.5 core 5 bit mantisa constant */
1117                 default:
1118                         return 0.00001f;
1119                 }
1120         }
1121
1122         /* Fixed types precision */
1123         if (isFixedSignedType(descriptor))
1124         {
1125                 return (float)(1.0 / pow(2.0, (double)(size - 1 /* sign bit */)));
1126         }
1127
1128         if (isFixedUnsignedType(descriptor))
1129         {
1130                 return (float)(1.0 / pow(2.0, (double)(size)));
1131         }
1132
1133         /* other aka (unsigned) integer */
1134         return 1;
1135 }
1136
1137 bool FunctionalTest::isTargetMultisampled(glw::GLenum target)
1138 {
1139         return (GL_TEXTURE_2D_MULTISAMPLE == target) || (GL_TEXTURE_2D_MULTISAMPLE_ARRAY == target);
1140 }
1141
1142 float FunctionalTest::convert_from_sRGB(float value)
1143 {
1144         /* For reference check OpenGL specification (eg. OpenGL 4.5 core profile specification chapter 8.24 */
1145         if (value > 0.04045f)
1146         {
1147                 return deFloatPow((value + 0.055f) / 1.055f, 2.4f);
1148         }
1149
1150         return value / 12.92f;
1151 }
1152
1153 const glw::GLfloat FunctionalTest::s_source_texture_data_f[] = { 0.125f, 0.25f, 0.5f, 0.75f };
1154
1155 const glw::GLfloat FunctionalTest::s_source_texture_data_n[] = { 0.125f, 0.25f, 0.5f, 0.75f };
1156
1157 const glw::GLfloat FunctionalTest::s_source_texture_data_sn[] = { -0.125f, 0.25f, -0.5f, 0.75f };
1158
1159 const glw::GLint FunctionalTest::s_source_texture_data_i[] = { -1, 2, -3, 4 };
1160
1161 const glw::GLuint FunctionalTest::s_source_texture_data_ui[] = { 4, 3, 2, 1 };
1162
1163 const glw::GLfloat FunctionalTest::s_destination_texture_data_f[] = {
1164         5.f
1165 }; /* False data for destination texture to be overwriten. */
1166
1167 const glw::GLint FunctionalTest::s_destination_texture_data_i[] = {
1168         -5
1169 }; /* False data for destination texture to be overwriten. */
1170
1171 const glw::GLuint FunctionalTest::s_destination_texture_data_ui[] = {
1172         5
1173 }; /* False data for destination texture to be overwriten. */
1174
1175 const glw::GLenum FunctionalTest::s_source_texture_targets[] = {
1176         GL_TEXTURE_1D,           GL_TEXTURE_2D, GL_TEXTURE_1D_ARRAY,       GL_TEXTURE_RECTANGLE,
1177         GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D, GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY
1178 };
1179
1180 const glw::GLchar* FunctionalTest::s_source_texture_targets_names[] = {
1181         STR(GL_TEXTURE_1D),               STR(GL_TEXTURE_2D), STR(GL_TEXTURE_1D_ARRAY),           STR(GL_TEXTURE_RECTANGLE),
1182         STR(GL_TEXTURE_2D_ARRAY), STR(GL_TEXTURE_3D), STR(GL_TEXTURE_2D_MULTISAMPLE), STR(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
1183 };
1184
1185 const glw::GLuint FunctionalTest::s_source_texture_targets_count =
1186         sizeof(s_source_texture_targets) / sizeof(s_source_texture_targets[0]);
1187
1188 const glw::GLuint FunctionalTest::s_source_texture_size = 1;
1189
1190 const glw::GLchar* FunctionalTest::s_color_channel_names[] = { "red", "green", "blue", "alpha", "all" };
1191
1192 const FunctionalTest::TextureInternalFormatDescriptor FunctionalTest::s_formats[] = {
1193         /*      context version,                                                        internal format,                internal format name,    is sRGB,       CR,size{R,      G,      B,      A,      D,      S},     type of R,                              type of G,                              type of B,                              type of A,                              type of depth                   */
1194         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R8, STR(GL_R8), false, true, 8, 0, 0, 0, 0, 0,
1195           GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1196         { glu::ContextType(3, 1, glu::PROFILE_CORE), GL_R8_SNORM, STR(GL_R8_SNORM), false, true, 8, 0, 0, 0, 0, 0,
1197           GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1198         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R16, STR(GL_R16), false, true, 16, 0, 0, 0, 0, 0,
1199           GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1200         { glu::ContextType(3, 1, glu::PROFILE_CORE), GL_R16_SNORM, STR(GL_R16_SNORM), false, true, 16, 0, 0, 0, 0, 0,
1201           GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1202         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG8, STR(GL_RG8), false, true, 8, 8, 0, 0, 0, 0,
1203           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE },
1204         { glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RG8_SNORM, STR(GL_RG8_SNORM), false, true, 8, 8, 0, 0, 0, 0,
1205           GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE },
1206         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG16, STR(GL_RG16), false, true, 16, 16, 0, 0, 0, 0,
1207           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE },
1208         { glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RG16_SNORM, STR(GL_RG16_SNORM), false, true, 16, 16, 0, 0, 0, 0,
1209           GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE },
1210         { glu::ContextType(4, 4, glu::PROFILE_CORE), GL_R3_G3_B2, STR(GL_R3_G3_B2), false, true, 3, 3, 2, 0, 0, 0,
1211           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1212         { glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGB4, STR(GL_RGB4), false, true, 4, 4, 4, 0, 0, 0,
1213           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1214         { glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGB5, STR(GL_RGB5), false, true, 5, 5, 5, 0, 0, 0,
1215           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1216         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB8, STR(GL_RGB8), false, true, 8, 8, 8, 0, 0, 0,
1217           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1218         { glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RGB8_SNORM, STR(GL_RGB8_SNORM), false, true, 8, 8, 8, 0, 0, 0,
1219           GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE },
1220         { glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGB10, STR(GL_RGB10), false, true, 10, 10, 10, 0, 0, 0,
1221           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1222         { glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGB12, STR(GL_RGB12), false, true, 12, 12, 12, 0, 0, 0,
1223           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1224         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB16, STR(GL_RGB16), false, true, 16, 16, 16, 0, 0, 0,
1225           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1226         { glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RGB16_SNORM, STR(GL_RGB16_SNORM), false, true, 16, 16, 16, 0, 0, 0,
1227           GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE },
1228         { glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGBA2, STR(GL_RGBA2), false, true, 2, 2, 2, 2, 0, 0,
1229           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1230         { glu::ContextType(4, 2, glu::PROFILE_CORE), GL_RGBA4, STR(GL_RGBA4), false, true, 4, 4, 4, 4, 0, 0,
1231           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1232         { glu::ContextType(4, 2, glu::PROFILE_CORE), GL_RGB5_A1, STR(GL_RGB5_A1), false, true, 5, 5, 5, 1, 0, 0,
1233           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1234         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA8, STR(GL_RGBA8), false, true, 8, 8, 8, 8, 0, 0,
1235           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1236         { glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RGBA8_SNORM, STR(GL_RGBA8_SNORM), false, true, 8, 8, 8, 8, 0, 0,
1237           GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE },
1238         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB10_A2, STR(GL_RGB10_A2), false, true, 10, 10, 10, 2, 0, 0,
1239           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1240         { glu::ContextType(3, 3, glu::PROFILE_CORE), GL_RGB10_A2UI, STR(GL_RGB10_A2UI), false, true, 10, 10, 10, 2, 0, 0,
1241           GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE },
1242         { glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGBA12, STR(GL_RGBA12), false, true, 12, 12, 12, 12, 0, 0,
1243           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1244         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA16, STR(GL_RGBA16), false, true, 16, 16, 16, 16, 0, 0,
1245           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1246         { glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RGBA16_SNORM, STR(GL_RGBA16_SNORM), false, true, 16, 16, 16, 16, 0,
1247           0, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE },
1248         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_SRGB8, STR(GL_SRGB8), true, true, 8, 8, 8, 0, 0, 0,
1249           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
1250         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_SRGB8_ALPHA8, STR(GL_SRGB8_ALPHA8), true, true, 8, 8, 8, 8, 0, 0,
1251           GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
1252         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R16F, STR(GL_R16F), false, true, 16, 0, 0, 0, 0, 0, GL_FLOAT,
1253           GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1254         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG16F, STR(GL_RG16F), false, true, 16, 16, 0, 0, 0, 0, GL_FLOAT,
1255           GL_FLOAT, GL_NONE, GL_NONE, GL_NONE },
1256         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB16F, STR(GL_RGB16F), false, true, 16, 16, 16, 0, 0, 0, GL_FLOAT,
1257           GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE },
1258         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA16F, STR(GL_RGBA16F), false, true, 16, 16, 16, 16, 0, 0,
1259           GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_NONE },
1260         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R32F, STR(GL_R32F), false, true, 32, 0, 0, 0, 0, 0, GL_FLOAT,
1261           GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1262         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG32F, STR(GL_RG32F), false, true, 32, 32, 0, 0, 0, 0, GL_FLOAT,
1263           GL_FLOAT, GL_NONE, GL_NONE, GL_NONE },
1264         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB32F, STR(GL_RGB32F), false, true, 32, 32, 32, 0, 0, 0, GL_FLOAT,
1265           GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE },
1266         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA32F, STR(GL_RGBA32F), false, true, 32, 32, 32, 32, 0, 0,
1267           GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_NONE },
1268         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R11F_G11F_B10F, STR(GL_R11F_G11F_B10F), false, true, 11, 11, 10, 0,
1269           0, 0, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE },
1270         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB9_E5, STR(GL_RGB9_E5), false, false, 9, 9, 9, 0, 0, 0, GL_FLOAT,
1271           GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE },
1272         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R8I, STR(GL_R8I), false, true, 8, 0, 0, 0, 0, 0, GL_INT, GL_NONE,
1273           GL_NONE, GL_NONE, GL_NONE },
1274         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R8UI, STR(GL_R8UI), false, true, 8, 0, 0, 0, 0, 0, GL_UNSIGNED_INT,
1275           GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1276         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R16I, STR(GL_R16I), false, true, 16, 0, 0, 0, 0, 0, GL_INT, GL_NONE,
1277           GL_NONE, GL_NONE, GL_NONE },
1278         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R16UI, STR(GL_R16UI), false, true, 16, 0, 0, 0, 0, 0,
1279           GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1280         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R32I, STR(GL_R32I), false, true, 32, 0, 0, 0, 0, 0, GL_INT, GL_NONE,
1281           GL_NONE, GL_NONE, GL_NONE },
1282         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R32UI, STR(GL_R32UI), false, true, 32, 0, 0, 0, 0, 0,
1283           GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
1284         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG8I, STR(GL_RG8I), false, true, 8, 8, 0, 0, 0, 0, GL_INT, GL_INT,
1285           GL_NONE, GL_NONE, GL_NONE },
1286         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG8UI, STR(GL_RG8UI), false, true, 8, 8, 0, 0, 0, 0,
1287           GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE },
1288         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG16I, STR(GL_RG16I), false, true, 16, 16, 0, 0, 0, 0, GL_INT,
1289           GL_INT, GL_NONE, GL_NONE, GL_NONE },
1290         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG16UI, STR(GL_RG16UI), false, true, 16, 16, 0, 0, 0, 0,
1291           GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE },
1292         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG32I, STR(GL_RG32I), false, true, 32, 32, 0, 0, 0, 0, GL_INT,
1293           GL_INT, GL_NONE, GL_NONE, GL_NONE },
1294         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG32UI, STR(GL_RG32UI), false, true, 32, 32, 0, 0, 0, 0,
1295           GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE },
1296         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB8I, STR(GL_RGB8I), false, true, 8, 8, 8, 0, 0, 0, GL_INT, GL_INT,
1297           GL_INT, GL_NONE, GL_NONE },
1298         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB8UI, STR(GL_RGB8UI), false, true, 8, 8, 8, 0, 0, 0,
1299           GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE },
1300         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB16I, STR(GL_RGB16I), false, true, 16, 16, 16, 0, 0, 0, GL_INT,
1301           GL_INT, GL_INT, GL_NONE, GL_NONE },
1302         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB16UI, STR(GL_RGB16UI), false, true, 16, 16, 16, 0, 0, 0,
1303           GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE },
1304         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB32I, STR(GL_RGB32I), false, true, 32, 32, 32, 0, 0, 0, GL_INT,
1305           GL_INT, GL_INT, GL_NONE, GL_NONE },
1306         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB32UI, STR(GL_RGB32UI), false, true, 32, 32, 32, 0, 0, 0,
1307           GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE },
1308         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA8I, STR(GL_RGBA8I), false, true, 8, 8, 8, 8, 0, 0, GL_INT,
1309           GL_INT, GL_INT, GL_INT, GL_NONE },
1310         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA8UI, STR(GL_RGBA8UI), false, true, 8, 8, 8, 8, 0, 0,
1311           GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE },
1312         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA16I, STR(GL_RGBA16I), false, true, 16, 16, 16, 16, 0, 0, GL_INT,
1313           GL_INT, GL_INT, GL_INT, GL_NONE },
1314         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA16UI, STR(GL_RGBA16UI), false, true, 16, 16, 16, 16, 0, 0,
1315           GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE },
1316         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA32I, STR(GL_RGBA32I), false, true, 32, 32, 32, 32, 0, 0, GL_INT,
1317           GL_INT, GL_INT, GL_INT, GL_NONE },
1318         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA32UI, STR(GL_RGBA32UI), false, true, 32, 32, 32, 32, 0, 0,
1319           GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE },
1320         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH_COMPONENT16, STR(GL_DEPTH_COMPONENT16), false, true, 0, 0, 0,
1321           0, 16, 0, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_UNSIGNED_NORMALIZED },
1322         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH_COMPONENT24, STR(GL_DEPTH_COMPONENT24), false, true, 0, 0, 0,
1323           0, 24, 0, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_UNSIGNED_NORMALIZED },
1324         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH_COMPONENT32F, STR(GL_DEPTH_COMPONENT32F), false, true, 0, 0,
1325           0, 0, 32, 0, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_FLOAT },
1326         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH24_STENCIL8, STR(GL_DEPTH24_STENCIL8), false, true, 0, 0, 0, 0,
1327           24, 8, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_UNSIGNED_NORMALIZED },
1328         { glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH32F_STENCIL8, STR(GL_DEPTH32F_STENCIL8), false, true, 0, 0, 0,
1329           0, 32, 8, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_FLOAT }
1330 };
1331
1332 const glw::GLuint FunctionalTest::s_formats_size = sizeof(s_formats) / sizeof(s_formats[0]);
1333
1334 const glw::GLchar* FunctionalTest::s_vertex_shader_code = "#version 150\n"
1335                                                                                                                   "\n"
1336                                                                                                                   "void main()\n"
1337                                                                                                                   "{\n"
1338                                                                                                                   "    switch(gl_VertexID % 4)\n"
1339                                                                                                                   "    {\n"
1340                                                                                                                   "    case 0:\n"
1341                                                                                                                   "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1342                                                                                                                   "        break;\n"
1343                                                                                                                   "    case 1:\n"
1344                                                                                                                   "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1345                                                                                                                   "        break;\n"
1346                                                                                                                   "    case 2:\n"
1347                                                                                                                   "        gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
1348                                                                                                                   "        break;\n"
1349                                                                                                                   "    case 3:\n"
1350                                                                                                                   "        gl_Position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
1351                                                                                                                   "        break;\n"
1352                                                                                                                   "    }\n"
1353                                                                                                                   "}\n";
1354
1355 const glw::GLchar* FunctionalTest::s_fragment_shader_template =
1356         "#version 150\n"
1357         "\n"
1358         "out TEMPLATE_TYPE result;\n"
1359         "\n"
1360         "uniform TEMPLATE_SAMPLER data;\n"
1361         "\n"
1362         "void main()\n"
1363         "{\n"
1364         "    result = texelFetch(data, TEMPLATE_TEXEL_FETCH_ARGUMENTS)TEMPLATE_COMPONENT;\n"
1365         "}\n";
1366
1367 /*===========================================================================================================*/
1368
1369 namespace Utilities
1370 {
1371
1372 glw::GLuint buildProgram(glw::Functions const& gl, tcu::TestLog& log, glw::GLchar const* const vertex_shader_source,
1373                                                  glw::GLchar const* const fragment_shader_source)
1374 {
1375         glw::GLuint program = 0;
1376
1377         struct Shader
1378         {
1379                 glw::GLchar const* const source;
1380                 glw::GLenum const                type;
1381                 glw::GLuint                              id;
1382         } shader[] = { { vertex_shader_source, GL_VERTEX_SHADER, 0 }, { fragment_shader_source, GL_FRAGMENT_SHADER, 0 } };
1383
1384         glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
1385
1386         try
1387         {
1388                 /* Create program. */
1389                 program = gl.createProgram();
1390                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
1391
1392                 /* Shader compilation. */
1393
1394                 for (glw::GLuint i = 0; i < shader_count; ++i)
1395                 {
1396                         if (DE_NULL != shader[i].source)
1397                         {
1398                                 shader[i].id = gl.createShader(shader[i].type);
1399
1400                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
1401
1402                                 gl.attachShader(program, shader[i].id);
1403
1404                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
1405
1406                                 gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
1407
1408                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
1409
1410                                 gl.compileShader(shader[i].id);
1411
1412                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
1413
1414                                 glw::GLint status = GL_FALSE;
1415
1416                                 gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
1417                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1418
1419                                 if (GL_FALSE == status)
1420                                 {
1421                                         glw::GLint log_size = 0;
1422                                         gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
1423                                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1424
1425                                         glw::GLchar* log_text = new glw::GLchar[log_size];
1426
1427                                         gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
1428
1429                                         log << tcu::TestLog::Message << "Shader compilation has failed.\n"
1430                                                 << "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
1431                                                 << "Shader compilation error log:\n"
1432                                                 << log_text << "\n"
1433                                                 << "Shader source code:\n"
1434                                                 << shader[i].source << "\n"
1435                                                 << tcu::TestLog::EndMessage;
1436
1437                                         delete[] log_text;
1438
1439                                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
1440
1441                                         throw 0;
1442                                 }
1443                         }
1444                 }
1445
1446                 /* Link. */
1447                 gl.linkProgram(program);
1448                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
1449
1450                 glw::GLint status = GL_FALSE;
1451
1452                 gl.getProgramiv(program, GL_LINK_STATUS, &status);
1453
1454                 if (GL_TRUE == status)
1455                 {
1456                         for (glw::GLuint i = 0; i < shader_count; ++i)
1457                         {
1458                                 if (shader[i].id)
1459                                 {
1460                                         gl.detachShader(program, shader[i].id);
1461
1462                                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
1463                                 }
1464                         }
1465                 }
1466                 else
1467                 {
1468                         glw::GLint log_size = 0;
1469
1470                         gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &log_size);
1471
1472                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
1473
1474                         glw::GLchar* log_text = new glw::GLchar[log_size];
1475
1476                         gl.getProgramInfoLog(program, log_size, NULL, &log_text[0]);
1477
1478                         log << tcu::TestLog::Message << "Program linkage has failed due to:\n"
1479                                 << log_text << "\n"
1480                                 << tcu::TestLog::EndMessage;
1481
1482                         delete[] log_text;
1483
1484                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
1485
1486                         throw 0;
1487                 }
1488         }
1489         catch (...)
1490         {
1491                 if (program)
1492                 {
1493                         gl.deleteProgram(program);
1494
1495                         program = 0;
1496                 }
1497         }
1498
1499         for (glw::GLuint i = 0; i < shader_count; ++i)
1500         {
1501                 if (0 != shader[i].id)
1502                 {
1503                         gl.deleteShader(shader[i].id);
1504
1505                         shader[i].id = 0;
1506                 }
1507         }
1508
1509         return program;
1510 }
1511
1512 std::string preprocessString(std::string source, std::string key, std::string value)
1513 {
1514         std::string destination = source;
1515
1516         while (true)
1517         {
1518                 /* Find token in source code. */
1519                 size_t position = destination.find(key, 0);
1520
1521                 /* No more occurences of this key. */
1522                 if (position == std::string::npos)
1523                 {
1524                         break;
1525                 }
1526
1527                 /* Replace token with sub_code. */
1528                 destination.replace(position, key.size(), value);
1529         }
1530
1531         return destination;
1532 }
1533
1534 std::string itoa(glw::GLint i)
1535 {
1536         std::stringstream stream;
1537
1538         stream << i;
1539
1540         return stream.str();
1541 }
1542
1543 } // namespace Utilities
1544 } // namespace TextureSizePromotion
1545 } // namespace gl3cts