Lower correlation threshold in flush-finish tests again am: 6455e6f987 am: 84373d7748...
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fFboSRGBWriteControlTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2017 The Android Open Source Project
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 FBO sRGB tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es31fFboSRGBWriteControlTests.hpp"
25 #include "es31fFboTestUtil.hpp"
26 #include "gluTextureUtil.hpp"
27 #include "gluContextInfo.hpp"
28 #include "tcuTestLog.hpp"
29 #include "glwEnums.hpp"
30 #include "sglrContextUtil.hpp"
31 #include "glwFunctions.hpp"
32 #include "deUniquePtr.hpp"
33 #include "deSharedPtr.hpp"
34 #include "gluObjectWrapper.hpp"
35 #include "gluPixelTransfer.hpp"
36 #include "glsTextureTestUtil.hpp"
37 #include "tcuVectorUtil.hpp"
38 #include "gluStrUtil.hpp"
39
40 namespace deqp
41 {
42 namespace gles31
43 {
44 namespace Functional
45 {
46 namespace
47 {
48
49 tcu::Vec4 getTestColorLinear (void)
50 {
51         return tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f);
52 }
53
54 tcu::Vec4 getTestColorSRGB (void)
55 {
56         return linearToSRGB(tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f));
57 }
58
59 tcu::Vec4 getTestColorBlank (void)
60 {
61         return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
62 }
63
64 tcu::Vec4 getEpsilonError (void)
65 {
66         return tcu::Vec4(0.005f);
67 }
68
69 enum QueryType
70 {
71         QUERYTYPE_ISENABLED = 0,
72         QUERYTYPE_BOOLEAN,
73         QUERYTYPE_FLOAT,
74         QUERYTYPE_INT,
75         QUERYTYPE_INT64,
76         QUERYTYPE_LAST
77 };
78
79 enum DataType
80 {
81         DATATYPE_BOOLEAN = 0,
82         DATATYPE_FLOAT,
83         DATATYPE_INT,
84         DATATYPE_INT64,
85 };
86
87 enum FramebufferSRGB
88 {
89         FRAMEBUFFERSRGB_ENABLED = 0,
90         FRAMEBUFFERSRGB_DISABLED
91 };
92
93 enum FramebufferBlend
94 {
95         FRAMEBUFFERBLEND_ENABLED = 0,
96         FRAMEBUFFERBLEND_DISABLED
97 };
98
99 enum TextureSourcesType
100 {
101         TEXTURESOURCESTYPE_RGBA         = 0,
102         TEXTURESOURCESTYPE_SRGBA,
103         TEXTURESOURCESTYPE_BOTH,
104         TEXTURESOURCESTYPE_NONE
105 };
106
107 enum FboType
108 {
109         FBOTYPE_SOURCE                  = 0,
110         FBOTYPE_DESTINATION
111 };
112
113 enum RendererTask
114 {
115         RENDERERTASK_DRAW = 0,
116         RENDERERTASK_COPY
117 };
118
119 enum SamplingType
120 {
121         SAMPLINGTYPE_TEXTURE                    = 0,
122         SAMPLINGTYPE_TEXTURE_LOD,
123         SAMPLINGTYPE_TEXTURE_GRAD,
124         SAMPLINGTYPE_TEXTURE_OFFSET,
125         SAMPLINGTYPE_TEXTURE_PROJ,
126 };
127
128 namespace TestTextureSizes
129 {
130         const int WIDTH = 128;
131         const int HEIGHT = 128;
132 } // global test texture sizes
133
134 namespace SampligTypeCount
135 {
136         const int MAX = 5;
137 } // global max number of sampling types
138
139 std::string buildSamplingPassType (const int samplerTotal)
140 {
141         std::ostringstream      shaderFragment;
142
143         const SamplingType      samplingTypeList [] =
144         {
145                 SAMPLINGTYPE_TEXTURE, SAMPLINGTYPE_TEXTURE_LOD, SAMPLINGTYPE_TEXTURE_GRAD, SAMPLINGTYPE_TEXTURE_OFFSET, SAMPLINGTYPE_TEXTURE_PROJ
146         } ;
147
148         for (int samplerTypeIdx = 0; samplerTypeIdx < DE_LENGTH_OF_ARRAY(samplingTypeList); samplerTypeIdx++)
149         {
150                 shaderFragment
151                         << "    if (uFunctionType == " << samplerTypeIdx << ") \n"
152                         << "    { \n";
153
154                 for (int samplerIdx = 0; samplerIdx < samplerTotal; samplerIdx++)
155                 {
156                         switch (static_cast<SamplingType>(samplerTypeIdx))
157                         {
158                                 case SAMPLINGTYPE_TEXTURE:
159                                 {
160                                         shaderFragment
161                                                 << "            texelColor" << samplerIdx << " = texture(uTexture" << samplerIdx << ", vs_aTexCoord); \n";
162                                         break;
163                                 }
164                                 case SAMPLINGTYPE_TEXTURE_LOD:
165                                 {
166                                         shaderFragment
167                                                 << "            texelColor" << samplerIdx << " = textureLod(uTexture" << samplerIdx << ", vs_aTexCoord, 0.0f); \n";
168                                         break;
169                                 }
170                                 case SAMPLINGTYPE_TEXTURE_GRAD:
171                                 {
172                                         shaderFragment
173                                                 << "            texelColor" << samplerIdx << " = textureGrad(uTexture" << samplerIdx << ", vs_aTexCoord, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f)); \n";
174                                         break;
175                                 }
176                                 case SAMPLINGTYPE_TEXTURE_OFFSET:
177                                 {
178                                         shaderFragment
179                                                 << "            texelColor" << samplerIdx << " = textureOffset(uTexture" << samplerIdx << ", vs_aTexCoord, ivec2(0.0f, 0.0f)); \n";
180                                         break;
181                                 }
182                                 case SAMPLINGTYPE_TEXTURE_PROJ:
183                                 {
184                                         shaderFragment
185                                                 << "            texelColor" << samplerIdx << " = textureProj(uTexture" << samplerIdx << ", vec3(vs_aTexCoord, 1.0f)); \n";
186                                         break;
187                                 }
188                                 default:
189                                         DE_FATAL("Error: sampling type unrecognised");
190                         }
191                 }
192
193                 shaderFragment
194                         << "    } \n";
195         }
196
197         return shaderFragment.str();
198 }
199
200 void logColor (Context& context, const std::string& colorLogMessage, const tcu::Vec4 resultColor)
201 {
202         tcu::TestLog&                   log             = context.getTestContext().getLog();
203         std::ostringstream              message;
204
205         message << colorLogMessage << " = (" << resultColor.x() << ", " << resultColor.y() << ", " << resultColor.z() << ", " << resultColor.w() << ")";
206                 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
207 }
208
209 struct TestFunction
210 {
211         explicit TestFunction   (const bool hasFunctionValue)
212                 : hasFunction           (hasFunctionValue) {}
213         TestFunction                    (const char* const functionNameValue, const char* const functionDefinition)
214                 : hasFunction           (true)
215                 , functionName          (functionNameValue)
216                 , functionDefintion     (functionDefinition) {}
217         ~TestFunction                   (void) {}
218
219         bool                    hasFunction;
220         const char*             functionName;
221         const char*             functionDefintion;
222 };
223
224 TestFunction getFunctionBlendLinearToSRGBCheck (void)
225 {
226         const char* const functionName = "blendPlusLinearToSRGB";
227
228         const char* const functionDefinition =
229                 "mediump vec4 blendPlusLinearToSRGB(in mediump vec4 colorSrc, in mediump vec4 colorDst) \n"
230                 "{ \n"
231                 "       const int MAX_VECTOR_SIZE = 4; \n"
232                 "       mediump vec4 colorConverted; \n"
233                 "       mediump vec4 colorBlended; \n"
234                 "       for (int idx = 0; idx < MAX_VECTOR_SIZE; idx++) \n"
235                 "       { \n"
236                 "               if (uBlendFunctionType == 0) \n"
237                 "               { \n"
238                 "                       colorBlended[idx] = (colorSrc[idx] * uFactorSrc) + colorDst[idx] * uFactorDst; \n"
239                 "               } \n"
240                 "               if (uBlendFunctionType == 1) \n"
241                 "               { \n"
242                 "                       colorBlended[idx] = (colorSrc[idx] * uFactorSrc) - (colorDst[idx] * uFactorDst); \n"
243                 "               } \n"
244                                 "if (uBlendFunctionType == 2) \n"
245                 "               { \n"
246                 "                       colorBlended[idx] = (colorDst[idx] * uFactorDst) - (colorSrc[idx] * uFactorSrc); \n"
247                 "               } \n"
248                 "               if (colorBlended[idx] < 0.0031308f) \n"
249                 "               { \n"
250                 "                       colorConverted[idx] = 12.92f * colorBlended[idx]; \n"
251                 "               } \n"
252                 "               else \n"
253                 "               { \n"
254                 "                       colorConverted[idx] = 1.055f * pow(colorBlended[idx], 0.41666f) - 0.055f; \n"
255                 "               } \n"
256                 "       } \n"
257                 "       return colorConverted; \n"
258                 "} \n";
259
260         TestFunction testFunction(functionName, functionDefinition);
261
262         return testFunction;
263 }
264
265 struct FBOConfig
266 {
267         FBOConfig                                       (const deUint32 textureInternalFormatValue,
268                                                                  const tcu::Vec4 textureColorValue,
269                                                                  const deUint32 fboTargetTypeValue,
270                                                                  const deUint32 fboColorAttachmentValue,
271                                                                  const FboType fboTypeValue)
272                 : textureInternalFormat (textureInternalFormatValue)
273                 , textureColor                  (textureColorValue)
274                 , fboTargetType                 (fboTargetTypeValue)
275                 , fboColorAttachment    (fboColorAttachmentValue)
276                 , fboType                               (fboTypeValue) {}
277         ~FBOConfig                                      (void) {}
278
279         deUint32        textureInternalFormat;
280         tcu::Vec4       textureColor;
281         deUint32        fboTargetType;
282         deUint32        fboColorAttachment;
283         FboType         fboType;
284 };
285
286 struct BlendConfig
287 {
288         deUint32        equation;
289         deUint32        funcSrc;
290         deUint32        funcDst;
291 };
292
293 std::vector<BlendConfig> getBlendingConfigList (void)
294 {
295         BlendConfig blendConfigs[12];
296
297         // add function permutations
298         blendConfigs[0].equation = GL_FUNC_ADD;
299         blendConfigs[1].equation = GL_FUNC_ADD;
300         blendConfigs[2].equation = GL_FUNC_ADD;
301         blendConfigs[3].equation = GL_FUNC_ADD;
302
303         blendConfigs[0].funcSrc = GL_ONE;
304         blendConfigs[0].funcDst = GL_ONE;
305         blendConfigs[1].funcSrc = GL_ONE;
306         blendConfigs[1].funcDst = GL_ZERO;
307         blendConfigs[2].funcSrc = GL_ZERO;
308         blendConfigs[2].funcDst = GL_ONE;
309         blendConfigs[3].funcSrc = GL_ZERO;
310         blendConfigs[3].funcDst = GL_ZERO;
311
312         // subtract function permutations
313         blendConfigs[4].equation = GL_FUNC_SUBTRACT;
314         blendConfigs[5].equation = GL_FUNC_SUBTRACT;
315         blendConfigs[6].equation = GL_FUNC_SUBTRACT;
316         blendConfigs[7].equation = GL_FUNC_SUBTRACT;
317
318         blendConfigs[4].funcSrc = GL_ONE;
319         blendConfigs[4].funcDst = GL_ONE;
320         blendConfigs[5].funcSrc = GL_ONE;
321         blendConfigs[5].funcDst = GL_ZERO;
322         blendConfigs[6].funcSrc = GL_ZERO;
323         blendConfigs[6].funcDst = GL_ONE;
324         blendConfigs[7].funcSrc = GL_ZERO;
325         blendConfigs[7].funcDst = GL_ZERO;
326
327         // reverse subtract function permutations
328         blendConfigs[8].equation = GL_FUNC_REVERSE_SUBTRACT;
329         blendConfigs[9].equation = GL_FUNC_REVERSE_SUBTRACT;
330         blendConfigs[10].equation = GL_FUNC_REVERSE_SUBTRACT;
331         blendConfigs[11].equation = GL_FUNC_REVERSE_SUBTRACT;
332
333         blendConfigs[8].funcSrc = GL_ONE;
334         blendConfigs[8].funcDst = GL_ONE;
335         blendConfigs[9].funcSrc = GL_ONE;
336         blendConfigs[9].funcDst = GL_ZERO;
337         blendConfigs[10].funcSrc = GL_ZERO;
338         blendConfigs[10].funcDst = GL_ONE;
339         blendConfigs[11].funcSrc = GL_ZERO;
340         blendConfigs[11].funcDst = GL_ZERO;
341
342         std::vector<BlendConfig> configList(blendConfigs, blendConfigs + DE_LENGTH_OF_ARRAY(blendConfigs));
343
344         return configList;
345 }
346
347 struct TestRenderPassConfig
348 {
349         TestRenderPassConfig            (void)
350                 : testFunction                  (false) {}
351
352         TestRenderPassConfig            (const TextureSourcesType textureSourcesTypeValue,
353                                                                 FBOConfig fboConfigListValue,
354                                                                 const FramebufferSRGB framebufferSRGBValue,
355                                                                 const FramebufferBlend framebufferBendValue,
356                                                                 const RendererTask rendererTaskValue)
357                 : textureSourcesType    (textureSourcesTypeValue)
358                 , framebufferSRGB               (framebufferSRGBValue)
359                 , frameBufferBlend              (framebufferBendValue)
360                 , testFunction                  (false)
361                 , rendererTask                  (rendererTaskValue) {fboConfigList.push_back(fboConfigListValue);}
362
363         TestRenderPassConfig            (const TextureSourcesType textureSourcesTypeValue,
364                                                                 FBOConfig fboConfigListValue,
365                                                                 const FramebufferSRGB framebufferSRGBValue,
366                                                                 const FramebufferBlend framebufferBendValue,
367                                                                 TestFunction testFunctionValue,
368                                                                 const RendererTask rendererTaskValue)
369                 : textureSourcesType    (textureSourcesTypeValue)
370                 , framebufferSRGB               (framebufferSRGBValue)
371                 , frameBufferBlend              (framebufferBendValue)
372                 , testFunction                  (testFunctionValue)
373                 , rendererTask                  (rendererTaskValue) {fboConfigList.push_back(fboConfigListValue);}
374
375         TestRenderPassConfig            (const TextureSourcesType textureSourcesTypeValue,
376                                                                 std::vector<FBOConfig> fboConfigListValue,
377                                                                 const FramebufferSRGB framebufferSRGBValue,
378                                                                 const FramebufferBlend framebufferBendValue,
379                                                                 TestFunction testFunctionValue,
380                                                                 const RendererTask rendererTaskValue)
381                 : textureSourcesType    (textureSourcesTypeValue)
382                 , fboConfigList                 (fboConfigListValue)
383                 , framebufferSRGB               (framebufferSRGBValue)
384                 , frameBufferBlend              (framebufferBendValue)
385                 , testFunction                  (testFunctionValue)
386                 , rendererTask                  (rendererTaskValue) {}
387
388         ~TestRenderPassConfig           (void) {}
389
390         TextureSourcesType              textureSourcesType;
391         std::vector<FBOConfig>  fboConfigList;
392         FramebufferSRGB                 framebufferSRGB;
393         FramebufferBlend                frameBufferBlend;
394         TestFunction                    testFunction;
395         RendererTask                    rendererTask;
396 };
397
398 class TestVertexData
399 {
400 public:
401                                                         TestVertexData          (Context& context);
402                                                         ~TestVertexData         (void);
403
404         void                                    init                            (void);
405
406         void                                    bind                            (void) const;
407         void                                    unbind                          (void) const;
408
409 private:
410         const glw::Functions*   m_gl;
411         std::vector<float>              m_data;
412         glw::GLuint                             m_vboHandle;
413         glw::GLuint                             m_vaoHandle;
414 };
415
416 TestVertexData::TestVertexData  (Context& context)
417         : m_gl                                          (&context.getRenderContext().getFunctions())
418 {
419         const glw::GLfloat              vertexData[]    =
420         {
421                 // position                             // texcoord
422                 -1.0f, -1.0f, 0.0f,             0.0f, 0.0f, // bottom left corner
423                  1.0f, -1.0f, 0.0f,             1.0f, 0.0f, // bottom right corner
424                  1.0f,  1.0f, 0.0f,             1.0f, 1.0f, // Top right corner
425
426                 -1.0f,  1.0f, 0.0f,             0.0f, 1.0f, // top left corner
427                  1.0f,  1.0f, 0.0f,             1.0f, 1.0f, // Top right corner
428                 -1.0f, -1.0f, 0.0f,             0.0f, 0.0f  // bottom left corner
429         };
430
431         m_data.resize(DE_LENGTH_OF_ARRAY(vertexData));
432         for (int idx = 0; idx < (int)m_data.size(); idx++)
433                 m_data[idx] = vertexData[idx];
434
435         m_gl->genVertexArrays(1, &m_vaoHandle);
436         m_gl->bindVertexArray(m_vaoHandle);
437
438         m_gl->genBuffers(1, &m_vboHandle);
439         m_gl->bindBuffer(GL_ARRAY_BUFFER, m_vboHandle);
440
441         m_gl->bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)(m_data.size() * sizeof(glw::GLfloat)), &m_data[0], GL_STATIC_DRAW);
442
443         m_gl->enableVertexAttribArray(0);
444         m_gl->vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)0);
445         m_gl->enableVertexAttribArray(1);
446         m_gl->vertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)(3 * sizeof(GL_FLOAT)));
447
448         m_gl->bindVertexArray(0);
449         m_gl->bindBuffer(GL_ARRAY_BUFFER, 0);
450         GLU_EXPECT_NO_ERROR(m_gl->getError(), "gl error during vertex data setup");
451 }
452
453 TestVertexData::~TestVertexData (void)
454 {
455         m_gl->deleteBuffers(1, &m_vboHandle);
456         m_gl->deleteVertexArrays(1, &m_vaoHandle);
457 }
458
459 void TestVertexData::bind (void) const
460 {
461         m_gl->bindVertexArray(m_vaoHandle);
462 }
463
464 void TestVertexData::unbind (void) const
465 {
466         m_gl->bindVertexArray(0);
467 }
468
469 class TestTexture2D
470 {
471 public:
472                                                                 TestTexture2D           (Context& context, const deUint32 internalFormatValue, const deUint32 transferFormatValue, const deUint32 transferTypeValue, const tcu::Vec4 imageColorValue, const int idx);
473                                                                 ~TestTexture2D          (void);
474
475         int                                                     getTextureUnit          (void) const;
476         deUint32                                        getHandle                       (void) const;
477         int                                                     getIdx                          (void) const;
478
479         void                                            bind                            (const int textureUnit);
480         void                                            unbind                          (void) const;
481
482 private:
483         const glw::Functions*           m_gl;
484         glw::GLuint                                     m_handle;
485         const deUint32                          m_internalFormat;
486         tcu::TextureFormat                      m_transferFormat;
487         int                                                     m_width;
488         int                                                     m_height;
489         tcu::TextureLevel                       m_imageData;
490         int                                                     m_textureUnit;
491         const int                                       m_idx;
492 };
493
494 TestTexture2D::TestTexture2D    (Context& context, const deUint32 internalFormat, const deUint32 transferFormat, const deUint32 transferType, const tcu::Vec4 imageColor, const int idx)
495         : m_gl                                          (&context.getRenderContext().getFunctions())
496         , m_internalFormat                      (internalFormat)
497         , m_transferFormat                      (tcu::TextureFormat(glu::mapGLTransferFormat(transferFormat, transferType)))
498         , m_width                                       (TestTextureSizes::WIDTH)
499         , m_height                                      (TestTextureSizes::HEIGHT)
500         , m_imageData                           (tcu::TextureLevel(glu::mapGLInternalFormat(internalFormat), m_width, m_height, 1))
501         , m_idx                                         (idx)
502 {
503         // fill image data with a solid test color
504         tcu::clear(m_imageData.getAccess(), tcu::Vec4(0.0f));
505         for (int py = 0; py < m_imageData.getHeight(); py++)
506         {
507                 for (int px = 0; px < m_imageData.getWidth(); px++)
508                         m_imageData.getAccess().setPixel(imageColor, px, py);
509         }
510
511         m_gl->genTextures(1, &m_handle);
512
513         m_gl->bindTexture(GL_TEXTURE_2D, m_handle);
514         m_gl->texParameteri(GL_TEXTURE_2D,      GL_TEXTURE_WRAP_S,              GL_MIRRORED_REPEAT);
515         m_gl->texParameteri(GL_TEXTURE_2D,      GL_TEXTURE_WRAP_T,              GL_MIRRORED_REPEAT);
516         m_gl->texParameteri(GL_TEXTURE_2D,      GL_TEXTURE_MIN_FILTER,  GL_NEAREST);
517         m_gl->texParameteri(GL_TEXTURE_2D,      GL_TEXTURE_MAG_FILTER,  GL_NEAREST);
518
519         m_gl->texImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFormat, transferType, m_imageData.getAccess().getDataPtr());
520
521         m_gl->bindTexture(GL_TEXTURE_2D, 0);
522 }
523
524 TestTexture2D::~TestTexture2D (void)
525 {
526         m_gl->deleteTextures(1, &m_handle);
527 }
528
529 int TestTexture2D::getTextureUnit (void) const
530 {
531         return m_textureUnit;
532 }
533
534 deUint32 TestTexture2D::getHandle (void) const
535 {
536         return m_handle;
537 }
538
539 int TestTexture2D::getIdx (void) const
540 {
541         return m_idx;
542 }
543
544 void TestTexture2D::bind (const int textureUnit)
545 {
546         m_textureUnit = textureUnit;
547         m_gl->activeTexture(GL_TEXTURE0 + m_textureUnit);
548         m_gl->bindTexture(GL_TEXTURE_2D, m_handle);
549 }
550
551 void TestTexture2D::unbind (void) const
552 {
553         m_gl->bindTexture(GL_TEXTURE_2D, 0);
554 }
555
556 class TestFramebuffer
557 {
558 public:
559                                                                                                 TestFramebuffer                 (void);
560                                                                                                 TestFramebuffer                 (Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx);
561                                                                                                 ~TestFramebuffer                (void);
562
563         void                                                                            setTargetType                   (const deUint32 targetType);
564
565         FboType                                                                         getType                                 (void) const;
566         deUint32                                                                        getHandle                               (void) const;
567         deUint32                                                                        getColorAttachment              (void) const;
568         int                                                                                     getIdx                                  (void) const;
569         deUint32                                                                        getTargetType                   (void) const;
570
571         void                                                                            bind                                    (void);
572         void                                                                            unbind                                  (void);
573
574         typedef de::UniquePtr<glu::Framebuffer>         fboUniquePtr;
575
576 private:
577         const glw::Functions*                                           m_gl;
578         fboUniquePtr                                                            m_referenceSource;
579         deUint32                                                                        m_targetType;
580         bool                                                                            m_bound;
581         bool                                                                            m_isSRGB;
582         FboType                                                                         m_type;
583         const int                                                                       m_idx;
584         deUint32                                                                        m_colorAttachment;
585 };
586
587 TestFramebuffer::TestFramebuffer        (Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx)
588         : m_gl                                                  (&context.getRenderContext().getFunctions())
589         , m_referenceSource                             (new glu::Framebuffer(context.getRenderContext()))
590         , m_targetType                                  (targetType)
591         , m_bound                                               (false)
592         , m_isSRGB                                              (isSRGB)
593         , m_type                                                (fboType)
594         , m_idx                                                 (idx)
595         , m_colorAttachment                             (colorAttachment)
596 {
597         m_gl->bindFramebuffer(m_targetType, **m_referenceSource);
598
599         m_gl->framebufferTexture2D(m_targetType, m_colorAttachment, GL_TEXTURE_2D, textureAttachmentHandle, 0);
600
601         TCU_CHECK(m_gl->checkFramebufferStatus(m_targetType) == GL_FRAMEBUFFER_COMPLETE);
602
603         if (targetType == GL_DRAW_BUFFER)
604         {
605                 glw::GLuint textureAttachments[] = {m_colorAttachment};
606                 m_gl->drawBuffers(DE_LENGTH_OF_ARRAY(textureAttachments), textureAttachments);
607                 GLU_EXPECT_NO_ERROR(m_gl->getError(), "glDrawBuffer()");
608         }
609
610         if (targetType == GL_READ_BUFFER)
611         {
612                 m_gl->readBuffer(m_colorAttachment);
613                 GLU_EXPECT_NO_ERROR(m_gl->getError(), "glReadBuffer()");
614         }
615
616         m_gl->bindFramebuffer(m_targetType, 0);
617 }
618
619 TestFramebuffer::~TestFramebuffer (void)
620 {
621 }
622
623 void TestFramebuffer::setTargetType (const deUint32 targetType)
624 {
625         m_targetType = targetType;
626 }
627
628 FboType TestFramebuffer::getType (void) const
629 {
630         return m_type;
631 }
632
633 deUint32 TestFramebuffer::getHandle (void) const
634 {
635         return **m_referenceSource;
636 }
637
638 deUint32 TestFramebuffer::getColorAttachment (void) const
639 {
640         return m_colorAttachment;
641 }
642
643 int TestFramebuffer::getIdx (void) const
644 {
645         return m_idx;
646 }
647
648 deUint32 TestFramebuffer::getTargetType (void) const
649 {
650         return m_targetType;
651 }
652
653 void TestFramebuffer::bind (void)
654 {
655         if (!m_bound)
656         {
657                 m_gl->bindFramebuffer(m_targetType, **m_referenceSource);
658                 m_bound = true;
659         }
660 }
661
662 void TestFramebuffer::unbind (void)
663 {
664         if (m_bound)
665         {
666                 m_gl->bindFramebuffer(m_targetType, 0);
667                 m_bound = false;
668         }
669 }
670
671 class TestShaderProgram
672 {
673 public:
674                                                                                 TestShaderProgram               (Context& context, const int samplerTotal, TestFunction testFunction);
675                                                                                 ~TestShaderProgram              (void);
676
677         glw::GLuint                                                     getHandle                               (void) const;
678         int                                                                     getSamplerTotal                 (void) const;
679
680         void                                                            use                                             (void) const;
681         void                                                            unuse                                   (void) const;
682
683         glu::ShaderProgramInfo                          getLogInfo                              (void);
684
685 private:
686         const glw::Functions*                           m_gl;
687         de::MovePtr<glu::ShaderProgram>         m_referenceSource;
688         const int                                                       m_samplerTotal;
689         const int                                                       m_shaderStagesTotal;
690 };
691
692 TestShaderProgram::TestShaderProgram    (Context& context, const int samplerTotal, TestFunction testFunction)
693         : m_gl                                                          (&context.getRenderContext().getFunctions())
694         , m_samplerTotal                                        (samplerTotal)
695         , m_shaderStagesTotal                           (2)
696 {
697         std::ostringstream              shaderFragment;
698
699         const char* const shaderVertex =
700                 "#version 310 es \n"
701                 "layout (location = 0) in mediump vec3 aPosition; \n"
702                 "layout (location = 1) in mediump vec2 aTexCoord; \n"
703                 "out mediump vec2 vs_aTexCoord; \n"
704                 "void main () \n"
705                 "{ \n"
706                 "       gl_Position = vec4(aPosition, 1.0f); \n"
707                 "       vs_aTexCoord = aTexCoord; \n"
708                 "} \n";
709
710         shaderFragment
711                 << "#version 310 es \n"
712                 << "in mediump vec2 vs_aTexCoord; \n"
713                 << "layout (location = 0) out mediump vec4 fs_aColor0; \n";
714
715         for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++)
716                 shaderFragment
717                         << "uniform sampler2D uTexture" << samplerIdx << "; \n";
718
719         shaderFragment
720                 << "uniform int uFunctionType; \n";
721
722         if (testFunction.hasFunction)
723                 shaderFragment
724                 << "uniform int uBlendFunctionType; \n"
725                 << "uniform mediump float uFactorSrc; \n"
726                 << "uniform mediump float uFactorDst; \n"
727                         << testFunction.functionDefintion;
728
729         shaderFragment
730                 << "void main () \n"
731                 << "{ \n";
732
733         for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++)
734                 shaderFragment
735                         <<"     mediump vec4 texelColor" << samplerIdx << " = vec4(0.0f, 0.0f, 0.0f, 1.0f); \n";
736
737         shaderFragment
738                 << buildSamplingPassType(m_samplerTotal);
739
740         if (testFunction.hasFunction)
741                 shaderFragment
742                         << "    fs_aColor0 = " << testFunction.functionName << "(texelColor0, texelColor1); \n";
743         else
744                 shaderFragment
745                         << "    fs_aColor0 = texelColor0; \n";
746
747         shaderFragment
748                 << "} \n";
749
750         m_referenceSource = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(context.getRenderContext(), glu::makeVtxFragSources(shaderVertex, shaderFragment.str())));
751         if (!m_referenceSource->isOk())
752         {
753                 tcu::TestLog& log = context.getTestContext().getLog();
754                 log << this->getLogInfo();
755                 TCU_FAIL("Failed to compile shaders and link program");
756         }
757 }
758
759 TestShaderProgram::~TestShaderProgram (void)
760 {
761         m_referenceSource = de::MovePtr<glu::ShaderProgram>(DE_NULL);
762         m_referenceSource.clear();
763 }
764
765 deUint32 TestShaderProgram::getHandle (void) const
766 {
767         return m_referenceSource->getProgram();
768 }
769
770 int TestShaderProgram::getSamplerTotal (void) const
771 {
772         return m_samplerTotal;
773 }
774
775 void TestShaderProgram::use (void) const
776 {
777         m_gl->useProgram(this->getHandle());
778 }
779
780 void TestShaderProgram::unuse (void) const
781 {
782         m_gl->useProgram(0);
783 }
784
785 glu::ShaderProgramInfo TestShaderProgram::getLogInfo (void)
786 {
787         glu::ShaderProgramInfo  buildInfo;
788
789         // log shader program info. Only vertex and fragment shaders included
790         buildInfo.program = m_referenceSource->getProgramInfo();
791         for (int shaderIdx = 0; shaderIdx < m_shaderStagesTotal; shaderIdx++)
792         {
793                 glu::ShaderInfo shaderInfo = m_referenceSource->getShaderInfo(static_cast<glu::ShaderType>(static_cast<int>(glu::SHADERTYPE_VERTEX) + static_cast<int>(shaderIdx)), 0);
794                 buildInfo.shaders.push_back(shaderInfo);
795         }
796         return buildInfo;
797 }
798
799 class Renderer
800 {
801 public:
802                                                                                         Renderer                                                (Context& context);
803                                                                                         ~Renderer                                               (void);
804
805         void                                                                    init                                                    (const TestRenderPassConfig& renderPassConfig, const int renderpass);
806         void                                                                    deinit                                                  (void);
807
808         void                                                                    setSamplingType                                 (const SamplingType samplerIdx);
809         void                                                                    setBlendIteration                               (const int blendIteration);
810         void                                                                    setFramebufferBlend                             (const bool blend);
811         void                                                                    setFramebufferSRGB                              (const bool sRGB);
812
813         std::vector<tcu::Vec4>                                  getResultsPreDraw                               (void) const;
814         std::vector<tcu::Vec4>                                  getResultsPostDraw                              (void) const;
815         int                                                                             getBlendConfigCount                             (void) const;
816         glu::ShaderProgramInfo                                  getShaderProgramInfo                    (void);
817
818         void                                                                    copyFrameBufferTexture                  (const int srcPx, const int srcPy, const int dstPx, const int dstPy);
819         void                                                                    draw                                                    (void);
820         void                                                                    storeShaderProgramInfo                  (void);
821         void                                                                    logShaderProgramInfo                    (void);
822
823         typedef de::SharedPtr<TestTexture2D>    TextureSp;
824         typedef de::SharedPtr<TestFramebuffer>  FboSp;
825
826 private:
827         void                                                                    createFBOwithColorAttachment    (const std::vector<FBOConfig> fboConfigList);
828         void                                                                    setShaderProgramSamplingType    (const int samplerIdx);
829         void                                                                    setShaderBlendFunctionType              (void);
830         void                                                                    setShaderBlendSrcDstValues              (void);
831         void                                                                    bindActiveTexturesSamplers              (void);
832         void                                                                    bindAllRequiredSourceTextures   (const TextureSourcesType texturesRequired);
833         void                                                                    unbindAllSourceTextures                 (void);
834         void                                                                    bindFramebuffer                                 (const int framebufferIdx);
835         void                                                                    unbindFramebuffer                               (const int framebufferIdx);
836         void                                                                    enableFramebufferSRGB                   (void);
837         void                                                                    enableFramebufferBlend                  (void);
838         bool                                                                    isFramebufferAttachmentSRGB             (const deUint32 targetType, const deUint32 attachment) const;
839         void                                                                    readTexels                                              (const int px, const int py, const deUint32 attachment, tcu::Vec4& texelData);
840         void                                                                    logState                                                (const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const;
841
842         // renderer specific constants initialized during constructor
843         Context&                                                                m_context;
844         const TestVertexData                                    m_vertexData;
845         const int                                                               m_textureSourceTotal;
846
847         // additional resources monitored by the renderer
848         std::vector<BlendConfig>                                m_blendConfigList;
849         std::vector<TextureSp>                                  m_textureSourceList;
850         TestRenderPassConfig                                    m_renderPassConfig;
851         std::vector<TextureSp>                                  m_fboTextureList;
852         TestShaderProgram*                                              m_shaderProgram;
853         std::vector<FboSp>                                              m_framebufferList;
854         std::vector<tcu::Vec4>                                  m_resultsListPreDraw;
855         std::vector<tcu::Vec4>                                  m_resultsListPostDraw;
856
857         // mutable state variables (internal access only)
858         bool                                                                    m_hasShaderProgramInfo;
859         int                                                                             m_renderPass;
860         int                                                                             m_samplersRequired;
861         bool                                                                    m_hasFunction;
862         bool                                                                    m_blittingEnabled;
863         glu::ShaderProgramInfo                                  m_shaderProgramInfo;
864
865         // mutable state variables (external access via setters)
866         SamplingType                                                    m_samplingType;
867         int                                                                             m_blendIteration;
868         bool                                                                    m_framebufferBlendEnabled;
869         bool                                                                    m_framebufferSRGBEnabled;
870 };
871
872 Renderer::Renderer                              (Context& context)
873         : m_context                                     (context)
874         , m_vertexData                          (context)
875         , m_textureSourceTotal          (2)
876         , m_blendConfigList                     (getBlendingConfigList())
877         , m_hasShaderProgramInfo        (false)
878 {
879         TextureSp textureLinear(new TestTexture2D(m_context, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear(), 0));
880         m_textureSourceList.push_back(textureLinear);
881
882         TextureSp textureSRGB(new TestTexture2D(m_context, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear(), 1));
883         m_textureSourceList.push_back(textureSRGB);
884 }
885
886 Renderer::~Renderer (void)
887 {
888         m_textureSourceList.clear();
889         this->deinit();
890 }
891
892 void Renderer::init (const TestRenderPassConfig& renderPassConfig, const int renderpass)
893 {
894         m_renderPassConfig = renderPassConfig;
895         m_renderPass = renderpass;
896
897         this->createFBOwithColorAttachment(m_renderPassConfig.fboConfigList);
898
899         if (m_renderPassConfig.textureSourcesType != TEXTURESOURCESTYPE_NONE)
900         {
901                 if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_RGBA || m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_SRGBA)
902                         m_samplersRequired = 1;
903                 else if (m_renderPassConfig.textureSourcesType ==TEXTURESOURCESTYPE_BOTH )
904                         m_samplersRequired = 2;
905                 else
906                         DE_FATAL("Error: Texture source required not recognised");
907
908                 m_shaderProgram = new TestShaderProgram(m_context, m_samplersRequired, m_renderPassConfig.testFunction);
909                 m_hasFunction = m_renderPassConfig.testFunction.hasFunction;
910         }
911         else
912                 m_shaderProgram = DE_NULL;
913 }
914
915 void Renderer::deinit (void)
916 {
917         if (m_shaderProgram != DE_NULL)
918         {
919                 delete m_shaderProgram;
920                 m_shaderProgram = DE_NULL;
921         }
922
923         m_fboTextureList.clear();
924         m_framebufferList.clear();
925 }
926
927 void Renderer::setSamplingType (const SamplingType samplingType)
928 {
929         m_samplingType = samplingType;
930 }
931
932 void Renderer::setBlendIteration (const int blendIteration)
933 {
934         m_blendIteration = blendIteration;
935 }
936
937 void Renderer::setFramebufferBlend (const bool blend)
938 {
939         m_framebufferBlendEnabled = blend;
940 }
941
942 void Renderer::setFramebufferSRGB (const bool sRGB)
943 {
944         m_framebufferSRGBEnabled = sRGB;
945 }
946
947 std::vector<tcu::Vec4> Renderer::getResultsPreDraw (void) const
948 {
949         return m_resultsListPreDraw;
950 }
951
952 std::vector<tcu::Vec4> Renderer::getResultsPostDraw (void) const
953 {
954         return m_resultsListPostDraw;
955 }
956
957 int Renderer::getBlendConfigCount (void) const
958 {
959         return (int)m_blendConfigList.size();
960 }
961
962 void Renderer::copyFrameBufferTexture (const int srcPx, const int srcPy, const int dstPx, const int dstPy)
963 {
964         const glw::Functions&   gl                                              = m_context.getRenderContext().getFunctions();
965         int                                             fboSrcIdx                               = -1;
966         int                                             fboDstIdx                               = -1;
967         deUint32                                fboSrcColAttachment             = GL_NONE;
968         deUint32                                fboDstColAttachment             = GL_NONE;
969
970         for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
971                 this->bindFramebuffer(idx);
972
973         // cache fbo attachments and idx locations
974         for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
975         {
976                 if (m_framebufferList[idx]->getType() == FBOTYPE_SOURCE)
977                 {
978                         fboSrcIdx = m_framebufferList[idx]->getIdx();
979                         fboSrcColAttachment = m_framebufferList[fboSrcIdx]->getColorAttachment();
980                 }
981                 if (m_framebufferList[idx]->getType() == FBOTYPE_DESTINATION)
982                 {
983                         fboDstIdx = m_framebufferList[idx]->getIdx();
984                         fboDstColAttachment = m_framebufferList[fboDstIdx]->getColorAttachment();
985                 }
986         }
987
988         for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
989                 m_framebufferList[idx]->unbind();
990
991         // store texel data from both src and dst before performing the copy
992         m_resultsListPreDraw.resize(2);
993         m_framebufferList[fboSrcIdx]->bind();
994         this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPreDraw[0]);
995         m_framebufferList[fboSrcIdx]->unbind();
996         m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER);
997         m_framebufferList[fboDstIdx]->bind();
998         this->readTexels(0, 0, fboDstColAttachment, m_resultsListPreDraw[1]);
999         m_framebufferList[fboDstIdx]->unbind();
1000         m_framebufferList[fboDstIdx]->setTargetType(GL_DRAW_FRAMEBUFFER);
1001
1002         m_framebufferList[fboSrcIdx]->bind();
1003         m_framebufferList[fboDstIdx]->bind();
1004
1005         this->enableFramebufferSRGB();
1006         this->enableFramebufferBlend();
1007
1008         gl.blitFramebuffer(     srcPx, srcPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT,
1009                                                 dstPx, dstPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT,
1010                                                 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1011
1012         m_resultsListPostDraw.resize(2);
1013         this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPostDraw[0]);
1014         m_framebufferList[fboSrcIdx]->unbind();
1015         m_framebufferList[fboDstIdx]->unbind();
1016
1017         m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER);
1018         m_framebufferList[fboDstIdx]->bind();
1019         this->readTexels(0, 0, fboDstColAttachment, m_resultsListPostDraw[1]);
1020         m_framebufferList[fboDstIdx]->unbind();
1021 }
1022
1023 void Renderer::draw (void)
1024 {
1025         const glw::Functions&   gl = m_context.getRenderContext().getFunctions();
1026
1027         if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_NONE)
1028                 DE_FATAL("Error: Attempted to draw with no texture sources");
1029
1030         // resize results storage with each render pass
1031         m_resultsListPreDraw.resize(m_renderPass + 1);
1032         m_resultsListPostDraw.resize(m_renderPass + 1);
1033
1034         m_shaderProgram->use();
1035         m_vertexData.bind();
1036
1037         for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
1038                 this->bindFramebuffer(idx);
1039
1040         this->bindAllRequiredSourceTextures(m_renderPassConfig.textureSourcesType);
1041         this->bindActiveTexturesSamplers();
1042
1043         this->enableFramebufferSRGB();
1044         this->enableFramebufferBlend();
1045
1046         this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPreDraw[m_renderPass]);
1047         this->setShaderProgramSamplingType(m_samplingType);
1048         if (m_hasFunction)
1049         {
1050                 this->setShaderBlendFunctionType();
1051                 this->setShaderBlendSrcDstValues();
1052         }
1053
1054         gl.drawArrays(GL_TRIANGLES, 0, 6);
1055
1056         this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPostDraw[m_renderPass]);
1057         this->logState(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_samplingType);
1058
1059         this->unbindAllSourceTextures();
1060         for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
1061                 this->unbindFramebuffer(idx);
1062         m_vertexData.unbind();
1063         m_shaderProgram->unuse();
1064 }
1065
1066 void Renderer::storeShaderProgramInfo (void)
1067 {
1068         m_shaderProgramInfo = m_shaderProgram->getLogInfo();
1069         m_hasShaderProgramInfo = true;
1070 }
1071
1072 void Renderer::logShaderProgramInfo (void)
1073 {
1074         tcu::TestLog& log = m_context.getTestContext().getLog();
1075
1076         if (m_hasShaderProgramInfo)
1077                 log << m_shaderProgramInfo;
1078 }
1079
1080 void Renderer::createFBOwithColorAttachment (const std::vector<FBOConfig> fboConfigList)
1081 {
1082         const int size = (int)fboConfigList.size();
1083         for (int idx = 0; idx < size; idx++)
1084         {
1085                 TextureSp texture(new TestTexture2D(m_context, fboConfigList[idx].textureInternalFormat, GL_RGBA, GL_UNSIGNED_BYTE, fboConfigList[idx].textureColor, idx));
1086                 m_fboTextureList.push_back(texture);
1087
1088                 bool isSRGB;
1089                 if (fboConfigList[idx].textureInternalFormat == GL_SRGB8_ALPHA8)
1090                         isSRGB = true;
1091                 else
1092                         isSRGB = false;
1093
1094                 FboSp framebuffer(new TestFramebuffer(m_context, fboConfigList[idx].fboTargetType, fboConfigList[idx].fboColorAttachment, texture->getHandle(), isSRGB, fboConfigList[idx].fboType, idx));
1095                 m_framebufferList.push_back(framebuffer);
1096         }
1097 }
1098
1099 void Renderer::setShaderProgramSamplingType (const int samplerIdx)
1100 {
1101         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1102
1103         glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFunctionType");
1104         DE_ASSERT(location != (glw::GLuint)-1);
1105         gl.uniform1i(location, samplerIdx);
1106 }
1107
1108 void Renderer::setShaderBlendFunctionType (void)
1109 {
1110         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1111
1112         int function = -1;
1113         if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD)
1114                 function = 0;
1115         else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT)
1116                 function = 1;
1117         else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT)
1118                 function = 2;
1119         else
1120                 DE_FATAL("Error: Blend function not recognised");
1121
1122         glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uBlendFunctionType");
1123         DE_ASSERT(location != (glw::GLuint)-1);
1124         gl.uniform1i(location, function);
1125 }
1126
1127 void Renderer::setShaderBlendSrcDstValues (void)
1128 {
1129         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1130
1131         float funcSrc;
1132         if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE)
1133                 funcSrc = 1.0f;
1134         else
1135                 funcSrc = 0.0f;
1136
1137         float funcDst;
1138                 if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE)
1139                 funcDst = 1.0f;
1140         else
1141                 funcDst = 0.0f;
1142
1143         glw::GLuint locationSrc = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorSrc");
1144         gl.uniform1f(locationSrc, funcSrc);
1145         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()");
1146
1147         glw::GLuint locationDst = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorDst");
1148         gl.uniform1f(locationDst, funcDst);
1149         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()");
1150 }
1151
1152 void Renderer::bindActiveTexturesSamplers (void)
1153 {
1154         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1155
1156         for (int idx = 0; idx < m_samplersRequired; idx++)
1157         {
1158                 std::ostringstream stream;
1159                 stream << "uTexture" << idx;
1160                 std::string uniformName(stream.str());
1161                 glw::GLint location = gl.getUniformLocation(m_shaderProgram->getHandle(), uniformName.c_str());
1162                 DE_ASSERT(location != -1);
1163                 gl.uniform1i(location, m_textureSourceList[idx]->getTextureUnit());
1164                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation()");
1165         }
1166 }
1167
1168 void Renderer::bindAllRequiredSourceTextures (const TextureSourcesType texturesRequired)
1169 {
1170         if (texturesRequired == TEXTURESOURCESTYPE_RGBA)
1171                 m_textureSourceList[0]->bind(0);
1172         else if (texturesRequired == TEXTURESOURCESTYPE_SRGBA)
1173                 m_textureSourceList[1]->bind(0);
1174         else if (texturesRequired == TEXTURESOURCESTYPE_BOTH)
1175         {
1176                 m_textureSourceList[0]->bind(0);
1177                 m_textureSourceList[1]->bind(1);
1178         }
1179         else
1180                 DE_FATAL("Error: Invalid sources requested in bind all");
1181 }
1182
1183 void Renderer::unbindAllSourceTextures (void)
1184 {
1185         for (int idx = 0; idx < (int)m_textureSourceList.size(); idx++)
1186                 m_textureSourceList[idx]->unbind();
1187 }
1188
1189 void Renderer::bindFramebuffer (const int framebufferIdx)
1190 {
1191         m_framebufferList[framebufferIdx]->bind();
1192 }
1193
1194 void Renderer::unbindFramebuffer (const int framebufferIdx)
1195 {
1196         m_framebufferList[framebufferIdx]->unbind();
1197 }
1198
1199 void Renderer::enableFramebufferSRGB (void)
1200 {
1201         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1202
1203         if (m_framebufferSRGBEnabled)
1204                 gl.enable(GL_FRAMEBUFFER_SRGB);
1205         else
1206                 gl.disable(GL_FRAMEBUFFER_SRGB);
1207 }
1208
1209 void Renderer::enableFramebufferBlend (void)
1210 {
1211         const glw::Functions&   gl      = m_context.getRenderContext().getFunctions();
1212         tcu::TestLog&                   log     = m_context.getTestContext().getLog();
1213         std::ostringstream              message;
1214
1215         message << "Blend settings = ";
1216
1217         if (m_framebufferBlendEnabled)
1218         {
1219                 gl.enable(GL_BLEND);
1220                 gl.blendEquation(m_blendConfigList[m_blendIteration].equation);
1221                 gl.blendFunc(m_blendConfigList[m_blendIteration].funcSrc, m_blendConfigList[m_blendIteration].funcDst);
1222
1223                 std::string equation, src, dst;
1224                 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD)
1225                         equation = "GL_FUNC_ADD";
1226                 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT)
1227                         equation = "GL_FUNC_SUBTRACT";
1228                 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT)
1229                         equation = "GL_FUNC_REVERSE_SUBTRACT";
1230                 if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE)
1231                         src = "GL_ONE";
1232                 else
1233                         src = "GL_ZERO";
1234                 if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE)
1235                         dst = "GL_ONE";
1236                 else
1237                         dst = "GL_ZERO";
1238
1239                 message << "Enabled: equation = " << equation << ", func src = " << src << ", func dst = " << dst;
1240         }
1241         else
1242         {
1243                 gl.disable(GL_BLEND);
1244                 message << "Disabled";
1245         }
1246
1247         log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
1248 }
1249
1250 bool Renderer::isFramebufferAttachmentSRGB (const deUint32 targetType, const deUint32 attachment) const
1251 {
1252         const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
1253         glw::GLint                              encodingType;
1254
1255         gl.getFramebufferAttachmentParameteriv(targetType, attachment, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encodingType);
1256         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetNamedFramebufferAttachmentParameteriv()");
1257
1258         switch (static_cast<glw::GLenum>(encodingType))
1259         {
1260                 case GL_SRGB:
1261                 {
1262                         return true;
1263                         break;
1264                 }
1265                 case GL_LINEAR:
1266                 {
1267                         return false;
1268                         break;
1269                 }
1270                 default:
1271                 {
1272                         DE_FATAL("Error: Color attachment format not recognised");
1273                         return false;
1274                 }
1275         }
1276 }
1277
1278 void Renderer::readTexels (const int px, const int py, const deUint32 mode, tcu::Vec4& texelData)
1279 {
1280         const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
1281         tcu::TextureLevel               textureRead;
1282
1283         // ensure result sampling coordinates are within range of the result color attachment
1284         DE_ASSERT((px >= 0) && (px < m_context.getRenderTarget().getWidth()));
1285         DE_ASSERT((py >= 0) && (py < m_context.getRenderTarget().getHeight()));
1286
1287         gl.readBuffer(mode);
1288         textureRead.setStorage(glu::mapGLTransferFormat(GL_RGBA, GL_UNSIGNED_BYTE), TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT);
1289         glu::readPixels(m_context.getRenderContext(), px, py, textureRead.getAccess());
1290         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
1291         texelData = textureRead.getAccess().getPixel(px, py);
1292 }
1293
1294 void Renderer::logState (const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const
1295 {
1296         tcu::TestLog&                   log                                     = m_context.getTestContext().getLog();
1297         std::ostringstream              message;
1298
1299         bool fboAttachmentSRGB = this->isFramebufferAttachmentSRGB(targetType, attachment);
1300         message.str("");
1301         message << "getFramebufferAttachmentParameteriv() check = ";
1302         if (fboAttachmentSRGB)
1303                 message << "GL_SRGB";
1304         else
1305                 message << "GL_LINEAR";
1306         log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
1307
1308         message.str("");
1309         message << "Framebuffer color attachment value BEFORE draw call";
1310         logColor(m_context, message.str(), m_resultsListPreDraw[m_renderPass]);
1311
1312         message.str("");
1313         message << "Framebuffer color attachment value AFTER draw call";
1314         logColor(m_context, message.str(), m_resultsListPostDraw[m_renderPass]);
1315
1316         message.str("");
1317         message << "Sampling type = ";
1318         std::string type;
1319         if (samplingType == 0)
1320                 type = "texture()";
1321         else if (samplingType == 1)
1322                 type = "textureLOD()";
1323         else if (samplingType == 2)
1324                 type = "textureGrad()";
1325         else if (samplingType == 3)
1326                 type = "textureOffset()";
1327         else if (samplingType == 4)
1328                 type = "textureProj()";
1329         else
1330                 DE_FATAL("Error: Sampling type unregonised");
1331         message << type;
1332         log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
1333
1334         message.str("");
1335         if (m_framebufferSRGBEnabled)
1336                 message << "Framebuffer SRGB = enabled";
1337         else
1338                 message << "Framebuffer SRGB = disabled";
1339         log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
1340 }
1341
1342 class FboSRGBTestCase : public TestCase
1343 {
1344 public:
1345                                                                                         FboSRGBTestCase                         (Context& context, const char* const name, const char* const desc);
1346                                                                                         ~FboSRGBTestCase                        (void);
1347
1348         void                                                                    init                                            (void);
1349         void                                                                    deinit                                          (void);
1350         IterateResult                                                   iterate                                         (void);
1351
1352         void                                                                    setTestConfig                           (std::vector<TestRenderPassConfig> renderPassConfigList);
1353
1354         virtual void                                                    setupTest                                       (void) = 0;
1355         virtual bool                                                    verifyResult                            (void) = 0;
1356
1357 protected:
1358         bool                                                                    m_hasTestConfig;
1359         std::vector<TestRenderPassConfig>               m_renderPassConfigList;
1360         bool                                                                    m_testcaseRequiresBlend;
1361         std::vector<tcu::Vec4>                                  m_resultsPreDraw;
1362         std::vector<tcu::Vec4>                                  m_resultsPostDraw;
1363
1364 private:
1365                                                                                         FboSRGBTestCase                         (const FboSRGBTestCase&);
1366         FboSRGBTestCase&                                                operator=                                       (const FboSRGBTestCase&);
1367 };
1368
1369 FboSRGBTestCase::FboSRGBTestCase        (Context& context, const char* const name, const char* const desc)
1370         : TestCase                                              (context, name, desc)
1371         , m_hasTestConfig                               (false)
1372 {
1373 }
1374
1375 FboSRGBTestCase::~FboSRGBTestCase (void)
1376 {
1377         FboSRGBTestCase::deinit();
1378 }
1379
1380 void FboSRGBTestCase::init (void)
1381 {
1382         // extensions requirements for test
1383         if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
1384                 TCU_THROW(NotSupportedError, "Test requires a context version equal or higher than 3.2");
1385
1386         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control"))
1387                 TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control");
1388
1389         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_decode"))
1390                 TCU_THROW(NotSupportedError, "Test requires GL_EXT_texture_sRGB_decode extension");
1391 }
1392
1393 void FboSRGBTestCase::deinit (void)
1394 {
1395 }
1396
1397 FboSRGBTestCase::IterateResult FboSRGBTestCase::iterate (void)
1398 {
1399         this->setupTest();
1400
1401         DE_ASSERT(m_hasTestConfig && "Error: Renderer was not supplied a test config");
1402
1403         Renderer renderer(m_context);
1404
1405         // loop through each sampling type
1406         for (int samplingIdx = 0; samplingIdx < SampligTypeCount::MAX; samplingIdx++)
1407         {
1408                 renderer.setSamplingType(static_cast<SamplingType>(samplingIdx));
1409
1410                 // loop through each blend configuration
1411                 const int blendCount = renderer.getBlendConfigCount();
1412                 for (int blendIdx = 0; blendIdx < blendCount; blendIdx++)
1413                 {
1414                         // loop through each render pass
1415                         const int renderPassCount = (int)m_renderPassConfigList.size();
1416                         for (int renderPassIdx = 0; renderPassIdx < renderPassCount; renderPassIdx++)
1417                         {
1418                                 TestRenderPassConfig renderPassConfig = m_renderPassConfigList[renderPassIdx];
1419
1420                                 renderer.init(renderPassConfig, renderPassIdx);
1421
1422                                 if (blendIdx == 0 && renderPassConfig.rendererTask == RENDERERTASK_DRAW)
1423                                         renderer.storeShaderProgramInfo();
1424
1425                                 if (renderPassConfig.frameBufferBlend == FRAMEBUFFERBLEND_ENABLED)
1426                                 {
1427                                         renderer.setBlendIteration(blendIdx);
1428                                         renderer.setFramebufferBlend(true);
1429                                 }
1430                                 else
1431                                         renderer.setFramebufferBlend(false);
1432
1433                                 if (renderPassConfig.framebufferSRGB == FRAMEBUFFERSRGB_ENABLED)
1434                                         renderer.setFramebufferSRGB(true);
1435                                 else
1436                                         renderer.setFramebufferSRGB(false);
1437
1438                                 if (renderPassConfig.rendererTask == RENDERERTASK_DRAW)
1439                                         renderer.draw();
1440                                 else if (renderPassConfig.rendererTask == RENDERERTASK_COPY)
1441                                         renderer.copyFrameBufferTexture(0, 0, 0, 0);
1442                                 else
1443                                         DE_FATAL("Error: render task not recognised");
1444
1445                                 renderer.deinit();
1446
1447                         } // render passes
1448
1449                         m_resultsPreDraw = renderer.getResultsPreDraw();
1450                         m_resultsPostDraw = renderer.getResultsPostDraw();
1451
1452                         bool testPassed = this->verifyResult();
1453                         if (testPassed)
1454                                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1455                         else
1456                         {
1457                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
1458                                 renderer.logShaderProgramInfo();
1459                                 return STOP;
1460                         }
1461
1462                         if (!m_testcaseRequiresBlend)
1463                                 break;
1464                 } // blend configs
1465
1466                 renderer.logShaderProgramInfo();
1467         } // sampling types
1468
1469         return STOP;
1470 }
1471
1472 void FboSRGBTestCase::setTestConfig (std::vector<TestRenderPassConfig> renderPassConfigList)
1473 {
1474         m_renderPassConfigList = renderPassConfigList;
1475         m_hasTestConfig = true;
1476
1477         for (int idx = 0; idx < (int)renderPassConfigList.size(); idx++)
1478         {
1479                 if (renderPassConfigList[idx].frameBufferBlend == FRAMEBUFFERBLEND_ENABLED)
1480                 {
1481                         m_testcaseRequiresBlend = true;
1482                         return;
1483                 }
1484         }
1485         m_testcaseRequiresBlend = false;
1486 }
1487
1488 class FboSRGBQueryCase : public TestCase
1489 {
1490 public:
1491                                         FboSRGBQueryCase        (Context& context, const char* const name, const char* const description);
1492                                         ~FboSRGBQueryCase       (void);
1493
1494         void                    init                            (void);
1495         void                    deinit                          (void);
1496         IterateResult   iterate                         (void);
1497 };
1498
1499 FboSRGBQueryCase::FboSRGBQueryCase      (Context& context, const char* const name, const char* const description)
1500         : TestCase                                              (context, name, description)
1501 {
1502 }
1503
1504 FboSRGBQueryCase::~FboSRGBQueryCase (void)
1505 {
1506         FboSRGBQueryCase::deinit();
1507 }
1508
1509 void FboSRGBQueryCase::init (void)
1510 {
1511         // extension requirements for test
1512         if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) && !m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control"))
1513                 TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control or a context version equal or higher than 3.2");
1514 }
1515
1516 void FboSRGBQueryCase::deinit (void)
1517 {
1518 }
1519
1520 FboSRGBQueryCase::IterateResult FboSRGBQueryCase::iterate (void)
1521 {
1522         // TEST INFO:
1523         // API tests which check when querying FRAMEBUFFER_SRGB_EXT capability returns the correct information when using glEnabled() or glDisabled()
1524
1525         const glw::Functions&   gl              = m_context.getRenderContext().getFunctions();
1526         tcu::TestLog&                   log             = m_context.getTestContext().getLog();
1527         const char*     const           msgPart = ", after disabling = ";
1528
1529         for (int idx = 0; idx < static_cast<int>(QUERYTYPE_LAST); idx++)
1530         {
1531                 std::ostringstream      message;
1532                 bool                            pass            = false;
1533
1534                 message << std::string("Results: After Enabling = ");
1535
1536                 gl.enable(GL_FRAMEBUFFER_SRGB);
1537
1538                 switch (static_cast<QueryType>(idx))
1539                 {
1540                         case QUERYTYPE_ISENABLED:
1541                         {
1542                                 glw::GLboolean enabled[2];
1543                                 enabled[0] = gl.isEnabled(GL_FRAMEBUFFER_SRGB);
1544                                 gl.disable(GL_FRAMEBUFFER_SRGB);
1545                                 enabled[1] = gl.isEnabled(GL_FRAMEBUFFER_SRGB);
1546
1547                                 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
1548                                 pass = (enabled[0] && !(enabled[1])) ? true : false;
1549                                 break;
1550                         }
1551                         case QUERYTYPE_BOOLEAN:
1552                         {
1553                                 glw::GLboolean enabled[2];
1554                                 gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[0]);
1555                                 gl.disable(GL_FRAMEBUFFER_SRGB);
1556                                 gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[1]);
1557
1558                                 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
1559                                 pass = (enabled[0] && !(enabled[1])) ? true : false;
1560                                 break;
1561                         }
1562                         case QUERYTYPE_FLOAT:
1563                         {
1564                                 glw::GLfloat enabled[2];
1565                                 gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[0]);
1566                                 gl.disable(GL_FRAMEBUFFER_SRGB);
1567                                 gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[1]);
1568
1569                                 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
1570                                 pass = ((int)enabled[0] && !((int)enabled[1])) ? true : false;
1571                                 break;
1572                         }
1573                         case QUERYTYPE_INT:
1574                         {
1575                                 glw::GLint enabled[2];
1576                                 gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[0]);
1577                                 gl.disable(GL_FRAMEBUFFER_SRGB);
1578                                 gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[1]);
1579
1580                                 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
1581                                 pass = (enabled[0] && !(enabled[1])) ? true : false;
1582                                 break;
1583                         }
1584                         case QUERYTYPE_INT64:
1585                         {
1586                                 glw::GLint64 enabled[2];
1587                                 gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[0]);
1588                                 gl.disable(GL_FRAMEBUFFER_SRGB);
1589                                 gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[1]);
1590
1591                                 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
1592                                 pass = (enabled[0] && !(enabled[1])) ? true : false;
1593                                 break;
1594                         }
1595                         default:
1596                                 DE_FATAL("Error: Datatype not recognised");
1597                 }
1598
1599                 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
1600
1601                 if (pass)
1602                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1603                 else
1604                 {
1605                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
1606                         return STOP;
1607                 }
1608         }
1609         return STOP;
1610 }
1611
1612 class FboSRGBColAttachCase : public FboSRGBTestCase
1613 {
1614 public:
1615                         FboSRGBColAttachCase    (Context& context, const char* const name, const char* const description)
1616                                 : FboSRGBTestCase       (context, name, description) {}
1617                         ~FboSRGBColAttachCase   (void) {}
1618
1619         void    setupTest                               (void);
1620         bool    verifyResult                    (void);
1621 };
1622
1623 void FboSRGBColAttachCase::setupTest (void)
1624 {
1625         // TEST INFO:
1626         // Check if FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING  set to SRGB and FRAMEBUFFER_SRGB_EXT enabled, destination colors are converted from SRGB to linear
1627         // before and after blending, finally the result is converted back to SRGB for storage
1628
1629         // NOTE:
1630         // if fbo pre-draw color set to linaer, color values get linearlized "twice"
1631         // (0.2f, 0.3f, 0.4f, 1.0f) when sampled i.e. converted in shader = (0.0331048f, 0.073239f, 0.132868f)
1632         // resulting in the follolwing blending equation (0.2f, 0.3f, 0.4f 1.0f) + (0.0331048, 0.073239, 0.132868) = (0.521569f, 0.647059f, 0.756863f, 1.0f)
1633
1634         FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE);
1635         FBOConfig fboConfig1 = FBOConfig(GL_RGBA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE);
1636
1637         const TestRenderPassConfig renderPassConfigs[] =
1638         {
1639                 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_ENABLED, RENDERERTASK_DRAW),
1640                 TestRenderPassConfig(TEXTURESOURCESTYPE_BOTH, fboConfig1, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, getFunctionBlendLinearToSRGBCheck(), RENDERERTASK_DRAW)
1641         };
1642         std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
1643
1644         this->setTestConfig(renderPassConfigList);
1645 }
1646
1647 bool FboSRGBColAttachCase::verifyResult (void)
1648 {
1649         if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], m_resultsPostDraw[1])))
1650                 return true;
1651         else
1652                 return false;
1653 }
1654
1655 class FboSRGBToggleBlendCase : public FboSRGBTestCase
1656 {
1657 public:
1658                         FboSRGBToggleBlendCase          (Context& context, const char* const name, const char* const description)
1659                                 : FboSRGBTestCase               (context, name, description) {}
1660                         ~FboSRGBToggleBlendCase         (void) {}
1661
1662         void    setupTest                                       (void);
1663         bool    verifyResult                            (void);
1664 };
1665
1666 void FboSRGBToggleBlendCase::setupTest (void)
1667 {
1668         //      TEST INFO:
1669         //      Test to check if changing FRAMEBUFFER_SRGB_EXT from enabled to disabled. Enabled should produce SRGB color whilst disabled
1670         //      should produce linear color. Test conducted with blending disabled.
1671
1672         FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION);
1673
1674         const TestRenderPassConfig renderPassConfigs[] =
1675         {
1676                 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED,  FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW),
1677                 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW)
1678         };
1679         std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
1680
1681         this->setTestConfig(renderPassConfigList);
1682 }
1683
1684 bool FboSRGBToggleBlendCase::verifyResult (void)
1685 {
1686         if (tcu::boolAny(tcu::greaterThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError())))
1687                 return true;
1688         else
1689                 return false;
1690 }
1691
1692 class FboSRGBRenderTargetIgnoreCase : public FboSRGBTestCase
1693 {
1694 public:
1695                         FboSRGBRenderTargetIgnoreCase           (Context& context, const char* const name, const char* const description)
1696                                 : FboSRGBTestCase                               (context, name, description) {}
1697                         ~FboSRGBRenderTargetIgnoreCase          (void) {}
1698
1699         void    setupTest                                                       (void);
1700         bool    verifyResult                                            (void);
1701 };
1702
1703 void FboSRGBRenderTargetIgnoreCase::setupTest (void)
1704 {
1705         // TEST INFO:
1706         // Check if render targets that are non-RGB ignore the state of GL_FRAMEBUFFER_SRGB_EXT. Rendering to an fbo with non-sRGB color
1707         // attachment should ignore color space conversion, producing linear color.
1708
1709         FBOConfig fboConfig0 = FBOConfig(GL_RGBA8, getTestColorBlank(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION);
1710
1711         const TestRenderPassConfig renderPassConfigs[] =
1712         {
1713                 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED,  FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW)
1714
1715         };
1716         std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
1717
1718         this->setTestConfig(renderPassConfigList);
1719 }
1720
1721 bool FboSRGBRenderTargetIgnoreCase::verifyResult (void)
1722 {
1723         if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], getTestColorLinear())))
1724                 return true;
1725         else
1726                 return false;
1727 }
1728
1729 class FboSRGBCopyToLinearCase : public FboSRGBTestCase
1730 {
1731 public:
1732                         FboSRGBCopyToLinearCase         (Context& context, const char* const name, const char* const description)
1733                                 : FboSRGBTestCase               (context, name, description) {}
1734                         ~FboSRGBCopyToLinearCase        (void) {}
1735
1736         void    setupTest                                       (void);
1737         bool    verifyResult                            (void);
1738 };
1739
1740 void FboSRGBCopyToLinearCase::setupTest (void)
1741 {
1742         // TEST INFO:
1743         // Check if copying from an fbo with an sRGB color attachment to an fbo with a linear color attachment with FRAMEBUFFER_EXT enabled results in
1744         // an sRGB to linear conversion
1745
1746         FBOConfig fboConfigs[] =
1747         {
1748                 FBOConfig(GL_SRGB8_ALPHA8, getTestColorSRGB(), GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE),
1749                 FBOConfig(GL_RGBA8, getTestColorBlank(), GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION)
1750         };
1751         std::vector<FBOConfig> fboConfigList(fboConfigs, fboConfigs + DE_LENGTH_OF_ARRAY(fboConfigs));
1752
1753         const TestRenderPassConfig renderPassConfigs[] =
1754         {
1755                 TestRenderPassConfig(TEXTURESOURCESTYPE_NONE, fboConfigList, FRAMEBUFFERSRGB_ENABLED,  FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_COPY)
1756         };
1757         std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
1758
1759         this->setTestConfig(renderPassConfigList);
1760 }
1761
1762 bool FboSRGBCopyToLinearCase::verifyResult (void)
1763 {
1764         logColor(m_context, "pre-copy source fbo color values", m_resultsPreDraw[0]);
1765         logColor(m_context, "pre-copy destination fbo color values", m_resultsPreDraw[1]);
1766         logColor(m_context, "post-copy source fbo color values", m_resultsPostDraw[0]);
1767         logColor(m_context, "post-copy destination fbo color values", m_resultsPostDraw[1]);
1768
1769         if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[1] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[1], getTestColorLinear())))
1770                 return true;
1771         else
1772                 return false;
1773 }
1774
1775 class FboSRGBUnsupportedEnumCase : public TestCase
1776 {
1777 public:
1778                                         FboSRGBUnsupportedEnumCase      (Context& context, const char* const name, const char* const description);
1779                                         ~FboSRGBUnsupportedEnumCase     (void);
1780
1781         void                    init                                            (void);
1782         void                    deinit                                          (void);
1783         bool                    isInvalidEnum                           (std::string functionName);
1784         IterateResult   iterate                                         (void);
1785 };
1786
1787 FboSRGBUnsupportedEnumCase::FboSRGBUnsupportedEnumCase  (Context& context, const char* const name, const char* const description)
1788         : TestCase                                              (context, name, description)
1789 {
1790 }
1791
1792 FboSRGBUnsupportedEnumCase::~FboSRGBUnsupportedEnumCase (void)
1793 {
1794         FboSRGBUnsupportedEnumCase::deinit();
1795 }
1796
1797 void FboSRGBUnsupportedEnumCase::init (void)
1798 {
1799         // extension requirements for test
1800         if (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) || m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control"))
1801                 TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control to be unsupported and a context version less than 3.2");
1802 }
1803
1804 void FboSRGBUnsupportedEnumCase::deinit (void)
1805 {
1806 }
1807
1808 bool FboSRGBUnsupportedEnumCase::isInvalidEnum (std::string functionName)
1809 {
1810         const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
1811         tcu::TestLog&                   log                     = m_context.getTestContext().getLog();
1812         bool                                    isOk            = true;
1813         glw::GLenum                             error           = GL_NO_ERROR;
1814
1815         log << tcu::TestLog::Message << "Checking call to " << functionName << tcu::TestLog::EndMessage;
1816
1817         error = gl.getError();
1818
1819         if (error != GL_INVALID_ENUM)
1820         {
1821                 log << tcu::TestLog::Message << " returned wrong value [" << glu::getErrorStr(error) << ", expected " << glu::getErrorStr(GL_INVALID_ENUM) << "]" << tcu::TestLog::EndMessage;
1822                 isOk = false;
1823         }
1824
1825         return isOk;
1826 }
1827
1828 FboSRGBUnsupportedEnumCase::IterateResult FboSRGBUnsupportedEnumCase::iterate (void)
1829 {
1830         // TEST INFO:
1831         // API tests that check calls using enum GL_FRAMEBUFFER_SRGB return GL_INVALID_ENUM  when GL_EXT_sRGB_write_control is not supported
1832
1833         const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
1834         bool                                    allPass         = true;
1835         glw::GLboolean                  bEnabled        = GL_FALSE;
1836         glw::GLfloat                    fEnabled        = 0;
1837         glw::GLint                              iEnabled        = 0;
1838         glw::GLint64                    lEnabled        = 0;
1839
1840         m_context.getTestContext().getLog() << tcu::TestLog::Message
1841                                                                                 << "Check calls using enum GL_FRAMEBUFFER_SRGB return GL_INVALID_ENUM  when GL_EXT_sRGB_write_control is not supported\n\n"
1842                                                                                 << tcu::TestLog::EndMessage;
1843
1844         gl.enable(GL_FRAMEBUFFER_SRGB);
1845         allPass &= isInvalidEnum("glEnable()");
1846
1847         gl.disable(GL_FRAMEBUFFER_SRGB);
1848         allPass &= isInvalidEnum("glDisable()");
1849
1850         gl.isEnabled(GL_FRAMEBUFFER_SRGB);
1851         allPass &= isInvalidEnum("glIsEnabled()");
1852
1853         gl.getBooleanv(GL_FRAMEBUFFER_SRGB, &bEnabled);
1854         allPass &= isInvalidEnum("glGetBooleanv()");
1855
1856         gl.getFloatv(GL_FRAMEBUFFER_SRGB, &fEnabled);
1857         allPass &= isInvalidEnum("glGetFloatv()");
1858
1859         gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &iEnabled);
1860         allPass &= isInvalidEnum("glGetIntegerv()");
1861
1862         gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &lEnabled);
1863         allPass &= isInvalidEnum("glGetInteger64v()");
1864
1865         if (allPass)
1866                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1867         else
1868                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1869
1870         return STOP;
1871 }
1872
1873 } // anonymous
1874
1875 FboSRGBWriteControlTests::FboSRGBWriteControlTests      (Context& context)
1876         : TestCaseGroup                 (context, "srgb_write_control", "Colorbuffer tests")
1877 {
1878 }
1879
1880 FboSRGBWriteControlTests::~FboSRGBWriteControlTests (void)
1881 {
1882 }
1883
1884 void FboSRGBWriteControlTests::init (void)
1885 {
1886         this->addChild(new FboSRGBQueryCase                                     (m_context, "framebuffer_srgb_enabled",                                                 "srgb enable framebuffer"));
1887         this->addChild(new FboSRGBColAttachCase                         (m_context, "framebuffer_srgb_enabled_col_attach",                              "srgb enable color attachment and framebuffer"));
1888         this->addChild(new FboSRGBToggleBlendCase                       (m_context, "framebuffer_srgb_enabled_blend",                                   "toggle framebuffer srgb settings with blend disabled"));
1889         this->addChild(new FboSRGBRenderTargetIgnoreCase        (m_context, "framebuffer_srgb_enabled_render_target_ignore",    "enable framebuffer srgb, non-srgb render target should ignore"));
1890         this->addChild(new FboSRGBCopyToLinearCase                      (m_context, "framebuffer_srgb_enabled_copy_to_linear",                  "no conversion when blittering between framebuffer srgb and linear"));
1891
1892         // negative
1893         this->addChild(new FboSRGBUnsupportedEnumCase           (m_context, "framebuffer_srgb_unsupported_enum",                                "check error codes for query functions when extension is not supported"));
1894 }
1895
1896 }
1897 } // gles31
1898 } // deqp