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