blob: 82a994eccb4a779813f756429898ad3c162429ae [file] [log] [blame]
/*-------------------------------------------------------------------------
* OpenGL Conformance Test Suite
* -----------------------------
*
* Copyright (c) 2015-2016 The Khronos Group Inc.
*
* 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
*/ /*-------------------------------------------------------------------*/
/**
* \file gl3cTextureSizePromotionTests.hpp
* \brief Implements test classes for testing of texture internal format
promotion mechanism.
*/ /*-------------------------------------------------------------------*/
#include "gl3cTextureSizePromotion.hpp"
#include "deMath.h"
#include "gluContextInfo.hpp"
#include "gluStrUtil.hpp"
#include "glwFunctions.hpp"
#include "tcuTestLog.hpp"
/* Stringify macro. */
#define _STR(s) STR(s)
#define STR(s) #s
namespace gl3cts
{
namespace TextureSizePromotion
{
Tests::Tests(deqp::Context& context)
: TestCaseGroup(context, "texture_size_promotion", "Verifies texture internal format size promotion mechanism.")
{
/* Left blank on purpose */
}
void Tests::init(void)
{
addChild(new TextureSizePromotion::FunctionalTest(m_context));
}
/*===========================================================================================================*/
FunctionalTest::FunctionalTest(deqp::Context& context)
: TestCase(context, "functional", "Verifies that texture internal format size promotion mechanism can be used.")
, m_vao(0)
, m_source_texture(0)
, m_destination_texture(0)
, m_framebuffer(0)
, m_program(0)
, m_max_samples(0)
{
/* Left blank on purpose */
}
tcu::TestNode::IterateResult FunctionalTest::iterate()
{
/* Get context setup. */
glu::ContextType context_type = m_context.getRenderContext().getType();
bool is_arb_texture_storage_multisample =
m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_storage_multisample");
/* Prepare initial results. */
bool is_ok = true;
bool was_error = false;
/* Iterate over test cases. */
try
{
/* Only for OpenGL 3.1 context. */
if (glu::contextSupports(context_type, glu::ApiType::core(3, 1)))
{
/* Generate and bind VAO. */
prepareVertexArrayObject();
/* For every required format */
for (glw::GLuint i = 0; i < s_formats_size; ++i)
{
/* Test only if format is required by context. */
if (glu::contextSupports(context_type, s_formats[i].required_by_context.getAPI()))
{
/* For every target. */
for (glw::GLuint j = 0; j < s_source_texture_targets_count; ++j)
{
/* Test if it is supported by context or internal format. */
if (isTargetMultisampled(s_source_texture_targets[j]))
{
if ((!is_arb_texture_storage_multisample) &&
(!glu::contextSupports(context_type, glu::ApiType::core(4, 3))))
{
continue;
}
if (!s_formats[i]
.is_color_renderable) /* Multisampled textures need to be set using rendering. */
{
continue;
}
if (isDepthType(s_formats[i]) || isStencilType(s_formats[i]))
{
continue;
}
}
if ((isDepthType(s_formats[i]) || isStencilType(s_formats[i])) &&
(GL_TEXTURE_3D == s_source_texture_targets[j]))
{
continue;
}
/* Prepare source texture to be tested. */
try
{
prepareSourceTexture(s_formats[i], s_source_texture_targets[j]);
}
catch (tcu::NotSupportedError&)
{
continue;
}
/* Check basic API queries for source texture. */
if (is_ok) is_ok = checkSourceTextureSizeAndType(s_formats[i], s_source_texture_targets[j]);
/* For every [R, G, B, A] component. */
for (glw::GLuint k = 0; k < COMPONENTS_COUNT; ++k)
{
/* Prepare destination texture. */
prepareDestinationTextureAndFramebuffer(s_formats[i], GL_TEXTURE_2D);
/* Building program (throws on failure). */
m_program =
prepareProgram(s_source_texture_targets[j], s_formats[i], ColorChannelSelector(k));
/* Setup GL and draw. */
makeProgramAndSourceTextureActive(s_source_texture_targets[j]);
drawQuad();
/* Check results. */
if (is_ok) is_ok = checkDestinationTexture(s_formats[i], ColorChannelSelector(k),
s_source_texture_targets[j],
s_source_texture_targets_names[j]);
/* Cleanup. */
cleanDestinationTexture();
cleanFramebuffer();
cleanProgram();
}
cleanSourceTexture();
}
}
}
}
}
catch (...)
{
/* Error have occured. */
is_ok = false;
was_error = true;
}
/* Clean all. */
cleanSourceTexture();
cleanDestinationTexture();
cleanFramebuffer();
cleanProgram();
cleanVertexArrayObject();
/* Result's setup. */
if (is_ok)
{
/* Log success. */
m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture Size Promotion Test have passed."
<< tcu::TestLog::EndMessage;
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
}
else
{
if (was_error)
{
/* Log error. */
m_context.getTestContext().getLog() << tcu::TestLog::Message
<< "Texture Size Promotion Test have approached error."
<< tcu::TestLog::EndMessage;
m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
}
else
{
/* Log fail. */
m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture Size Promotion Test have failed."
<< tcu::TestLog::EndMessage;
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
}
}
/* End test. */
return tcu::TestNode::STOP;
}
void FunctionalTest::prepareVertexArrayObject()
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.genVertexArrays(1, &m_vao);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays have failed");
gl.bindVertexArray(m_vao);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray have failed");
}
void FunctionalTest::prepareSourceTexture(TextureInternalFormatDescriptor descriptor, glw::GLenum target)
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Create and bind texture object. */
gl.genTextures(1, &m_source_texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
gl.bindTexture(target, m_source_texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
if (!isTargetMultisampled(target))
{
glu::ContextType context_type = m_context.getRenderContext().getType();
if (isDepthType(descriptor) && glu::contextSupports(context_type, glu::ApiType::core(3, 1)))
{
/* 3.1 context may have GL_ARB_compatibility which has
* GL_DEPTH_TEXTURE_MODE set to GL_LUMINANCE by default.
* Set it to GL_RED since we expect depth texture sampling
* to return vec4(depth, 0, 0, 1).
*/
gl.texParameteri(target, 0x884B, GL_RED);
gl.getError();
}
gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
}
/* Select proper data set. */
glw::GLvoid* source_data = DE_NULL;
glw::GLenum source_type = GL_NONE;
glw::GLenum source_format = GL_RGBA;
if (isFloatType(descriptor)) /* For floating type. */
{
source_data = (glw::GLvoid*)s_source_texture_data_f;
source_type = GL_FLOAT;
source_format = GL_RGBA;
}
else
{
if (isFixedSignedType(descriptor)) /* For fixed signed type. */
{
source_data = (glw::GLvoid*)s_source_texture_data_sn;
source_type = GL_FLOAT;
source_format = GL_RGBA;
}
else
{
if (isFixedUnsignedType(descriptor)) /* For fixed unsigned type. */
{
source_data = (glw::GLvoid*)s_source_texture_data_n;
source_type = GL_FLOAT;
source_format = GL_RGBA;
}
else
{
if (isIntegerSignedType(descriptor)) /* For integral signed type. */
{
source_data = (glw::GLvoid*)s_source_texture_data_i;
source_type = GL_INT;
source_format = GL_RGBA_INTEGER;
}
else
{
if (isIntegerUnsignedType(descriptor)) /* For integral unsigned type. */
{
source_data = (glw::GLvoid*)s_source_texture_data_ui;
source_type = GL_UNSIGNED_INT;
source_format = GL_RGBA_INTEGER;
}
else
{
if (isDepthType(descriptor)) /* For depth type. */
{
source_data = (glw::GLvoid*)s_source_texture_data_f;
source_type = GL_FLOAT;
source_format = GL_DEPTH_COMPONENT;
}
else
{
if (isStencilType(descriptor)) /* For stencil type. */
{
source_data = (glw::GLvoid*)s_source_texture_data_ui;
source_type = GL_UNSIGNED_INT;
source_format = GL_STENCIL_INDEX;
}
}
}
}
}
}
}
/* Prepare texture storage depending on the target. */
switch (target)
{
case GL_TEXTURE_1D:
gl.texImage1D(target, 0, descriptor.internal_format, s_source_texture_size, 0, source_format, source_type,
source_data);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
break;
case GL_TEXTURE_1D_ARRAY:
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE:
gl.texImage2D(target, 0, descriptor.internal_format, s_source_texture_size, s_source_texture_size, 0,
source_format, source_type, source_data);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
break;
case GL_TEXTURE_2D_ARRAY:
case GL_TEXTURE_3D:
gl.texImage3D(target, 0, descriptor.internal_format, s_source_texture_size, s_source_texture_size,
s_source_texture_size, 0, source_format, source_type, source_data);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
break;
case GL_TEXTURE_2D_MULTISAMPLE:
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
renderDataIntoMultisampledTexture(descriptor, target);
break;
default:
throw 0;
}
}
void FunctionalTest::renderDataIntoMultisampledTexture(TextureInternalFormatDescriptor descriptor, glw::GLenum target)
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Fetch limits. */
gl.getIntegerv(GL_MAX_SAMPLES, &m_max_samples);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv have failed");
if (m_max_samples == 0)
{
m_max_samples = 1;
}
/* Setup target. */
glw::GLenum non_ms_target = (target == GL_TEXTURE_2D_MULTISAMPLE) ? GL_TEXTURE_2D : GL_TEXTURE_2D_ARRAY;
/* Cleanup required by prepareSourceTexture(...). */
cleanSourceTexture();
/* Prepare textures and program. */
prepareSourceTexture(descriptor, non_ms_target);
prepareDestinationTextureAndFramebuffer(descriptor, target);
m_program = prepareProgram(non_ms_target, descriptor, COMPONENTS_COUNT);
/* Setup GL and render texture. */
makeProgramAndSourceTextureActive(non_ms_target);
drawQuad();
/* Cleanup. */
cleanFramebuffer();
cleanSourceTexture();
/* Swpaing destination texture to source texture. */
m_source_texture = m_destination_texture;
m_destination_texture = 0;
/* Clean program. */
cleanProgram();
}
void FunctionalTest::prepareDestinationTextureAndFramebuffer(TextureInternalFormatDescriptor descriptor,
glw::GLenum target)
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Get internal format. */
glw::GLenum internal_format = getDestinationFormatForChannel(descriptor);
/* Create framebuffer object. */
gl.genFramebuffers(1, &m_framebuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
/* Create framebuffer's destination texture. */
gl.genTextures(1, &m_destination_texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
gl.bindTexture(target, m_destination_texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
/* Allocate texture storage and upload data for test rendering. */
if (target == GL_TEXTURE_2D)
{
glw::GLenum destination_format = GL_RED;
glw::GLenum destination_type = GL_FLOAT;
glw::GLvoid* destination_data = (glw::GLvoid*)s_destination_texture_data_f;
if (isIntegerSignedType(descriptor))
{
destination_format = GL_RED_INTEGER;
destination_type = GL_INT;
destination_data = (glw::GLvoid*)s_destination_texture_data_i;
}
if (isIntegerUnsignedType(descriptor))
{
destination_format = GL_RED_INTEGER;
destination_type = GL_UNSIGNED_INT;
destination_data = (glw::GLvoid*)s_destination_texture_data_ui;
}
gl.texImage2D(target, 0, internal_format, s_source_texture_size, s_source_texture_size, 0, destination_format,
destination_type, destination_data);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_destination_texture, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D have failed");
}
else /* Allocate texture storage for uploading datat for multisampled targets (upload must be done via shader). */
{
if (target == GL_TEXTURE_2D_MULTISAMPLE)
{
gl.texImage2DMultisample(target, m_max_samples - 1, descriptor.internal_format, s_source_texture_size,
s_source_texture_size, GL_TRUE);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, m_destination_texture, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D have failed");
}
else
{
gl.texImage3DMultisample(target, m_max_samples - 1, descriptor.internal_format, s_source_texture_size,
s_source_texture_size, s_source_texture_size, GL_TRUE);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
gl.framebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_destination_texture, 0, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D have failed");
}
}
/* Check framebuffer completness. */
if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_UNSUPPORTED)
throw tcu::NotSupportedError("unsupported framebuffer configuration");
else
throw 0;
}
/* Setup viewport. */
gl.viewport(0, 0, s_source_texture_size, s_source_texture_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
}
void FunctionalTest::makeProgramAndSourceTextureActive(glw::GLenum target)
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Use GLSL program. */
gl.useProgram(m_program);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram have failed");
/* Setup source texture. */
gl.activeTexture(GL_TEXTURE0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture have failed");
gl.bindTexture(target, m_source_texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
glw::GLint location = gl.getUniformLocation(m_program, "data");
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation have failed");
gl.uniform1i(location, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i have failed");
}
bool FunctionalTest::checkSourceTextureSizeAndType(TextureInternalFormatDescriptor descriptor, glw::GLenum target)
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* query result storage */
glw::GLint red_size = 0;
glw::GLint blue_size = 0;
glw::GLint green_size = 0;
glw::GLint alpha_size = 0;
glw::GLint depth_size = 0;
glw::GLint stencil_size = 0;
glw::GLint red_type = 0;
glw::GLint green_type = 0;
glw::GLint blue_type = 0;
glw::GLint alpha_type = 0;
glw::GLint depth_type = 0;
/* Bind texture */
gl.bindTexture(target, m_source_texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
/* queries */
gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_RED_SIZE, &red_size);
gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_GREEN_SIZE, &green_size);
gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_BLUE_SIZE, &blue_size);
gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size);
gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_DEPTH_SIZE, &depth_size);
gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_STENCIL_SIZE, &stencil_size);
gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_RED_TYPE, &red_type);
gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_GREEN_TYPE, &green_type);
gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_BLUE_TYPE, &blue_type);
gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_ALPHA_TYPE, &alpha_type);
gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_DEPTH_TYPE, &depth_type);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv have failed");
/* check expected values */
bool is_ok = true;
is_ok = is_ok && (red_size >= descriptor.min_red_size);
is_ok = is_ok && (green_size >= descriptor.min_green_size);
is_ok = is_ok && (blue_size >= descriptor.min_blue_size);
is_ok = is_ok && (alpha_size >= descriptor.min_alpha_size);
is_ok = is_ok && (depth_size >= descriptor.min_depth_size);
is_ok = is_ok && (stencil_size >= descriptor.min_stencil_size);
is_ok = is_ok && ((glw::GLenum)red_type == descriptor.expected_red_type);
is_ok = is_ok && ((glw::GLenum)green_type == descriptor.expected_green_type);
is_ok = is_ok && ((glw::GLenum)blue_type == descriptor.expected_blue_type);
is_ok = is_ok && ((glw::GLenum)alpha_type == descriptor.expected_alpha_type);
is_ok = is_ok && ((glw::GLenum)depth_type == descriptor.expected_depth_type);
/* Log on failure. */
if (!is_ok)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
<< " have failed during glGetTexLevelParameteriv query. "
<< "Expected red size = " << descriptor.min_red_size
<< ", expected green size = " << descriptor.min_green_size
<< ", expected blue size = " << descriptor.min_blue_size
<< ", expected alpha size = " << descriptor.min_alpha_size
<< ", expected depth size = " << descriptor.min_depth_size
<< ", expected stencil size = " << descriptor.min_stencil_size << ". Queried red size = " << red_size
<< ", queried green size = " << green_size << ", queried blue size = " << blue_size
<< ", queried alpha size = " << alpha_size << ", queried depth size = " << depth_size
<< ", queried stencil size = " << stencil_size << ". "
<< "Expected red type = " << glu::getTypeStr(descriptor.expected_red_type)
<< ", expected green type = " << glu::getTypeStr(descriptor.expected_green_type)
<< ", expected blue type = " << glu::getTypeStr(descriptor.expected_blue_type)
<< ", expected alpha type = " << glu::getTypeStr(descriptor.expected_alpha_type)
<< ", expected depth type = " << glu::getTypeStr(descriptor.expected_depth_type)
<< ". Queried red type = " << glu::getTypeStr(red_type)
<< ", queried green type = " << glu::getTypeStr(green_type)
<< ", queried blue type = " << glu::getTypeStr(blue_type)
<< ", queried alpha type = " << glu::getTypeStr(alpha_type)
<< ", queried depth type = " << glu::getTypeStr(depth_type) << "." << tcu::TestLog::EndMessage;
}
/* return results. */
return is_ok;
}
glw::GLenum FunctionalTest::getDestinationFormatForChannel(TextureInternalFormatDescriptor descriptor)
{
if (isFloatType(descriptor))
{
return GL_R32F;
}
if (isFixedUnsignedType(descriptor))
{
return GL_R16;
}
if (isFixedSignedType(descriptor))
{
return GL_R16_SNORM;
}
if (isIntegerUnsignedType(descriptor))
{
return GL_R32UI;
}
if (isIntegerSignedType(descriptor))
{
return GL_R32I;
}
return GL_R32F;
}
glw::GLuint FunctionalTest::prepareProgram(glw::GLenum target, TextureInternalFormatDescriptor descriptor,
ColorChannelSelector channel)
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Preparing sampler name and textelFetch arguments */
std::string sampler_name = "";
std::string texel_fetch_arguments_tail = "";
switch (target)
{
case GL_TEXTURE_1D:
sampler_name = "sampler1D";
texel_fetch_arguments_tail = "0, 0";
break;
case GL_TEXTURE_2D:
sampler_name = "sampler2D";
texel_fetch_arguments_tail = "ivec2(0), 0";
break;
case GL_TEXTURE_1D_ARRAY:
sampler_name = "sampler1DArray";
texel_fetch_arguments_tail = "ivec2(0), 0";
break;
case GL_TEXTURE_RECTANGLE:
sampler_name = "sampler2DRect";
texel_fetch_arguments_tail = "ivec2(0)";
break;
case GL_TEXTURE_2D_ARRAY:
sampler_name = "sampler2DArray";
texel_fetch_arguments_tail = "ivec3(0), 0";
break;
case GL_TEXTURE_3D:
sampler_name = "sampler3D";
texel_fetch_arguments_tail = "ivec3(0), 0";
break;
case GL_TEXTURE_2D_MULTISAMPLE:
sampler_name = "sampler2DMS";
texel_fetch_arguments_tail = "ivec2(0), ";
texel_fetch_arguments_tail.append(Utilities::itoa(m_max_samples - 1));
break;
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
sampler_name = "sampler2DMSArray";
texel_fetch_arguments_tail = "ivec3(0), ";
texel_fetch_arguments_tail.append(Utilities::itoa(m_max_samples - 1));
break;
default:
throw 0;
}
/* Preparing component selector name */
std::string component_name = "";
switch (channel)
{
case RED_COMPONENT:
component_name = ".r";
break;
case GREEN_COMPONENT:
component_name = ".g";
break;
case BLUE_COMPONENT:
component_name = ".b";
break;
case ALPHA_COMPONENT:
component_name = ".a";
break;
case COMPONENTS_COUNT:
break;
default:
throw 0;
}
/* Preparing output type name and sampler prefix */
std::string type_name = "";
std::string sampler_prefix = "";
if (isFloatType(descriptor) || isFixedSignedType(descriptor) || isFixedUnsignedType(descriptor) ||
isDepthType(descriptor) || isStencilType(descriptor))
{
if (channel == COMPONENTS_COUNT)
{
type_name = "vec4";
}
else
{
type_name = "float";
}
sampler_prefix = "";
}
else
{
if (isIntegerSignedType(descriptor))
{
if (channel == COMPONENTS_COUNT)
{
type_name = "ivec4";
}
else
{
type_name = "int";
}
sampler_prefix = "i";
}
else
{
if (channel == COMPONENTS_COUNT)
{
type_name = "uvec4";
}
else
{
type_name = "uint";
}
sampler_prefix = "u";
}
}
/* Preprocessing fragment shader source code. */
std::string fragment_shader = s_fragment_shader_template;
fragment_shader = Utilities::preprocessString(fragment_shader, "TEMPLATE_TYPE", type_name);
fragment_shader =
Utilities::preprocessString(fragment_shader, "TEMPLATE_SAMPLER", sampler_prefix.append(sampler_name));
fragment_shader =
Utilities::preprocessString(fragment_shader, "TEMPLATE_TEXEL_FETCH_ARGUMENTS", texel_fetch_arguments_tail);
fragment_shader = Utilities::preprocessString(fragment_shader, "TEMPLATE_COMPONENT", component_name);
/* Building program. */
glw::GLuint program =
Utilities::buildProgram(gl, m_context.getTestContext().getLog(), s_vertex_shader_code, fragment_shader.c_str());
if (0 == program)
{
throw 0;
}
/* Return program name. */
return program;
}
void FunctionalTest::drawQuad()
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Draw quad. */
gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays have failed");
}
void FunctionalTest::cleanSourceTexture()
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Delete object. */
if (m_source_texture)
{
gl.deleteTextures(1, &m_source_texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures have failed");
m_source_texture = 0;
}
}
void FunctionalTest::cleanDestinationTexture()
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Delete object. */
if (m_destination_texture)
{
gl.deleteTextures(1, &m_destination_texture);
m_destination_texture = 0;
}
}
void FunctionalTest::cleanFramebuffer()
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Delete object. */
if (m_framebuffer)
{
gl.deleteFramebuffers(1, &m_framebuffer);
m_framebuffer = 0;
}
}
void FunctionalTest::cleanProgram()
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Delete object. */
if (m_program)
{
gl.useProgram(0);
gl.deleteProgram(m_program);
m_program = 0;
}
}
void FunctionalTest::cleanVertexArrayObject()
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Delete object. */
if (m_vao)
{
gl.deleteVertexArrays(1, &m_vao);
m_vao = 0;
}
}
bool FunctionalTest::checkDestinationTexture(TextureInternalFormatDescriptor descriptor, ColorChannelSelector channel,
glw::GLenum target, const glw::GLchar* target_name)
{
/* GL functions object. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Check depending on format. */
if (isDepthType(descriptor) || isStencilType(descriptor))
{
/* Fetch results from destination texture (attached to current framebuffer). */
glw::GLfloat pixel = 3.1415927f;
gl.readPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &pixel);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
/* Setup expected value. */
glw::GLfloat expected_value = (channel == RED_COMPONENT) ?
s_source_texture_data_f[0] :
(channel == ALPHA_COMPONENT) ? 1.f : 0.f;
/* Compare expected and fetched values. */
if (fabs(pixel - expected_value) <= getMinPrecision(descriptor, channel))
{
/* Test succeeded*/
return true;
}
else
{
/* Log failure. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
<< " have failed during functional test of " << s_color_channel_names[channel]
<< " channel with target " << target_name << ". Expected value = " << expected_value
<< " read value = " << pixel << "." << tcu::TestLog::EndMessage;
}
}
else
{
if (isFloatType(descriptor))
{
/* Fetch results from destination texture (attached to current framebuffer). */
glw::GLfloat pixel = 3.1415927f;
gl.readPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &pixel);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
/* Setup expected value. */
glw::GLfloat expected_value = isChannelTypeNone(descriptor, channel) ?
((channel == ALPHA_COMPONENT) ? 1.f : 0.f) :
s_source_texture_data_f[channel];
/* Compare expected and fetched values. */
if (fabs(pixel - expected_value) <= getMinPrecision(descriptor, channel))
{
/* Test succeeded*/
return true;
}
else
{
/* Log failure. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
<< " have failed during functional test of " << s_color_channel_names[channel]
<< " channel with target " << target_name << ". Expected value = " << expected_value
<< " read value = " << pixel << "." << tcu::TestLog::EndMessage;
}
}
else
{
if (isFixedSignedType(descriptor))
{
/* Fetch results from destination texture (attached to current framebuffer). */
glw::GLfloat pixel = 3.1415927f;
gl.readPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &pixel);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
/* Setup expected value. */
/* Signed fixed-point read color are clamped to [0, 1] by default */
glw::GLfloat expected_value = isChannelTypeNone(descriptor, channel) ?
((channel == ALPHA_COMPONENT) ? 1.f : 0.f) :
deFloatClamp(s_source_texture_data_sn[channel], 0, 1);
/* Compare expected and fetched values. */
if (fabs(pixel - expected_value) <= getMinPrecision(descriptor, channel))
{
/* Test succeeded*/
return true;
}
else
{
/* Log failure. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
<< " have failed during functional test of " << s_color_channel_names[channel]
<< " channel with target " << target_name << ". Expected value = " << expected_value
<< " read value = " << pixel << "." << tcu::TestLog::EndMessage;
}
}
else
{
if (isFixedUnsignedType(descriptor))
{
/* Fetch results from destination texture (attached to current framebuffer). */
glw::GLfloat pixel = 3.1415927f;
gl.readPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &pixel);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
/* Setup expected value. */
glw::GLfloat expected_value = isChannelTypeNone(descriptor, channel) ?
((channel == ALPHA_COMPONENT) ? 1.f : 0.f) :
s_source_texture_data_n[channel];
/* For sRGB internal formats convert value to linear space. */
if (descriptor.is_sRGB && (channel < ALPHA_COMPONENT))
{
expected_value = convert_from_sRGB(expected_value);
if (isTargetMultisampled(
target)) /* In multisampled targets two conversions are made (in upload and in shader) */
{
expected_value = convert_from_sRGB(expected_value);
}
}
/* Compare expected and fetched values. */
if (fabs(pixel - expected_value) <= getMinPrecision(descriptor, channel))
{
/* Test succeeded*/
return true;
}
else
{
/* Log failure. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Promotion from internal format " << descriptor.internal_format_name
<< " have failed during functional test of " << s_color_channel_names[channel]
<< " channel with target " << target_name << ". Expected value = " << expected_value
<< " read value = " << pixel << "." << tcu::TestLog::EndMessage;
}
}
else
{
if (isIntegerSignedType(descriptor))
{
/* Fetch results from destination texture (attached to current framebuffer). */
glw::GLint pixel = 5;
gl.readPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_INT, &pixel);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
/* Setup expected value. */
glw::GLint expected_value = isChannelTypeNone(descriptor, channel) ?
((channel == ALPHA_COMPONENT) ? 1 : 0) :
s_source_texture_data_i[channel];
/* Compare expected and fetched values. */
if (pixel == expected_value)
{
/* Test succeeded*/
return true;
}
else
{
/* Log failure. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Promotion from internal format "
<< descriptor.internal_format_name << " have failed during functional test of "
<< s_color_channel_names[channel] << " channel with target " << target_name
<< ". Expected value = " << expected_value << " read value = " << pixel << "."
<< tcu::TestLog::EndMessage;
}
}
else
{
if (isIntegerUnsignedType(descriptor))
{
/* Fetch results from destination texture (attached to current framebuffer). */
glw::GLuint pixel = 5;
gl.readPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixel);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
/* Setup expected value. */
glw::GLuint expected_value = isChannelTypeNone(descriptor, channel) ?
((channel == ALPHA_COMPONENT) ? 1 : 0) :
s_source_texture_data_ui[channel];
/* Compare expected and fetched values. */
if (pixel == expected_value)
{
/* Test succeeded*/
return true;
}
else
{
/* Log failure. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Promotion from internal format "
<< descriptor.internal_format_name << " have failed during functional test of "
<< s_color_channel_names[channel] << " channel with target " << target_name
<< ". Expected value = " << expected_value << " read value = " << pixel << "."
<< tcu::TestLog::EndMessage;
}
}
}
}
}
}
}
/* Test failed. */
return false;
}
bool FunctionalTest::isFloatType(TextureInternalFormatDescriptor descriptor)
{
return (GL_FLOAT == descriptor.expected_red_type) || (GL_FLOAT == descriptor.expected_green_type) ||
(GL_FLOAT == descriptor.expected_blue_type) || (GL_FLOAT == descriptor.expected_alpha_type);
}
bool FunctionalTest::isFixedSignedType(TextureInternalFormatDescriptor descriptor)
{
return (GL_SIGNED_NORMALIZED == descriptor.expected_red_type) ||
(GL_SIGNED_NORMALIZED == descriptor.expected_green_type) ||
(GL_SIGNED_NORMALIZED == descriptor.expected_blue_type) ||
(GL_SIGNED_NORMALIZED == descriptor.expected_alpha_type);
}
bool FunctionalTest::isFixedUnsignedType(TextureInternalFormatDescriptor descriptor)
{
return (GL_UNSIGNED_NORMALIZED == descriptor.expected_red_type) ||
(GL_UNSIGNED_NORMALIZED == descriptor.expected_green_type) ||
(GL_UNSIGNED_NORMALIZED == descriptor.expected_blue_type) ||
(GL_UNSIGNED_NORMALIZED == descriptor.expected_alpha_type);
}
bool FunctionalTest::isIntegerSignedType(TextureInternalFormatDescriptor descriptor)
{
return (GL_INT == descriptor.expected_red_type) || (GL_INT == descriptor.expected_green_type) ||
(GL_INT == descriptor.expected_blue_type) || (GL_INT == descriptor.expected_alpha_type);
}
bool FunctionalTest::isIntegerUnsignedType(TextureInternalFormatDescriptor descriptor)
{
return (GL_UNSIGNED_INT == descriptor.expected_red_type) || (GL_UNSIGNED_INT == descriptor.expected_green_type) ||
(GL_UNSIGNED_INT == descriptor.expected_blue_type) || (GL_UNSIGNED_INT == descriptor.expected_alpha_type);
}
bool FunctionalTest::isDepthType(TextureInternalFormatDescriptor descriptor)
{
return (GL_NONE != descriptor.expected_depth_type);
}
bool FunctionalTest::isStencilType(TextureInternalFormatDescriptor descriptor)
{
return (descriptor.min_stencil_size > 0);
}
bool FunctionalTest::isChannelTypeNone(TextureInternalFormatDescriptor descriptor, ColorChannelSelector channel)
{
switch (channel)
{
case RED_COMPONENT:
return (GL_NONE == descriptor.expected_red_type);
case GREEN_COMPONENT:
return (GL_NONE == descriptor.expected_green_type);
case BLUE_COMPONENT:
return (GL_NONE == descriptor.expected_blue_type);
case ALPHA_COMPONENT:
return (GL_NONE == descriptor.expected_alpha_type);
default:
throw 0;
}
return false;
}
glw::GLfloat FunctionalTest::getMinPrecision(TextureInternalFormatDescriptor descriptor, ColorChannelSelector channel)
{
/* Select channel data. */
glw::GLenum type = GL_NONE;
glw::GLuint size = 0;
switch (channel)
{
case RED_COMPONENT:
type = descriptor.expected_red_type;
size = descriptor.min_red_size;
break;
case GREEN_COMPONENT:
type = descriptor.expected_green_type;
size = descriptor.min_green_size;
break;
case BLUE_COMPONENT:
type = descriptor.expected_blue_type;
size = descriptor.min_blue_size;
break;
case ALPHA_COMPONENT:
type = descriptor.expected_alpha_type;
size = descriptor.min_alpha_size;
break;
default:
throw 0;
}
/* If it is empty channel. */
if ((type == GL_NONE) || (size == 0))
{
return 0.1f;
}
/* If float type. */
if (isFloatType(descriptor))
{
switch (size)
{
case 32:
return 0.00001f; /* specification GL4.5 core constant */
case 16:
return 1.f / 1024.f; /* specification GL4.5 core 10 bit mantisa constant */
case 11:
return 1.f / 64.f; /* specification GL4.5 core 6 bit mantisa constant */
case 10:
return 1.f / 32.f; /* specification GL4.5 core 5 bit mantisa constant */
default:
return 0.00001f;
}
}
/* Fixed types precision */
if (isFixedSignedType(descriptor))
{
return (float)(2.0 / pow(2.0, (double)(size - 1 /* sign bit */)));
}
if (isFixedUnsignedType(descriptor))
{
return (float)(2.0 / pow(2.0, (double)(size)));
}
/* other aka (unsigned) integer */
return 1;
}
bool FunctionalTest::isTargetMultisampled(glw::GLenum target)
{
return (GL_TEXTURE_2D_MULTISAMPLE == target) || (GL_TEXTURE_2D_MULTISAMPLE_ARRAY == target);
}
float FunctionalTest::convert_from_sRGB(float value)
{
/* For reference check OpenGL specification (eg. OpenGL 4.5 core profile specification chapter 8.24 */
if (value > 0.04045f)
{
return deFloatPow((value + 0.055f) / 1.055f, 2.4f);
}
return value / 12.92f;
}
const glw::GLfloat FunctionalTest::s_source_texture_data_f[] = { 0.125f, 0.25f, 0.5f, 0.75f };
const glw::GLfloat FunctionalTest::s_source_texture_data_n[] = { 0.125f, 0.25f, 0.5f, 0.75f };
const glw::GLfloat FunctionalTest::s_source_texture_data_sn[] = { -0.125f, 0.25f, -0.5f, 0.75f };
const glw::GLint FunctionalTest::s_source_texture_data_i[] = { -1, 2, -3, 4 };
const glw::GLuint FunctionalTest::s_source_texture_data_ui[] = { 4, 3, 2, 1 };
const glw::GLfloat FunctionalTest::s_destination_texture_data_f[] = {
5.f
}; /* False data for destination texture to be overwriten. */
const glw::GLint FunctionalTest::s_destination_texture_data_i[] = {
-5
}; /* False data for destination texture to be overwriten. */
const glw::GLuint FunctionalTest::s_destination_texture_data_ui[] = {
5
}; /* False data for destination texture to be overwriten. */
const glw::GLenum FunctionalTest::s_source_texture_targets[] = {
GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_RECTANGLE,
GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D, GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY
};
const glw::GLchar* FunctionalTest::s_source_texture_targets_names[] = {
STR(GL_TEXTURE_1D), STR(GL_TEXTURE_2D), STR(GL_TEXTURE_1D_ARRAY), STR(GL_TEXTURE_RECTANGLE),
STR(GL_TEXTURE_2D_ARRAY), STR(GL_TEXTURE_3D), STR(GL_TEXTURE_2D_MULTISAMPLE), STR(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
};
const glw::GLuint FunctionalTest::s_source_texture_targets_count =
sizeof(s_source_texture_targets) / sizeof(s_source_texture_targets[0]);
const glw::GLuint FunctionalTest::s_source_texture_size = 1;
const glw::GLchar* FunctionalTest::s_color_channel_names[] = { "red", "green", "blue", "alpha", "all" };
const FunctionalTest::TextureInternalFormatDescriptor FunctionalTest::s_formats[] = {
/* context version, internal format, internal format name, is sRGB, CR,size{R, G, B, A, D, S}, type of R, type of G, type of B, type of A, type of depth */
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R8, STR(GL_R8), false, true, 8, 0, 0, 0, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_R8_SNORM, STR(GL_R8_SNORM), false, true, 8, 0, 0, 0, 0, 0,
GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R16, STR(GL_R16), false, true, 16, 0, 0, 0, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_R16_SNORM, STR(GL_R16_SNORM), false, true, 16, 0, 0, 0, 0, 0,
GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG8, STR(GL_RG8), false, true, 8, 8, 0, 0, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RG8_SNORM, STR(GL_RG8_SNORM), false, true, 8, 8, 0, 0, 0, 0,
GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG16, STR(GL_RG16), false, true, 16, 16, 0, 0, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RG16_SNORM, STR(GL_RG16_SNORM), false, true, 16, 16, 0, 0, 0, 0,
GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_R3_G3_B2, STR(GL_R3_G3_B2), false, true, 3, 3, 2, 0, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGB4, STR(GL_RGB4), false, true, 4, 4, 4, 0, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGB5, STR(GL_RGB5), false, true, 5, 5, 5, 0, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB8, STR(GL_RGB8), false, true, 8, 8, 8, 0, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RGB8_SNORM, STR(GL_RGB8_SNORM), false, true, 8, 8, 8, 0, 0, 0,
GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE },
{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGB10, STR(GL_RGB10), false, true, 10, 10, 10, 0, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGB12, STR(GL_RGB12), false, true, 12, 12, 12, 0, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB16, STR(GL_RGB16), false, true, 16, 16, 16, 0, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RGB16_SNORM, STR(GL_RGB16_SNORM), false, true, 16, 16, 16, 0, 0, 0,
GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE, GL_NONE },
{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGBA2, STR(GL_RGBA2), false, true, 2, 2, 2, 2, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
{ glu::ContextType(4, 2, glu::PROFILE_CORE), GL_RGBA4, STR(GL_RGBA4), false, true, 4, 4, 4, 4, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
{ glu::ContextType(4, 2, glu::PROFILE_CORE), GL_RGB5_A1, STR(GL_RGB5_A1), false, true, 5, 5, 5, 1, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA8, STR(GL_RGBA8), false, true, 8, 8, 8, 8, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RGBA8_SNORM, STR(GL_RGBA8_SNORM), false, true, 8, 8, 8, 8, 0, 0,
GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB10_A2, STR(GL_RGB10_A2), false, true, 10, 10, 10, 2, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
{ glu::ContextType(3, 3, glu::PROFILE_CORE), GL_RGB10_A2UI, STR(GL_RGB10_A2UI), false, true, 10, 10, 10, 2, 0, 0,
GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE },
{ glu::ContextType(4, 4, glu::PROFILE_CORE), GL_RGBA12, STR(GL_RGBA12), false, true, 12, 12, 12, 12, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA16, STR(GL_RGBA16), false, true, 16, 16, 16, 16, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
{ glu::ContextType(3, 1, glu::PROFILE_CORE), GL_RGBA16_SNORM, STR(GL_RGBA16_SNORM), false, true, 16, 16, 16, 16, 0,
0, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_SIGNED_NORMALIZED, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_SRGB8, STR(GL_SRGB8), true, true, 8, 8, 8, 0, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_SRGB8_ALPHA8, STR(GL_SRGB8_ALPHA8), true, true, 8, 8, 8, 8, 0, 0,
GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_NORMALIZED, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R16F, STR(GL_R16F), false, true, 16, 0, 0, 0, 0, 0, GL_FLOAT,
GL_NONE, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG16F, STR(GL_RG16F), false, true, 16, 16, 0, 0, 0, 0, GL_FLOAT,
GL_FLOAT, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB16F, STR(GL_RGB16F), false, true, 16, 16, 16, 0, 0, 0, GL_FLOAT,
GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA16F, STR(GL_RGBA16F), false, true, 16, 16, 16, 16, 0, 0,
GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R32F, STR(GL_R32F), false, true, 32, 0, 0, 0, 0, 0, GL_FLOAT,
GL_NONE, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG32F, STR(GL_RG32F), false, true, 32, 32, 0, 0, 0, 0, GL_FLOAT,
GL_FLOAT, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB32F, STR(GL_RGB32F), false, true, 32, 32, 32, 0, 0, 0, GL_FLOAT,
GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA32F, STR(GL_RGBA32F), false, true, 32, 32, 32, 32, 0, 0,
GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R11F_G11F_B10F, STR(GL_R11F_G11F_B10F), false, true, 11, 11, 10, 0,
0, 0, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB9_E5, STR(GL_RGB9_E5), false, false, 9, 9, 9, 0, 0, 0, GL_FLOAT,
GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R8I, STR(GL_R8I), false, true, 8, 0, 0, 0, 0, 0, GL_INT, GL_NONE,
GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R8UI, STR(GL_R8UI), false, true, 8, 0, 0, 0, 0, 0, GL_UNSIGNED_INT,
GL_NONE, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R16I, STR(GL_R16I), false, true, 16, 0, 0, 0, 0, 0, GL_INT, GL_NONE,
GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R16UI, STR(GL_R16UI), false, true, 16, 0, 0, 0, 0, 0,
GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R32I, STR(GL_R32I), false, true, 32, 0, 0, 0, 0, 0, GL_INT, GL_NONE,
GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_R32UI, STR(GL_R32UI), false, true, 32, 0, 0, 0, 0, 0,
GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG8I, STR(GL_RG8I), false, true, 8, 8, 0, 0, 0, 0, GL_INT, GL_INT,
GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG8UI, STR(GL_RG8UI), false, true, 8, 8, 0, 0, 0, 0,
GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG16I, STR(GL_RG16I), false, true, 16, 16, 0, 0, 0, 0, GL_INT,
GL_INT, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG16UI, STR(GL_RG16UI), false, true, 16, 16, 0, 0, 0, 0,
GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG32I, STR(GL_RG32I), false, true, 32, 32, 0, 0, 0, 0, GL_INT,
GL_INT, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RG32UI, STR(GL_RG32UI), false, true, 32, 32, 0, 0, 0, 0,
GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB8I, STR(GL_RGB8I), false, true, 8, 8, 8, 0, 0, 0, GL_INT, GL_INT,
GL_INT, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB8UI, STR(GL_RGB8UI), false, true, 8, 8, 8, 0, 0, 0,
GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB16I, STR(GL_RGB16I), false, true, 16, 16, 16, 0, 0, 0, GL_INT,
GL_INT, GL_INT, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB16UI, STR(GL_RGB16UI), false, true, 16, 16, 16, 0, 0, 0,
GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB32I, STR(GL_RGB32I), false, true, 32, 32, 32, 0, 0, 0, GL_INT,
GL_INT, GL_INT, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGB32UI, STR(GL_RGB32UI), false, true, 32, 32, 32, 0, 0, 0,
GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA8I, STR(GL_RGBA8I), false, true, 8, 8, 8, 8, 0, 0, GL_INT,
GL_INT, GL_INT, GL_INT, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA8UI, STR(GL_RGBA8UI), false, true, 8, 8, 8, 8, 0, 0,
GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA16I, STR(GL_RGBA16I), false, true, 16, 16, 16, 16, 0, 0, GL_INT,
GL_INT, GL_INT, GL_INT, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA16UI, STR(GL_RGBA16UI), false, true, 16, 16, 16, 16, 0, 0,
GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA32I, STR(GL_RGBA32I), false, true, 32, 32, 32, 32, 0, 0, GL_INT,
GL_INT, GL_INT, GL_INT, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_RGBA32UI, STR(GL_RGBA32UI), false, true, 32, 32, 32, 32, 0, 0,
GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH_COMPONENT16, STR(GL_DEPTH_COMPONENT16), false, true, 0, 0, 0,
0, 16, 0, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_UNSIGNED_NORMALIZED },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH_COMPONENT24, STR(GL_DEPTH_COMPONENT24), false, true, 0, 0, 0,
0, 24, 0, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_UNSIGNED_NORMALIZED },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH_COMPONENT32F, STR(GL_DEPTH_COMPONENT32F), false, true, 0, 0,
0, 0, 32, 0, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_FLOAT },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH24_STENCIL8, STR(GL_DEPTH24_STENCIL8), false, true, 0, 0, 0, 0,
24, 8, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_UNSIGNED_NORMALIZED },
{ glu::ContextType(3, 0, glu::PROFILE_CORE), GL_DEPTH32F_STENCIL8, STR(GL_DEPTH32F_STENCIL8), false, true, 0, 0, 0,
0, 32, 8, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_FLOAT }
};
const glw::GLuint FunctionalTest::s_formats_size = sizeof(s_formats) / sizeof(s_formats[0]);
const glw::GLchar* FunctionalTest::s_vertex_shader_code = "#version 140\n"
"\n"
"void main()\n"
"{\n"
" switch(gl_VertexID % 4)\n"
" {\n"
" case 0:\n"
" gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
" break;\n"
" case 1:\n"
" gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
" break;\n"
" case 2:\n"
" gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
" break;\n"
" case 3:\n"
" gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
" break;\n"
" }\n"
"}\n";
const glw::GLchar* FunctionalTest::s_fragment_shader_template =
"#version 140\n"
"#extension GL_ARB_texture_multisample : enable\n"
"\n"
"out TEMPLATE_TYPE result;\n"
"\n"
"uniform TEMPLATE_SAMPLER data;\n"
"\n"
"void main()\n"
"{\n"
" result = texelFetch(data, TEMPLATE_TEXEL_FETCH_ARGUMENTS)TEMPLATE_COMPONENT;\n"
"}\n";
/*===========================================================================================================*/
namespace Utilities
{
glw::GLuint buildProgram(glw::Functions const& gl, tcu::TestLog& log, glw::GLchar const* const vertex_shader_source,
glw::GLchar const* const fragment_shader_source)
{
glw::GLuint program = 0;
struct Shader
{
glw::GLchar const* const source;
glw::GLenum const type;
glw::GLuint id;
} shader[] = { { vertex_shader_source, GL_VERTEX_SHADER, 0 }, { fragment_shader_source, GL_FRAGMENT_SHADER, 0 } };
glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
try
{
/* Create program. */
program = gl.createProgram();
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
/* Shader compilation. */
for (glw::GLuint i = 0; i < shader_count; ++i)
{
if (DE_NULL != shader[i].source)
{
shader[i].id = gl.createShader(shader[i].type);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
gl.attachShader(program, shader[i].id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
gl.compileShader(shader[i].id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
glw::GLint status = GL_FALSE;
gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
if (GL_FALSE == status)
{
glw::GLint log_size = 0;
gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
glw::GLchar* log_text = new glw::GLchar[log_size];
gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
log << tcu::TestLog::Message << "Shader compilation has failed.\n"
<< "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
<< "Shader compilation error log:\n"
<< log_text << "\n"
<< "Shader source code:\n"
<< shader[i].source << "\n"
<< tcu::TestLog::EndMessage;
delete[] log_text;
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
throw 0;
}
}
}
/* Link. */
gl.linkProgram(program);
GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
glw::GLint status = GL_FALSE;
gl.getProgramiv(program, GL_LINK_STATUS, &status);
if (GL_TRUE == status)
{
for (glw::GLuint i = 0; i < shader_count; ++i)
{
if (shader[i].id)
{
gl.detachShader(program, shader[i].id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
}
}
}
else
{
glw::GLint log_size = 0;
gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &log_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
glw::GLchar* log_text = new glw::GLchar[log_size];
gl.getProgramInfoLog(program, log_size, NULL, &log_text[0]);
log << tcu::TestLog::Message << "Program linkage has failed due to:\n"
<< log_text << "\n"
<< tcu::TestLog::EndMessage;
delete[] log_text;
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
throw 0;
}
}
catch (...)
{
if (program)
{
gl.deleteProgram(program);
program = 0;
}
}
for (glw::GLuint i = 0; i < shader_count; ++i)
{
if (0 != shader[i].id)
{
gl.deleteShader(shader[i].id);
shader[i].id = 0;
}
}
return program;
}
std::string preprocessString(std::string source, std::string key, std::string value)
{
std::string destination = source;
while (true)
{
/* Find token in source code. */
size_t position = destination.find(key, 0);
/* No more occurences of this key. */
if (position == std::string::npos)
{
break;
}
/* Replace token with sub_code. */
destination.replace(position, key.size(), value);
}
return destination;
}
std::string itoa(glw::GLint i)
{
std::stringstream stream;
stream << i;
return stream.str();
}
} // namespace Utilities
} // namespace TextureSizePromotion
} // namespace gl3cts