| /*------------------------------------------------------------------------- |
| * drawElements Quality Program OpenGL ES 3.1 Module |
| * ------------------------------------------------- |
| * |
| * Copyright 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief FBO sRGB tests. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "es31fFboSRGBWriteControlTests.hpp" |
| #include "es31fFboTestUtil.hpp" |
| #include "gluTextureUtil.hpp" |
| #include "gluContextInfo.hpp" |
| #include "tcuTestLog.hpp" |
| #include "glwEnums.hpp" |
| #include "sglrContextUtil.hpp" |
| #include "glwFunctions.hpp" |
| #include "deUniquePtr.hpp" |
| #include "deSharedPtr.hpp" |
| #include "gluObjectWrapper.hpp" |
| #include "gluPixelTransfer.hpp" |
| #include "glsTextureTestUtil.hpp" |
| #include "tcuVectorUtil.hpp" |
| #include "gluStrUtil.hpp" |
| |
| namespace deqp |
| { |
| namespace gles31 |
| { |
| namespace Functional |
| { |
| namespace |
| { |
| |
| tcu::Vec4 getTestColorLinear (void) |
| { |
| return tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f); |
| } |
| |
| tcu::Vec4 getTestColorSRGB (void) |
| { |
| return linearToSRGB(tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f)); |
| } |
| |
| tcu::Vec4 getTestColorBlank (void) |
| { |
| return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f); |
| } |
| |
| tcu::Vec4 getEpsilonError (void) |
| { |
| return tcu::Vec4(0.005f); |
| } |
| |
| enum QueryType |
| { |
| QUERYTYPE_ISENABLED = 0, |
| QUERYTYPE_BOOLEAN, |
| QUERYTYPE_FLOAT, |
| QUERYTYPE_INT, |
| QUERYTYPE_INT64, |
| QUERYTYPE_LAST |
| }; |
| |
| enum DataType |
| { |
| DATATYPE_BOOLEAN = 0, |
| DATATYPE_FLOAT, |
| DATATYPE_INT, |
| DATATYPE_INT64, |
| }; |
| |
| enum FramebufferSRGB |
| { |
| FRAMEBUFFERSRGB_ENABLED = 0, |
| FRAMEBUFFERSRGB_DISABLED |
| }; |
| |
| enum FramebufferBlend |
| { |
| FRAMEBUFFERBLEND_ENABLED = 0, |
| FRAMEBUFFERBLEND_DISABLED |
| }; |
| |
| enum TextureSourcesType |
| { |
| TEXTURESOURCESTYPE_RGBA = 0, |
| TEXTURESOURCESTYPE_SRGBA, |
| TEXTURESOURCESTYPE_BOTH, |
| TEXTURESOURCESTYPE_NONE |
| }; |
| |
| enum FboType |
| { |
| FBOTYPE_SOURCE = 0, |
| FBOTYPE_DESTINATION |
| }; |
| |
| enum RendererTask |
| { |
| RENDERERTASK_DRAW = 0, |
| RENDERERTASK_COPY |
| }; |
| |
| enum SamplingType |
| { |
| SAMPLINGTYPE_TEXTURE = 0, |
| SAMPLINGTYPE_TEXTURE_LOD, |
| SAMPLINGTYPE_TEXTURE_GRAD, |
| SAMPLINGTYPE_TEXTURE_OFFSET, |
| SAMPLINGTYPE_TEXTURE_PROJ, |
| }; |
| |
| namespace TestTextureSizes |
| { |
| const int WIDTH = 128; |
| const int HEIGHT = 128; |
| } // global test texture sizes |
| |
| namespace SampligTypeCount |
| { |
| const int MAX = 5; |
| } // global max number of sampling types |
| |
| std::string buildSamplingPassType (const int samplerTotal) |
| { |
| std::ostringstream shaderFragment; |
| |
| const SamplingType samplingTypeList [] = |
| { |
| SAMPLINGTYPE_TEXTURE, SAMPLINGTYPE_TEXTURE_LOD, SAMPLINGTYPE_TEXTURE_GRAD, SAMPLINGTYPE_TEXTURE_OFFSET, SAMPLINGTYPE_TEXTURE_PROJ |
| } ; |
| |
| for (int samplerTypeIdx = 0; samplerTypeIdx < DE_LENGTH_OF_ARRAY(samplingTypeList); samplerTypeIdx++) |
| { |
| shaderFragment |
| << " if (uFunctionType == " << samplerTypeIdx << ") \n" |
| << " { \n"; |
| |
| for (int samplerIdx = 0; samplerIdx < samplerTotal; samplerIdx++) |
| { |
| switch (static_cast<SamplingType>(samplerTypeIdx)) |
| { |
| case SAMPLINGTYPE_TEXTURE: |
| { |
| shaderFragment |
| << " texelColor" << samplerIdx << " = texture(uTexture" << samplerIdx << ", vs_aTexCoord); \n"; |
| break; |
| } |
| case SAMPLINGTYPE_TEXTURE_LOD: |
| { |
| shaderFragment |
| << " texelColor" << samplerIdx << " = textureLod(uTexture" << samplerIdx << ", vs_aTexCoord, 0.0f); \n"; |
| break; |
| } |
| case SAMPLINGTYPE_TEXTURE_GRAD: |
| { |
| shaderFragment |
| << " texelColor" << samplerIdx << " = textureGrad(uTexture" << samplerIdx << ", vs_aTexCoord, vec2(0.0f, 0.0f), vec2(0.0f, 0.0f)); \n"; |
| break; |
| } |
| case SAMPLINGTYPE_TEXTURE_OFFSET: |
| { |
| shaderFragment |
| << " texelColor" << samplerIdx << " = textureOffset(uTexture" << samplerIdx << ", vs_aTexCoord, ivec2(0.0f, 0.0f)); \n"; |
| break; |
| } |
| case SAMPLINGTYPE_TEXTURE_PROJ: |
| { |
| shaderFragment |
| << " texelColor" << samplerIdx << " = textureProj(uTexture" << samplerIdx << ", vec3(vs_aTexCoord, 1.0f)); \n"; |
| break; |
| } |
| default: |
| DE_FATAL("Error: sampling type unrecognised"); |
| } |
| } |
| |
| shaderFragment |
| << " } \n"; |
| } |
| |
| return shaderFragment.str(); |
| } |
| |
| void logColor (Context& context, const std::string& colorLogMessage, const tcu::Vec4 resultColor) |
| { |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| std::ostringstream message; |
| |
| message << colorLogMessage << " = (" << resultColor.x() << ", " << resultColor.y() << ", " << resultColor.z() << ", " << resultColor.w() << ")"; |
| log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; |
| } |
| |
| struct TestFunction |
| { |
| explicit TestFunction (const bool hasFunctionValue) |
| : hasFunction (hasFunctionValue) {} |
| TestFunction (const char* const functionNameValue, const char* const functionDefinition) |
| : hasFunction (true) |
| , functionName (functionNameValue) |
| , functionDefintion (functionDefinition) {} |
| ~TestFunction (void) {} |
| |
| bool hasFunction; |
| const char* functionName; |
| const char* functionDefintion; |
| }; |
| |
| TestFunction getFunctionBlendLinearToSRGBCheck (void) |
| { |
| const char* const functionName = "blendPlusLinearToSRGB"; |
| |
| const char* const functionDefinition = |
| "mediump vec4 blendPlusLinearToSRGB(in mediump vec4 colorSrc, in mediump vec4 colorDst) \n" |
| "{ \n" |
| " const int MAX_VECTOR_SIZE = 4; \n" |
| " mediump vec4 colorConverted; \n" |
| " mediump vec4 colorBlended; \n" |
| " for (int idx = 0; idx < MAX_VECTOR_SIZE; idx++) \n" |
| " { \n" |
| " if (uBlendFunctionType == 0) \n" |
| " { \n" |
| " colorBlended[idx] = (colorSrc[idx] * uFactorSrc) + colorDst[idx] * uFactorDst; \n" |
| " } \n" |
| " if (uBlendFunctionType == 1) \n" |
| " { \n" |
| " colorBlended[idx] = (colorSrc[idx] * uFactorSrc) - (colorDst[idx] * uFactorDst); \n" |
| " } \n" |
| "if (uBlendFunctionType == 2) \n" |
| " { \n" |
| " colorBlended[idx] = (colorDst[idx] * uFactorDst) - (colorSrc[idx] * uFactorSrc); \n" |
| " } \n" |
| " if (colorBlended[idx] < 0.0031308f) \n" |
| " { \n" |
| " colorConverted[idx] = 12.92f * colorBlended[idx]; \n" |
| " } \n" |
| " else \n" |
| " { \n" |
| " colorConverted[idx] = 1.055f * pow(colorBlended[idx], 0.41666f) - 0.055f; \n" |
| " } \n" |
| " } \n" |
| " return colorConverted; \n" |
| "} \n"; |
| |
| TestFunction testFunction(functionName, functionDefinition); |
| |
| return testFunction; |
| } |
| |
| struct FBOConfig |
| { |
| FBOConfig (const deUint32 textureInternalFormatValue, |
| const tcu::Vec4 textureColorValue, |
| const deUint32 fboTargetTypeValue, |
| const deUint32 fboColorAttachmentValue, |
| const FboType fboTypeValue) |
| : textureInternalFormat (textureInternalFormatValue) |
| , textureColor (textureColorValue) |
| , fboTargetType (fboTargetTypeValue) |
| , fboColorAttachment (fboColorAttachmentValue) |
| , fboType (fboTypeValue) {} |
| ~FBOConfig (void) {} |
| |
| deUint32 textureInternalFormat; |
| tcu::Vec4 textureColor; |
| deUint32 fboTargetType; |
| deUint32 fboColorAttachment; |
| FboType fboType; |
| }; |
| |
| struct BlendConfig |
| { |
| deUint32 equation; |
| deUint32 funcSrc; |
| deUint32 funcDst; |
| }; |
| |
| std::vector<BlendConfig> getBlendingConfigList (void) |
| { |
| BlendConfig blendConfigs[12]; |
| |
| // add function permutations |
| blendConfigs[0].equation = GL_FUNC_ADD; |
| blendConfigs[1].equation = GL_FUNC_ADD; |
| blendConfigs[2].equation = GL_FUNC_ADD; |
| blendConfigs[3].equation = GL_FUNC_ADD; |
| |
| blendConfigs[0].funcSrc = GL_ONE; |
| blendConfigs[0].funcDst = GL_ONE; |
| blendConfigs[1].funcSrc = GL_ONE; |
| blendConfigs[1].funcDst = GL_ZERO; |
| blendConfigs[2].funcSrc = GL_ZERO; |
| blendConfigs[2].funcDst = GL_ONE; |
| blendConfigs[3].funcSrc = GL_ZERO; |
| blendConfigs[3].funcDst = GL_ZERO; |
| |
| // subtract function permutations |
| blendConfigs[4].equation = GL_FUNC_SUBTRACT; |
| blendConfigs[5].equation = GL_FUNC_SUBTRACT; |
| blendConfigs[6].equation = GL_FUNC_SUBTRACT; |
| blendConfigs[7].equation = GL_FUNC_SUBTRACT; |
| |
| blendConfigs[4].funcSrc = GL_ONE; |
| blendConfigs[4].funcDst = GL_ONE; |
| blendConfigs[5].funcSrc = GL_ONE; |
| blendConfigs[5].funcDst = GL_ZERO; |
| blendConfigs[6].funcSrc = GL_ZERO; |
| blendConfigs[6].funcDst = GL_ONE; |
| blendConfigs[7].funcSrc = GL_ZERO; |
| blendConfigs[7].funcDst = GL_ZERO; |
| |
| // reverse subtract function permutations |
| blendConfigs[8].equation = GL_FUNC_REVERSE_SUBTRACT; |
| blendConfigs[9].equation = GL_FUNC_REVERSE_SUBTRACT; |
| blendConfigs[10].equation = GL_FUNC_REVERSE_SUBTRACT; |
| blendConfigs[11].equation = GL_FUNC_REVERSE_SUBTRACT; |
| |
| blendConfigs[8].funcSrc = GL_ONE; |
| blendConfigs[8].funcDst = GL_ONE; |
| blendConfigs[9].funcSrc = GL_ONE; |
| blendConfigs[9].funcDst = GL_ZERO; |
| blendConfigs[10].funcSrc = GL_ZERO; |
| blendConfigs[10].funcDst = GL_ONE; |
| blendConfigs[11].funcSrc = GL_ZERO; |
| blendConfigs[11].funcDst = GL_ZERO; |
| |
| std::vector<BlendConfig> configList(blendConfigs, blendConfigs + DE_LENGTH_OF_ARRAY(blendConfigs)); |
| |
| return configList; |
| } |
| |
| struct TestRenderPassConfig |
| { |
| TestRenderPassConfig (void) |
| : testFunction (false) {} |
| |
| TestRenderPassConfig (const TextureSourcesType textureSourcesTypeValue, |
| FBOConfig fboConfigListValue, |
| const FramebufferSRGB framebufferSRGBValue, |
| const FramebufferBlend framebufferBendValue, |
| const RendererTask rendererTaskValue) |
| : textureSourcesType (textureSourcesTypeValue) |
| , framebufferSRGB (framebufferSRGBValue) |
| , frameBufferBlend (framebufferBendValue) |
| , testFunction (false) |
| , rendererTask (rendererTaskValue) {fboConfigList.push_back(fboConfigListValue);} |
| |
| TestRenderPassConfig (const TextureSourcesType textureSourcesTypeValue, |
| FBOConfig fboConfigListValue, |
| const FramebufferSRGB framebufferSRGBValue, |
| const FramebufferBlend framebufferBendValue, |
| TestFunction testFunctionValue, |
| const RendererTask rendererTaskValue) |
| : textureSourcesType (textureSourcesTypeValue) |
| , framebufferSRGB (framebufferSRGBValue) |
| , frameBufferBlend (framebufferBendValue) |
| , testFunction (testFunctionValue) |
| , rendererTask (rendererTaskValue) {fboConfigList.push_back(fboConfigListValue);} |
| |
| TestRenderPassConfig (const TextureSourcesType textureSourcesTypeValue, |
| std::vector<FBOConfig> fboConfigListValue, |
| const FramebufferSRGB framebufferSRGBValue, |
| const FramebufferBlend framebufferBendValue, |
| TestFunction testFunctionValue, |
| const RendererTask rendererTaskValue) |
| : textureSourcesType (textureSourcesTypeValue) |
| , fboConfigList (fboConfigListValue) |
| , framebufferSRGB (framebufferSRGBValue) |
| , frameBufferBlend (framebufferBendValue) |
| , testFunction (testFunctionValue) |
| , rendererTask (rendererTaskValue) {} |
| |
| ~TestRenderPassConfig (void) {} |
| |
| TextureSourcesType textureSourcesType; |
| std::vector<FBOConfig> fboConfigList; |
| FramebufferSRGB framebufferSRGB; |
| FramebufferBlend frameBufferBlend; |
| TestFunction testFunction; |
| RendererTask rendererTask; |
| }; |
| |
| class TestVertexData |
| { |
| public: |
| TestVertexData (Context& context); |
| ~TestVertexData (void); |
| |
| void init (void); |
| |
| void bind (void) const; |
| void unbind (void) const; |
| |
| private: |
| const glw::Functions* m_gl; |
| std::vector<float> m_data; |
| glw::GLuint m_vboHandle; |
| glw::GLuint m_vaoHandle; |
| }; |
| |
| TestVertexData::TestVertexData (Context& context) |
| : m_gl (&context.getRenderContext().getFunctions()) |
| { |
| const glw::GLfloat vertexData[] = |
| { |
| // position // texcoord |
| -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom left corner |
| 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom right corner |
| 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top right corner |
| |
| -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top left corner |
| 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top right corner |
| -1.0f, -1.0f, 0.0f, 0.0f, 0.0f // bottom left corner |
| }; |
| |
| m_data.resize(DE_LENGTH_OF_ARRAY(vertexData)); |
| for (int idx = 0; idx < (int)m_data.size(); idx++) |
| m_data[idx] = vertexData[idx]; |
| |
| m_gl->genVertexArrays(1, &m_vaoHandle); |
| m_gl->bindVertexArray(m_vaoHandle); |
| |
| m_gl->genBuffers(1, &m_vboHandle); |
| m_gl->bindBuffer(GL_ARRAY_BUFFER, m_vboHandle); |
| |
| m_gl->bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)(m_data.size() * sizeof(glw::GLfloat)), &m_data[0], GL_STATIC_DRAW); |
| |
| m_gl->enableVertexAttribArray(0); |
| m_gl->vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)0); |
| m_gl->enableVertexAttribArray(1); |
| m_gl->vertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)(3 * sizeof(GL_FLOAT))); |
| |
| m_gl->bindVertexArray(0); |
| m_gl->bindBuffer(GL_ARRAY_BUFFER, 0); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "gl error during vertex data setup"); |
| } |
| |
| TestVertexData::~TestVertexData (void) |
| { |
| m_gl->deleteBuffers(1, &m_vboHandle); |
| m_gl->deleteVertexArrays(1, &m_vaoHandle); |
| } |
| |
| void TestVertexData::bind (void) const |
| { |
| m_gl->bindVertexArray(m_vaoHandle); |
| } |
| |
| void TestVertexData::unbind (void) const |
| { |
| m_gl->bindVertexArray(0); |
| } |
| |
| class TestTexture2D |
| { |
| public: |
| TestTexture2D (Context& context, const deUint32 internalFormatValue, const deUint32 transferFormatValue, const deUint32 transferTypeValue, const tcu::Vec4 imageColorValue); |
| ~TestTexture2D (void); |
| |
| int getTextureUnit (void) const; |
| deUint32 getHandle (void) const; |
| |
| void bind (const int textureUnit); |
| void unbind (void) const; |
| |
| private: |
| const glw::Functions* m_gl; |
| glw::GLuint m_handle; |
| const deUint32 m_internalFormat; |
| tcu::TextureFormat m_transferFormat; |
| int m_width; |
| int m_height; |
| tcu::TextureLevel m_imageData; |
| int m_textureUnit; |
| }; |
| |
| TestTexture2D::TestTexture2D (Context& context, const deUint32 internalFormat, const deUint32 transferFormat, const deUint32 transferType, const tcu::Vec4 imageColor) |
| : m_gl (&context.getRenderContext().getFunctions()) |
| , m_internalFormat (internalFormat) |
| , m_transferFormat (tcu::TextureFormat(glu::mapGLTransferFormat(transferFormat, transferType))) |
| , m_width (TestTextureSizes::WIDTH) |
| , m_height (TestTextureSizes::HEIGHT) |
| , m_imageData (tcu::TextureLevel(glu::mapGLInternalFormat(internalFormat), m_width, m_height, 1)) |
| { |
| // fill image data with a solid test color |
| tcu::clear(m_imageData.getAccess(), tcu::Vec4(0.0f)); |
| for (int py = 0; py < m_imageData.getHeight(); py++) |
| { |
| for (int px = 0; px < m_imageData.getWidth(); px++) |
| m_imageData.getAccess().setPixel(imageColor, px, py); |
| } |
| |
| m_gl->genTextures(1, &m_handle); |
| |
| m_gl->bindTexture(GL_TEXTURE_2D, m_handle); |
| m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); |
| m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); |
| m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| m_gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| |
| m_gl->texImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFormat, transferType, m_imageData.getAccess().getDataPtr()); |
| |
| m_gl->bindTexture(GL_TEXTURE_2D, 0); |
| } |
| |
| TestTexture2D::~TestTexture2D (void) |
| { |
| m_gl->deleteTextures(1, &m_handle); |
| } |
| |
| int TestTexture2D::getTextureUnit (void) const |
| { |
| return m_textureUnit; |
| } |
| |
| deUint32 TestTexture2D::getHandle (void) const |
| { |
| return m_handle; |
| } |
| |
| void TestTexture2D::bind (const int textureUnit) |
| { |
| m_textureUnit = textureUnit; |
| m_gl->activeTexture(GL_TEXTURE0 + m_textureUnit); |
| m_gl->bindTexture(GL_TEXTURE_2D, m_handle); |
| } |
| |
| void TestTexture2D::unbind (void) const |
| { |
| m_gl->bindTexture(GL_TEXTURE_2D, 0); |
| } |
| |
| class TestFramebuffer |
| { |
| public: |
| TestFramebuffer (void); |
| TestFramebuffer (Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx); |
| ~TestFramebuffer (void); |
| |
| void setTargetType (const deUint32 targetType); |
| |
| FboType getType (void) const; |
| deUint32 getColorAttachment (void) const; |
| int getIdx (void) const; |
| |
| void bind (void); |
| void unbind (void); |
| |
| typedef de::UniquePtr<glu::Framebuffer> fboUniquePtr; |
| |
| private: |
| const glw::Functions* m_gl; |
| fboUniquePtr m_referenceSource; |
| deUint32 m_targetType; |
| bool m_bound; |
| bool m_isSRGB; |
| FboType m_type; |
| const int m_idx; |
| deUint32 m_colorAttachment; |
| }; |
| |
| TestFramebuffer::TestFramebuffer (Context& context, const deUint32 targetType, const deUint32 colorAttachment, glw::GLuint textureAttachmentHandle, const bool isSRGB, const FboType fboType, const int idx) |
| : m_gl (&context.getRenderContext().getFunctions()) |
| , m_referenceSource (new glu::Framebuffer(context.getRenderContext())) |
| , m_targetType (targetType) |
| , m_bound (false) |
| , m_isSRGB (isSRGB) |
| , m_type (fboType) |
| , m_idx (idx) |
| , m_colorAttachment (colorAttachment) |
| { |
| m_gl->bindFramebuffer(m_targetType, **m_referenceSource); |
| |
| m_gl->framebufferTexture2D(m_targetType, m_colorAttachment, GL_TEXTURE_2D, textureAttachmentHandle, 0); |
| |
| TCU_CHECK(m_gl->checkFramebufferStatus(m_targetType) == GL_FRAMEBUFFER_COMPLETE); |
| |
| if (targetType == GL_DRAW_BUFFER) |
| { |
| glw::GLuint textureAttachments[] = {m_colorAttachment}; |
| m_gl->drawBuffers(DE_LENGTH_OF_ARRAY(textureAttachments), textureAttachments); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "glDrawBuffer()"); |
| } |
| |
| if (targetType == GL_READ_BUFFER) |
| { |
| m_gl->readBuffer(m_colorAttachment); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "glReadBuffer()"); |
| } |
| |
| m_gl->bindFramebuffer(m_targetType, 0); |
| } |
| |
| TestFramebuffer::~TestFramebuffer (void) |
| { |
| } |
| |
| void TestFramebuffer::setTargetType (const deUint32 targetType) |
| { |
| m_targetType = targetType; |
| } |
| |
| FboType TestFramebuffer::getType (void) const |
| { |
| return m_type; |
| } |
| |
| deUint32 TestFramebuffer::getColorAttachment (void) const |
| { |
| return m_colorAttachment; |
| } |
| |
| int TestFramebuffer::getIdx (void) const |
| { |
| return m_idx; |
| } |
| |
| void TestFramebuffer::bind (void) |
| { |
| if (!m_bound) |
| { |
| m_gl->bindFramebuffer(m_targetType, **m_referenceSource); |
| m_bound = true; |
| } |
| } |
| |
| void TestFramebuffer::unbind (void) |
| { |
| if (m_bound) |
| { |
| m_gl->bindFramebuffer(m_targetType, 0); |
| m_bound = false; |
| } |
| } |
| |
| class TestShaderProgram |
| { |
| public: |
| TestShaderProgram (Context& context, const int samplerTotal, TestFunction testFunction); |
| ~TestShaderProgram (void); |
| |
| glw::GLuint getHandle (void) const; |
| |
| void use (void) const; |
| void unuse (void) const; |
| |
| glu::ShaderProgramInfo getLogInfo (void); |
| |
| private: |
| const glw::Functions* m_gl; |
| de::MovePtr<glu::ShaderProgram> m_referenceSource; |
| const int m_samplerTotal; |
| const int m_shaderStagesTotal; |
| }; |
| |
| TestShaderProgram::TestShaderProgram (Context& context, const int samplerTotal, TestFunction testFunction) |
| : m_gl (&context.getRenderContext().getFunctions()) |
| , m_samplerTotal (samplerTotal) |
| , m_shaderStagesTotal (2) |
| { |
| std::ostringstream shaderFragment; |
| |
| const char* const shaderVertex = |
| "#version 310 es \n" |
| "layout (location = 0) in mediump vec3 aPosition; \n" |
| "layout (location = 1) in mediump vec2 aTexCoord; \n" |
| "out mediump vec2 vs_aTexCoord; \n" |
| "void main () \n" |
| "{ \n" |
| " gl_Position = vec4(aPosition, 1.0f); \n" |
| " vs_aTexCoord = aTexCoord; \n" |
| "} \n"; |
| |
| shaderFragment |
| << "#version 310 es \n" |
| << "in mediump vec2 vs_aTexCoord; \n" |
| << "layout (location = 0) out mediump vec4 fs_aColor0; \n"; |
| |
| for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++) |
| shaderFragment |
| << "uniform sampler2D uTexture" << samplerIdx << "; \n"; |
| |
| shaderFragment |
| << "uniform int uFunctionType; \n"; |
| |
| if (testFunction.hasFunction) |
| shaderFragment |
| << "uniform int uBlendFunctionType; \n" |
| << "uniform mediump float uFactorSrc; \n" |
| << "uniform mediump float uFactorDst; \n" |
| << testFunction.functionDefintion; |
| |
| shaderFragment |
| << "void main () \n" |
| << "{ \n"; |
| |
| for (int samplerIdx = 0; samplerIdx < m_samplerTotal; samplerIdx++) |
| shaderFragment |
| <<" mediump vec4 texelColor" << samplerIdx << " = vec4(0.0f, 0.0f, 0.0f, 1.0f); \n"; |
| |
| shaderFragment |
| << buildSamplingPassType(m_samplerTotal); |
| |
| if (testFunction.hasFunction) |
| shaderFragment |
| << " fs_aColor0 = " << testFunction.functionName << "(texelColor0, texelColor1); \n"; |
| else |
| shaderFragment |
| << " fs_aColor0 = texelColor0; \n"; |
| |
| shaderFragment |
| << "} \n"; |
| |
| m_referenceSource = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(context.getRenderContext(), glu::makeVtxFragSources(shaderVertex, shaderFragment.str()))); |
| if (!m_referenceSource->isOk()) |
| { |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| log << this->getLogInfo(); |
| TCU_FAIL("Failed to compile shaders and link program"); |
| } |
| } |
| |
| TestShaderProgram::~TestShaderProgram (void) |
| { |
| m_referenceSource = de::MovePtr<glu::ShaderProgram>(DE_NULL); |
| m_referenceSource.clear(); |
| } |
| |
| deUint32 TestShaderProgram::getHandle (void) const |
| { |
| return m_referenceSource->getProgram(); |
| } |
| |
| void TestShaderProgram::use (void) const |
| { |
| m_gl->useProgram(this->getHandle()); |
| } |
| |
| void TestShaderProgram::unuse (void) const |
| { |
| m_gl->useProgram(0); |
| } |
| |
| glu::ShaderProgramInfo TestShaderProgram::getLogInfo (void) |
| { |
| glu::ShaderProgramInfo buildInfo; |
| |
| // log shader program info. Only vertex and fragment shaders included |
| buildInfo.program = m_referenceSource->getProgramInfo(); |
| for (int shaderIdx = 0; shaderIdx < m_shaderStagesTotal; shaderIdx++) |
| { |
| glu::ShaderInfo shaderInfo = m_referenceSource->getShaderInfo(static_cast<glu::ShaderType>(static_cast<int>(glu::SHADERTYPE_VERTEX) + static_cast<int>(shaderIdx)), 0); |
| buildInfo.shaders.push_back(shaderInfo); |
| } |
| return buildInfo; |
| } |
| |
| class Renderer |
| { |
| public: |
| Renderer (Context& context); |
| ~Renderer (void); |
| |
| void init (const TestRenderPassConfig& renderPassConfig, const int renderpass); |
| void deinit (void); |
| |
| void setSamplingType (const SamplingType samplerIdx); |
| void setBlendIteration (const int blendIteration); |
| void setFramebufferBlend (const bool blend); |
| void setFramebufferSRGB (const bool sRGB); |
| |
| std::vector<tcu::Vec4> getResultsPreDraw (void) const; |
| std::vector<tcu::Vec4> getResultsPostDraw (void) const; |
| int getBlendConfigCount (void) const; |
| glu::ShaderProgramInfo getShaderProgramInfo (void); |
| |
| void copyFrameBufferTexture (const int srcPx, const int srcPy, const int dstPx, const int dstPy); |
| void draw (void); |
| void storeShaderProgramInfo (void); |
| void logShaderProgramInfo (void); |
| |
| typedef de::SharedPtr<TestTexture2D> TextureSp; |
| typedef de::SharedPtr<TestFramebuffer> FboSp; |
| |
| private: |
| void createFBOwithColorAttachment (const std::vector<FBOConfig> fboConfigList); |
| void setShaderProgramSamplingType (const int samplerIdx); |
| void setShaderBlendFunctionType (void); |
| void setShaderBlendSrcDstValues (void); |
| void bindActiveTexturesSamplers (void); |
| void bindAllRequiredSourceTextures (const TextureSourcesType texturesRequired); |
| void unbindAllSourceTextures (void); |
| void bindFramebuffer (const int framebufferIdx); |
| void unbindFramebuffer (const int framebufferIdx); |
| void enableFramebufferSRGB (void); |
| void enableFramebufferBlend (void); |
| bool isFramebufferAttachmentSRGB (const deUint32 targetType, const deUint32 attachment) const; |
| void readTexels (const int px, const int py, const deUint32 attachment, tcu::Vec4& texelData); |
| void logState (const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const; |
| |
| // renderer specific constants initialized during constructor |
| Context& m_context; |
| const TestVertexData m_vertexData; |
| const int m_textureSourceTotal; |
| |
| // additional resources monitored by the renderer |
| std::vector<BlendConfig> m_blendConfigList; |
| std::vector<TextureSp> m_textureSourceList; |
| TestRenderPassConfig m_renderPassConfig; |
| std::vector<TextureSp> m_fboTextureList; |
| TestShaderProgram* m_shaderProgram; |
| std::vector<FboSp> m_framebufferList; |
| std::vector<tcu::Vec4> m_resultsListPreDraw; |
| std::vector<tcu::Vec4> m_resultsListPostDraw; |
| |
| // mutable state variables (internal access only) |
| bool m_hasShaderProgramInfo; |
| int m_renderPass; |
| int m_samplersRequired; |
| bool m_hasFunction; |
| bool m_blittingEnabled; |
| glu::ShaderProgramInfo m_shaderProgramInfo; |
| |
| // mutable state variables (external access via setters) |
| SamplingType m_samplingType; |
| int m_blendIteration; |
| bool m_framebufferBlendEnabled; |
| bool m_framebufferSRGBEnabled; |
| }; |
| |
| Renderer::Renderer (Context& context) |
| : m_context (context) |
| , m_vertexData (context) |
| , m_textureSourceTotal (2) |
| , m_blendConfigList (getBlendingConfigList()) |
| , m_hasShaderProgramInfo (false) |
| { |
| TextureSp textureLinear(new TestTexture2D(m_context, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear())); |
| m_textureSourceList.push_back(textureLinear); |
| |
| TextureSp textureSRGB(new TestTexture2D(m_context, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, getTestColorLinear())); |
| m_textureSourceList.push_back(textureSRGB); |
| } |
| |
| Renderer::~Renderer (void) |
| { |
| m_textureSourceList.clear(); |
| this->deinit(); |
| } |
| |
| void Renderer::init (const TestRenderPassConfig& renderPassConfig, const int renderpass) |
| { |
| m_renderPassConfig = renderPassConfig; |
| m_renderPass = renderpass; |
| |
| this->createFBOwithColorAttachment(m_renderPassConfig.fboConfigList); |
| |
| if (m_renderPassConfig.textureSourcesType != TEXTURESOURCESTYPE_NONE) |
| { |
| if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_RGBA || m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_SRGBA) |
| m_samplersRequired = 1; |
| else if (m_renderPassConfig.textureSourcesType ==TEXTURESOURCESTYPE_BOTH ) |
| m_samplersRequired = 2; |
| else |
| DE_FATAL("Error: Texture source required not recognised"); |
| |
| m_shaderProgram = new TestShaderProgram(m_context, m_samplersRequired, m_renderPassConfig.testFunction); |
| m_hasFunction = m_renderPassConfig.testFunction.hasFunction; |
| } |
| else |
| m_shaderProgram = DE_NULL; |
| } |
| |
| void Renderer::deinit (void) |
| { |
| if (m_shaderProgram != DE_NULL) |
| { |
| delete m_shaderProgram; |
| m_shaderProgram = DE_NULL; |
| } |
| |
| m_fboTextureList.clear(); |
| m_framebufferList.clear(); |
| } |
| |
| void Renderer::setSamplingType (const SamplingType samplingType) |
| { |
| m_samplingType = samplingType; |
| } |
| |
| void Renderer::setBlendIteration (const int blendIteration) |
| { |
| m_blendIteration = blendIteration; |
| } |
| |
| void Renderer::setFramebufferBlend (const bool blend) |
| { |
| m_framebufferBlendEnabled = blend; |
| } |
| |
| void Renderer::setFramebufferSRGB (const bool sRGB) |
| { |
| m_framebufferSRGBEnabled = sRGB; |
| } |
| |
| std::vector<tcu::Vec4> Renderer::getResultsPreDraw (void) const |
| { |
| return m_resultsListPreDraw; |
| } |
| |
| std::vector<tcu::Vec4> Renderer::getResultsPostDraw (void) const |
| { |
| return m_resultsListPostDraw; |
| } |
| |
| int Renderer::getBlendConfigCount (void) const |
| { |
| return (int)m_blendConfigList.size(); |
| } |
| |
| void Renderer::copyFrameBufferTexture (const int srcPx, const int srcPy, const int dstPx, const int dstPy) |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| int fboSrcIdx = -1; |
| int fboDstIdx = -1; |
| deUint32 fboSrcColAttachment = GL_NONE; |
| deUint32 fboDstColAttachment = GL_NONE; |
| |
| for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) |
| this->bindFramebuffer(idx); |
| |
| // cache fbo attachments and idx locations |
| for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) |
| { |
| if (m_framebufferList[idx]->getType() == FBOTYPE_SOURCE) |
| { |
| fboSrcIdx = m_framebufferList[idx]->getIdx(); |
| fboSrcColAttachment = m_framebufferList[fboSrcIdx]->getColorAttachment(); |
| } |
| if (m_framebufferList[idx]->getType() == FBOTYPE_DESTINATION) |
| { |
| fboDstIdx = m_framebufferList[idx]->getIdx(); |
| fboDstColAttachment = m_framebufferList[fboDstIdx]->getColorAttachment(); |
| } |
| } |
| |
| for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) |
| m_framebufferList[idx]->unbind(); |
| |
| // store texel data from both src and dst before performing the copy |
| m_resultsListPreDraw.resize(2); |
| m_framebufferList[fboSrcIdx]->bind(); |
| this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPreDraw[0]); |
| m_framebufferList[fboSrcIdx]->unbind(); |
| m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER); |
| m_framebufferList[fboDstIdx]->bind(); |
| this->readTexels(0, 0, fboDstColAttachment, m_resultsListPreDraw[1]); |
| m_framebufferList[fboDstIdx]->unbind(); |
| m_framebufferList[fboDstIdx]->setTargetType(GL_DRAW_FRAMEBUFFER); |
| |
| m_framebufferList[fboSrcIdx]->bind(); |
| m_framebufferList[fboDstIdx]->bind(); |
| |
| this->enableFramebufferSRGB(); |
| this->enableFramebufferBlend(); |
| |
| gl.blitFramebuffer( srcPx, srcPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT, |
| dstPx, dstPy, TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT, |
| GL_COLOR_BUFFER_BIT, GL_NEAREST); |
| |
| m_resultsListPostDraw.resize(2); |
| this->readTexels(0, 0, fboSrcColAttachment, m_resultsListPostDraw[0]); |
| m_framebufferList[fboSrcIdx]->unbind(); |
| m_framebufferList[fboDstIdx]->unbind(); |
| |
| m_framebufferList[fboDstIdx]->setTargetType(GL_READ_FRAMEBUFFER); |
| m_framebufferList[fboDstIdx]->bind(); |
| this->readTexels(0, 0, fboDstColAttachment, m_resultsListPostDraw[1]); |
| m_framebufferList[fboDstIdx]->unbind(); |
| } |
| |
| void Renderer::draw (void) |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_renderPassConfig.textureSourcesType == TEXTURESOURCESTYPE_NONE) |
| DE_FATAL("Error: Attempted to draw with no texture sources"); |
| |
| // resize results storage with each render pass |
| m_resultsListPreDraw.resize(m_renderPass + 1); |
| m_resultsListPostDraw.resize(m_renderPass + 1); |
| |
| m_shaderProgram->use(); |
| m_vertexData.bind(); |
| |
| for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) |
| this->bindFramebuffer(idx); |
| |
| this->bindAllRequiredSourceTextures(m_renderPassConfig.textureSourcesType); |
| this->bindActiveTexturesSamplers(); |
| |
| this->enableFramebufferSRGB(); |
| this->enableFramebufferBlend(); |
| |
| this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPreDraw[m_renderPass]); |
| this->setShaderProgramSamplingType(m_samplingType); |
| if (m_hasFunction) |
| { |
| this->setShaderBlendFunctionType(); |
| this->setShaderBlendSrcDstValues(); |
| } |
| |
| gl.drawArrays(GL_TRIANGLES, 0, 6); |
| |
| this->readTexels(0, 0, GL_COLOR_ATTACHMENT0, m_resultsListPostDraw[m_renderPass]); |
| this->logState(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_samplingType); |
| |
| this->unbindAllSourceTextures(); |
| for (int idx = 0; idx < (int)m_framebufferList.size(); idx++) |
| this->unbindFramebuffer(idx); |
| m_vertexData.unbind(); |
| m_shaderProgram->unuse(); |
| } |
| |
| void Renderer::storeShaderProgramInfo (void) |
| { |
| m_shaderProgramInfo = m_shaderProgram->getLogInfo(); |
| m_hasShaderProgramInfo = true; |
| } |
| |
| void Renderer::logShaderProgramInfo (void) |
| { |
| tcu::TestLog& log = m_context.getTestContext().getLog(); |
| |
| if (m_hasShaderProgramInfo) |
| log << m_shaderProgramInfo; |
| } |
| |
| void Renderer::createFBOwithColorAttachment (const std::vector<FBOConfig> fboConfigList) |
| { |
| const int size = (int)fboConfigList.size(); |
| for (int idx = 0; idx < size; idx++) |
| { |
| TextureSp texture(new TestTexture2D(m_context, fboConfigList[idx].textureInternalFormat, GL_RGBA, GL_UNSIGNED_BYTE, fboConfigList[idx].textureColor)); |
| m_fboTextureList.push_back(texture); |
| |
| bool isSRGB; |
| if (fboConfigList[idx].textureInternalFormat == GL_SRGB8_ALPHA8) |
| isSRGB = true; |
| else |
| isSRGB = false; |
| |
| FboSp framebuffer(new TestFramebuffer(m_context, fboConfigList[idx].fboTargetType, fboConfigList[idx].fboColorAttachment, texture->getHandle(), isSRGB, fboConfigList[idx].fboType, idx)); |
| m_framebufferList.push_back(framebuffer); |
| } |
| } |
| |
| void Renderer::setShaderProgramSamplingType (const int samplerIdx) |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFunctionType"); |
| DE_ASSERT(location != (glw::GLuint)-1); |
| gl.uniform1i(location, samplerIdx); |
| } |
| |
| void Renderer::setShaderBlendFunctionType (void) |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| int function = -1; |
| if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD) |
| function = 0; |
| else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT) |
| function = 1; |
| else if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT) |
| function = 2; |
| else |
| DE_FATAL("Error: Blend function not recognised"); |
| |
| glw::GLuint location = gl.getUniformLocation(m_shaderProgram->getHandle(), "uBlendFunctionType"); |
| DE_ASSERT(location != (glw::GLuint)-1); |
| gl.uniform1i(location, function); |
| } |
| |
| void Renderer::setShaderBlendSrcDstValues (void) |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| float funcSrc; |
| if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE) |
| funcSrc = 1.0f; |
| else |
| funcSrc = 0.0f; |
| |
| float funcDst; |
| if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE) |
| funcDst = 1.0f; |
| else |
| funcDst = 0.0f; |
| |
| glw::GLuint locationSrc = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorSrc"); |
| gl.uniform1f(locationSrc, funcSrc); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()"); |
| |
| glw::GLuint locationDst = gl.getUniformLocation(m_shaderProgram->getHandle(), "uFactorDst"); |
| gl.uniform1f(locationDst, funcDst); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f()"); |
| } |
| |
| void Renderer::bindActiveTexturesSamplers (void) |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| for (int idx = 0; idx < m_samplersRequired; idx++) |
| { |
| std::ostringstream stream; |
| stream << "uTexture" << idx; |
| std::string uniformName(stream.str()); |
| glw::GLint location = gl.getUniformLocation(m_shaderProgram->getHandle(), uniformName.c_str()); |
| DE_ASSERT(location != -1); |
| gl.uniform1i(location, m_textureSourceList[idx]->getTextureUnit()); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation()"); |
| } |
| } |
| |
| void Renderer::bindAllRequiredSourceTextures (const TextureSourcesType texturesRequired) |
| { |
| if (texturesRequired == TEXTURESOURCESTYPE_RGBA) |
| m_textureSourceList[0]->bind(0); |
| else if (texturesRequired == TEXTURESOURCESTYPE_SRGBA) |
| m_textureSourceList[1]->bind(0); |
| else if (texturesRequired == TEXTURESOURCESTYPE_BOTH) |
| { |
| m_textureSourceList[0]->bind(0); |
| m_textureSourceList[1]->bind(1); |
| } |
| else |
| DE_FATAL("Error: Invalid sources requested in bind all"); |
| } |
| |
| void Renderer::unbindAllSourceTextures (void) |
| { |
| for (int idx = 0; idx < (int)m_textureSourceList.size(); idx++) |
| m_textureSourceList[idx]->unbind(); |
| } |
| |
| void Renderer::bindFramebuffer (const int framebufferIdx) |
| { |
| m_framebufferList[framebufferIdx]->bind(); |
| } |
| |
| void Renderer::unbindFramebuffer (const int framebufferIdx) |
| { |
| m_framebufferList[framebufferIdx]->unbind(); |
| } |
| |
| void Renderer::enableFramebufferSRGB (void) |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_framebufferSRGBEnabled) |
| gl.enable(GL_FRAMEBUFFER_SRGB); |
| else |
| gl.disable(GL_FRAMEBUFFER_SRGB); |
| } |
| |
| void Renderer::enableFramebufferBlend (void) |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| tcu::TestLog& log = m_context.getTestContext().getLog(); |
| std::ostringstream message; |
| |
| message << "Blend settings = "; |
| |
| if (m_framebufferBlendEnabled) |
| { |
| gl.enable(GL_BLEND); |
| gl.blendEquation(m_blendConfigList[m_blendIteration].equation); |
| gl.blendFunc(m_blendConfigList[m_blendIteration].funcSrc, m_blendConfigList[m_blendIteration].funcDst); |
| |
| std::string equation, src, dst; |
| if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_ADD) |
| equation = "GL_FUNC_ADD"; |
| if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_SUBTRACT) |
| equation = "GL_FUNC_SUBTRACT"; |
| if (m_blendConfigList[m_blendIteration].equation == GL_FUNC_REVERSE_SUBTRACT) |
| equation = "GL_FUNC_REVERSE_SUBTRACT"; |
| if (m_blendConfigList[m_blendIteration].funcSrc == GL_ONE) |
| src = "GL_ONE"; |
| else |
| src = "GL_ZERO"; |
| if (m_blendConfigList[m_blendIteration].funcDst == GL_ONE) |
| dst = "GL_ONE"; |
| else |
| dst = "GL_ZERO"; |
| |
| message << "Enabled: equation = " << equation << ", func src = " << src << ", func dst = " << dst; |
| } |
| else |
| { |
| gl.disable(GL_BLEND); |
| message << "Disabled"; |
| } |
| |
| log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; |
| } |
| |
| bool Renderer::isFramebufferAttachmentSRGB (const deUint32 targetType, const deUint32 attachment) const |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| glw::GLint encodingType; |
| |
| gl.getFramebufferAttachmentParameteriv(targetType, attachment, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encodingType); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetNamedFramebufferAttachmentParameteriv()"); |
| |
| switch (static_cast<glw::GLenum>(encodingType)) |
| { |
| case GL_SRGB: |
| { |
| return true; |
| break; |
| } |
| case GL_LINEAR: |
| { |
| return false; |
| break; |
| } |
| default: |
| { |
| DE_FATAL("Error: Color attachment format not recognised"); |
| return false; |
| } |
| } |
| } |
| |
| void Renderer::readTexels (const int px, const int py, const deUint32 mode, tcu::Vec4& texelData) |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| tcu::TextureLevel textureRead; |
| |
| // ensure result sampling coordinates are within range of the result color attachment |
| DE_ASSERT((px >= 0) && (px < m_context.getRenderTarget().getWidth())); |
| DE_ASSERT((py >= 0) && (py < m_context.getRenderTarget().getHeight())); |
| |
| gl.readBuffer(mode); |
| textureRead.setStorage(glu::mapGLTransferFormat(GL_RGBA, GL_UNSIGNED_BYTE), TestTextureSizes::WIDTH, TestTextureSizes::HEIGHT); |
| glu::readPixels(m_context.getRenderContext(), px, py, textureRead.getAccess()); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()"); |
| texelData = textureRead.getAccess().getPixel(px, py); |
| } |
| |
| void Renderer::logState (const deUint32 targetType, const deUint32 attachment, const SamplingType samplingType) const |
| { |
| tcu::TestLog& log = m_context.getTestContext().getLog(); |
| std::ostringstream message; |
| |
| bool fboAttachmentSRGB = this->isFramebufferAttachmentSRGB(targetType, attachment); |
| message.str(""); |
| message << "getFramebufferAttachmentParameteriv() check = "; |
| if (fboAttachmentSRGB) |
| message << "GL_SRGB"; |
| else |
| message << "GL_LINEAR"; |
| log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; |
| |
| message.str(""); |
| message << "Framebuffer color attachment value BEFORE draw call"; |
| logColor(m_context, message.str(), m_resultsListPreDraw[m_renderPass]); |
| |
| message.str(""); |
| message << "Framebuffer color attachment value AFTER draw call"; |
| logColor(m_context, message.str(), m_resultsListPostDraw[m_renderPass]); |
| |
| message.str(""); |
| message << "Sampling type = "; |
| std::string type; |
| if (samplingType == 0) |
| type = "texture()"; |
| else if (samplingType == 1) |
| type = "textureLOD()"; |
| else if (samplingType == 2) |
| type = "textureGrad()"; |
| else if (samplingType == 3) |
| type = "textureOffset()"; |
| else if (samplingType == 4) |
| type = "textureProj()"; |
| else |
| DE_FATAL("Error: Sampling type unregonised"); |
| message << type; |
| log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; |
| |
| message.str(""); |
| if (m_framebufferSRGBEnabled) |
| message << "Framebuffer SRGB = enabled"; |
| else |
| message << "Framebuffer SRGB = disabled"; |
| log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; |
| } |
| |
| class FboSRGBTestCase : public TestCase |
| { |
| public: |
| FboSRGBTestCase (Context& context, const char* const name, const char* const desc); |
| ~FboSRGBTestCase (void); |
| |
| void init (void); |
| void deinit (void); |
| IterateResult iterate (void); |
| |
| void setTestConfig (std::vector<TestRenderPassConfig> renderPassConfigList); |
| |
| virtual void setupTest (void) = 0; |
| virtual bool verifyResult (void) = 0; |
| |
| protected: |
| bool m_hasTestConfig; |
| std::vector<TestRenderPassConfig> m_renderPassConfigList; |
| bool m_testcaseRequiresBlend; |
| std::vector<tcu::Vec4> m_resultsPreDraw; |
| std::vector<tcu::Vec4> m_resultsPostDraw; |
| |
| private: |
| FboSRGBTestCase (const FboSRGBTestCase&); |
| FboSRGBTestCase& operator= (const FboSRGBTestCase&); |
| }; |
| |
| FboSRGBTestCase::FboSRGBTestCase (Context& context, const char* const name, const char* const desc) |
| : TestCase (context, name, desc) |
| , m_hasTestConfig (false) |
| { |
| } |
| |
| FboSRGBTestCase::~FboSRGBTestCase (void) |
| { |
| FboSRGBTestCase::deinit(); |
| } |
| |
| void FboSRGBTestCase::init (void) |
| { |
| // extensions requirements for test |
| if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2))) |
| TCU_THROW(NotSupportedError, "Test requires a context version equal or higher than 3.2"); |
| |
| if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control")) |
| TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control"); |
| |
| if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_decode")) |
| TCU_THROW(NotSupportedError, "Test requires GL_EXT_texture_sRGB_decode extension"); |
| } |
| |
| void FboSRGBTestCase::deinit (void) |
| { |
| } |
| |
| FboSRGBTestCase::IterateResult FboSRGBTestCase::iterate (void) |
| { |
| this->setupTest(); |
| |
| DE_ASSERT(m_hasTestConfig && "Error: Renderer was not supplied a test config"); |
| |
| Renderer renderer(m_context); |
| |
| // loop through each sampling type |
| for (int samplingIdx = 0; samplingIdx < SampligTypeCount::MAX; samplingIdx++) |
| { |
| renderer.setSamplingType(static_cast<SamplingType>(samplingIdx)); |
| |
| // loop through each blend configuration |
| const int blendCount = renderer.getBlendConfigCount(); |
| for (int blendIdx = 0; blendIdx < blendCount; blendIdx++) |
| { |
| // loop through each render pass |
| const int renderPassCount = (int)m_renderPassConfigList.size(); |
| for (int renderPassIdx = 0; renderPassIdx < renderPassCount; renderPassIdx++) |
| { |
| TestRenderPassConfig renderPassConfig = m_renderPassConfigList[renderPassIdx]; |
| |
| renderer.init(renderPassConfig, renderPassIdx); |
| |
| if (blendIdx == 0 && renderPassConfig.rendererTask == RENDERERTASK_DRAW) |
| renderer.storeShaderProgramInfo(); |
| |
| if (renderPassConfig.frameBufferBlend == FRAMEBUFFERBLEND_ENABLED) |
| { |
| renderer.setBlendIteration(blendIdx); |
| renderer.setFramebufferBlend(true); |
| } |
| else |
| renderer.setFramebufferBlend(false); |
| |
| if (renderPassConfig.framebufferSRGB == FRAMEBUFFERSRGB_ENABLED) |
| renderer.setFramebufferSRGB(true); |
| else |
| renderer.setFramebufferSRGB(false); |
| |
| if (renderPassConfig.rendererTask == RENDERERTASK_DRAW) |
| renderer.draw(); |
| else if (renderPassConfig.rendererTask == RENDERERTASK_COPY) |
| renderer.copyFrameBufferTexture(0, 0, 0, 0); |
| else |
| DE_FATAL("Error: render task not recognised"); |
| |
| renderer.deinit(); |
| |
| } // render passes |
| |
| m_resultsPreDraw = renderer.getResultsPreDraw(); |
| m_resultsPostDraw = renderer.getResultsPostDraw(); |
| |
| bool testPassed = this->verifyResult(); |
| if (testPassed) |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed"); |
| renderer.logShaderProgramInfo(); |
| return STOP; |
| } |
| |
| if (!m_testcaseRequiresBlend) |
| break; |
| } // blend configs |
| |
| renderer.logShaderProgramInfo(); |
| } // sampling types |
| |
| return STOP; |
| } |
| |
| void FboSRGBTestCase::setTestConfig (std::vector<TestRenderPassConfig> renderPassConfigList) |
| { |
| m_renderPassConfigList = renderPassConfigList; |
| m_hasTestConfig = true; |
| |
| for (int idx = 0; idx < (int)renderPassConfigList.size(); idx++) |
| { |
| if (renderPassConfigList[idx].frameBufferBlend == FRAMEBUFFERBLEND_ENABLED) |
| { |
| m_testcaseRequiresBlend = true; |
| return; |
| } |
| } |
| m_testcaseRequiresBlend = false; |
| } |
| |
| class FboSRGBQueryCase : public TestCase |
| { |
| public: |
| FboSRGBQueryCase (Context& context, const char* const name, const char* const description); |
| ~FboSRGBQueryCase (void); |
| |
| void init (void); |
| void deinit (void); |
| IterateResult iterate (void); |
| }; |
| |
| FboSRGBQueryCase::FboSRGBQueryCase (Context& context, const char* const name, const char* const description) |
| : TestCase (context, name, description) |
| { |
| } |
| |
| FboSRGBQueryCase::~FboSRGBQueryCase (void) |
| { |
| FboSRGBQueryCase::deinit(); |
| } |
| |
| void FboSRGBQueryCase::init (void) |
| { |
| // extension requirements for test |
| if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control")) |
| TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control"); |
| } |
| |
| void FboSRGBQueryCase::deinit (void) |
| { |
| } |
| |
| FboSRGBQueryCase::IterateResult FboSRGBQueryCase::iterate (void) |
| { |
| // TEST INFO: |
| // API tests which check when querying FRAMEBUFFER_SRGB_EXT capability returns the correct information when using glEnabled() or glDisabled() |
| |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| tcu::TestLog& log = m_context.getTestContext().getLog(); |
| const char* const msgPart = ", after disabling = "; |
| |
| for (int idx = 0; idx < static_cast<int>(QUERYTYPE_LAST); idx++) |
| { |
| std::ostringstream message; |
| bool pass = false; |
| |
| message << std::string("Results: After Enabling = "); |
| |
| gl.enable(GL_FRAMEBUFFER_SRGB); |
| |
| switch (static_cast<QueryType>(idx)) |
| { |
| case QUERYTYPE_ISENABLED: |
| { |
| glw::GLboolean enabled[2]; |
| enabled[0] = gl.isEnabled(GL_FRAMEBUFFER_SRGB); |
| gl.disable(GL_FRAMEBUFFER_SRGB); |
| enabled[1] = gl.isEnabled(GL_FRAMEBUFFER_SRGB); |
| |
| message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); |
| pass = (enabled[0] && !(enabled[1])) ? true : false; |
| break; |
| } |
| case QUERYTYPE_BOOLEAN: |
| { |
| glw::GLboolean enabled[2]; |
| gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[0]); |
| gl.disable(GL_FRAMEBUFFER_SRGB); |
| gl.getBooleanv(GL_FRAMEBUFFER_SRGB,&enabled[1]); |
| |
| message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); |
| pass = (enabled[0] && !(enabled[1])) ? true : false; |
| break; |
| } |
| case QUERYTYPE_FLOAT: |
| { |
| glw::GLfloat enabled[2]; |
| gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[0]); |
| gl.disable(GL_FRAMEBUFFER_SRGB); |
| gl.getFloatv(GL_FRAMEBUFFER_SRGB, &enabled[1]); |
| |
| message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); |
| pass = ((int)enabled[0] && !((int)enabled[1])) ? true : false; |
| break; |
| } |
| case QUERYTYPE_INT: |
| { |
| glw::GLint enabled[2]; |
| gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[0]); |
| gl.disable(GL_FRAMEBUFFER_SRGB); |
| gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &enabled[1]); |
| |
| message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); |
| pass = (enabled[0] && !(enabled[1])) ? true : false; |
| break; |
| } |
| case QUERYTYPE_INT64: |
| { |
| glw::GLint64 enabled[2]; |
| gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[0]); |
| gl.disable(GL_FRAMEBUFFER_SRGB); |
| gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &enabled[1]); |
| |
| message << static_cast<float>(enabled[0]) << msgPart << static_cast<float>(enabled[1]); |
| pass = (enabled[0] && !(enabled[1])) ? true : false; |
| break; |
| } |
| default: |
| DE_FATAL("Error: Datatype not recognised"); |
| } |
| |
| log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage; |
| |
| if (pass) |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed"); |
| return STOP; |
| } |
| } |
| return STOP; |
| } |
| |
| class FboSRGBColAttachCase : public FboSRGBTestCase |
| { |
| public: |
| FboSRGBColAttachCase (Context& context, const char* const name, const char* const description) |
| : FboSRGBTestCase (context, name, description) {} |
| ~FboSRGBColAttachCase (void) {} |
| |
| void setupTest (void); |
| bool verifyResult (void); |
| }; |
| |
| void FboSRGBColAttachCase::setupTest (void) |
| { |
| // TEST INFO: |
| // Check if FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING set to SRGB and FRAMEBUFFER_SRGB_EXT enabled, destination colors are converted from SRGB to linear |
| // before and after blending, finally the result is converted back to SRGB for storage |
| |
| // NOTE: |
| // if fbo pre-draw color set to linaer, color values get linearlized "twice" |
| // (0.2f, 0.3f, 0.4f, 1.0f) when sampled i.e. converted in shader = (0.0331048f, 0.073239f, 0.132868f) |
| // 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) |
| |
| FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE); |
| FBOConfig fboConfig1 = FBOConfig(GL_RGBA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE); |
| |
| const TestRenderPassConfig renderPassConfigs[] = |
| { |
| TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_ENABLED, RENDERERTASK_DRAW), |
| TestRenderPassConfig(TEXTURESOURCESTYPE_BOTH, fboConfig1, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, getFunctionBlendLinearToSRGBCheck(), RENDERERTASK_DRAW) |
| }; |
| std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs)); |
| |
| this->setTestConfig(renderPassConfigList); |
| } |
| |
| bool FboSRGBColAttachCase::verifyResult (void) |
| { |
| if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], m_resultsPostDraw[1]))) |
| return true; |
| else |
| return false; |
| } |
| |
| class FboSRGBToggleBlendCase : public FboSRGBTestCase |
| { |
| public: |
| FboSRGBToggleBlendCase (Context& context, const char* const name, const char* const description) |
| : FboSRGBTestCase (context, name, description) {} |
| ~FboSRGBToggleBlendCase (void) {} |
| |
| void setupTest (void); |
| bool verifyResult (void); |
| }; |
| |
| void FboSRGBToggleBlendCase::setupTest (void) |
| { |
| // TEST INFO: |
| // Test to check if changing FRAMEBUFFER_SRGB_EXT from enabled to disabled. Enabled should produce SRGB color whilst disabled |
| // should produce linear color. Test conducted with blending disabled. |
| |
| FBOConfig fboConfig0 = FBOConfig(GL_SRGB8_ALPHA8, getTestColorLinear(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION); |
| |
| const TestRenderPassConfig renderPassConfigs[] = |
| { |
| TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW), |
| TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_DISABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW) |
| }; |
| std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs)); |
| |
| this->setTestConfig(renderPassConfigList); |
| } |
| |
| bool FboSRGBToggleBlendCase::verifyResult (void) |
| { |
| if (tcu::boolAny(tcu::greaterThan(tcu::abs(m_resultsPostDraw[0] - m_resultsPostDraw[1]), getEpsilonError()))) |
| return true; |
| else |
| return false; |
| } |
| |
| class FboSRGBRenderTargetIgnoreCase : public FboSRGBTestCase |
| { |
| public: |
| FboSRGBRenderTargetIgnoreCase (Context& context, const char* const name, const char* const description) |
| : FboSRGBTestCase (context, name, description) {} |
| ~FboSRGBRenderTargetIgnoreCase (void) {} |
| |
| void setupTest (void); |
| bool verifyResult (void); |
| }; |
| |
| void FboSRGBRenderTargetIgnoreCase::setupTest (void) |
| { |
| // TEST INFO: |
| // Check if render targets that are non-RGB ignore the state of GL_FRAMEBUFFER_SRGB_EXT. Rendering to an fbo with non-sRGB color |
| // attachment should ignore color space conversion, producing linear color. |
| |
| FBOConfig fboConfig0 = FBOConfig(GL_RGBA8, getTestColorBlank(), GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION); |
| |
| const TestRenderPassConfig renderPassConfigs[] = |
| { |
| TestRenderPassConfig(TEXTURESOURCESTYPE_RGBA, fboConfig0, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_DRAW) |
| |
| }; |
| std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs)); |
| |
| this->setTestConfig(renderPassConfigList); |
| } |
| |
| bool FboSRGBRenderTargetIgnoreCase::verifyResult (void) |
| { |
| if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[0] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[0], getTestColorLinear()))) |
| return true; |
| else |
| return false; |
| } |
| |
| class FboSRGBCopyToLinearCase : public FboSRGBTestCase |
| { |
| public: |
| FboSRGBCopyToLinearCase (Context& context, const char* const name, const char* const description) |
| : FboSRGBTestCase (context, name, description) {} |
| ~FboSRGBCopyToLinearCase (void) {} |
| |
| void setupTest (void); |
| bool verifyResult (void); |
| }; |
| |
| void FboSRGBCopyToLinearCase::setupTest (void) |
| { |
| // TEST INFO: |
| // 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 |
| // an sRGB to linear conversion |
| |
| FBOConfig fboConfigs[] = |
| { |
| FBOConfig(GL_SRGB8_ALPHA8, getTestColorSRGB(), GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_SOURCE), |
| FBOConfig(GL_RGBA8, getTestColorBlank(), GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FBOTYPE_DESTINATION) |
| }; |
| std::vector<FBOConfig> fboConfigList(fboConfigs, fboConfigs + DE_LENGTH_OF_ARRAY(fboConfigs)); |
| |
| const TestRenderPassConfig renderPassConfigs[] = |
| { |
| TestRenderPassConfig(TEXTURESOURCESTYPE_NONE, fboConfigList, FRAMEBUFFERSRGB_ENABLED, FRAMEBUFFERBLEND_DISABLED, TestFunction(false), RENDERERTASK_COPY) |
| }; |
| std::vector<TestRenderPassConfig> renderPassConfigList(renderPassConfigs, renderPassConfigs + DE_LENGTH_OF_ARRAY(renderPassConfigs)); |
| |
| this->setTestConfig(renderPassConfigList); |
| } |
| |
| bool FboSRGBCopyToLinearCase::verifyResult (void) |
| { |
| logColor(m_context, "pre-copy source fbo color values", m_resultsPreDraw[0]); |
| logColor(m_context, "pre-copy destination fbo color values", m_resultsPreDraw[1]); |
| logColor(m_context, "post-copy source fbo color values", m_resultsPostDraw[0]); |
| logColor(m_context, "post-copy destination fbo color values", m_resultsPostDraw[1]); |
| |
| if (tcu::boolAll(tcu::lessThan(tcu::abs(m_resultsPostDraw[1] - getTestColorLinear()), getEpsilonError())) || tcu::boolAll(tcu::equal(m_resultsPostDraw[1], getTestColorLinear()))) |
| return true; |
| else |
| return false; |
| } |
| |
| class FboSRGBUnsupportedEnumCase : public TestCase |
| { |
| public: |
| FboSRGBUnsupportedEnumCase (Context& context, const char* const name, const char* const description); |
| ~FboSRGBUnsupportedEnumCase (void); |
| |
| void init (void); |
| void deinit (void); |
| bool isInvalidEnum (std::string functionName); |
| IterateResult iterate (void); |
| }; |
| |
| FboSRGBUnsupportedEnumCase::FboSRGBUnsupportedEnumCase (Context& context, const char* const name, const char* const description) |
| : TestCase (context, name, description) |
| { |
| } |
| |
| FboSRGBUnsupportedEnumCase::~FboSRGBUnsupportedEnumCase (void) |
| { |
| FboSRGBUnsupportedEnumCase::deinit(); |
| } |
| |
| void FboSRGBUnsupportedEnumCase::init (void) |
| { |
| // extension requirements for test |
| if (m_context.getContextInfo().isExtensionSupported("GL_EXT_sRGB_write_control")) |
| TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_sRGB_write_control to be unsupported"); |
| } |
| |
| void FboSRGBUnsupportedEnumCase::deinit (void) |
| { |
| } |
| |
| bool FboSRGBUnsupportedEnumCase::isInvalidEnum (std::string functionName) |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| tcu::TestLog& log = m_context.getTestContext().getLog(); |
| bool isOk = true; |
| glw::GLenum error = GL_NO_ERROR; |
| |
| log << tcu::TestLog::Message << "Checking call to " << functionName << tcu::TestLog::EndMessage; |
| |
| error = gl.getError(); |
| |
| if (error != GL_INVALID_ENUM) |
| { |
| log << tcu::TestLog::Message << " returned wrong value [" << glu::getErrorStr(error) << ", expected " << glu::getErrorStr(GL_INVALID_ENUM) << "]" << tcu::TestLog::EndMessage; |
| isOk = false; |
| } |
| |
| return isOk; |
| } |
| |
| FboSRGBUnsupportedEnumCase::IterateResult FboSRGBUnsupportedEnumCase::iterate (void) |
| { |
| // TEST INFO: |
| // API tests that check calls using enum GL_FRAMEBUFFER_SRGB return GL_INVALID_ENUM when GL_EXT_sRGB_write_control is not supported |
| |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool allPass = true; |
| glw::GLboolean bEnabled = GL_FALSE; |
| glw::GLfloat fEnabled = 0; |
| glw::GLint iEnabled = 0; |
| glw::GLint64 lEnabled = 0; |
| |
| m_context.getTestContext().getLog() << tcu::TestLog::Message |
| << "Check calls using enum GL_FRAMEBUFFER_SRGB return GL_INVALID_ENUM when GL_EXT_sRGB_write_control is not supported\n\n" |
| << tcu::TestLog::EndMessage; |
| |
| gl.enable(GL_FRAMEBUFFER_SRGB); |
| allPass &= isInvalidEnum("glEnable()"); |
| |
| gl.disable(GL_FRAMEBUFFER_SRGB); |
| allPass &= isInvalidEnum("glDisable()"); |
| |
| gl.isEnabled(GL_FRAMEBUFFER_SRGB); |
| allPass &= isInvalidEnum("glIsEnabled()"); |
| |
| gl.getBooleanv(GL_FRAMEBUFFER_SRGB, &bEnabled); |
| allPass &= isInvalidEnum("glGetBooleanv()"); |
| |
| gl.getFloatv(GL_FRAMEBUFFER_SRGB, &fEnabled); |
| allPass &= isInvalidEnum("glGetFloatv()"); |
| |
| gl.getIntegerv(GL_FRAMEBUFFER_SRGB, &iEnabled); |
| allPass &= isInvalidEnum("glGetIntegerv()"); |
| |
| gl.getInteger64v(GL_FRAMEBUFFER_SRGB, &lEnabled); |
| allPass &= isInvalidEnum("glGetInteger64v()"); |
| |
| if (allPass) |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| else |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| |
| return STOP; |
| } |
| |
| } // anonymous |
| |
| FboSRGBWriteControlTests::FboSRGBWriteControlTests (Context& context) |
| : TestCaseGroup (context, "srgb_write_control", "Colorbuffer tests") |
| { |
| } |
| |
| FboSRGBWriteControlTests::~FboSRGBWriteControlTests (void) |
| { |
| } |
| |
| void FboSRGBWriteControlTests::init (void) |
| { |
| this->addChild(new FboSRGBQueryCase (m_context, "framebuffer_srgb_enabled", "srgb enable framebuffer")); |
| this->addChild(new FboSRGBColAttachCase (m_context, "framebuffer_srgb_enabled_col_attach", "srgb enable color attachment and framebuffer")); |
| this->addChild(new FboSRGBToggleBlendCase (m_context, "framebuffer_srgb_enabled_blend", "toggle framebuffer srgb settings with blend disabled")); |
| this->addChild(new FboSRGBRenderTargetIgnoreCase (m_context, "framebuffer_srgb_enabled_render_target_ignore", "enable framebuffer srgb, non-srgb render target should ignore")); |
| this->addChild(new FboSRGBCopyToLinearCase (m_context, "framebuffer_srgb_enabled_copy_to_linear", "no conversion when blittering between framebuffer srgb and linear")); |
| |
| // negative |
| this->addChild(new FboSRGBUnsupportedEnumCase (m_context, "framebuffer_srgb_unsupported_enum", "check error codes for query functions when extension is not supported")); |
| } |
| |
| } |
| } // gles31 |
| } // deqp |