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