Merge Vulkan CTS 1.0.2.2 into goog/oc-dev
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fSRGBDecodeTests.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 Texture format tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es31fSRGBDecodeTests.hpp"
25 #include "gluContextInfo.hpp"
26 #include "gluCallLogWrapper.hpp"
27 #include "gluRenderContext.hpp"
28 #include "gluTexture.hpp"
29 #include "glsTextureTestUtil.hpp"
30 #include "tcuPixelFormat.hpp"
31 #include "tcuTestContext.hpp"
32 #include "tcuRenderTarget.hpp"
33 #include "gluTextureUtil.hpp"
34 #include "tcuTextureUtil.hpp"
35 #include "glwFunctions.hpp"
36 #include "gluDefs.hpp"
37 #include "glwEnums.hpp"
38 #include "deUniquePtr.hpp"
39 #include "gluPixelTransfer.hpp"
40 #include "tcuDefs.hpp"
41 #include "tcuVectorUtil.hpp"
42 #include "gluObjectWrapper.hpp"
43 #include "gluStrUtil.hpp"
44 #include "tcuTestLog.hpp"
45
46 namespace deqp
47 {
48 namespace gles31
49 {
50 namespace Functional
51 {
52 namespace
53 {
54
55 using glu::TextureTestUtil::TEXTURETYPE_2D;
56
57 enum SRGBDecode
58 {
59         SRGBDECODE_SKIP_DECODE          = 0,
60         SRGBDECODE_DECODE,
61         SRGBDECODE_DECODE_DEFAULT
62 };
63
64 enum ShaderOutputs
65 {
66         SHADEROUTPUTS_ONE       = 1,
67         SHADEROUTPUTS_TWO,
68 };
69
70 enum ShaderUniforms
71 {
72         SHADERUNIFORMS_ONE      = 1,
73         SHADERUNIFORMS_TWO,
74 };
75
76 enum ShaderSamplingGroup
77 {
78         SHADERSAMPLINGGROUP_TEXTURE             = 0,
79         SHADERSAMPLINGGROUP_TEXEL_FETCH
80 };
81
82 enum ShaderSamplingType
83 {
84         TEXTURESAMPLING_TEXTURE                                                                                                 = 0,
85         TEXTURESAMPLING_TEXTURE_LOD,
86         TEXTURESAMPLING_TEXTURE_GRAD,
87         TEXTURESAMPLING_TEXTURE_OFFSET,
88         TEXTURESAMPLING_TEXTURE_PROJ,
89         TEXTURESAMPLING_TEXELFETCH,
90         TEXTURESAMPLING_TEXELFETCH_OFFSET,
91
92         // ranges required for looping mechanism in a case nodes iteration function
93         TEXTURESAMPLING_TEXTURE_START           = TEXTURESAMPLING_TEXTURE,
94         TEXTURESAMPLING_TEXTURE_END                     = TEXTURESAMPLING_TEXTURE_PROJ          + 1,
95         TEXTURESAMPLING_TEXELFETCH_START        = TEXTURESAMPLING_TEXELFETCH,
96         TEXTURESAMPLING_TEXELFETCH_END          = TEXTURESAMPLING_TEXELFETCH_OFFSET     + 1
97 };
98
99 enum FunctionParameters
100 {
101         FUNCTIONPARAMETERS_ONE = 1,
102         FUNCTIONPARAMETERS_TWO
103 };
104
105 enum Blending
106 {
107         BLENDING_REQUIRED               = 0,
108         BLENDING_NOT_REQUIRED
109 };
110
111 enum Toggling
112 {
113         TOGGLING_REQUIRED               = 0,
114         TOGGLING_NOT_REQUIRED
115 };
116
117 tcu::Vec4 getColorReferenceLinear (void)
118 {
119         return tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f);
120 }
121
122 tcu::Vec4 getColorReferenceSRGB (void)
123 {
124         return tcu::linearToSRGB(tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f));
125 }
126
127 tcu::Vec4 getColorGreenPass (void)
128 {
129         return tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
130 }
131
132 namespace TestDimensions
133 {
134         const int WIDTH         = 128;
135         const int HEIGHT        = 128;
136 } // global test texture dimensions
137
138 namespace TestSamplingPositions
139 {
140         const int X_POS = 0;
141         const int Y_POS = 0;
142 } // global test sampling positions
143
144 const char* getFunctionDefinitionSRGBToLinearCheck (void)
145 {
146         static const char* functionDefinition =
147                         "mediump vec4 srgbToLinearCheck(in mediump vec4 texelSRGBA, in mediump vec4 texelLinear) \n"
148                         "{ \n"
149                         "       const int NUM_CHANNELS = 4;"
150                         "       mediump vec4 texelSRGBAConverted; \n"
151                         "       mediump vec4 epsilonErr = vec4(0.005); \n"
152                         "       mediump vec4 testResult; \n"
153                         "       for (int idx = 0; idx < NUM_CHANNELS; idx++) \n"
154                         "       { \n"
155                         "               texelSRGBAConverted[idx] = pow( (texelSRGBA[idx] + 0.055) / 1.055, 1.0 / 0.4116); \n"
156                         "       } \n"
157                         "       if ( all(lessThan(abs(texelSRGBAConverted - texelLinear), epsilonErr)) || all(equal(texelSRGBAConverted, texelLinear)) ) \n"
158                         "       { \n"
159                         "               return testResult = vec4(0.0, 1.0, 0.0, 1.0); \n"
160                         "       } \n"
161                         "       else \n"
162                         "       { \n"
163                         "               return testResult = vec4(1.0, 0.0, 0.0, 1.0); \n"
164                         "       } \n"
165                         "} \n";
166
167         return functionDefinition;
168 }
169
170 const char* getFunctionDefinitionEqualCheck (void)
171 {
172         static const char* functionDefinition =
173                         "mediump vec4 colorsEqualCheck(in mediump vec4 colorA, in mediump vec4 colorB) \n"
174                         "{ \n"
175                         "       mediump vec4 epsilonErr = vec4(0.005); \n"
176                         "       mediump vec4 testResult; \n"
177                         "       if ( all(lessThan(abs(colorA - colorB), epsilonErr)) || all(equal(colorA, colorB)) ) \n"
178                         "       { \n"
179                         "               return testResult = vec4(0.0, 1.0, 0.0, 1.0); \n"
180                         "       } \n"
181                         "       else \n"
182                         "       { \n"
183                         "               return testResult = vec4(1.0, 0.0, 0.0, 1.0); \n"
184                         "       } \n"
185                         "} \n";
186
187         return functionDefinition;
188 }
189
190 namespace EpsilonError
191 {
192         const float CPU = 0.005f;
193 }
194
195 struct TestGroupConfig
196 {
197         TestGroupConfig                 (const char* groupName, const char* groupDescription, const tcu::TextureFormat groupInternalFormat)
198                 : name                          (groupName)
199                 , description           (groupDescription)
200                 , internalFormat        (groupInternalFormat) {}
201
202         ~TestGroupConfig                (void) {};
203
204         const char*                                     name;
205         const char*                                     description;
206         const tcu::TextureFormat        internalFormat;
207 };
208
209 struct UniformData
210 {
211         UniformData                     (glw::GLuint uniformLocation, const std::string& uniformName)
212                 : location              (uniformLocation)
213                 , name                  (uniformName)
214                 , toggleDecode  (false) {}
215
216         ~UniformData            (void) {}
217
218         glw::GLuint     location;
219         std::string     name;
220         bool            toggleDecode;
221 };
222
223 struct UniformToToggle
224 {
225         UniformToToggle         (const int uniformProgramIdx, const std::string& uniformName)
226                 : programIdx    (uniformProgramIdx)
227                 , name                  (uniformName) {}
228
229         ~UniformToToggle        (void) {}
230
231         int                     programIdx;
232         std::string     name;
233 };
234
235 struct ComparisonFunction
236 {
237         ComparisonFunction              (const std::string& funcName, const FunctionParameters funcParameters, const std::string& funcImplementation)
238                 : name                          (funcName)
239                 , parameters            (funcParameters)
240                 , implementation        (funcImplementation) {}
241
242         ~ComparisonFunction             (void) {}
243
244         std::string                     name;
245         FunctionParameters      parameters;
246         std::string                     implementation;
247 };
248
249 struct FragmentShaderParameters
250 {
251         FragmentShaderParameters        (const ShaderOutputs    outputTotal,
252                                                                  const ShaderUniforms   uniformTotal,
253                                                                  ComparisonFunction*    comparisonFunction,
254                                                                  Blending                               blendRequired,
255                                                                  Toggling                               toggleRequired);
256
257         ~FragmentShaderParameters       (void);
258
259         ShaderOutputs                           outputTotal;
260         ShaderUniforms                          uniformTotal;
261         ShaderSamplingType                      samplingType;
262         std::string                                     functionName;
263         FunctionParameters                      functionParameters;
264         std::string                                     functionImplementation;
265         bool                                            hasFunction;
266         Blending                                        blendRequired;
267         Toggling                                        toggleRequired;
268         std::vector<std::string>        uniformsToToggle;
269 };
270
271 FragmentShaderParameters::FragmentShaderParameters      (const ShaderOutputs    paramsOutputTotal,
272                                                                                                          const ShaderUniforms   paramsUniformTotal,
273                                                                                                          ComparisonFunction*    paramsComparisonFunction,
274                                                                                                          Blending                               paramsBlendRequired,
275                                                                                                          Toggling                               paramsToggleRequired)
276         : outputTotal                                                                   (paramsOutputTotal)
277         , uniformTotal                                                                  (paramsUniformTotal)
278         , blendRequired                                                                 (paramsBlendRequired)
279         , toggleRequired                                                                (paramsToggleRequired)
280 {
281         if (paramsComparisonFunction != DE_NULL)
282         {
283                 functionName                    = paramsComparisonFunction->name;
284                 functionParameters              = paramsComparisonFunction->parameters;
285                 functionImplementation  = paramsComparisonFunction->implementation;
286
287                 hasFunction = true;
288         }
289         else
290         {
291                 hasFunction = false;
292         }
293 }
294
295 FragmentShaderParameters::~FragmentShaderParameters (void)
296 {
297 }
298
299 class SRGBTestSampler
300 {
301 public:
302                                 SRGBTestSampler         (Context&                                               context,
303                                                                          const tcu::Sampler::WrapMode   wrapS,
304                                                                          const tcu::Sampler::WrapMode   wrapT,
305                                                                          const tcu::Sampler::FilterMode minFilter,
306                                                                          const tcu::Sampler::FilterMode magFilter,
307                                                                          const SRGBDecode                               decoding);
308                                 ~SRGBTestSampler        (void);
309
310         void            setDecode                       (const SRGBDecode decoding);
311         void            setTextureUnit          (const deUint32 textureUnit);
312         void            setIsActive                     (const bool isActive);
313
314         deUint32        getHandle                       (void) const;
315         bool            getIsActive                     (void) const;
316
317         void            bindToTexture           (void);
318         void            unbindFromTexture       (void);
319
320 private:
321         const glw::Functions*           m_gl;
322         deUint32                                        m_samplerHandle;
323         tcu::Sampler::WrapMode          m_wrapS;
324         tcu::Sampler::WrapMode          m_wrapT;
325         tcu::Sampler::FilterMode        m_minFilter;
326         tcu::Sampler::FilterMode        m_magFilter;
327         SRGBDecode                                      m_decoding;
328         deUint32                                        m_textureUnit;
329         bool                                            m_isActive;
330 };
331
332 SRGBTestSampler::SRGBTestSampler        (Context&                                               context,
333                                                                          const tcu::Sampler::WrapMode   wrapS,
334                                                                          const tcu::Sampler::WrapMode   wrapT,
335                                                                          const tcu::Sampler::FilterMode minFilter,
336                                                                          const tcu::Sampler::FilterMode magFilter,
337                                                                          const SRGBDecode                               decoding)
338         : m_gl                                                  (&context.getRenderContext().getFunctions())
339         , m_wrapS                                               (wrapS)
340         , m_wrapT                                               (wrapT)
341         , m_minFilter                                   (minFilter)
342         , m_magFilter                                   (magFilter)
343         , m_isActive                                    (false)
344 {
345         m_gl->genSamplers(1, &m_samplerHandle);
346
347         m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(m_wrapS));
348         m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(m_wrapT));
349         m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(m_minFilter));
350         m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(m_magFilter));
351
352         this->setDecode(decoding);
353 }
354
355 SRGBTestSampler::~SRGBTestSampler (void)
356 {
357         m_gl->deleteSamplers(1, &m_samplerHandle);
358 }
359
360 void SRGBTestSampler::setDecode (const SRGBDecode decoding)
361 {
362         if (decoding == SRGBDECODE_SKIP_DECODE)
363         {
364                 m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
365                 GLU_EXPECT_NO_ERROR(m_gl->getError(), "samplerParameteri(m_samplerID, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT)");
366         }
367         else if (decoding == SRGBDECODE_DECODE)
368         {
369                 m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
370                 GLU_EXPECT_NO_ERROR(m_gl->getError(), "samplerParameteri(m_samplerID, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)");
371         }
372         else
373         {
374                 DE_FATAL("sRGB texture sampler must have either GL_SKIP_DECODE_EXT or GL_DECODE_EXT settings");
375         }
376
377         m_decoding = decoding;
378 }
379
380 void SRGBTestSampler::setTextureUnit (const deUint32 textureUnit)
381 {
382         m_textureUnit = textureUnit;
383 }
384
385 void SRGBTestSampler::setIsActive (const bool isActive)
386 {
387         m_isActive = isActive;
388 }
389
390 deUint32 SRGBTestSampler::getHandle (void) const
391 {
392         return m_samplerHandle;
393 }
394
395 bool SRGBTestSampler::getIsActive (void) const
396 {
397         return m_isActive;
398 }
399
400 void SRGBTestSampler::bindToTexture (void)
401 {
402         m_gl->bindSampler(m_textureUnit, m_samplerHandle);
403 }
404
405 void SRGBTestSampler::unbindFromTexture (void)
406 {
407         m_gl->bindSampler(m_textureUnit, 0);
408 }
409
410 class SRGBTestTexture
411 {
412 public:
413                                 SRGBTestTexture         (Context&                                                                       context,
414                                                                          const glu::TextureTestUtil::TextureType        targetType,
415                                                                          const tcu::TextureFormat                                       internalFormat,
416                                                                          const int                                                                      width,
417                                                                          const int                                                                      height,
418                                                                          const tcu::Vec4                                                        color,
419                                                                          const tcu::Sampler::WrapMode                           wrapS,
420                                                                          const tcu::Sampler::WrapMode                           wrapT,
421                                                                          const tcu::Sampler::FilterMode                         minFilter,
422                                                                          const tcu::Sampler::FilterMode                         magFilter,
423                                                                          const SRGBDecode                                                       decoding);
424                                 ~SRGBTestTexture        (void);
425
426         void            setParameters           (void);
427         void            setDecode                       (const SRGBDecode decoding);
428         void            setHasSampler           (const bool hasSampler);
429
430         deUint32        getHandle                       (void) const;
431         deUint32        getGLTargetType         (void) const;
432         SRGBDecode      getDecode                       (void) const;
433         bool            getHasSampler           (void) const;
434
435         void            upload                          (void);
436
437 private:
438         void            setColor                        (void);
439
440         Context&                                                        m_context;
441         glu::Texture2D                                          m_source;
442         glu::TextureTestUtil::TextureType       m_targetType;
443         const tcu::TextureFormat                        m_internalFormat;
444         const int                                                       m_width;
445         const int                                                       m_height;
446         tcu::Vec4                                                       m_color;
447         tcu::Sampler::WrapMode                          m_wrapS;
448         tcu::Sampler::WrapMode                          m_wrapT;
449         tcu::Sampler::FilterMode                        m_minFilter;
450         tcu::Sampler::FilterMode                        m_magFilter;
451         SRGBDecode                                                      m_decoding;
452         bool                                                            m_hasSampler;
453 };
454
455 SRGBTestTexture::SRGBTestTexture        (Context&                                                                       context,
456                                                                          const glu::TextureTestUtil::TextureType        targetType,
457                                                                          const tcu::TextureFormat                                       internalFormat,
458                                                                          const int                                                                      width,
459                                                                          const int                                                                      height,
460                                                                          const tcu::Vec4                                                        color,
461                                                                          const tcu::Sampler::WrapMode                           wrapS,
462                                                                          const tcu::Sampler::WrapMode                           wrapT,
463                                                                          const tcu::Sampler::FilterMode                         minFilter,
464                                                                          const tcu::Sampler::FilterMode                         magFilter,
465                                                                          SRGBDecode                                                                     decoding)
466         : m_context                                             (context)
467         , m_source                                              (context.getRenderContext(), glu::getInternalFormat(internalFormat), width, height)
468         , m_targetType                                  (targetType)
469         , m_internalFormat                              (internalFormat)
470         , m_width                                               (width)
471         , m_height                                              (height)
472         , m_color                                               (color)
473         , m_wrapS                                               (wrapS)
474         , m_wrapT                                               (wrapT)
475         , m_minFilter                                   (minFilter)
476         , m_magFilter                                   (magFilter)
477         , m_decoding                                    (decoding)
478         , m_hasSampler                                  (false)
479 {
480         this->setColor();
481 }
482
483 SRGBTestTexture::~SRGBTestTexture (void)
484 {
485 }
486
487 void SRGBTestTexture::setParameters (void)
488 {
489         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
490
491         gl.bindTexture(this->getGLTargetType(), this->getHandle());
492
493         gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_WRAP_S, glu::getGLWrapMode(m_wrapS));
494         gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_WRAP_T, glu::getGLWrapMode(m_wrapT));
495         gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(m_minFilter));
496         gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(m_magFilter));
497
498         gl.bindTexture(this->getGLTargetType(), 0);
499
500         setDecode(m_decoding);
501 }
502
503 void SRGBTestTexture::setDecode (const SRGBDecode decoding)
504 {
505         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
506
507         gl.bindTexture(this->getGLTargetType(), this->getHandle());
508
509         switch (decoding)
510         {
511                 case SRGBDECODE_SKIP_DECODE:
512                 {
513                         gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
514                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT)");
515                         break;
516                 }
517                 case SRGBDECODE_DECODE:
518                 {
519                         gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
520                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)");
521                         break;
522                 }
523                 case SRGBDECODE_DECODE_DEFAULT:
524                 {
525                         // do not use srgb decode options. Set to default
526                         break;
527                 }
528                 default:
529                         DE_FATAL("Error: Decoding option not recognised");
530         }
531
532         gl.bindTexture(this->getGLTargetType(), 0);
533
534         m_decoding = decoding;
535 }
536
537 void SRGBTestTexture::setHasSampler (const bool hasSampler)
538 {
539         m_hasSampler = hasSampler;
540 }
541
542 deUint32 SRGBTestTexture::getHandle (void) const
543 {
544         return m_source.getGLTexture();
545 }
546
547 deUint32 SRGBTestTexture::getGLTargetType (void) const
548 {
549         switch (m_targetType)
550         {
551                 case TEXTURETYPE_2D:
552                 {
553                         return GL_TEXTURE_2D;
554                 }
555                 default:
556                 {
557                         DE_FATAL("Error: Target type not recognised");
558                         return -1;
559                 }
560         }
561 }
562
563 SRGBDecode SRGBTestTexture::getDecode (void) const
564 {
565         return m_decoding;
566 }
567
568 bool SRGBTestTexture::getHasSampler (void) const
569 {
570         return m_hasSampler;
571 }
572
573 void SRGBTestTexture::upload (void)
574 {
575         m_source.upload();
576 }
577
578 void SRGBTestTexture::setColor (void)
579 {
580         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
581
582         gl.bindTexture(this->getGLTargetType(), this->getHandle());
583
584         m_source.getRefTexture().allocLevel(0);
585
586         for (int py = 0; py < m_height; py++)
587         {
588                 for (int px = 0; px < m_width; px++)
589                 {
590                         m_source.getRefTexture().getLevel(0).setPixel(m_color, px, py);
591                 }
592         }
593
594         gl.bindTexture(this->getGLTargetType(), 0);
595 }
596
597 class SRGBTestProgram
598 {
599 public:
600                                                                         SRGBTestProgram                 (Context& context, const FragmentShaderParameters& shaderParameters);
601                                                                         ~SRGBTestProgram                (void);
602
603         void                                                    setBlendRequired                (bool blendRequired);
604         void                                                    setToggleRequired               (bool toggleRequired);
605         void                                                    setUniformToggle                (int location, bool toggleDecodeValue);
606
607         int                                                             getUniformTotal                 (void) const;
608         const std::vector<UniformData>& getUniformDataList              (void) const;
609         const UniformData&                              getUniformAtLocation    (int location) const;
610         int                                                             getUniformLocation              (const std::string& name);
611         deUint32                                                getHandle                               (void) const;
612         bool                                                    getBlendRequired                (void) const;
613         bool                                                    getToggleRequired               (void) const;
614         const std::string&                              getFragmentShader               (void) const;
615
616 private:
617         std::string                                             genFunctionCall                 (ShaderSamplingType samplingType, const int uniformIdx);
618         void                                                    genFragmentShader               (void);
619
620         Context&                                                m_context;
621         de::MovePtr<glu::ShaderProgram> m_program;
622         FragmentShaderParameters                m_shaderFragmentParameters;
623         std::string                                             m_shaderVertex;
624         std::string                                             m_shaderFragment;
625         std::vector<UniformData>                m_uniformDataList;
626         bool                                                    m_blendRequired;
627         bool                                                    m_toggleRequired;
628 };
629
630 SRGBTestProgram::SRGBTestProgram        (Context& context, const FragmentShaderParameters& shaderParameters)
631         : m_context                                             (context)
632         , m_shaderFragmentParameters    (shaderParameters)
633         , m_blendRequired                               (false)
634         , m_toggleRequired                              (false)
635 {
636         const glw::Functions&   gl                                      = m_context.getRenderContext().getFunctions();
637         tcu::TestLog&                   log                                     = m_context.getTestContext().getLog();
638         glu::ShaderProgramInfo  buildInfo;
639         const int                               totalShaderStages       = 2;
640
641         // default vertex shader used in all tests
642         m_shaderVertex =        "#version 310 es \n"
643                                                 "layout (location = 0) in mediump vec3 aPosition; \n"
644                                                 "layout (location = 1) in mediump vec2 aTexCoord; \n"
645                                                 "out mediump vec2 vs_aTexCoord; \n"
646                                                 "void main () \n"
647                                                 "{ \n"
648                                                 "       gl_Position = vec4(aPosition, 1.0); \n"
649                                                 "       vs_aTexCoord = aTexCoord; \n"
650                                                 "} \n";
651
652         this->genFragmentShader();
653
654         m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(m_shaderVertex, m_shaderFragment)));
655
656         if (!m_program->isOk())
657         {
658                 TCU_FAIL("Failed to compile shaders and link program");
659         }
660
661         glw::GLint activeUniforms, maxLen;
662         glw::GLint size, location;
663         glw::GLenum type;
664
665         gl.getProgramiv(this->getHandle(), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen);
666         gl.getProgramiv(this->getHandle(), GL_ACTIVE_UNIFORMS, &activeUniforms);
667
668         std::vector<glw::GLchar> uniformName(static_cast<int>(maxLen));
669         for (int idx = 0; idx < activeUniforms; idx++)
670         {
671                 gl.getActiveUniform(this->getHandle(), idx, maxLen, NULL, &size, &type, &uniformName[0]);
672                 location = gl.getUniformLocation(this->getHandle(), &uniformName[0]);
673
674                 UniformData uniformData(location, std::string(&uniformName[0], strlen(&uniformName[0])));
675                 m_uniformDataList.push_back(uniformData);
676         }
677
678         // log shader program info. Only vertex and fragment shaders included
679         buildInfo.program = m_program->getProgramInfo();
680         for (int shaderIdx = 0; shaderIdx < totalShaderStages; shaderIdx++)
681         {
682                 glu::ShaderInfo shaderInfo = m_program->getShaderInfo(static_cast<glu::ShaderType>(static_cast<int>(glu::SHADERTYPE_VERTEX) + static_cast<int>(shaderIdx)), 0);
683                 buildInfo.shaders.push_back(shaderInfo);
684         }
685
686         log << buildInfo;
687 }
688
689 SRGBTestProgram::~SRGBTestProgram (void)
690 {
691         m_program       = de::MovePtr<glu::ShaderProgram>(DE_NULL);
692 }
693
694 void SRGBTestProgram::setBlendRequired (bool blendRequired)
695 {
696         m_blendRequired = blendRequired;
697 }
698
699 void SRGBTestProgram::setToggleRequired (bool toggleRequired)
700 {
701         m_toggleRequired = toggleRequired;
702 }
703
704 void SRGBTestProgram::setUniformToggle (int location, bool toggleDecodeValue)
705 {
706         if ( (m_uniformDataList.empty() == false) && (location >= 0) && (location <= (int)m_uniformDataList.size()) )
707         {
708                 m_uniformDataList[location].toggleDecode = toggleDecodeValue;
709         }
710         else
711         {
712                 TCU_THROW(TestError, "Error: Uniform location not found. glGetActiveUniforms returned uniforms incorrectly ");
713         }
714 }
715
716 int SRGBTestProgram::getUniformTotal (void) const
717 {
718         return (int)m_uniformDataList.size();
719 }
720
721 const std::vector<UniformData>& SRGBTestProgram::getUniformDataList (void) const
722 {
723         return m_uniformDataList;
724 }
725
726 const UniformData& SRGBTestProgram::getUniformAtLocation (int location) const
727 {
728         return m_uniformDataList[location];
729 }
730
731 int SRGBTestProgram::getUniformLocation (const std::string& name)
732 {
733         for (std::size_t idx = 0; idx < m_uniformDataList.size(); idx++)
734         {
735                 if (m_uniformDataList[idx].name == name)
736                 {
737                         return m_uniformDataList[idx].location;
738                 }
739         }
740
741         TCU_THROW(TestError, "Error: If name correctly requested then glGetActiveUniforms() returned active uniform data incorrectly");
742         return -1;
743 }
744
745 glw::GLuint SRGBTestProgram::getHandle (void) const
746 {
747         return m_program->getProgram();
748 }
749
750 bool SRGBTestProgram::getBlendRequired (void) const
751 {
752         return m_blendRequired;
753 }
754
755 bool SRGBTestProgram::getToggleRequired (void) const
756 {
757         return m_toggleRequired;
758 }
759
760 const std::string& SRGBTestProgram::getFragmentShader (void) const
761 {
762         return m_shaderFragment;
763 }
764
765 std::string SRGBTestProgram::genFunctionCall (ShaderSamplingType samplingType, const int uniformIdx)
766 {
767         std::ostringstream functionCall;
768
769         functionCall << "       mediump vec4 texelColor" << uniformIdx << " = ";
770
771         switch (samplingType)
772                 {
773                         case TEXTURESAMPLING_TEXTURE:
774                         {
775                                 functionCall << "texture(uTexture" << uniformIdx << ", vs_aTexCoord); \n";
776                                 break;
777                         }
778                         case TEXTURESAMPLING_TEXTURE_LOD:
779                         {
780                                 functionCall << "textureLod(uTexture" << uniformIdx << ", vs_aTexCoord, 0.0); \n";
781                                 break;
782                         }
783                         case TEXTURESAMPLING_TEXTURE_GRAD:
784                         {
785                                 functionCall << "textureGrad(uTexture" << uniformIdx << ", vs_aTexCoord, vec2(0.0, 0.0), vec2(0.0, 0.0)); \n";
786                                 break;
787                         }
788                         case TEXTURESAMPLING_TEXTURE_OFFSET:
789                         {
790                                 functionCall << "textureOffset(uTexture" << uniformIdx << ", vs_aTexCoord, ivec2(0.0, 0.0)); \n";
791                                 break;
792                         }
793                         case TEXTURESAMPLING_TEXTURE_PROJ:
794                         {
795                                 functionCall << "textureProj(uTexture" << uniformIdx << ", vec3(vs_aTexCoord, 1.0)); \n";
796                                 break;
797                         }
798                         case TEXTURESAMPLING_TEXELFETCH:
799                         {
800                                 functionCall << "texelFetch(uTexture" << uniformIdx << ", ivec2(vs_aTexCoord), 0); \n";
801                                 break;
802                         }
803                         case TEXTURESAMPLING_TEXELFETCH_OFFSET:
804                         {
805                                 functionCall << "texelFetchOffset(uTexture" << uniformIdx << ", ivec2(vs_aTexCoord), 0, ivec2(0.0, 0.0)); \n";
806                                 break;
807                         }
808                         default:
809                         {
810                                 DE_FATAL("Error: Sampling type not recognised");
811                         }
812                 }
813
814         return functionCall.str();
815 }
816
817 void SRGBTestProgram::genFragmentShader (void)
818 {
819         std::ostringstream source;
820         std::ostringstream sampleTexture;
821         std::ostringstream functionParameters;
822         std::ostringstream shaderOutputs;
823
824         // if comparison function is present resulting shader requires precisely one output
825         DE_ASSERT( !(m_shaderFragmentParameters.hasFunction && (static_cast<int>(m_shaderFragmentParameters.outputTotal) != static_cast<int>(SHADEROUTPUTS_ONE))) );
826
827         // function parameters must equal the number of uniforms i.e. textures passed into the function
828         DE_ASSERT( !(m_shaderFragmentParameters.hasFunction && (static_cast<int>(m_shaderFragmentParameters.uniformTotal) != static_cast<int>(m_shaderFragmentParameters.functionParameters))) );
829
830         // fragment shader cannot contain more outputs than the number of texture uniforms
831         DE_ASSERT( !(static_cast<int>(m_shaderFragmentParameters.outputTotal) > static_cast<int>(m_shaderFragmentParameters.uniformTotal)) ) ;
832
833         source << "#version 310 es \n"
834                 << "in mediump vec2 vs_aTexCoord; \n";
835
836         for (int output = 0; output < m_shaderFragmentParameters.outputTotal; output++)
837         {
838                 source << "layout (location = " << output << ") out mediump vec4 fs_aColor" << output << "; \n";
839         }
840
841         for (int uniform = 0; uniform < m_shaderFragmentParameters.uniformTotal; uniform++)
842         {
843                 source << "uniform sampler2D uTexture" << uniform << "; \n";
844         }
845
846         if (m_shaderFragmentParameters.hasFunction == true)
847         {
848                 source << m_shaderFragmentParameters.functionImplementation;
849         }
850
851         source << "void main () \n"
852                 << "{ \n";
853
854         for (int uniformIdx = 0; uniformIdx < m_shaderFragmentParameters.uniformTotal; uniformIdx++)
855         {
856                 source << this->genFunctionCall(m_shaderFragmentParameters.samplingType, uniformIdx);
857         }
858
859         if (m_shaderFragmentParameters.hasFunction == true)
860         {
861                 switch ( static_cast<FunctionParameters>(m_shaderFragmentParameters.functionParameters) )
862                 {
863                         case FUNCTIONPARAMETERS_ONE:
864                         {
865                                 functionParameters << "(texelColor0)";
866                                 break;
867                         }
868                         case FUNCTIONPARAMETERS_TWO:
869                         {
870                                 functionParameters << "(texelColor0, texelColor1)";
871                                 break;
872                         }
873                         default:
874                         {
875                                 DE_FATAL("Error: Number of comparison function parameters invalid");
876                         }
877                 }
878
879                 shaderOutputs << "      fs_aColor0 = " << m_shaderFragmentParameters.functionName << functionParameters.str() << "; \n";
880         }
881         else
882         {
883                 for (int output = 0; output < m_shaderFragmentParameters.outputTotal; output++)
884                 {
885                         shaderOutputs << "      fs_aColor" << output << " = texelColor" << output << "; \n";
886                 }
887         }
888
889         source << shaderOutputs.str();
890         source << "} \n";
891
892         m_shaderFragment = source.str();
893 }
894
895 class SRGBTestCase : public TestCase
896 {
897 public:
898                                                         SRGBTestCase                                    (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat);
899                                                         ~SRGBTestCase                                   (void);
900
901         void                                    init                                                    (void);
902         void                                    deinit                                                  (void);
903         virtual IterateResult   iterate                                                 (void);
904
905         void                                    setSamplingGroup                                (const ShaderSamplingGroup samplingGroup);
906         void                                    setSamplingLocations                    (const int px, const int py);
907         void                                    setShaderProgramBlendRequired   (const int programIdx, const bool blend);
908         void                                    setShaderProgramToggleRequired  (const int programIdx, const bool toggle);
909         void                                    setUniformToggle                                (const int programIdx, const std::string& uniformName, bool toggleDecode);
910
911         deUint32                                getShaderProgramHandle                  (const int programIdx) const;
912         deUint32                                getTextureHandle                                (const int textureIdx) const;
913
914         void                                    addTexture                                              (const glu::TextureTestUtil::TextureType        targetType,
915                                                                                                                          const int                                                                      width,
916                                                                                                                          const int                                                                      height,
917                                                                                                                          const tcu::Vec4                                                        color,
918                                                                                                                          const tcu::Sampler::WrapMode                           wrapS,
919                                                                                                                          const tcu::Sampler::WrapMode                           wrapT,
920                                                                                                                          const tcu::Sampler::FilterMode                         minFilter,
921                                                                                                                          const tcu::Sampler::FilterMode                         magFilter,
922                                                                                                                          const SRGBDecode                                                       decoding);
923         void                                    addSampler                                              (const tcu::Sampler::WrapMode   wrapS,
924                                                                                                                          const tcu::Sampler::WrapMode   wrapT,
925                                                                                                                          const tcu::Sampler::FilterMode minFilter,
926                                                                                                                          const tcu::Sampler::FilterMode magFilter,
927                                                                                                                          const SRGBDecode                               decoding);
928         void                                    addShaderProgram                                (const FragmentShaderParameters& shaderParameters);
929
930         void                                    genShaderPrograms                               (ShaderSamplingType samplingType);
931         void                                    deleteShaderPrograms                    (void);
932
933         void                                    readResultTextures                              (void);
934         void                                    storeResultPixels                               (std::vector<tcu::Vec4>& resultPixelData);
935
936         void                                    toggleDecode                                    (const std::vector<UniformData>& uniformDataList);
937         void                                    bindSamplerToTexture                    (const int samplerIdx, const int textureIdx, const deUint32 textureUnit);
938         void                                    activateSampler                                 (const int samplerIdx, const bool active);
939         void                                    logColor                                                (const std::string& colorLogMessage, int colorIdx, tcu::Vec4 color) const;
940         tcu::Vec4                               formatReferenceColor                    (tcu::Vec4 referenceColor);
941
942         // render function has a default implentation. Can be overriden for special cases
943         virtual void                    render                                                  (void);
944
945         // following functions must be overidden to perform individual test cases
946         virtual void                    setupTest                                               (void) = 0;
947         virtual bool                    verifyResult                                    (void) = 0;
948
949 protected:
950         de::MovePtr<glu::Framebuffer>                   m_framebuffer;
951         std::vector<SRGBTestTexture*>                   m_textureSourceList;
952         std::vector<SRGBTestSampler*>                   m_samplerList;
953         std::vector<glw::GLuint>                                m_renderBufferList;
954         const tcu::Vec4                                                 m_epsilonError;
955         std::vector<tcu::TextureLevel>                  m_textureResultList;
956         int                                                                             m_resultOutputTotal;
957         tcu::TextureFormat                                              m_resultTextureFormat;
958         glw::GLuint                                                             m_vaoID;
959         glw::GLuint                                                             m_vertexDataID;
960         std::vector<FragmentShaderParameters>   m_shaderParametersList;
961         std::vector<SRGBTestProgram*>                   m_shaderProgramList;
962         ShaderSamplingGroup                                             m_samplingGroup;
963         int                                                                             m_px;
964         int                                                                             m_py;
965         const tcu::TextureFormat                                m_internalFormat;
966
967 private:
968         void                    uploadTextures  (void);
969         void                    initFrameBuffer (void);
970         void                    initVertexData  (void);
971
972                                         SRGBTestCase    (const SRGBTestCase&);
973         SRGBTestCase&   operator=               (const SRGBTestCase&);
974 };
975
976 SRGBTestCase::SRGBTestCase      (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
977         : TestCase                              (context, name, description)
978         , m_epsilonError                (EpsilonError::CPU)
979         , m_resultTextureFormat (tcu::TextureFormat(tcu::TextureFormat::sRGBA, tcu::TextureFormat::UNORM_INT8))
980         , m_vaoID                               (0)
981         , m_vertexDataID                (0)
982         , m_samplingGroup               (SHADERSAMPLINGGROUP_TEXTURE)
983         , m_internalFormat              (internalFormat)
984 {
985 }
986
987 SRGBTestCase::~SRGBTestCase (void)
988 {
989         deinit();
990 }
991
992 void SRGBTestCase::init (void)
993 {
994         // extension requirements for test
995         if ( (glu::getInternalFormat(m_internalFormat) == GL_SRGB8_ALPHA8) && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_decode") )
996         {
997                 throw tcu::NotSupportedError("Test requires GL_EXT_texture_sRGB_decode extension");
998         }
999
1000         if ( (glu::getInternalFormat(m_internalFormat) == GL_SR8_EXT) && !(m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_R8")) )
1001         {
1002                 throw tcu::NotSupportedError("Test requires GL_EXT_texture_sRGB_R8 extension");
1003         }
1004
1005         m_framebuffer = de::MovePtr<glu::Framebuffer>(new glu::Framebuffer(m_context.getRenderContext()));
1006 }
1007
1008 void SRGBTestCase::deinit (void)
1009 {
1010         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1011
1012         m_framebuffer   = de::MovePtr<glu::Framebuffer>(DE_NULL);
1013
1014         for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
1015         {
1016                 gl.deleteRenderbuffers(1, &m_renderBufferList[renderBufferIdx]);
1017         }
1018         m_renderBufferList.clear();
1019
1020         for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
1021         {
1022                 delete m_textureSourceList[textureSourceIdx];
1023         }
1024         m_textureSourceList.clear();
1025
1026         for (std::size_t samplerIdx = 0; samplerIdx < m_samplerList.size(); samplerIdx++)
1027         {
1028                 delete m_samplerList[samplerIdx];
1029         }
1030         m_samplerList.clear();
1031
1032         if (m_vaoID != 0)
1033         {
1034                 gl.deleteVertexArrays(1, &m_vaoID);
1035                 m_vaoID = 0;
1036         }
1037
1038         if (m_vertexDataID != 0)
1039         {
1040                 gl.deleteBuffers(1, &m_vertexDataID);
1041                 m_vertexDataID = 0;
1042         }
1043 }
1044
1045 SRGBTestCase::IterateResult SRGBTestCase::iterate (void)
1046 {
1047         bool    result;
1048         int             startIdx        = -1;
1049         int             endIdx          = -1;
1050
1051         this->setupTest();
1052
1053         if (m_samplingGroup == SHADERSAMPLINGGROUP_TEXTURE)
1054         {
1055                 startIdx        = static_cast<int>(TEXTURESAMPLING_TEXTURE_START);
1056                 endIdx          = static_cast<int>(TEXTURESAMPLING_TEXTURE_END);
1057         }
1058         else if (m_samplingGroup == SHADERSAMPLINGGROUP_TEXEL_FETCH)
1059         {
1060                 startIdx        = static_cast<int>(TEXTURESAMPLING_TEXELFETCH_START);
1061                 endIdx          = static_cast<int>(TEXTURESAMPLING_TEXELFETCH_END);
1062         }
1063         else
1064         {
1065                 DE_FATAL("Error: Sampling group not defined");
1066         }
1067
1068         this->initVertexData();
1069         this->initFrameBuffer();
1070
1071         // loop through all sampling types in the required sampling group, performing individual tests for each
1072         for (int samplingTypeIdx = startIdx; samplingTypeIdx < endIdx; samplingTypeIdx++)
1073         {
1074                 this->genShaderPrograms(static_cast<ShaderSamplingType>(samplingTypeIdx));
1075                 this->uploadTextures();
1076                 this->render();
1077
1078                 result = this->verifyResult();
1079
1080                 this->deleteShaderPrograms();
1081
1082                 if (result == true)
1083                 {
1084                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1085                 }
1086                 else
1087                 {
1088                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
1089                         return STOP;
1090                 }
1091         }
1092
1093         return STOP;
1094 }
1095
1096 void SRGBTestCase::setSamplingGroup (const ShaderSamplingGroup samplingGroup)
1097 {
1098         m_samplingGroup = samplingGroup;
1099 }
1100
1101 void SRGBTestCase::setSamplingLocations (const int px, const int py)
1102 {
1103         m_px = px;
1104         m_py = py;
1105 }
1106
1107 void SRGBTestCase::setShaderProgramBlendRequired (const int programIdx, const bool blend)
1108 {
1109         m_shaderProgramList[programIdx]->setBlendRequired(blend);
1110 }
1111
1112 void SRGBTestCase::setShaderProgramToggleRequired (const int programIdx, const bool toggle)
1113 {
1114         m_shaderProgramList[programIdx]->setToggleRequired(toggle);
1115 }
1116
1117 void SRGBTestCase::setUniformToggle (const int programIdx, const std::string& uniformName, bool toggleDecodeValue)
1118 {
1119         int uniformLocation = m_shaderProgramList[programIdx]->getUniformLocation(uniformName);
1120         m_shaderProgramList[programIdx]->setUniformToggle(uniformLocation, toggleDecodeValue);
1121 }
1122
1123 deUint32 SRGBTestCase::getShaderProgramHandle (const int programIdx) const
1124 {
1125         return m_shaderProgramList[programIdx]->getHandle();
1126 }
1127
1128 deUint32 SRGBTestCase::getTextureHandle (const int textureIdx) const
1129 {
1130         return m_textureSourceList[textureIdx]->getHandle();
1131 }
1132
1133 void SRGBTestCase::addTexture ( const glu::TextureTestUtil::TextureType targetType,
1134                                                                 const int                                                               width,
1135                                                                 const int                                                               height,
1136                                                                 const tcu::Vec4                                                 color,
1137                                                                 const tcu::Sampler::WrapMode                    wrapS,
1138                                                                 const tcu::Sampler::WrapMode                    wrapT,
1139                                                                 const tcu::Sampler::FilterMode                  minFilter,
1140                                                                 const tcu::Sampler::FilterMode                  magFilter,
1141                                                                 const SRGBDecode                                                decoding)
1142 {
1143         SRGBTestTexture* texture = new SRGBTestTexture(m_context, targetType, m_internalFormat, width, height, color, wrapS, wrapT, minFilter, magFilter, decoding);
1144         m_textureSourceList.push_back(texture);
1145 }
1146
1147 void SRGBTestCase::addSampler ( const tcu::Sampler::WrapMode    wrapS,
1148                                                                 const tcu::Sampler::WrapMode    wrapT,
1149                                                                 const tcu::Sampler::FilterMode  minFilter,
1150                                                                 const tcu::Sampler::FilterMode  magFilter,
1151                                                                 const SRGBDecode                                decoding)
1152 {
1153         SRGBTestSampler *sampler = new SRGBTestSampler(m_context, wrapS, wrapT, minFilter, magFilter, decoding);
1154         m_samplerList.push_back(sampler);
1155 }
1156
1157 void SRGBTestCase::addShaderProgram (const FragmentShaderParameters& shaderParameters)
1158 {
1159         m_shaderParametersList.push_back(shaderParameters);
1160         m_resultOutputTotal = shaderParameters.outputTotal;
1161 }
1162
1163 void SRGBTestCase::genShaderPrograms (ShaderSamplingType samplingType)
1164 {
1165         for (int shaderParamsIdx = 0; shaderParamsIdx < (int)m_shaderParametersList.size(); shaderParamsIdx++)
1166         {
1167                 m_shaderParametersList[shaderParamsIdx].samplingType = samplingType;
1168                 SRGBTestProgram* shaderProgram = new SRGBTestProgram(m_context, m_shaderParametersList[shaderParamsIdx]);
1169
1170                 if (m_shaderParametersList[shaderParamsIdx].blendRequired == BLENDING_REQUIRED)
1171                 {
1172                         shaderProgram->setBlendRequired(true);
1173                 }
1174
1175                 if (m_shaderParametersList[shaderParamsIdx].toggleRequired == TOGGLING_REQUIRED)
1176                 {
1177                         shaderProgram->setToggleRequired(true);
1178                         std::vector<std::string> uniformsToToggle = m_shaderParametersList[shaderParamsIdx].uniformsToToggle;
1179
1180                         for (int uniformNameIdx = 0; uniformNameIdx < (int)uniformsToToggle.size(); uniformNameIdx++)
1181                         {
1182                                 shaderProgram->setUniformToggle(shaderProgram->getUniformLocation(uniformsToToggle[uniformNameIdx]), true);
1183                         }
1184                 }
1185
1186                 m_shaderProgramList.push_back(shaderProgram);
1187         }
1188 }
1189
1190 void SRGBTestCase::deleteShaderPrograms (void)
1191 {
1192         for (std::size_t idx = 0; idx < m_shaderProgramList.size(); idx++)
1193         {
1194                 delete m_shaderProgramList[idx];
1195         }
1196         m_shaderProgramList.clear();
1197 }
1198
1199 void SRGBTestCase::readResultTextures (void)
1200 {
1201         const glw::Functions&   gl              = m_context.getRenderContext().getFunctions();
1202         int                                             width   = m_context.getRenderContext().getRenderTarget().getWidth();
1203         int                                             height  = m_context.getRenderContext().getRenderTarget().getHeight();
1204
1205         gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
1206
1207         m_textureResultList.resize(m_renderBufferList.size());
1208
1209         for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
1210         {
1211                 gl.readBuffer(GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx);
1212                 m_textureResultList[renderBufferIdx].setStorage(m_resultTextureFormat, width, height);
1213                 glu::readPixels(m_context.getRenderContext(), 0, 0, m_textureResultList[renderBufferIdx].getAccess());
1214                 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
1215         }
1216
1217         gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1218 }
1219
1220 void SRGBTestCase::storeResultPixels (std::vector<tcu::Vec4>& resultPixelData)
1221 {
1222         tcu::TestLog&           log                     = m_context.getTestContext().getLog();
1223         std::ostringstream      message;
1224         int                                     width           = m_context.getRenderContext().getRenderTarget().getWidth();
1225         int                                     height          = m_context.getRenderContext().getRenderTarget().getHeight();
1226
1227         // ensure result sampling coordinates are within range of the result color attachment
1228         DE_ASSERT((m_px >= 0) && (m_px < width));
1229         DE_ASSERT((m_py >= 0) && (m_py < height));
1230         DE_UNREF(width && height);
1231
1232         for (int idx = 0; idx < (int)m_textureResultList.size(); idx++)
1233         {
1234                 resultPixelData.push_back(m_textureResultList[idx].getAccess().getPixel(m_px, m_py));
1235                 this->logColor(std::string("Result color: "), idx, resultPixelData[idx]);
1236         }
1237
1238         // log error rate (threshold)
1239         message << m_epsilonError;
1240         log << tcu::TestLog::Message << std::string("Epsilon error: ") << message.str() << tcu::TestLog::EndMessage;
1241 }
1242
1243 void SRGBTestCase::toggleDecode (const std::vector<UniformData>& uniformDataList)
1244 {
1245         DE_ASSERT( uniformDataList.size() <= m_textureSourceList.size() );
1246
1247         for (int uniformIdx = 0; uniformIdx < (int)uniformDataList.size(); uniformIdx++)
1248         {
1249                 if (uniformDataList[uniformIdx].toggleDecode == true)
1250                 {
1251                         if (m_textureSourceList[uniformIdx]->getDecode() == SRGBDECODE_DECODE_DEFAULT)
1252                         {
1253                                 // cannot toggle default
1254                                 continue;
1255                         }
1256
1257                         // toggle sRGB decode values (ignoring value if set to default)
1258                         m_textureSourceList[uniformIdx]->setDecode((SRGBDecode)((m_textureSourceList[uniformIdx]->getDecode() + 1) % SRGBDECODE_DECODE_DEFAULT));
1259                 }
1260         }
1261 }
1262
1263 void SRGBTestCase::bindSamplerToTexture (const int samplerIdx, const int textureIdx, const deUint32 textureUnit)
1264 {
1265         deUint32 enumConversion = textureUnit - GL_TEXTURE0;
1266         m_textureSourceList[textureIdx]->setHasSampler(true);
1267         m_samplerList[samplerIdx]->setTextureUnit(enumConversion);
1268 }
1269
1270 void SRGBTestCase::activateSampler (const int samplerIdx, const bool active)
1271 {
1272         m_samplerList[samplerIdx]->setIsActive(active);
1273 }
1274
1275 void SRGBTestCase::logColor (const std::string& colorLogMessage, int colorIdx, tcu::Vec4 color) const
1276 {
1277         tcu::TestLog&                   log             = m_context.getTestContext().getLog();
1278         std::ostringstream              message;
1279
1280         message << colorLogMessage << colorIdx << " = (" << color.x() << ", " << color.y() << ", " << color.z() << ", " << color.w() << ")";
1281         log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
1282 }
1283
1284 tcu::Vec4 SRGBTestCase::formatReferenceColor (tcu::Vec4 referenceColor)
1285 {
1286         switch (glu::getInternalFormat(m_internalFormat))
1287         {
1288                 case GL_SRGB8_ALPHA8:
1289                 {
1290                         return referenceColor;
1291                 }
1292                 case GL_SR8_EXT:
1293                 {
1294                         // zero unwanted color channels
1295                         referenceColor.y() = 0;
1296                         referenceColor.z() = 0;
1297                         return referenceColor;
1298                 }
1299                 default:
1300                 {
1301                         DE_FATAL("Error: Internal format not recognised");
1302                         return referenceColor;
1303                 }
1304         }
1305 }
1306
1307 void SRGBTestCase::render (void)
1308 {
1309         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1310
1311         // default rendering only uses one program
1312         gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
1313         gl.bindVertexArray(m_vaoID);
1314
1315         gl.useProgram(m_shaderProgramList[0]->getHandle());
1316
1317         for (int textureSourceIdx = 0; textureSourceIdx < (int)m_textureSourceList.size(); textureSourceIdx++)
1318         {
1319                 gl.activeTexture(GL_TEXTURE0 + (glw::GLenum)textureSourceIdx);
1320                 gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), m_textureSourceList[textureSourceIdx]->getHandle());
1321                 glw::GLuint samplerUniformLocationID = gl.getUniformLocation(m_shaderProgramList[0]->getHandle(), m_shaderProgramList[0]->getUniformAtLocation(textureSourceIdx).name.c_str());
1322                 TCU_CHECK(samplerUniformLocationID != (glw::GLuint)-1);
1323                 gl.uniform1i(samplerUniformLocationID, (glw::GLenum)textureSourceIdx);
1324         }
1325
1326         for (int samplerIdx = 0; samplerIdx < (int)m_samplerList.size(); samplerIdx++)
1327         {
1328                 if (m_samplerList[samplerIdx]->getIsActive() == true)
1329                 {
1330                         m_samplerList[samplerIdx]->bindToTexture();
1331                 }
1332         }
1333
1334         gl.drawArrays(GL_TRIANGLES, 0, 6);
1335
1336         for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
1337         {
1338                 gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), 0);
1339         }
1340         gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1341         gl.bindVertexArray(0);
1342         gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1343 }
1344
1345 void SRGBTestCase::uploadTextures (void)
1346 {
1347         for (std::size_t idx = 0; idx < m_textureSourceList.size(); idx++)
1348         {
1349                 m_textureSourceList[idx]->upload();
1350                 m_textureSourceList[idx]->setParameters();
1351         }
1352 }
1353
1354 void SRGBTestCase::initFrameBuffer (void)
1355 {
1356         const glw::Functions&   gl              = m_context.getRenderContext().getFunctions();
1357         int                                             width   = m_context.getRenderContext().getRenderTarget().getWidth();
1358         int                                             height  = m_context.getRenderContext().getRenderTarget().getHeight();
1359
1360         if (m_resultOutputTotal == 0)
1361         {
1362                 throw std::invalid_argument("SRGBTestExecutor must have at least 1 rendered result");
1363         }
1364
1365         gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
1366
1367         DE_ASSERT(m_renderBufferList.empty());
1368         for (int outputIdx = 0; outputIdx < m_resultOutputTotal; outputIdx++)
1369         {
1370                 glw::GLuint renderBuffer = -1;
1371                 m_renderBufferList.push_back(renderBuffer);
1372         }
1373
1374         for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
1375         {
1376                 gl.genRenderbuffers(1, &m_renderBufferList[renderBufferIdx]);
1377                 gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderBufferList[renderBufferIdx]);
1378                 gl.renderbufferStorage(GL_RENDERBUFFER, glu::getInternalFormat(m_resultTextureFormat), width, height);
1379                 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx, GL_RENDERBUFFER, m_renderBufferList[renderBufferIdx]);
1380                 GLU_EXPECT_NO_ERROR(gl.getError(), "Create and setup renderbuffer object");
1381         }
1382         TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
1383
1384         std::vector<glw::GLenum> renderBufferTargets(m_renderBufferList.size());
1385         for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
1386         {
1387                 renderBufferTargets[renderBufferIdx] = GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx;
1388         }
1389         gl.drawBuffers((glw::GLsizei)renderBufferTargets.size(), &renderBufferTargets[0]);
1390         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffer()");
1391
1392         gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1393 }
1394
1395 void SRGBTestCase::initVertexData (void)
1396 {
1397         const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
1398
1399         static const glw::GLfloat squareVertexData[] =
1400         {
1401                 // position                             // texcoord
1402                 -1.0f, -1.0f, 0.0f,             0.0f, 0.0f, // bottom left corner
1403                  1.0f, -1.0f, 0.0f,             1.0f, 0.0f, // bottom right corner
1404                  1.0f,  1.0f, 0.0f,             1.0f, 1.0f, // Top right corner
1405
1406                 -1.0f,  1.0f, 0.0f,             0.0f, 1.0f, // top left corner
1407                  1.0f,  1.0f, 0.0f,             1.0f, 1.0f, // Top right corner
1408                 -1.0f, -1.0f, 0.0f,             0.0f, 0.0f  // bottom left corner
1409         };
1410
1411         DE_ASSERT(m_vaoID == 0);
1412         gl.genVertexArrays(1, &m_vaoID);
1413         gl.bindVertexArray(m_vaoID);
1414
1415         gl.genBuffers(1, &m_vertexDataID);
1416         gl.bindBuffer(GL_ARRAY_BUFFER, m_vertexDataID);
1417         gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)sizeof(squareVertexData), squareVertexData, GL_STATIC_DRAW);
1418
1419         gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)0);
1420         gl.enableVertexAttribArray(0);
1421         gl.vertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)(3 * sizeof(GL_FLOAT)));
1422         gl.enableVertexAttribArray(1);
1423
1424         gl.bindVertexArray(0);
1425         gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1426 }
1427
1428 class TextureDecodeSkippedCase : public SRGBTestCase
1429 {
1430 public:
1431                         TextureDecodeSkippedCase        (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
1432                                 : SRGBTestCase                  (context, name, description, internalFormat) {}
1433
1434                         ~TextureDecodeSkippedCase       (void) {}
1435
1436         void    setupTest                                       (void);
1437         bool    verifyResult                            (void);
1438 };
1439
1440 void TextureDecodeSkippedCase::setupTest (void)
1441 {
1442         // TEST STEPS:
1443         //      - create and set texture to DECODE_SKIP_EXT
1444         //      - store texture on GPU
1445         //      - in fragment shader, sample the texture using texture*() and render texel values to a color attachment in the FBO
1446         //      - on the host, read back the pixel values into a tcu::TextureLevel
1447         //      - analyse the texel values, expecting them in sRGB format i.e. linear space decoding was skipped
1448
1449         FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
1450
1451         this->addTexture(       TEXTURETYPE_2D,
1452                                                 TestDimensions::WIDTH,
1453                                                 TestDimensions::HEIGHT,
1454                                                 getColorReferenceLinear(),
1455                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1456                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1457                                                 tcu::Sampler::LINEAR,
1458                                                 tcu::Sampler::LINEAR,
1459                                                 SRGBDECODE_SKIP_DECODE);
1460
1461         this->addShaderProgram(shaderParameters);
1462         this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
1463
1464         this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
1465 }
1466
1467 bool TextureDecodeSkippedCase::verifyResult (void)
1468 {
1469         tcu::TestLog&                   log                             = m_context.getTestContext().getLog();
1470         const int                               resultColorIdx  = 0;
1471         std::vector<tcu::Vec4>  pixelResultList;
1472         tcu::Vec4                               pixelConverted;
1473         tcu::Vec4                               pixelReference;
1474         tcu::Vec4                               pixelExpected;
1475
1476         this->readResultTextures();
1477         this->storeResultPixels(pixelResultList);
1478
1479         pixelConverted = tcu::sRGBToLinear(pixelResultList[resultColorIdx]);
1480         pixelReference = this->formatReferenceColor(getColorReferenceLinear());
1481         pixelExpected = this->formatReferenceColor(getColorReferenceSRGB());
1482
1483         this->formatReferenceColor(pixelReference);
1484         this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
1485
1486         // result color 0 should be sRGB. Compare with linear reference color
1487         if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
1488         {
1489                 log << tcu::TestLog::Message << std::string("sRGB as expected") << tcu::TestLog::EndMessage;
1490                 return true;
1491         }
1492         else
1493         {
1494                 log << tcu::TestLog::Message << std::string("not sRGB as expected") << tcu::TestLog::EndMessage;
1495                 return false;
1496         }
1497 }
1498
1499 class TextureDecodeEnabledCase : public SRGBTestCase
1500 {
1501 public:
1502                 TextureDecodeEnabledCase        (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
1503                         : SRGBTestCase                  (context, name, description, internalFormat) {}
1504
1505                 ~TextureDecodeEnabledCase       (void) {}
1506
1507                 void    setupTest                       (void);
1508                 bool    verifyResult            (void);
1509 };
1510
1511 void TextureDecodeEnabledCase::setupTest (void)
1512 {
1513         // TEST STEPS:
1514         //      - create and set texture to DECODE_EXT
1515         //      - store texture on GPU
1516         //      - in fragment shader, sample the texture using texture*() and render texel values to a color attachment in the FBO
1517         //      - on the host, read back the pixel values into a tcu::TextureLevel
1518         //      - analyse the texel values, expecting them in lRGB format i.e. linear space decoding was enabled
1519
1520         FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
1521
1522         this->addTexture(       TEXTURETYPE_2D,
1523                                                 TestDimensions::WIDTH,
1524                                                 TestDimensions::HEIGHT,
1525                                                 getColorReferenceLinear(),
1526                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1527                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1528                                                 tcu::Sampler::LINEAR,
1529                                                 tcu::Sampler::LINEAR,
1530                                                 SRGBDECODE_DECODE);
1531
1532         this->addShaderProgram(shaderParameters);
1533
1534         this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
1535
1536         this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
1537 }
1538
1539 bool TextureDecodeEnabledCase::verifyResult (void)
1540 {
1541         tcu::TestLog&                   log                             = m_context.getTestContext().getLog();
1542         const int                               resultColorIdx  = 0;
1543         std::vector<tcu::Vec4>  pixelResultList;
1544         tcu::Vec4                               pixelConverted;
1545         tcu::Vec4                               pixelReference;
1546         tcu::Vec4                               pixelExpected;
1547
1548         this->readResultTextures();
1549         this->storeResultPixels(pixelResultList);
1550
1551         pixelConverted = tcu::linearToSRGB(pixelResultList[resultColorIdx]);
1552         pixelReference = this->formatReferenceColor(getColorReferenceSRGB());
1553         pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
1554
1555         this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
1556
1557         // result color 0 should be SRGB. Compare with sRGB reference color
1558         if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
1559         {
1560                 log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
1561                 return true;
1562         }
1563         else
1564         {
1565                 log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
1566                 return false;
1567         }
1568 }
1569
1570 class TexelFetchDecodeSkippedcase : public SRGBTestCase
1571 {
1572 public:
1573                         TexelFetchDecodeSkippedcase             (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
1574                                 : SRGBTestCase                          (context, name, description, internalFormat) {}
1575
1576                         ~TexelFetchDecodeSkippedcase    (void) {}
1577
1578         void    setupTest                                               (void);
1579         bool    verifyResult                                    (void);
1580 };
1581
1582 void TexelFetchDecodeSkippedcase::setupTest (void)
1583 {
1584         // TEST STEPS:
1585         //      - create and set texture to DECODE_SKIP_EXT
1586         //      - store texture on GPU
1587         //      - in fragment shader, sample the texture using texelFetch*() and render texel values to a color attachment in the FBO
1588         //      - on the host, read back the pixel values into a tcu::TextureLevel
1589         //      - analyse the texel values, expecting them in lRGB format i.e. linear space decoding is always enabled with texelFetch*()
1590
1591         FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
1592
1593         this->addTexture(       TEXTURETYPE_2D,
1594                                                 TestDimensions::WIDTH,
1595                                                 TestDimensions::HEIGHT,
1596                                                 getColorReferenceLinear(),
1597                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1598                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1599                                                 tcu::Sampler::LINEAR,
1600                                                 tcu::Sampler::LINEAR,
1601                                                 SRGBDECODE_SKIP_DECODE);
1602
1603         this->addShaderProgram(shaderParameters);
1604
1605         this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
1606
1607         this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXEL_FETCH);
1608 }
1609
1610 bool TexelFetchDecodeSkippedcase::verifyResult (void)
1611 {
1612         tcu::TestLog&                   log                             = m_context.getTestContext().getLog();
1613         const int                               resultColorIdx  = 0;
1614         std::vector<tcu::Vec4>  pixelResultList;
1615         tcu::Vec4                               pixelReference;
1616         tcu::Vec4                               pixelExpected;
1617
1618         this->readResultTextures();
1619         this->storeResultPixels(pixelResultList);
1620
1621         pixelReference = pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
1622
1623         this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
1624
1625         // result color 0 should be linear due to automatic conversion via texelFetch*(). Compare with linear reference color
1626         if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelResultList[0] - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelResultList[0], pixelReference))) )
1627         {
1628                 log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
1629                 return true;
1630         }
1631         else
1632         {
1633                 log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
1634                 return false;
1635         }
1636 }
1637
1638 class GPUConversionDecodeEnabledCase : public SRGBTestCase
1639 {
1640 public:
1641                         GPUConversionDecodeEnabledCase  (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
1642                                 : SRGBTestCase                          (context, name, description, internalFormat) {}
1643
1644                         ~GPUConversionDecodeEnabledCase (void) {}
1645
1646         void    setupTest                                               (void);
1647         bool    verifyResult                                    (void);
1648 };
1649
1650 void GPUConversionDecodeEnabledCase::setupTest (void)
1651 {
1652         // TEST STEPS:
1653         //      - create and set texture_a to DECODE_SKIP_EXT and texture_b to default
1654         //      - store textures on GPU
1655         //      - in fragment shader, sample both textures using texture*() and manually perform sRGB to lRGB conversion on texture_b
1656         //      - in fragment shader, compare converted texture_b with texture_a
1657         //      - render green image for pass or red for fail
1658
1659         ComparisonFunction comparisonFunction("srgbToLinearCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionSRGBToLinearCheck());
1660
1661         FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &comparisonFunction, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
1662
1663         this->addTexture(       TEXTURETYPE_2D,
1664                                                 TestDimensions::WIDTH,
1665                                                 TestDimensions::HEIGHT,
1666                                                 getColorReferenceLinear(),
1667                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1668                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1669                                                 tcu::Sampler::LINEAR,
1670                                                 tcu::Sampler::LINEAR,
1671                                                 SRGBDECODE_SKIP_DECODE);
1672
1673         this->addTexture(       TEXTURETYPE_2D,
1674                                                 TestDimensions::WIDTH,
1675                                                 TestDimensions::HEIGHT,
1676                                                 getColorReferenceLinear(),
1677                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1678                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1679                                                 tcu::Sampler::LINEAR,
1680                                                 tcu::Sampler::LINEAR,
1681                                                 SRGBDECODE_DECODE_DEFAULT);
1682
1683         this->addShaderProgram(shaderParameters);
1684
1685         this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
1686
1687         this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
1688 }
1689
1690 bool GPUConversionDecodeEnabledCase::verifyResult (void)
1691 {
1692         tcu::TestLog&                   log                             = m_context.getTestContext().getLog();
1693         const int                               resultColorIdx  = 0;
1694         std::vector<tcu::Vec4>  pixelResultList;
1695
1696         this->readResultTextures();
1697         this->storeResultPixels(pixelResultList);
1698         this->logColor(std::string("Expected color: "), resultColorIdx, getColorGreenPass());
1699
1700         // result color returned from GPU is either green (pass) or fail (red)
1701         if ( tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], getColorGreenPass())) )
1702         {
1703                 log << tcu::TestLog::Message << std::string("returned pass color from GPU") << tcu::TestLog::EndMessage;
1704                 return true;
1705         }
1706         else
1707         {
1708                 log << tcu::TestLog::Message << std::string("returned fail color from GPU") << tcu::TestLog::EndMessage;
1709                 return false;
1710         }
1711 }
1712
1713 class DecodeToggledCase : public SRGBTestCase
1714 {
1715 public:
1716                         DecodeToggledCase       (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
1717                                 : SRGBTestCase  (context, name, description, internalFormat) {}
1718
1719                         ~DecodeToggledCase      (void) {}
1720
1721         void    render                          (void);
1722         void    setupTest                       (void);
1723         bool    verifyResult            (void);
1724 };
1725
1726 void DecodeToggledCase::render (void)
1727 {
1728         // override the base SRGBTestCase render function with the purpose of switching between shader programs,
1729         // toggling texture sRGB decode state between draw calls
1730         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1731
1732         gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
1733         gl.bindVertexArray(m_vaoID);
1734
1735         for (std::size_t programIdx = 0; programIdx < m_shaderProgramList.size(); programIdx++)
1736         {
1737                 gl.useProgram(m_shaderProgramList[programIdx]->getHandle());
1738
1739                 this->toggleDecode(m_shaderProgramList[programIdx]->getUniformDataList());
1740
1741                 for (int textureSourceIdx = 0; textureSourceIdx < (int)m_textureSourceList.size(); textureSourceIdx++)
1742                 {
1743                         gl.activeTexture(GL_TEXTURE0 + (glw::GLenum)textureSourceIdx);
1744                         gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), m_textureSourceList[textureSourceIdx]->getHandle());
1745                         glw::GLuint samplerUniformLocationID = gl.getUniformLocation(m_shaderProgramList[programIdx]->getHandle(), m_shaderProgramList[programIdx]->getUniformAtLocation(textureSourceIdx).name.c_str());
1746                         TCU_CHECK(samplerUniformLocationID != (glw::GLuint) - 1);
1747                         gl.uniform1i(samplerUniformLocationID, (glw::GLenum)textureSourceIdx);
1748                 }
1749
1750                 for (int samplerIdx = 0; samplerIdx < (int)m_samplerList.size(); samplerIdx++)
1751                 {
1752                         if (m_samplerList[samplerIdx]->getIsActive() == true)
1753                         {
1754                                 m_samplerList[samplerIdx]->bindToTexture();
1755                         }
1756                 }
1757
1758                 if (m_shaderProgramList[programIdx]->getBlendRequired() == true)
1759                 {
1760                         gl.enable(GL_BLEND);
1761                         gl.blendEquation(GL_MAX);
1762                         gl.blendFunc(GL_ONE, GL_ONE);
1763                 }
1764                 else
1765                 {
1766                         gl.disable(GL_BLEND);
1767                 }
1768
1769                 gl.drawArrays(GL_TRIANGLES, 0, 6);
1770
1771                 // reset sRGB decode state on textures
1772                 this->toggleDecode(m_shaderProgramList[programIdx]->getUniformDataList());
1773         }
1774
1775         for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
1776         {
1777                 gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), 0);
1778         }
1779         gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1780         gl.bindVertexArray(0);
1781         gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1782 }
1783
1784 void DecodeToggledCase::setupTest (void)
1785 {
1786         // TEST STEPS:
1787         //      - create and set texture_a to DECODE_SKIP_EXT and texture_b to DECODE_EXT
1788         //      - create and use two seperate shader programs, program_a and program_b, each using different fragment shaders
1789         //      - store texture_a and texture_b on GPU
1790         // FIRST PASS:
1791         //      - use program_a
1792         //      - in fragment shader, sample both textures using texture*() and manually perform sRGB to lRGB conversion on texture_a
1793         //      - in fragment shader, test converted texture_a value with texture_b
1794         //      - render green image for pass or red for fail
1795         //      - store result in a color attachement 0
1796         // TOGGLE STAGE
1797         //      - during rendering, toggle texture_a from DECODE_SKIP_EXT to DECODE_EXT
1798         // SECOND PASS:
1799         //      - use program_b
1800         //      - in fragment shader, sample both textures using texture*() and manually perform equality check. Both should be linear
1801         //      - blend first pass result with second pass. Anything but a green result equals fail
1802
1803         ComparisonFunction srgbToLinearFunction("srgbToLinearCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionSRGBToLinearCheck());
1804         ComparisonFunction colorsEqualFunction("colorsEqualCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionEqualCheck());
1805
1806         FragmentShaderParameters shaderParametersA(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &srgbToLinearFunction, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
1807         FragmentShaderParameters shaderParametersB(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &colorsEqualFunction, BLENDING_REQUIRED, TOGGLING_REQUIRED);
1808
1809         // need to specify which texture uniform to toggle DECODE_EXT/SKIP_DECODE_EXT
1810         shaderParametersB.uniformsToToggle.push_back("uTexture0");
1811
1812         this->addTexture(       TEXTURETYPE_2D,
1813                                                 TestDimensions::WIDTH,
1814                                                 TestDimensions::HEIGHT,
1815                                                 getColorReferenceLinear(),
1816                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1817                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1818                                                 tcu::Sampler::LINEAR,
1819                                                 tcu::Sampler::LINEAR,
1820                                                 SRGBDECODE_SKIP_DECODE);
1821
1822         this->addTexture(       TEXTURETYPE_2D,
1823                                                 TestDimensions::WIDTH,
1824                                                 TestDimensions::HEIGHT,
1825                                                 getColorReferenceLinear(),
1826                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1827                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1828                                                 tcu::Sampler::LINEAR,
1829                                                 tcu::Sampler::LINEAR,
1830                                                 SRGBDECODE_DECODE);
1831
1832         this->addShaderProgram(shaderParametersA);
1833         this->addShaderProgram(shaderParametersB);
1834
1835         this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
1836         this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
1837 }
1838
1839 bool DecodeToggledCase::verifyResult (void)
1840 {
1841         tcu::TestLog&                   log                             = m_context.getTestContext().getLog();
1842         const int                               resultColorIdx  = 0;
1843         std::vector<tcu::Vec4>  pixelResultList;
1844
1845         this->readResultTextures();
1846         this->storeResultPixels(pixelResultList);
1847         this->logColor(std::string("Expected color: "), resultColorIdx, getColorGreenPass());
1848
1849         //      result color is either green (pass) or fail (red)
1850         if ( tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], getColorGreenPass())) )
1851         {
1852                 log << tcu::TestLog::Message << std::string("returned pass color from GPU") << tcu::TestLog::EndMessage;
1853                 return true;
1854         }
1855         else
1856         {
1857                 log << tcu::TestLog::Message << std::string("returned fail color from GPU") << tcu::TestLog::EndMessage;
1858                 return false;
1859         }
1860 }
1861
1862 class DecodeMultipleTexturesCase : public SRGBTestCase
1863 {
1864 public:
1865                         DecodeMultipleTexturesCase      (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
1866                                 : SRGBTestCase                  (context, name, description, internalFormat) {}
1867
1868                         ~DecodeMultipleTexturesCase     (void) {}
1869
1870         void    setupTest                                       (void);
1871         bool    verifyResult                            (void);
1872 };
1873
1874 void DecodeMultipleTexturesCase::setupTest (void)
1875 {
1876         // TEST STEPS:
1877         //      - create and set texture_a to DECODE_SKIP_EXT and texture_b to DECODE_EXT
1878         //      - upload textures to the GPU and bind to seperate uniform variables
1879         //      - sample both textures using texture*()
1880         //      - read texel values back to the CPU
1881         //      - compare the texel values, both should be different from each other
1882
1883         FragmentShaderParameters shaderParameters(SHADEROUTPUTS_TWO, SHADERUNIFORMS_TWO, NULL,  BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
1884
1885         this->addTexture(       TEXTURETYPE_2D,
1886                                                 TestDimensions::WIDTH,
1887                                                 TestDimensions::HEIGHT,
1888                                                 getColorReferenceLinear(),
1889                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1890                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1891                                                 tcu::Sampler::LINEAR,
1892                                                 tcu::Sampler::LINEAR,
1893                                                 SRGBDECODE_SKIP_DECODE);
1894
1895         this->addTexture(       TEXTURETYPE_2D,
1896                                                 TestDimensions::WIDTH,
1897                                                 TestDimensions::HEIGHT,
1898                                                 getColorReferenceLinear(),
1899                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1900                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1901                                                 tcu::Sampler::LINEAR,
1902                                                 tcu::Sampler::LINEAR,
1903                                                 SRGBDECODE_DECODE);
1904
1905         this->addShaderProgram(shaderParameters);
1906
1907         this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
1908         this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
1909 }
1910
1911 bool DecodeMultipleTexturesCase::verifyResult (void)
1912 {
1913         tcu::TestLog&                   log                             = m_context.getTestContext().getLog();
1914         const int                               resultColorIdx  = 0;
1915         std::vector<tcu::Vec4>  pixelResultList;
1916         tcu::Vec4                               pixelExpected0;
1917         tcu::Vec4                               pixelExpected1;
1918
1919         this->readResultTextures();
1920         this->storeResultPixels(pixelResultList);
1921
1922         pixelExpected0 = this->formatReferenceColor(getColorReferenceSRGB());
1923         pixelExpected1 = this->formatReferenceColor(getColorReferenceLinear());
1924
1925         this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected0);
1926         this->logColor(std::string("Expected color: "), resultColorIdx +1, pixelExpected1);
1927
1928         //      check if the two textures have different values i.e. uTexture0 = sRGB and uTexture1 = linear
1929         if ( !(tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], pixelResultList[resultColorIdx +1]))) )
1930         {
1931                 log << tcu::TestLog::Message << std::string("texel values are different") << tcu::TestLog::EndMessage;
1932                 return true;
1933         }
1934         else
1935         {
1936                 log << tcu::TestLog::Message << std::string("texel values are equal") << tcu::TestLog::EndMessage;
1937                 return false;
1938         }
1939 }
1940
1941 class DecodeSamplerCase : public SRGBTestCase
1942 {
1943 public:
1944                         DecodeSamplerCase       (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
1945                                 : SRGBTestCase  (context, name, description, internalFormat) {}
1946
1947                         ~DecodeSamplerCase      (void) {}
1948
1949         void    setupTest                       (void);
1950         bool    verifyResult            (void);
1951 };
1952
1953 void DecodeSamplerCase::setupTest (void)
1954 {
1955         // TEST STEPS:
1956         //      - create and set texture_a to DECODE_SKIP_EXT
1957         //      - upload texture to the GPU and bind to sampler
1958         //      - sample texture using texture*()
1959         //      - read texel values back to the CPU
1960         //      - compare the texel values, should be in sampler format (linear)
1961
1962         FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
1963
1964         this->addTexture(       TEXTURETYPE_2D,
1965                                                 TestDimensions::WIDTH,
1966                                                 TestDimensions::HEIGHT,
1967                                                 getColorReferenceLinear(),
1968                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1969                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1970                                                 tcu::Sampler::LINEAR,
1971                                                 tcu::Sampler::LINEAR,
1972                                                 SRGBDECODE_SKIP_DECODE);
1973
1974         this->addSampler(       tcu::Sampler::MIRRORED_REPEAT_GL,
1975                                                 tcu::Sampler::MIRRORED_REPEAT_GL,
1976                                                 tcu::Sampler::LINEAR,
1977                                                 tcu::Sampler::LINEAR,
1978                                                 SRGBDECODE_DECODE);
1979
1980         this->addShaderProgram(shaderParameters);
1981
1982         this->bindSamplerToTexture(0, 0, GL_TEXTURE0);
1983         this->activateSampler(0, true);
1984
1985         this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
1986         this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
1987 }
1988
1989 bool DecodeSamplerCase::verifyResult (void)
1990 {
1991         tcu::TestLog&                   log                             = m_context.getTestContext().getLog();
1992         const int                               resultColorIdx  = 0;
1993         std::vector<tcu::Vec4>  pixelResultList;
1994         tcu::Vec4                               pixelConverted;
1995         tcu::Vec4                               pixelReference;
1996         tcu::Vec4                               pixelExpected;
1997
1998         this->readResultTextures();
1999         this->storeResultPixels(pixelResultList);
2000
2001         pixelConverted = tcu::linearToSRGB(pixelResultList[resultColorIdx]);
2002         pixelReference = this->formatReferenceColor(getColorReferenceSRGB());
2003         pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
2004
2005         this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
2006
2007         //      texture was rendered using a sampler object with setting DECODE_EXT, therefore, results should be linear
2008         if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
2009         {
2010                 log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
2011                 return true;
2012         }
2013         else
2014         {
2015                 log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
2016                 return false;
2017         }
2018 }
2019
2020 } // anonymous
2021
2022 SRGBDecodeTests::SRGBDecodeTests        (Context& context)
2023         : TestCaseGroup                                 (context, "skip_decode", "sRGB skip decode tests")
2024 {
2025 }
2026
2027 SRGBDecodeTests::~SRGBDecodeTests (void)
2028 {
2029 }
2030
2031 void SRGBDecodeTests::init (void)
2032 {
2033         const TestGroupConfig testGroupConfigList[] =
2034         {
2035                 TestGroupConfig("srgba8",       "srgb decode tests using srgba internal format",        tcu::TextureFormat(tcu::TextureFormat::sRGBA, tcu::TextureFormat::UNORM_INT8)),
2036                 TestGroupConfig("sr8",          "srgb decode tests using sr8 internal format",          tcu::TextureFormat(tcu::TextureFormat::sR, tcu::TextureFormat::UNORM_INT8))
2037         };
2038
2039         // create groups for all desired internal formats, adding test cases to each
2040         for (std::size_t idx = 0; idx < DE_LENGTH_OF_ARRAY(testGroupConfigList); idx++)
2041         {
2042                 tcu::TestCaseGroup* const testGroup = new tcu::TestCaseGroup(m_testCtx, testGroupConfigList[idx].name, testGroupConfigList[idx].description);
2043                 tcu::TestNode::addChild(testGroup);
2044
2045                 testGroup->addChild(new TextureDecodeSkippedCase                (m_context, "skipped",                  "testing for sRGB color values with sRGB texture decoding skipped",             testGroupConfigList[idx].internalFormat));
2046                 testGroup->addChild(new TextureDecodeEnabledCase                (m_context, "enabled",                  "testing for linear color values with sRGB texture decoding enabled",   testGroupConfigList[idx].internalFormat));
2047                 testGroup->addChild(new TexelFetchDecodeSkippedcase             (m_context, "texel_fetch",              "testing for linear color values with sRGB texture decoding skipped",   testGroupConfigList[idx].internalFormat));
2048                 testGroup->addChild(new GPUConversionDecodeEnabledCase  (m_context, "conversion_gpu",   "sampling linear values and performing conversion on the gpu",                  testGroupConfigList[idx].internalFormat));
2049                 testGroup->addChild(new DecodeToggledCase                               (m_context, "toggled",                  "toggle the sRGB decoding between draw calls",                                                  testGroupConfigList[idx].internalFormat));
2050                 testGroup->addChild(new DecodeMultipleTexturesCase              (m_context, "multiple_textures","upload multiple textures with different sRGB decode values and sample",testGroupConfigList[idx].internalFormat));
2051                 testGroup->addChild(new DecodeSamplerCase                               (m_context, "using_sampler",    "testing that sampler object takes priority over texture state",                testGroupConfigList[idx].internalFormat));
2052         }
2053 }
2054
2055 } // Functional
2056 } // gles31
2057 } // deqp