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