You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1879 lines
58 KiB
1879 lines
58 KiB
/*-------------------------------------------------------------------------
|
|
* 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)
|
|
{
|
|
if (glu::isContextTypeES(m_context.getRenderContext().getType()))
|
|
{
|
|
// 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)
|
|
{
|
|
if(!glu::isContextTypeES(m_context.getRenderContext().getType()))
|
|
TCU_THROW(NotSupportedError, "The test is not supported in a non-GLES context");
|
|
|
|
// 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
|