1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
5 * Copyright 2017 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief FBO sRGB tests.
22 *//*--------------------------------------------------------------------*/
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"
49 tcu::Vec4 getTestColorLinear (void)
51 return tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f);
54 tcu::Vec4 getTestColorSRGB (void)
56 return linearToSRGB(tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f));
59 tcu::Vec4 getTestColorBlank (void)
61 return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
64 tcu::Vec4 getEpsilonError (void)
66 return tcu::Vec4(0.005f);
71 QUERYTYPE_ISENABLED = 0,
89 FRAMEBUFFERSRGB_ENABLED = 0,
90 FRAMEBUFFERSRGB_DISABLED
95 FRAMEBUFFERBLEND_ENABLED = 0,
96 FRAMEBUFFERBLEND_DISABLED
99 enum TextureSourcesType
101 TEXTURESOURCESTYPE_RGBA = 0,
102 TEXTURESOURCESTYPE_SRGBA,
103 TEXTURESOURCESTYPE_BOTH,
104 TEXTURESOURCESTYPE_NONE
115 RENDERERTASK_DRAW = 0,
121 SAMPLINGTYPE_TEXTURE = 0,
122 SAMPLINGTYPE_TEXTURE_LOD,
123 SAMPLINGTYPE_TEXTURE_GRAD,
124 SAMPLINGTYPE_TEXTURE_OFFSET,
125 SAMPLINGTYPE_TEXTURE_PROJ,
128 namespace TestTextureSizes
130 const int WIDTH = 128;
131 const int HEIGHT = 128;
132 } // global test texture sizes
134 namespace SampligTypeCount
137 } // global max number of sampling types
139 std::string buildSamplingPassType (const int samplerTotal)
141 std::ostringstream shaderFragment;
143 const SamplingType samplingTypeList [] =
145 SAMPLINGTYPE_TEXTURE, SAMPLINGTYPE_TEXTURE_LOD, SAMPLINGTYPE_TEXTURE_GRAD, SAMPLINGTYPE_TEXTURE_OFFSET, SAMPLINGTYPE_TEXTURE_PROJ
148 for (int samplerTypeIdx = 0; samplerTypeIdx < DE_LENGTH_OF_ARRAY(samplingTypeList); samplerTypeIdx++)
151 << " if (uFunctionType == " << samplerTypeIdx << ") \n"
154 for (int samplerIdx = 0; samplerIdx < samplerTotal; samplerIdx++)
156 switch (static_cast<SamplingType>(samplerTypeIdx))
158 case SAMPLINGTYPE_TEXTURE:
161 << " texelColor" << samplerIdx << " = texture(uTexture" << samplerIdx << ", vs_aTexCoord); \n";
164 case SAMPLINGTYPE_TEXTURE_LOD:
167 << " texelColor" << samplerIdx << " = textureLod(uTexture" << samplerIdx << ", vs_aTexCoord, 0.0f); \n";
170 case SAMPLINGTYPE_TEXTURE_GRAD:
173 << " texelColor" << samplerIdx << " = textureGrad(uTexture" << samplerIdx << ", vs_aTexCoord, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f)); \n";
176 case SAMPLINGTYPE_TEXTURE_OFFSET:
179 << " texelColor" << samplerIdx << " = textureOffset(uTexture" << samplerIdx << ", vs_aTexCoord, ivec2(0.0f, 0.0f)); \n";
182 case SAMPLINGTYPE_TEXTURE_PROJ:
185 << " texelColor" << samplerIdx << " = textureProj(uTexture" << samplerIdx << ", vec3(vs_aTexCoord, 1.0f)); \n";
189 DE_FATAL("Error: sampling type unrecognised");
197 return shaderFragment.str();
200 void logColor (Context& context, const std::string& colorLogMessage, const tcu::Vec4 resultColor)
202 tcu::TestLog& log = context.getTestContext().getLog();
203 std::ostringstream message;
205 message << colorLogMessage << " = (" << resultColor.x() << ", " << resultColor.y() << ", " << resultColor.z() << ", " << resultColor.w() << ")";
206 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
211 explicit TestFunction (const bool hasFunctionValue)
212 : hasFunction (hasFunctionValue) {}
213 TestFunction (const char* const functionNameValue, const char* const functionDefinition)
215 , functionName (functionNameValue)
216 , functionDefintion (functionDefinition) {}
217 ~TestFunction (void) {}
220 const char* functionName;
221 const char* functionDefintion;
224 TestFunction getFunctionBlendLinearToSRGBCheck (void)
226 const char* const functionName = "blendPlusLinearToSRGB";
228 const char* const functionDefinition =
229 "mediump vec4 blendPlusLinearToSRGB(in mediump vec4 colorSrc, in mediump vec4 colorDst) \n"
231 " const int MAX_VECTOR_SIZE = 4; \n"
232 " mediump vec4 colorConverted; \n"
233 " mediump vec4 colorBlended; \n"
234 " for (int idx = 0; idx < MAX_VECTOR_SIZE; idx++) \n"
236 " if (uBlendFunctionType == 0) \n"
238 " colorBlended[idx] = (colorSrc[idx] * uFactorSrc) + colorDst[idx] * uFactorDst; \n"
240 " if (uBlendFunctionType == 1) \n"
242 " colorBlended[idx] = (colorSrc[idx] * uFactorSrc) - (colorDst[idx] * uFactorDst); \n"
244 "if (uBlendFunctionType == 2) \n"
246 " colorBlended[idx] = (colorDst[idx] * uFactorDst) - (colorSrc[idx] * uFactorSrc); \n"
248 " if (colorBlended[idx] < 0.0031308f) \n"
250 " colorConverted[idx] = 12.92f * colorBlended[idx]; \n"
254 " colorConverted[idx] = 1.055f * pow(colorBlended[idx], 0.41666f) - 0.055f; \n"
257 " return colorConverted; \n"
260 TestFunction testFunction(functionName, functionDefinition);
267 FBOConfig (const deUint32 textureInternalFormatValue,
268 const tcu::Vec4 textureColorValue,
269 const deUint32 fboTargetTypeValue,
270 const deUint32 fboColorAttachmentValue,
271 const FboType fboTypeValue)
272 : textureInternalFormat (textureInternalFormatValue)
273 , textureColor (textureColorValue)
274 , fboTargetType (fboTargetTypeValue)
275 , fboColorAttachment (fboColorAttachmentValue)
276 , fboType (fboTypeValue) {}
279 deUint32 textureInternalFormat;
280 tcu::Vec4 textureColor;
281 deUint32 fboTargetType;
282 deUint32 fboColorAttachment;
293 std::vector<BlendConfig> getBlendingConfigList (void)
295 BlendConfig blendConfigs[12];
297 // add function permutations
298 blendConfigs[0].equation = GL_FUNC_ADD;
299 blendConfigs[1].equation = GL_FUNC_ADD;
300 blendConfigs[2].equation = GL_FUNC_ADD;
301 blendConfigs[3].equation = GL_FUNC_ADD;
303 blendConfigs[0].funcSrc = GL_ONE;
304 blendConfigs[0].funcDst = GL_ONE;
305 blendConfigs[1].funcSrc = GL_ONE;
306 blendConfigs[1].funcDst = GL_ZERO;
307 blendConfigs[2].funcSrc = GL_ZERO;
308 blendConfigs[2].funcDst = GL_ONE;
309 blendConfigs[3].funcSrc = GL_ZERO;
310 blendConfigs[3].funcDst = GL_ZERO;
312 // subtract function permutations
313 blendConfigs[4].equation = GL_FUNC_SUBTRACT;
314 blendConfigs[5].equation = GL_FUNC_SUBTRACT;
315 blendConfigs[6].equation = GL_FUNC_SUBTRACT;
316 blendConfigs[7].equation = GL_FUNC_SUBTRACT;
318 blendConfigs[4].funcSrc = GL_ONE;
319 blendConfigs[4].funcDst = GL_ONE;
320 blendConfigs[5].funcSrc = GL_ONE;
321 blendConfigs[5].funcDst = GL_ZERO;
322 blendConfigs[6].funcSrc = GL_ZERO;
323 blendConfigs[6].funcDst = GL_ONE;
324 blendConfigs[7].funcSrc = GL_ZERO;
325 blendConfigs[7].funcDst = GL_ZERO;
327 // reverse subtract function permutations
328 blendConfigs[8].equation = GL_FUNC_REVERSE_SUBTRACT;
329 blendConfigs[9].equation = GL_FUNC_REVERSE_SUBTRACT;
330 blendConfigs[10].equation = GL_FUNC_REVERSE_SUBTRACT;
331 blendConfigs[11].equation = GL_FUNC_REVERSE_SUBTRACT;
333 blendConfigs[8].funcSrc = GL_ONE;
334 blendConfigs[8].funcDst = GL_ONE;
335 blendConfigs[9].funcSrc = GL_ONE;
336 blendConfigs[9].funcDst = GL_ZERO;
337 blendConfigs[10].funcSrc = GL_ZERO;
338 blendConfigs[10].funcDst = GL_ONE;
339 blendConfigs[11].funcSrc = GL_ZERO;
340 blendConfigs[11].funcDst = GL_ZERO;
342 std::vector<BlendConfig> configList(blendConfigs, blendConfigs + DE_LENGTH_OF_ARRAY(blendConfigs));
347 struct TestRenderPassConfig
349 TestRenderPassConfig (void)
350 : testFunction (false) {}
352 TestRenderPassConfig (const TextureSourcesType textureSourcesTypeValue,
353 FBOConfig fboConfigListValue,
354 const FramebufferSRGB framebufferSRGBValue,
355 const FramebufferBlend framebufferBendValue,
356 const RendererTask rendererTaskValue)
357 : textureSourcesType (textureSourcesTypeValue)
358 , framebufferSRGB (framebufferSRGBValue)
359 , frameBufferBlend (framebufferBendValue)
360 , testFunction (false)
361 , rendererTask (rendererTaskValue) {fboConfigList.push_back(fboConfigListValue);}
363 TestRenderPassConfig (const TextureSourcesType textureSourcesTypeValue,
364 FBOConfig fboConfigListValue,
365 const FramebufferSRGB framebufferSRGBValue,
366 const FramebufferBlend framebufferBendValue,
367 TestFunction testFunctionValue,
368 const RendererTask rendererTaskValue)
369 : textureSourcesType (textureSourcesTypeValue)
370 , framebufferSRGB (framebufferSRGBValue)
371 , frameBufferBlend (framebufferBendValue)
372 , testFunction (testFunctionValue)
373 , rendererTask (rendererTaskValue) {fboConfigList.push_back(fboConfigListValue);}
375 TestRenderPassConfig (const TextureSourcesType textureSourcesTypeValue,
376 std::vector<FBOConfig> fboConfigListValue,
377 const FramebufferSRGB framebufferSRGBValue,
378 const FramebufferBlend framebufferBendValue,
379 TestFunction testFunctionValue,
380 const RendererTask rendererTaskValue)
381 : textureSourcesType (textureSourcesTypeValue)
382 , fboConfigList (fboConfigListValue)
383 , framebufferSRGB (framebufferSRGBValue)
384 , frameBufferBlend (framebufferBendValue)
385 , testFunction (testFunctionValue)
386 , rendererTask (rendererTaskValue) {}
388 ~TestRenderPassConfig (void) {}
390 TextureSourcesType textureSourcesType;
391 std::vector<FBOConfig> fboConfigList;
392 FramebufferSRGB framebufferSRGB;
393 FramebufferBlend frameBufferBlend;
394 TestFunction testFunction;
395 RendererTask rendererTask;
401 TestVertexData (Context& context);
402 ~TestVertexData (void);
406 void bind (void) const;
407 void unbind (void) const;
410 const glw::Functions* m_gl;
411 std::vector<float> m_data;
412 glw::GLuint m_vboHandle;
413 glw::GLuint m_vaoHandle;
416 TestVertexData::TestVertexData (Context& context)
417 : m_gl (&context.getRenderContext().getFunctions())
419 const glw::GLfloat vertexData[] =
421 // position // texcoord
422 -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom left corner
423 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom right corner
424 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top right corner
426 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top left corner
427 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top right corner
428 -1.0f, -1.0f, 0.0f, 0.0f, 0.0f // bottom left corner
431 m_data.resize(DE_LENGTH_OF_ARRAY(vertexData));
432 for (int idx = 0; idx < (int)m_data.size(); idx++)
433 m_data[idx] = vertexData[idx];
435 m_gl->genVertexArrays(1, &m_vaoHandle);
436 m_gl->bindVertexArray(m_vaoHandle);
438 m_gl->genBuffers(1, &m_vboHandle);
439 m_gl->bindBuffer(GL_ARRAY_BUFFER, m_vboHandle);
441 m_gl->bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)(m_data.size() * sizeof(glw::GLfloat)), &m_data[0], GL_STATIC_DRAW);
443 m_gl->enableVertexAttribArray(0);
444 m_gl->vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)0);
445 m_gl->enableVertexAttribArray(1);
446 m_gl->vertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)(3 * sizeof(GL_FLOAT)));
448 m_gl->bindVertexArray(0);
449 m_gl->bindBuffer(GL_ARRAY_BUFFER, 0);
450 GLU_EXPECT_NO_ERROR(m_gl->getError(), "gl error during vertex data setup");
453 TestVertexData::~TestVertexData (void)
455 m_gl->deleteBuffers(1, &m_vboHandle);
456 m_gl->deleteVertexArrays(1, &m_vaoHandle);
459 void TestVertexData::bind (void) const
461 m_gl->bindVertexArray(m_vaoHandle);
464 void TestVertexData::unbind (void) const
466 m_gl->bindVertexArray(0);
472 TestTexture2D (Context& context, const deUint32 internalFormatValue, const deUint32 transferFormatValue, const deUint32 transferTypeValue, const tcu::Vec4 imageColorValue);
473 ~TestTexture2D (void);
475 int getTextureUnit (void) const;
476 deUint32 getHandle (void) const;
478 void bind (const int textureUnit);
479 void unbind (void) const;
482 const glw::Functions* m_gl;
483 glw::GLuint m_handle;
484 const deUint32 m_internalFormat;
485 tcu::TextureFormat m_transferFormat;
488 tcu::TextureLevel m_imageData;
492 TestTexture2D::TestTexture2D (Context& context, const deUint32 internalFormat, const deUint32 transferFormat, const deUint32 transferType, const tcu::Vec4 imageColor)
493 : m_gl (&context.getRenderContext().getFunctions())
494 , m_internalFormat (internalFormat)
495 , m_transferFormat (tcu::TextureFormat(glu::mapGLTransferFormat(transferFormat, transferType)))
496 , m_width (TestTextureSizes::WIDTH)
497 , m_height (TestTextureSizes::HEIGHT)
498 , m_imageData (tcu::TextureLevel(glu::mapGLInternalFormat(internalFormat), m_width, m_height, 1))
500 // fill image data with a solid test color
501 tcu::clear(m_imageData.getAccess(), tcu::Vec4(0.0f));
502 for (int py = 0; py < m_imageData.getHeight(); py++)
504 for (int px = 0; px < m_imageData.getWidth(); px++)
505 m_imageData.getAccess().setPixel(imageColor, px, py);
508 m_gl->genTextures(1, &m_handle);
510 m_gl->bindTexture(GL_TEXTURE_2D, m_handle);
511 m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
512 m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
513 m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
514 m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
516 m_gl->texImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFormat, transferType, m_imageData.getAccess().getDataPtr());
518 m_gl->bindTexture(GL_TEXTURE_2D, 0);
521 TestTexture2D::~TestTexture2D (void)
523 m_gl->deleteTextures(1, &m_handle);
526 int TestTexture2D::getTextureUnit (void) const
528 return m_textureUnit;
531 deUint32 TestTexture2D::getHandle (void) const
536 void TestTexture2D::bind (const int textureUnit)
538 m_textureUnit = textureUnit;
539 m_gl->activeTexture(GL_TEXTURE0 + m_textureUnit);
540 m_gl->bindTexture(GL_TEXTURE_2D, m_handle);
543 void TestTexture2D::unbind (void) const
545 m_gl->bindTexture(GL_TEXTURE_2D, 0);
548 class TestFramebuffer
551 TestFramebuffer (void);
552 TestFramebuffer (Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx);
553 ~TestFramebuffer (void);
555 void setTargetType (const deUint32 targetType);
557 FboType getType (void) const;
558 deUint32 getColorAttachment (void) const;
559 int getIdx (void) const;
564 typedef de::UniquePtr<glu::Framebuffer> fboUniquePtr;
567 const glw::Functions* m_gl;
568 fboUniquePtr m_referenceSource;
569 deUint32 m_targetType;
574 deUint32 m_colorAttachment;
577 TestFramebuffer::TestFramebuffer (Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx)
578 : m_gl (&context.getRenderContext().getFunctions())
579 , m_referenceSource (new glu::Framebuffer(context.getRenderContext()))
580 , m_targetType (targetType)
585 , m_colorAttachment (colorAttachment)
587 m_gl->bindFramebuffer(m_targetType, **m_referenceSource);
589 m_gl->framebufferTexture2D(m_targetType, m_colorAttachment, GL_TEXTURE_2D, textureAttachmentHandle, 0);
591 TCU_CHECK(m_gl->checkFramebufferStatus(m_targetType) == GL_FRAMEBUFFER_COMPLETE);
593 if (targetType == GL_DRAW_BUFFER)
595 glw::GLuint textureAttachments[] = {m_colorAttachment};
596 m_gl->drawBuffers(DE_LENGTH_OF_ARRAY(textureAttachments), textureAttachments);
597 GLU_EXPECT_NO_ERROR(m_gl->getError(), "glDrawBuffer()");
600 if (targetType == GL_READ_BUFFER)
602 m_gl->readBuffer(m_colorAttachment);
603 GLU_EXPECT_NO_ERROR(m_gl->getError(), "glReadBuffer()");
606 m_gl->bindFramebuffer(m_targetType, 0);
609 TestFramebuffer::~TestFramebuffer (void)
613 void TestFramebuffer::setTargetType (const deUint32 targetType)
615 m_targetType = targetType;
618 FboType TestFramebuffer::getType (void) const
623 deUint32 TestFramebuffer::getColorAttachment (void) const
625 return m_colorAttachment;
628 int TestFramebuffer::getIdx (void) const
633 void TestFramebuffer::bind (void)
637 m_gl->bindFramebuffer(m_targetType, **m_referenceSource);
642 void TestFramebuffer::unbind (void)
646 m_gl->bindFramebuffer(m_targetType, 0);
651 class TestShaderProgram
654 TestShaderProgram (Context& context, const int samplerTotal, TestFunction testFunction);
655 ~TestShaderProgram (void);
657 glw::GLuint getHandle (void) const;
659 void use (void) const;
660 void unuse (void) const;
662 glu::ShaderProgramInfo getLogInfo (void);
665 const glw::Functions* m_gl;
666 de::MovePtr<glu::ShaderProgram> m_referenceSource;
667 const int m_samplerTotal;
668 const int m_shaderStagesTotal;
671 TestShaderProgram::TestShaderProgram (Context& context, const int samplerTotal, TestFunction testFunction)
672 : m_gl (&context.getRenderContext().getFunctions())
673 , m_samplerTotal (samplerTotal)
674 , m_shaderStagesTotal (2)
676 std::ostringstream shaderFragment;
678 const char* const shaderVertex =
680 "layout (location = 0) in mediump vec3 aPosition; \n"
681 "layout (location = 1) in mediump vec2 aTexCoord; \n"
682 "out mediump vec2 vs_aTexCoord; \n"
685 " gl_Position = vec4(aPosition, 1.0f); \n"
686 " vs_aTexCoord = aTexCoord; \n"
690 << "#version 310 es \n"
691 << "in mediump vec2 vs_aTexCoord; \n"
692 << "layout (location = 0) out mediump vec4 fs_aColor0; \n";
694 for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++)
696 << "uniform sampler2D uTexture" << samplerIdx << "; \n";
699 << "uniform int uFunctionType; \n";
701 if (testFunction.hasFunction)
703 << "uniform int uBlendFunctionType; \n"
704 << "uniform mediump float uFactorSrc; \n"
705 << "uniform mediump float uFactorDst; \n"
706 << testFunction.functionDefintion;
712 for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++)
714 <<" mediump vec4 texelColor" << samplerIdx << " = vec4(0.0f, 0.0f, 0.0f, 1.0f); \n";
717 << buildSamplingPassType(m_samplerTotal);
719 if (testFunction.hasFunction)
721 << " fs_aColor0 = " << testFunction.functionName << "(texelColor0, texelColor1); \n";
724 << " fs_aColor0 = texelColor0; \n";
729 m_referenceSource = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(context.getRenderContext(), glu::makeVtxFragSources(shaderVertex, shaderFragment.str())));
730 if (!m_referenceSource->isOk())
732 tcu::TestLog& log = context.getTestContext().getLog();
733 log << this->getLogInfo();
734 TCU_FAIL("Failed to compile shaders and link program");
738 TestShaderProgram::~TestShaderProgram (void)
740 m_referenceSource = de::MovePtr<glu::ShaderProgram>(DE_NULL);
741 m_referenceSource.clear();
744 deUint32 TestShaderProgram::getHandle (void) const
746 return m_referenceSource->getProgram();
749 void TestShaderProgram::use (void) const
751 m_gl->useProgram(this->getHandle());
754 void TestShaderProgram::unuse (void) const
759 glu::ShaderProgramInfo TestShaderProgram::getLogInfo (void)
761 glu::ShaderProgramInfo buildInfo;
763 // log shader program info. Only vertex and fragment shaders included
764 buildInfo.program = m_referenceSource->getProgramInfo();
765 for (int shaderIdx = 0; shaderIdx < m_shaderStagesTotal; shaderIdx++)
767 glu::ShaderInfo shaderInfo = m_referenceSource->getShaderInfo(static_cast<glu::ShaderType>(static_cast<int>(glu::SHADERTYPE_VERTEX) + static_cast<int>(shaderIdx)), 0);
768 buildInfo.shaders.push_back(shaderInfo);
776 Renderer (Context& context);
779 void init (const TestRenderPassConfig& renderPassConfig, const int renderpass);
782 void setSamplingType (const SamplingType samplerIdx);
783 void setBlendIteration (const int blendIteration);
784 void setFramebufferBlend (const bool blend);
785 void setFramebufferSRGB (const bool sRGB);
787 std::vector<tcu::Vec4> getResultsPreDraw (void) const;
788 std::vector<tcu::Vec4> getResultsPostDraw (void) const;
789 int getBlendConfigCount (void) const;
790 glu::ShaderProgramInfo getShaderProgramInfo (void);
792 void copyFrameBufferTexture (const int srcPx, const int srcPy, const int dstPx, const int dstPy);
794 void storeShaderProgramInfo (void);
795 void logShaderProgramInfo (void);
797 typedef de::SharedPtr<TestTexture2D> TextureSp;
798 typedef de::SharedPtr<TestFramebuffer> FboSp;
801 void createFBOwithColorAttachment (const std::vector<FBOConfig> fboConfigList);
802 void setShaderProgramSamplingType (const int samplerIdx);
803 void setShaderBlendFunctionType (void);
804 void setShaderBlendSrcDstValues (void);
805 void bindActiveTexturesSamplers (void);
806 void bindAllRequiredSourceTextures (const TextureSourcesType texturesRequired);
807 void unbindAllSourceTextures (void);
808 void bindFramebuffer (const int framebufferIdx);
809 void unbindFramebuffer (const int framebufferIdx);
810 void enableFramebufferSRGB (void);
811 void enableFramebufferBlend (void);
812 bool isFramebufferAttachmentSRGB (const deUint32 targetType, const deUint32 attachment) const;
813 void readTexels (const int px, const int py, const deUint32 attachment, tcu::Vec4& texelData);
814 void logState (const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const;
816 // renderer specific constants initialized during constructor
818 const TestVertexData m_vertexData;
819 const int m_textureSourceTotal;
821 // additional resources monitored by the renderer
822 std::vector<BlendConfig> m_blendConfigList;
823 std::vector<TextureSp> m_textureSourceList;
824 TestRenderPassConfig m_renderPassConfig;
825 std::vector<TextureSp> m_fboTextureList;
826 TestShaderProgram* m_shaderProgram;
827 std::vector<FboSp> m_framebufferList;
828 std::vector<tcu::Vec4> m_resultsListPreDraw;
829 std::vector<tcu::Vec4> m_resultsListPostDraw;
831 // mutable state variables (internal access only)
832 bool m_hasShaderProgramInfo;
834 int m_samplersRequired;
836 bool m_blittingEnabled;
837 glu::ShaderProgramInfo m_shaderProgramInfo;
839 // mutable state variables (external access via setters)
840 SamplingType m_samplingType;
841 int m_blendIteration;
842 bool m_framebufferBlendEnabled;
843 bool m_framebufferSRGBEnabled;
846 Renderer::Renderer (Context& context)
847 : m_context (context)
848 , m_vertexData (context)
849 , m_textureSourceTotal (2)
850 , m_blendConfigList (getBlendingConfigList())
851 , m_hasShaderProgramInfo (false)
853 TextureSp textureLinear(new TestTexture2D(m_context, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear()));
854 m_textureSourceList.push_back(textureLinear);
856 TextureSp textureSRGB(new TestTexture2D(m_context, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear()));
857 m_textureSourceList.push_back(textureSRGB);
860 Renderer::~Renderer (void)
862 m_textureSourceList.clear();
866 void Renderer::init (const TestRenderPassConfig& renderPassConfig, const int renderpass)
868 m_renderPassConfig = renderPassConfig;
869 m_renderPass = renderpass;
871 this->createFBOwithColorAttachment(m_renderPassConfig.fboConfigList);
873 if (m_renderPassConfig.textureSourcesType != TEXTURESOURCESTYPE_NONE)
875 if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_RGBA || m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_SRGBA)
876 m_samplersRequired = 1;
877 else if (m_renderPassConfig.textureSourcesType ==TEXTURESOURCESTYPE_BOTH )
878 m_samplersRequired = 2;
880 DE_FATAL("Error: Texture source required not recognised");
882 m_shaderProgram = new TestShaderProgram(m_context, m_samplersRequired, m_renderPassConfig.testFunction);
883 m_hasFunction = m_renderPassConfig.testFunction.hasFunction;
886 m_shaderProgram = DE_NULL;
889 void Renderer::deinit (void)
891 if (m_shaderProgram != DE_NULL)
893 delete m_shaderProgram;
894 m_shaderProgram = DE_NULL;
897 m_fboTextureList.clear();
898 m_framebufferList.clear();
901 void Renderer::setSamplingType (const SamplingType samplingType)
903 m_samplingType = samplingType;
906 void Renderer::setBlendIteration (const int blendIteration)
908 m_blendIteration = blendIteration;
911 void Renderer::setFramebufferBlend (const bool blend)
913 m_framebufferBlendEnabled = blend;
916 void Renderer::setFramebufferSRGB (const bool sRGB)
918 m_framebufferSRGBEnabled = sRGB;
921 std::vector<tcu::Vec4> Renderer::getResultsPreDraw (void) const
923 return m_resultsListPreDraw;
926 std::vector<tcu::Vec4> Renderer::getResultsPostDraw (void) const
928 return m_resultsListPostDraw;
931 int Renderer::getBlendConfigCount (void) const
933 return (int)m_blendConfigList.size();
936 void Renderer::copyFrameBufferTexture (const int srcPx, const int srcPy, const int dstPx, const int dstPy)
938 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
941 deUint32 fboSrcColAttachment = GL_NONE;
942 deUint32 fboDstColAttachment = GL_NONE;
944 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
945 this->bindFramebuffer(idx);
947 // cache fbo attachments and idx locations
948 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
950 if (m_framebufferList[idx]->getType() == FBOTYPE_SOURCE)
952 fboSrcIdx = m_framebufferList[idx]->getIdx();
953 fboSrcColAttachment = m_framebufferList[fboSrcIdx]->getColorAttachment();
955 if (m_framebufferList[idx]->getType() == FBOTYPE_DESTINATION)
957 fboDstIdx = m_framebufferList[idx]->getIdx();
958 fboDstColAttachment = m_framebufferList[fboDstIdx]->getColorAttachment();
962 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
963 m_framebufferList[idx]->unbind();
965 // store texel data from both src and dst before performing the copy
966 m_resultsListPreDraw.resize(2);
967 m_framebufferList[fboSrcIdx]->bind();
968 this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPreDraw[0]);
969 m_framebufferList[fboSrcIdx]->unbind();
970 m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER);
971 m_framebufferList[fboDstIdx]->bind();
972 this->readTexels(0, 0, fboDstColAttachment, m_resultsListPreDraw[1]);
973 m_framebufferList[fboDstIdx]->unbind();
974 m_framebufferList[fboDstIdx]->setTargetType(GL_DRAW_FRAMEBUFFER);
976 m_framebufferList[fboSrcIdx]->bind();
977 m_framebufferList[fboDstIdx]->bind();
979 this->enableFramebufferSRGB();
980 this->enableFramebufferBlend();
982 gl.blitFramebuffer( srcPx, srcPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT,
983 dstPx, dstPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT,
984 GL_COLOR_BUFFER_BIT, GL_NEAREST);
986 m_resultsListPostDraw.resize(2);
987 this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPostDraw[0]);
988 m_framebufferList[fboSrcIdx]->unbind();
989 m_framebufferList[fboDstIdx]->unbind();
991 m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER);
992 m_framebufferList[fboDstIdx]->bind();
993 this->readTexels(0, 0, fboDstColAttachment, m_resultsListPostDraw[1]);
994 m_framebufferList[fboDstIdx]->unbind();
997 void Renderer::draw (void)
999 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1001 if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_NONE)
1002 DE_FATAL("Error: Attempted to draw with no texture sources");
1004 // resize results storage with each render pass
1005 m_resultsListPreDraw.resize(m_renderPass + 1);
1006 m_resultsListPostDraw.resize(m_renderPass + 1);
1008 m_shaderProgram->use();
1009 m_vertexData.bind();
1011 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
1012 this->bindFramebuffer(idx);
1014 this->bindAllRequiredSourceTextures(m_renderPassConfig.textureSourcesType);
1015 this->bindActiveTexturesSamplers();
1017 this->enableFramebufferSRGB();
1018 this->enableFramebufferBlend();
1020 this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPreDraw[m_renderPass]);
1021 this->setShaderProgramSamplingType(m_samplingType);
1024 this->setShaderBlendFunctionType();
1025 this->setShaderBlendSrcDstValues();
1028 gl.drawArrays(GL_TRIANGLES, 0, 6);
1030 this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPostDraw[m_renderPass]);
1031 this->logState(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_samplingType);
1033 this->unbindAllSourceTextures();
1034 for (int idx = 0; idx < (int)m_framebufferList.size(); idx++)
1035 this->unbindFramebuffer(idx);
1036 m_vertexData.unbind();
1037 m_shaderProgram->unuse();
1040 void Renderer::storeShaderProgramInfo (void)
1042 m_shaderProgramInfo = m_shaderProgram->getLogInfo();
1043 m_hasShaderProgramInfo = true;
1046 void Renderer::logShaderProgramInfo (void)
1048 tcu::TestLog& log = m_context.getTestContext().getLog();
1050 if (m_hasShaderProgramInfo)
1051 log << m_shaderProgramInfo;
1054 void Renderer::createFBOwithColorAttachment (const std::vector<FBOConfig> fboConfigList)
1056 const int size = (int)fboConfigList.size();
1057 for (int idx = 0; idx < size; idx++)
1059 TextureSp texture(new TestTexture2D(m_context, fboConfigList[idx].textureInternalFormat, GL_RGBA, GL_UNSIGNED_BYTE, fboConfigList[idx].textureColor));
1060 m_fboTextureList.push_back(texture);
1063 if (fboConfigList[idx].textureInternalFormat == GL_SRGB8_ALPHA8)
1068 FboSp framebuffer(new TestFramebuffer(m_context, fboConfigList[idx].fboTargetType, fboConfigList[idx].fboColorAttachment, texture->getHandle(), isSRGB, fboConfigList[idx].fboType, idx));
1069 m_framebufferList.push_back(framebuffer);
1073 void Renderer::setShaderProgramSamplingType (const int samplerIdx)
1075 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1077 glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFunctionType");
1078 DE_ASSERT(location != (glw::GLuint)-1);
1079 gl.uniform1i(location, samplerIdx);
1082 void Renderer::setShaderBlendFunctionType (void)
1084 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1087 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD)
1089 else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT)
1091 else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT)
1094 DE_FATAL("Error: Blend function not recognised");
1096 glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uBlendFunctionType");
1097 DE_ASSERT(location != (glw::GLuint)-1);
1098 gl.uniform1i(location, function);
1101 void Renderer::setShaderBlendSrcDstValues (void)
1103 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1106 if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE)
1112 if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE)
1117 glw::GLuint locationSrc = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorSrc");
1118 gl.uniform1f(locationSrc, funcSrc);
1119 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()");
1121 glw::GLuint locationDst = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorDst");
1122 gl.uniform1f(locationDst, funcDst);
1123 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()");
1126 void Renderer::bindActiveTexturesSamplers (void)
1128 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1130 for (int idx = 0; idx < m_samplersRequired; idx++)
1132 std::ostringstream stream;
1133 stream << "uTexture" << idx;
1134 std::string uniformName(stream.str());
1135 glw::GLint location = gl.getUniformLocation(m_shaderProgram->getHandle(), uniformName.c_str());
1136 DE_ASSERT(location != -1);
1137 gl.uniform1i(location, m_textureSourceList[idx]->getTextureUnit());
1138 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation()");
1142 void Renderer::bindAllRequiredSourceTextures (const TextureSourcesType texturesRequired)
1144 if (texturesRequired == TEXTURESOURCESTYPE_RGBA)
1145 m_textureSourceList[0]->bind(0);
1146 else if (texturesRequired == TEXTURESOURCESTYPE_SRGBA)
1147 m_textureSourceList[1]->bind(0);
1148 else if (texturesRequired == TEXTURESOURCESTYPE_BOTH)
1150 m_textureSourceList[0]->bind(0);
1151 m_textureSourceList[1]->bind(1);
1154 DE_FATAL("Error: Invalid sources requested in bind all");
1157 void Renderer::unbindAllSourceTextures (void)
1159 for (int idx = 0; idx < (int)m_textureSourceList.size(); idx++)
1160 m_textureSourceList[idx]->unbind();
1163 void Renderer::bindFramebuffer (const int framebufferIdx)
1165 m_framebufferList[framebufferIdx]->bind();
1168 void Renderer::unbindFramebuffer (const int framebufferIdx)
1170 m_framebufferList[framebufferIdx]->unbind();
1173 void Renderer::enableFramebufferSRGB (void)
1175 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1177 if (m_framebufferSRGBEnabled)
1178 gl.enable(GL_FRAMEBUFFER_SRGB);
1180 gl.disable(GL_FRAMEBUFFER_SRGB);
1183 void Renderer::enableFramebufferBlend (void)
1185 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1186 tcu::TestLog& log = m_context.getTestContext().getLog();
1187 std::ostringstream message;
1189 message << "Blend settings = ";
1191 if (m_framebufferBlendEnabled)
1193 gl.enable(GL_BLEND);
1194 gl.blendEquation(m_blendConfigList[m_blendIteration].equation);
1195 gl.blendFunc(m_blendConfigList[m_blendIteration].funcSrc, m_blendConfigList[m_blendIteration].funcDst);
1197 std::string equation, src, dst;
1198 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD)
1199 equation = "GL_FUNC_ADD";
1200 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT)
1201 equation = "GL_FUNC_SUBTRACT";
1202 if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT)
1203 equation = "GL_FUNC_REVERSE_SUBTRACT";
1204 if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE)
1208 if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE)
1213 message << "Enabled: equation = " << equation << ", func src = " << src << ", func dst = " << dst;
1217 gl.disable(GL_BLEND);
1218 message << "Disabled";
1221 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
1224 bool Renderer::isFramebufferAttachmentSRGB (const deUint32 targetType, const deUint32 attachment) const
1226 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1227 glw::GLint encodingType;
1229 gl.getFramebufferAttachmentParameteriv(targetType, attachment, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encodingType);
1230 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetNamedFramebufferAttachmentParameteriv()");
1232 switch (static_cast<glw::GLenum>(encodingType))
1246 DE_FATAL("Error: Color attachment format not recognised");
1252 void Renderer::readTexels (const int px, const int py, const deUint32 mode, tcu::Vec4& texelData)
1254 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1255 tcu::TextureLevel textureRead;
1257 // ensure result sampling coordinates are within range of the result color attachment
1258 DE_ASSERT((px >= 0) && (px < m_context.getRenderTarget().getWidth()));
1259 DE_ASSERT((py >= 0) && (py < m_context.getRenderTarget().getHeight()));
1261 gl.readBuffer(mode);
1262 textureRead.setStorage(glu::mapGLTransferFormat(GL_RGBA, GL_UNSIGNED_BYTE), TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT);
1263 glu::readPixels(m_context.getRenderContext(), px, py, textureRead.getAccess());
1264 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
1265 texelData = textureRead.getAccess().getPixel(px, py);
1268 void Renderer::logState (const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const
1270 tcu::TestLog& log = m_context.getTestContext().getLog();
1271 std::ostringstream message;
1273 bool fboAttachmentSRGB = this->isFramebufferAttachmentSRGB(targetType, attachment);
1275 message << "getFramebufferAttachmentParameteriv() check = ";
1276 if (fboAttachmentSRGB)
1277 message << "GL_SRGB";
1279 message << "GL_LINEAR";
1280 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
1283 message << "Framebuffer color attachment value BEFORE draw call";
1284 logColor(m_context, message.str(), m_resultsListPreDraw[m_renderPass]);
1287 message << "Framebuffer color attachment value AFTER draw call";
1288 logColor(m_context, message.str(), m_resultsListPostDraw[m_renderPass]);
1291 message << "Sampling type = ";
1293 if (samplingType == 0)
1295 else if (samplingType == 1)
1296 type = "textureLOD()";
1297 else if (samplingType == 2)
1298 type = "textureGrad()";
1299 else if (samplingType == 3)
1300 type = "textureOffset()";
1301 else if (samplingType == 4)
1302 type = "textureProj()";
1304 DE_FATAL("Error: Sampling type unregonised");
1306 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
1309 if (m_framebufferSRGBEnabled)
1310 message << "Framebuffer SRGB = enabled";
1312 message << "Framebuffer SRGB = disabled";
1313 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
1316 class FboSRGBTestCase : public TestCase
1319 FboSRGBTestCase (Context& context, const char* const name, const char* const desc);
1320 ~FboSRGBTestCase (void);
1324 IterateResult iterate (void);
1326 void setTestConfig (std::vector<TestRenderPassConfig> renderPassConfigList);
1328 virtual void setupTest (void) = 0;
1329 virtual bool verifyResult (void) = 0;
1332 bool m_hasTestConfig;
1333 std::vector<TestRenderPassConfig> m_renderPassConfigList;
1334 bool m_testcaseRequiresBlend;
1335 std::vector<tcu::Vec4> m_resultsPreDraw;
1336 std::vector<tcu::Vec4> m_resultsPostDraw;
1339 FboSRGBTestCase (const FboSRGBTestCase&);
1340 FboSRGBTestCase& operator= (const FboSRGBTestCase&);
1343 FboSRGBTestCase::FboSRGBTestCase (Context& context, const char* const name, const char* const desc)
1344 : TestCase (context, name, desc)
1345 , m_hasTestConfig (false)
1349 FboSRGBTestCase::~FboSRGBTestCase (void)
1351 FboSRGBTestCase::deinit();
1354 void FboSRGBTestCase::init (void)
1356 // extensions requirements for test
1357 if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
1358 TCU_THROW(NotSupportedError, "Test requires a context version equal or higher than 3.2");
1360 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control"))
1361 TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control");
1363 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_decode"))
1364 TCU_THROW(NotSupportedError, "Test requires GL_EXT_texture_sRGB_decode extension");
1367 void FboSRGBTestCase::deinit (void)
1371 FboSRGBTestCase::IterateResult FboSRGBTestCase::iterate (void)
1375 DE_ASSERT(m_hasTestConfig && "Error: Renderer was not supplied a test config");
1377 Renderer renderer(m_context);
1379 // loop through each sampling type
1380 for (int samplingIdx = 0; samplingIdx < SampligTypeCount::MAX; samplingIdx++)
1382 renderer.setSamplingType(static_cast<SamplingType>(samplingIdx));
1384 // loop through each blend configuration
1385 const int blendCount = renderer.getBlendConfigCount();
1386 for (int blendIdx = 0; blendIdx < blendCount; blendIdx++)
1388 // loop through each render pass
1389 const int renderPassCount = (int)m_renderPassConfigList.size();
1390 for (int renderPassIdx = 0; renderPassIdx < renderPassCount; renderPassIdx++)
1392 TestRenderPassConfig renderPassConfig = m_renderPassConfigList[renderPassIdx];
1394 renderer.init(renderPassConfig, renderPassIdx);
1396 if (blendIdx == 0 && renderPassConfig.rendererTask == RENDERERTASK_DRAW)
1397 renderer.storeShaderProgramInfo();
1399 if (renderPassConfig.frameBufferBlend == FRAMEBUFFERBLEND_ENABLED)
1401 renderer.setBlendIteration(blendIdx);
1402 renderer.setFramebufferBlend(true);
1405 renderer.setFramebufferBlend(false);
1407 if (renderPassConfig.framebufferSRGB == FRAMEBUFFERSRGB_ENABLED)
1408 renderer.setFramebufferSRGB(true);
1410 renderer.setFramebufferSRGB(false);
1412 if (renderPassConfig.rendererTask == RENDERERTASK_DRAW)
1414 else if (renderPassConfig.rendererTask == RENDERERTASK_COPY)
1415 renderer.copyFrameBufferTexture(0, 0, 0, 0);
1417 DE_FATAL("Error: render task not recognised");
1423 m_resultsPreDraw = renderer.getResultsPreDraw();
1424 m_resultsPostDraw = renderer.getResultsPostDraw();
1426 bool testPassed = this->verifyResult();
1428 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1431 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
1432 renderer.logShaderProgramInfo();
1436 if (!m_testcaseRequiresBlend)
1440 renderer.logShaderProgramInfo();
1446 void FboSRGBTestCase::setTestConfig (std::vector<TestRenderPassConfig> renderPassConfigList)
1448 m_renderPassConfigList = renderPassConfigList;
1449 m_hasTestConfig = true;
1451 for (int idx = 0; idx < (int)renderPassConfigList.size(); idx++)
1453 if (renderPassConfigList[idx].frameBufferBlend == FRAMEBUFFERBLEND_ENABLED)
1455 m_testcaseRequiresBlend = true;
1459 m_testcaseRequiresBlend = false;
1462 class FboSRGBQueryCase : public TestCase
1465 FboSRGBQueryCase (Context& context, const char* const name, const char* const description);
1466 ~FboSRGBQueryCase (void);
1470 IterateResult iterate (void);
1473 FboSRGBQueryCase::FboSRGBQueryCase (Context& context, const char* const name, const char* const description)
1474 : TestCase (context, name, description)
1478 FboSRGBQueryCase::~FboSRGBQueryCase (void)
1480 FboSRGBQueryCase::deinit();
1483 void FboSRGBQueryCase::init (void)
1485 // extension requirements for test
1486 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control"))
1487 TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control");
1490 void FboSRGBQueryCase::deinit (void)
1494 FboSRGBQueryCase::IterateResult FboSRGBQueryCase::iterate (void)
1497 // API tests which check when querying FRAMEBUFFER_SRGB_EXT capability returns the correct information when using glEnabled() or glDisabled()
1499 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1500 tcu::TestLog& log = m_context.getTestContext().getLog();
1501 const char* const msgPart = ", after disabling = ";
1503 for (int idx = 0; idx < static_cast<int>(QUERYTYPE_LAST); idx++)
1505 std::ostringstream message;
1508 message << std::string("Results: After Enabling = ");
1510 gl.enable(GL_FRAMEBUFFER_SRGB);
1512 switch (static_cast<QueryType>(idx))
1514 case QUERYTYPE_ISENABLED:
1516 glw::GLboolean enabled[2];
1517 enabled[0] = gl.isEnabled(GL_FRAMEBUFFER_SRGB);
1518 gl.disable(GL_FRAMEBUFFER_SRGB);
1519 enabled[1] = gl.isEnabled(GL_FRAMEBUFFER_SRGB);
1521 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
1522 pass = (enabled[0] && !(enabled[1])) ? true : false;
1525 case QUERYTYPE_BOOLEAN:
1527 glw::GLboolean enabled[2];
1528 gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[0]);
1529 gl.disable(GL_FRAMEBUFFER_SRGB);
1530 gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[1]);
1532 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
1533 pass = (enabled[0] && !(enabled[1])) ? true : false;
1536 case QUERYTYPE_FLOAT:
1538 glw::GLfloat enabled[2];
1539 gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[0]);
1540 gl.disable(GL_FRAMEBUFFER_SRGB);
1541 gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[1]);
1543 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
1544 pass = ((int)enabled[0] && !((int)enabled[1])) ? true : false;
1549 glw::GLint enabled[2];
1550 gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[0]);
1551 gl.disable(GL_FRAMEBUFFER_SRGB);
1552 gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[1]);
1554 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
1555 pass = (enabled[0] && !(enabled[1])) ? true : false;
1558 case QUERYTYPE_INT64:
1560 glw::GLint64 enabled[2];
1561 gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[0]);
1562 gl.disable(GL_FRAMEBUFFER_SRGB);
1563 gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[1]);
1565 message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]);
1566 pass = (enabled[0] && !(enabled[1])) ? true : false;
1570 DE_FATAL("Error: Datatype not recognised");
1573 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
1576 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1579 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
1586 class FboSRGBColAttachCase : public FboSRGBTestCase
1589 FboSRGBColAttachCase (Context& context, const char* const name, const char* const description)
1590 : FboSRGBTestCase (context, name, description) {}
1591 ~FboSRGBColAttachCase (void) {}
1593 void setupTest (void);
1594 bool verifyResult (void);
1597 void FboSRGBColAttachCase::setupTest (void)
1600 // Check if FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING set to SRGB and FRAMEBUFFER_SRGB_EXT enabled, destination colors are converted from SRGB to linear
1601 // before and after blending, finally the result is converted back to SRGB for storage
1604 // if fbo pre-draw color set to linaer, color values get linearlized "twice"
1605 // (0.2f, 0.3f, 0.4f, 1.0f) when sampled i.e. converted in shader = (0.0331048f, 0.073239f, 0.132868f)
1606 // 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)
1608 FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE);
1609 FBOConfig fboConfig1 = FBOConfig(GL_RGBA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE);
1611 const TestRenderPassConfig renderPassConfigs[] =
1613 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_ENABLED, RENDERERTASK_DRAW),
1614 TestRenderPassConfig(TEXTURESOURCESTYPE_BOTH, fboConfig1, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, getFunctionBlendLinearToSRGBCheck(), RENDERERTASK_DRAW)
1616 std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
1618 this->setTestConfig(renderPassConfigList);
1621 bool FboSRGBColAttachCase::verifyResult (void)
1623 if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], m_resultsPostDraw[1])))
1629 class FboSRGBToggleBlendCase : public FboSRGBTestCase
1632 FboSRGBToggleBlendCase (Context& context, const char* const name, const char* const description)
1633 : FboSRGBTestCase (context, name, description) {}
1634 ~FboSRGBToggleBlendCase (void) {}
1636 void setupTest (void);
1637 bool verifyResult (void);
1640 void FboSRGBToggleBlendCase::setupTest (void)
1643 // Test to check if changing FRAMEBUFFER_SRGB_EXT from enabled to disabled. Enabled should produce SRGB color whilst disabled
1644 // should produce linear color. Test conducted with blending disabled.
1646 FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION);
1648 const TestRenderPassConfig renderPassConfigs[] =
1650 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW),
1651 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW)
1653 std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
1655 this->setTestConfig(renderPassConfigList);
1658 bool FboSRGBToggleBlendCase::verifyResult (void)
1660 if (tcu::boolAny(tcu::greaterThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError())))
1666 class FboSRGBRenderTargetIgnoreCase : public FboSRGBTestCase
1669 FboSRGBRenderTargetIgnoreCase (Context& context, const char* const name, const char* const description)
1670 : FboSRGBTestCase (context, name, description) {}
1671 ~FboSRGBRenderTargetIgnoreCase (void) {}
1673 void setupTest (void);
1674 bool verifyResult (void);
1677 void FboSRGBRenderTargetIgnoreCase::setupTest (void)
1680 // Check if render targets that are non-RGB ignore the state of GL_FRAMEBUFFER_SRGB_EXT. Rendering to an fbo with non-sRGB color
1681 // attachment should ignore color space conversion, producing linear color.
1683 FBOConfig fboConfig0 = FBOConfig(GL_RGBA8, getTestColorBlank(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION);
1685 const TestRenderPassConfig renderPassConfigs[] =
1687 TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW)
1690 std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
1692 this->setTestConfig(renderPassConfigList);
1695 bool FboSRGBRenderTargetIgnoreCase::verifyResult (void)
1697 if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], getTestColorLinear())))
1703 class FboSRGBCopyToLinearCase : public FboSRGBTestCase
1706 FboSRGBCopyToLinearCase (Context& context, const char* const name, const char* const description)
1707 : FboSRGBTestCase (context, name, description) {}
1708 ~FboSRGBCopyToLinearCase (void) {}
1710 void setupTest (void);
1711 bool verifyResult (void);
1714 void FboSRGBCopyToLinearCase::setupTest (void)
1717 // 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
1718 // an sRGB to linear conversion
1720 FBOConfig fboConfigs[] =
1722 FBOConfig(GL_SRGB8_ALPHA8, getTestColorSRGB(), GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE),
1723 FBOConfig(GL_RGBA8, getTestColorBlank(), GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION)
1725 std::vector<FBOConfig> fboConfigList(fboConfigs, fboConfigs + DE_LENGTH_OF_ARRAY(fboConfigs));
1727 const TestRenderPassConfig renderPassConfigs[] =
1729 TestRenderPassConfig(TEXTURESOURCESTYPE_NONE, fboConfigList, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_COPY)
1731 std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs));
1733 this->setTestConfig(renderPassConfigList);
1736 bool FboSRGBCopyToLinearCase::verifyResult (void)
1738 logColor(m_context, "pre-copy source fbo color values", m_resultsPreDraw[0]);
1739 logColor(m_context, "pre-copy destination fbo color values", m_resultsPreDraw[1]);
1740 logColor(m_context, "post-copy source fbo color values", m_resultsPostDraw[0]);
1741 logColor(m_context, "post-copy destination fbo color values", m_resultsPostDraw[1]);
1743 if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[1] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[1], getTestColorLinear())))
1749 class FboSRGBUnsupportedEnumCase : public TestCase
1752 FboSRGBUnsupportedEnumCase (Context& context, const char* const name, const char* const description);
1753 ~FboSRGBUnsupportedEnumCase (void);
1757 bool isInvalidEnum (std::string functionName);
1758 IterateResult iterate (void);
1761 FboSRGBUnsupportedEnumCase::FboSRGBUnsupportedEnumCase (Context& context, const char* const name, const char* const description)
1762 : TestCase (context, name, description)
1766 FboSRGBUnsupportedEnumCase::~FboSRGBUnsupportedEnumCase (void)
1768 FboSRGBUnsupportedEnumCase::deinit();
1771 void FboSRGBUnsupportedEnumCase::init (void)
1773 // extension requirements for test
1774 if (m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control"))
1775 TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control to be unsupported");
1778 void FboSRGBUnsupportedEnumCase::deinit (void)
1782 bool FboSRGBUnsupportedEnumCase::isInvalidEnum (std::string functionName)
1784 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1785 tcu::TestLog& log = m_context.getTestContext().getLog();
1787 glw::GLenum error = GL_NO_ERROR;
1789 log << tcu::TestLog::Message << "Checking call to " << functionName << tcu::TestLog::EndMessage;
1791 error = gl.getError();
1793 if (error != GL_INVALID_ENUM)
1795 log << tcu::TestLog::Message << " returned wrong value [" << glu::getErrorStr(error) << ", expected " << glu::getErrorStr(GL_INVALID_ENUM) << "]" << tcu::TestLog::EndMessage;
1802 FboSRGBUnsupportedEnumCase::IterateResult FboSRGBUnsupportedEnumCase::iterate (void)
1805 // API tests that check calls using enum GL_FRAMEBUFFER_SRGB return GL_INVALID_ENUM when GL_EXT_sRGB_write_control is not supported
1807 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1808 bool allPass = true;
1809 glw::GLboolean bEnabled = GL_FALSE;
1810 glw::GLfloat fEnabled = 0;
1811 glw::GLint iEnabled = 0;
1812 glw::GLint64 lEnabled = 0;
1814 m_context.getTestContext().getLog() << tcu::TestLog::Message
1815 << "Check calls using enum GL_FRAMEBUFFER_SRGB return GL_INVALID_ENUM when GL_EXT_sRGB_write_control is not supported\n\n"
1816 << tcu::TestLog::EndMessage;
1818 gl.enable(GL_FRAMEBUFFER_SRGB);
1819 allPass &= isInvalidEnum("glEnable()");
1821 gl.disable(GL_FRAMEBUFFER_SRGB);
1822 allPass &= isInvalidEnum("glDisable()");
1824 gl.isEnabled(GL_FRAMEBUFFER_SRGB);
1825 allPass &= isInvalidEnum("glIsEnabled()");
1827 gl.getBooleanv(GL_FRAMEBUFFER_SRGB, &bEnabled);
1828 allPass &= isInvalidEnum("glGetBooleanv()");
1830 gl.getFloatv(GL_FRAMEBUFFER_SRGB, &fEnabled);
1831 allPass &= isInvalidEnum("glGetFloatv()");
1833 gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &iEnabled);
1834 allPass &= isInvalidEnum("glGetIntegerv()");
1836 gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &lEnabled);
1837 allPass &= isInvalidEnum("glGetInteger64v()");
1840 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1842 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1849 FboSRGBWriteControlTests::FboSRGBWriteControlTests (Context& context)
1850 : TestCaseGroup (context, "srgb_write_control", "Colorbuffer tests")
1854 FboSRGBWriteControlTests::~FboSRGBWriteControlTests (void)
1858 void FboSRGBWriteControlTests::init (void)
1860 this->addChild(new FboSRGBQueryCase (m_context, "framebuffer_srgb_enabled", "srgb enable framebuffer"));
1861 this->addChild(new FboSRGBColAttachCase (m_context, "framebuffer_srgb_enabled_col_attach", "srgb enable color attachment and framebuffer"));
1862 this->addChild(new FboSRGBToggleBlendCase (m_context, "framebuffer_srgb_enabled_blend", "toggle framebuffer srgb settings with blend disabled"));
1863 this->addChild(new FboSRGBRenderTargetIgnoreCase (m_context, "framebuffer_srgb_enabled_render_target_ignore", "enable framebuffer srgb, non-srgb render target should ignore"));
1864 this->addChild(new FboSRGBCopyToLinearCase (m_context, "framebuffer_srgb_enabled_copy_to_linear", "no conversion when blittering between framebuffer srgb and linear"));
1867 this->addChild(new FboSRGBUnsupportedEnumCase (m_context, "framebuffer_srgb_unsupported_enum", "check error codes for query functions when extension is not supported"));