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