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