blob: 5ab8c6e991f677b69729636ff97c13f72d4028d9 [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 gl4cDirectStateAccessXFBTests.cpp
* \brief Conformance tests for the Direct State Access feature functionality (Transform Feedbeck access part).
*/ /*-----------------------------------------------------------------------------------------------------------*/
/* Includes. */
#include "gl4cDirectStateAccessTests.hpp"
#include "deSharedPtr.hpp"
#include "gluContextInfo.hpp"
#include "gluDefs.hpp"
#include "gluPixelTransfer.hpp"
#include "gluStrUtil.hpp"
#include "tcuFuzzyImageCompare.hpp"
#include "tcuImageCompare.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuSurface.hpp"
#include "tcuTestLog.hpp"
#include "glw.h"
#include "glwFunctions.hpp"
namespace gl4cts
{
namespace DirectStateAccess
{
namespace Samplers
{
/******************************** Creation Test Implementation ********************************/
/** @brief Creation Test constructor.
*
* @param [in] context OpenGL context.
*/
CreationTest::CreationTest(deqp::Context& context)
: deqp::TestCase(context, "samplers_creation", "Sampler Objects Creation Test")
{
/* Intentionally left blank. */
}
/** @brief Iterate Creation Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult CreationTest::iterate()
{
/* Shortcut for GL functionality */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Get context setup. */
bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
{
m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
return STOP;
}
/* Running tests. */
bool is_ok = true;
bool is_error = false;
/* Samplers objects */
static const glw::GLuint samplers_count = 2;
glw::GLuint samplers_dsa[samplers_count] = {};
try
{
/* Check direct state creation. */
gl.createSamplers(samplers_count, samplers_dsa);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateSamplers have failed");
for (glw::GLuint i = 0; i < samplers_count; ++i)
{
if (!gl.isSampler(samplers_dsa[i]))
{
is_ok = false;
/* Log. */
m_context.getTestContext().getLog() << tcu::TestLog::Message
<< "CreateSamplers has not created defualt objects."
<< tcu::TestLog::EndMessage;
}
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
for (glw::GLuint i = 0; i < samplers_count; ++i)
{
if (samplers_dsa[i])
{
gl.deleteSamplers(1, &samplers_dsa[i]);
samplers_dsa[i] = 0;
}
}
/* Result's setup. */
if (is_ok)
{
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
}
else
{
if (is_error)
{
m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
}
else
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
}
}
return STOP;
}
/******************************** Defaults Test Implementation ********************************/
/** @brief Defaults Test constructor.
*
* @param [in] context OpenGL context.
*/
DefaultsTest::DefaultsTest(deqp::Context& context)
: deqp::TestCase(context, "samplers_defaults", "Samplers Defaults Test"), m_sampler_dsa(0)
{
/* Intentionally left blank. */
}
/** @brief Iterate Defaults Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult DefaultsTest::iterate()
{
/* Get context setup. */
bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
{
m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
return STOP;
}
/* Running tests. */
bool is_ok = true;
bool is_error = false;
try
{
prepare();
glw::GLfloat expected_vector[4] = { 0.0, 0.0, 0.0, 0.0 };
is_ok &= testSamplerFloatVectorParameter(GL_TEXTURE_BORDER_COLOR, expected_vector);
is_ok &= testSamplerIntegerParameter(GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
is_ok &= testSamplerIntegerParameter(GL_TEXTURE_COMPARE_MODE, GL_NONE);
is_ok &= testSamplerFloatParameter(GL_TEXTURE_LOD_BIAS, 0.0);
is_ok &= testSamplerFloatParameter(GL_TEXTURE_MAX_LOD, 1000);
is_ok &= testSamplerIntegerParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
is_ok &= testSamplerIntegerParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
is_ok &= testSamplerFloatParameter(GL_TEXTURE_MIN_LOD, -1000);
is_ok &= testSamplerIntegerParameter(GL_TEXTURE_WRAP_S, GL_REPEAT);
is_ok &= testSamplerIntegerParameter(GL_TEXTURE_WRAP_T, GL_REPEAT);
is_ok &= testSamplerIntegerParameter(GL_TEXTURE_WRAP_R, GL_REPEAT);
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Clean up. */
clean();
/* Result's setup. */
if (is_ok)
{
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
}
else
{
if (is_error)
{
m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
}
else
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
}
}
return STOP;
}
/** @brief Create Sampler Objects.
*
* @note The function may throw if unexpected error has occured.
*
* @return True if test succeeded, false otherwise.
*/
void DefaultsTest::prepare()
{
/* Shortcut for GL functionality */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Sampler object creation */
gl.createSamplers(1, &m_sampler_dsa);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
}
/** @brief Test Sampler Integer Parameter.
*
* @note The function may throw if unexpected error has occured.
*
* @return True if test succeeded, false otherwise.
*/
bool DefaultsTest::testSamplerIntegerParameter(glw::GLenum pname, glw::GLint expected_value)
{
/* Shortcut for GL functionality */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Get data. */
glw::GLint value = -1;
gl.getSamplerParameteriv(m_sampler_dsa, pname, &value);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSamplerParameteriv have failed");
if (-1 == value)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "glGetSamplerParameteriv with parameter " << glu::getTextureParameterName(pname)
<< " has not returned anything and error has not been generated." << tcu::TestLog::EndMessage;
return false;
}
else
{
if (expected_value != value)
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "glGetSamplerParameteriv with parameter "
<< glu::getTextureParameterName(pname) << " has returned " << value
<< ", however " << expected_value << " was expected."
<< tcu::TestLog::EndMessage;
return false;
}
}
return true;
}
/** @brief Test Sampler Float Parameter.
*
* @note The function may throw if unexpected error has occured.
*
* @return True if test succeeded, false otherwise.
*/
bool DefaultsTest::testSamplerFloatParameter(glw::GLenum pname, glw::GLfloat expected_value)
{
/* Shortcut for GL functionality */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Get data. */
glw::GLfloat value = -1.0;
gl.getSamplerParameterfv(m_sampler_dsa, pname, &value);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSamplerParameteriv have failed");
if (de::abs(expected_value - value) > 0.015625f /* Precision */)
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "glGetSamplerParameterfv with parameter "
<< glu::getTextureParameterName(pname) << " has returned " << value
<< ", however " << expected_value << " was expected."
<< tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Test Sampler Float Parameter.
*
* @note The function may throw if unexpected error has occured.
*
* @return True if test succeeded, false otherwise.
*/
bool DefaultsTest::testSamplerFloatVectorParameter(glw::GLenum pname, glw::GLfloat expected_value[4])
{
/* Shortcut for GL functionality */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Get data. */
glw::GLfloat value[4] = { -1.0, -1.0, -1.0, -1.0 };
gl.getSamplerParameterfv(m_sampler_dsa, pname, value);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSamplerParameterfv have failed");
if ((de::abs(expected_value[0] - value[0]) > 0.015625f /* Precision */) ||
(de::abs(expected_value[1] - value[1]) > 0.015625f /* Precision */) ||
(de::abs(expected_value[2] - value[2]) > 0.015625f /* Precision */) ||
(de::abs(expected_value[3] - value[3]) > 0.015625f /* Precision */))
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "glGetSamplerParameterfv with parameter "
<< glu::getTextureParameterName(pname) << " has returned [" << value[0]
<< ", " << value[1] << ", " << value[2] << ", " << value[3] << "], however "
<< expected_value << " was expected." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Release GL objects.
*/
void DefaultsTest::clean()
{
/* Shortcut for GL functionality */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
if (m_sampler_dsa)
{
gl.deleteSamplers(1, &m_sampler_dsa);
m_sampler_dsa = 0;
}
}
/******************************** Errors Test Implementation ********************************/
/** @brief Errors Test constructor.
*
* @param [in] context OpenGL context.
*/
ErrorsTest::ErrorsTest(deqp::Context& context) : deqp::TestCase(context, "samplers_errors", "Samplers Errors Test")
{
/* Intentionally left blank. */
}
/** @brief Iterate Errors Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult ErrorsTest::iterate()
{
/* Shortcut for GL functionality */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Get context setup. */
bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
{
m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
return STOP;
}
/* Running tests. */
bool is_ok = true;
bool is_error = false;
glw::GLuint sampler_dsa = 0;
try
{
/* Check direct state creation. */
gl.createSamplers(-1, &sampler_dsa);
glw::GLenum error = GL_NO_ERROR;
if (GL_INVALID_VALUE != (error = gl.getError()))
{
is_ok = false;
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "CreateSamplers has not generated INVALID_VALUE error when callded with "
"negative number of samplers to be created."
<< "Instead, " << glu::getErrorStr(error) << " error value was generated." << tcu::TestLog::EndMessage;
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
if (sampler_dsa)
{
gl.deleteSamplers(1, &sampler_dsa);
sampler_dsa = 0;
}
/* Result's setup. */
if (is_ok)
{
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
}
else
{
if (is_error)
{
m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
}
else
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
}
}
return STOP;
}
/******************************** Functional Test Implementation ********************************/
/** @brief Functional Test constructor.
*
* @param [in] context OpenGL context.
*/
FunctionalTest::FunctionalTest(deqp::Context& context)
: deqp::TestCase(context, "samplers_functional", "Samplers Functional Test")
, m_fbo(0)
, m_rbo(0)
, m_vao(0)
, m_to(0)
, m_so(0)
, m_po(0)
{
/* Intentionally left blank. */
}
/** @brief Iterate Functional Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult FunctionalTest::iterate()
{
/* Get context setup. */
bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
{
m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
return STOP;
}
/* Running tests. */
bool is_ok = true;
bool is_error = false;
try
{
prepareFramebuffer();
prepareVertexArrayObject();
prepareProgram();
prepareTexture();
prepareSampler();
draw();
is_ok &= checkFramebufferContent();
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Clean-up. */
clean();
/* Result's setup. */
if (is_ok)
{
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
}
else
{
if (is_error)
{
m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
}
else
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
}
}
return STOP;
}
/** @brief Function prepares framebuffer with RGBA8 color attachment.
* Viewport is set up. Content of the framebuffer is cleared.
*
* @note The function may throw if unexpected error has occured.
*/
void FunctionalTest::prepareFramebuffer()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Prepare framebuffer. */
gl.genFramebuffers(1, &m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
gl.genRenderbuffers(1, &m_rbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1 /* x size */, 1 /* y size */);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
throw 0;
}
gl.viewport(0, 0, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
/* Clear framebuffer's content. */
gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
gl.clear(GL_COLOR_BUFFER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
}
/** @brief Function generate and bind empty vertex array object.
*
* @note The function may throw if unexpected error has occured.
*/
void FunctionalTest::prepareVertexArrayObject()
{
/* Shortcut for GL functionality */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.genVertexArrays(1, &m_vao);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
gl.bindVertexArray(m_vao);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
}
/** @brief Function builds test's GLSL program.
* If succeded, the program will be set to be used.
*
* @note The function may throw if unexpected error has occured.
*/
void FunctionalTest::prepareProgram()
{
/* Shortcut for GL functionality */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
struct Shader
{
glw::GLchar const* const source;
glw::GLenum const type;
glw::GLuint id;
} shader[] = { { s_vertex_shader, GL_VERTEX_SHADER, 0 }, { s_fragment_shader, GL_FRAGMENT_SHADER, 0 } };
glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
try
{
/* Create program. */
m_po = 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(m_po, 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]);
m_context.getTestContext().getLog() << 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(m_po);
GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
glw::GLint status = GL_FALSE;
gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
if (GL_TRUE == status)
{
for (glw::GLuint i = 0; i < shader_count; ++i)
{
if (shader[i].id)
{
gl.detachShader(m_po, shader[i].id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
}
}
}
else
{
glw::GLint log_size = 0;
gl.getProgramiv(m_po, 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(m_po, log_size, NULL, &log_text[0]);
m_context.getTestContext().getLog() << 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 (m_po)
{
gl.deleteProgram(m_po);
m_po = 0;
}
}
for (glw::GLuint i = 0; i < shader_count; ++i)
{
if (0 != shader[i].id)
{
gl.deleteShader(shader[i].id);
shader[i].id = 0;
}
}
if (m_po)
{
gl.useProgram(m_po);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
}
if (0 == m_po)
{
throw 0;
}
}
/** @brief Function prepares texture object with test's data.
*
* @note The function may throw if unexpected error has occured.
*/
void FunctionalTest::prepareTexture()
{
/* Shortcut for GL functionality */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.activeTexture(GL_TEXTURE0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture call failed.");
/* Texture creation and binding. */
gl.genTextures(1, &m_to);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures call failed.");
gl.bindTexture(GL_TEXTURE_2D, m_to);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture call failed.");
/* Uploading texture. */
gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, s_texture_data);
GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D call failed.");
/* Setup fragment shader's sampler. */
glw::GLint location = 0;
gl.getUniformLocation(m_po, s_uniform_sampler);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
gl.uniform1i(location, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i call failed.");
}
/** @brief Function prepares sampler with test setup and binds it to unit 0.
*
* @note The function may throw if unexpected error has occured.
*/
void FunctionalTest::prepareSampler()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Sampler creation and setup. */
gl.createSamplers(1, &m_so);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
gl.bindSampler(0, m_so);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindSampler have failed");
gl.samplerParameteri(m_so, GL_TEXTURE_WRAP_S, GL_REPEAT);
gl.samplerParameteri(m_so, GL_TEXTURE_WRAP_T, GL_REPEAT);
gl.samplerParameteri(m_so, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.samplerParameteri(m_so, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "glSamplerParameteri have failed");
}
/** @brief Function draws a quad.
*
* @note The function may throw if unexpected error has occured.
*/
void FunctionalTest::draw()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays have failed");
}
/** @brief Check content of the framebuffer and compare it with expected data.
*
* @note The function may throw if unexpected error has occured.
*
* @return True if succeeded, false otherwise.
*/
bool FunctionalTest::checkFramebufferContent()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Fetch framebuffer data. */
glw::GLubyte pixel[4] = { 0 };
gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
/* Comparison with expected values. */
if ((s_texture_data[0] != pixel[0]) || (s_texture_data[1] != pixel[1]) || (s_texture_data[2] != pixel[2]) ||
(s_texture_data[3] != pixel[3]))
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Frameuffer content (" << (unsigned int)pixel[0] << ", "
<< (unsigned int)pixel[1] << ", " << (unsigned int)pixel[2] << ", " << (unsigned int)pixel[3]
<< ") is different than expected (" << (unsigned int)s_texture_data[0] << ", "
<< (unsigned int)s_texture_data[1] << ", " << (unsigned int)s_texture_data[2] << ", "
<< (unsigned int)s_texture_data[3] << ")." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Release all GL objects.
*/
void FunctionalTest::clean()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Release framebuffer. */
if (m_fbo)
{
gl.deleteFramebuffers(1, &m_fbo);
m_fbo = 0;
}
/* Release renderbuffer. */
if (m_rbo)
{
gl.deleteRenderbuffers(1, &m_rbo);
m_rbo = 0;
}
/* Release vertex array object. */
if (m_vao)
{
gl.deleteVertexArrays(1, &m_vao);
m_vao = 0;
}
/* Release texture. */
if (m_to)
{
gl.deleteTextures(1, &m_to);
m_to = 0;
}
/* Release sampler. */
if (m_so)
{
gl.deleteSamplers(1, &m_so);
m_so = 0;
}
/* Release GLSL program. */
if (m_po)
{
gl.useProgram(0);
gl.deleteProgram(m_po);
m_po = 0;
}
}
/* Vertex shader source code. */
const glw::GLchar FunctionalTest::s_vertex_shader[] = "#version 330\n"
"\n"
"void main()\n"
"{\n"
" switch(gl_VertexID)\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";
/* Fragment shader source program. */
const glw::GLchar FunctionalTest::s_fragment_shader[] =
"#version 330\n"
"\n"
"uniform sampler2D texture_sampler;\n"
"\n"
"out vec4 color;\n"
"\n"
"void main()\n"
"{\n"
" color = texture(texture_sampler, vec2(0.33333, 0.33333));\n"
"}\n";
/* Name of texture sampler uniform. */
const glw::GLchar FunctionalTest::s_uniform_sampler[] = "texture_sampler";
/* Test's texture data. */
const glw::GLubyte FunctionalTest::s_texture_data[] = {
0xFF, 0x00, 0x00, 0xFF, /* RED */
0x00, 0xFF, 0x00, 0xFF, /* GREEN */
0x00, 0x00, 0xFF, 0xFF, /* BLUE */
0xFF, 0xFF, 0x00, 0xFF /* YELLOW */
};
} /* Samplers namespace. */
} /* DirectStateAccess namespace. */
} /* gl4cts namespace. */