blob: 4e608e3090464f212fba1a0fd264d2200410c39d [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 gl4cDirectStateAccessFramebuffersAndRenderbuffersTests.cpp
* \brief Conformance tests for the Direct State Access feature functionality (Framebuffers and Renderbuffer 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"
#include <algorithm>
#include <climits>
#include <cmath>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
namespace gl4cts
{
namespace DirectStateAccess
{
namespace Framebuffers
{
/******************************** Framebuffer Creation Test Implementation ********************************/
/** @brief Creation Test constructor.
*
* @param [in] context OpenGL context.
*/
CreationTest::CreationTest(deqp::Context& context)
: deqp::TestCase(context, "framebuffers_creation", "Framebuffer 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;
/* Framebuffers' objects */
static const glw::GLuint framebuffers_count = 2;
glw::GLuint framebuffers_legacy[framebuffers_count] = {};
glw::GLuint framebuffers_dsa[framebuffers_count] = {};
try
{
/* Check legacy state creation. */
gl.genFramebuffers(framebuffers_count, framebuffers_legacy);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed");
for (glw::GLuint i = 0; i < framebuffers_count; ++i)
{
if (gl.isFramebuffer(framebuffers_legacy[i]))
{
is_ok = false;
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "GenFramebuffers has created default objects, but it should create only a names."
<< tcu::TestLog::EndMessage;
}
}
/* Check direct state creation. */
gl.createFramebuffers(framebuffers_count, framebuffers_dsa);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateFramebuffers has failed");
for (glw::GLuint i = 0; i < framebuffers_count; ++i)
{
if (!gl.isFramebuffer(framebuffers_dsa[i]))
{
is_ok = false;
/* Log. */
m_context.getTestContext().getLog() << tcu::TestLog::Message
<< "CreateFramebuffers has not created default objects."
<< tcu::TestLog::EndMessage;
}
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
for (glw::GLuint i = 0; i < framebuffers_count; ++i)
{
if (framebuffers_legacy[i])
{
gl.deleteFramebuffers(1, &framebuffers_legacy[i]);
framebuffers_legacy[i] = 0;
}
if (framebuffers_dsa[i])
{
gl.deleteFramebuffers(1, &framebuffers_dsa[i]);
framebuffers_dsa[i] = 0;
}
}
/* Errors clean up. */
while (gl.getError())
;
/* 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;
}
/******************************** Framebuffer Renderbuffer Attachment Test Implementation ********************************/
/** @brief Framebuffer Renderbuffer Attachment Test constructor.
*
* @param [in] context OpenGL context.
*/
RenderbufferAttachmentTest::RenderbufferAttachmentTest(deqp::Context& context)
: deqp::TestCase(context, "framebuffers_renderbuffer_attachment", "Framebuffer Renderbuffer Attachment Test")
, m_fbo(0)
, m_rbo(0)
{
/* Intentionally left blank. */
}
/** @brief Iterate Framebuffer Renderbuffer Attachment Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult RenderbufferAttachmentTest::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;
try
{
glw::GLint max_color_attachments = 8 /* Specification minimum OpenGL 4.5 Core Profile p. 627 */;
gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed");
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
is_ok &= Test(GL_COLOR_ATTACHMENT0 + i, GL_RGBA8);
Clean();
}
is_ok &= Test(GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24);
Clean();
is_ok &= Test(GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8);
Clean();
is_ok &= Test(GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH24_STENCIL8);
Clean();
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
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 Test functionality.
*
* @param [in] attachment Framebuffer attachment.
* @param [in] internalformat Internal format.
*
* @return True if test succeeded, false otherwise.
*/
bool RenderbufferAttachmentTest::Test(glw::GLenum attachment, glw::GLenum internalformat)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* RBO creation. */
gl.genRenderbuffers(1, &m_rbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed");
gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer has failed");
gl.renderbufferStorage(GL_RENDERBUFFER, internalformat, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer has failed");
/* FBO creation. */
gl.createFramebuffers(1, &m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateFramebuffers has failed");
gl.namedFramebufferRenderbuffer(m_fbo, attachment, GL_RENDERBUFFER, m_rbo);
if (glw::GLenum error = gl.getError())
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "NamedFramebufferRenderbuffer for "
<< glu::getFramebufferAttachmentStr(attachment)
<< " attachment failed with error value " << glu::getErrorStr(error) << "."
<< tcu::TestLog::EndMessage;
return false;
}
gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
glw::GLenum status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
if (GL_FRAMEBUFFER_COMPLETE != status)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Named Framebuffer Renderbuffer Attachment test failed because of framebuffer "
<< glu::getFramebufferStatusStr(status) << " with renderbuffer set up as "
<< glu::getFramebufferAttachmentStr(attachment) << " attachment." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Clean up GL state.
*/
void RenderbufferAttachmentTest::Clean()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Cleanup. */
if (m_fbo)
{
gl.deleteFramebuffers(1, &m_fbo);
m_fbo = 0;
}
if (m_rbo)
{
gl.deleteRenderbuffers(1, &m_rbo);
m_rbo = 0;
}
/* Errors clean up. */
while (gl.getError())
;
}
/******************************** Framebuffer Texture Attachment Test Implementation ********************************/
/** @brief Creation Test constructor.
*
* @param [in] context OpenGL context.
*/
TextureAttachmentTest::TextureAttachmentTest(deqp::Context& context)
: deqp::TestCase(context, "framebuffers_texture_attachment", "Framebuffer Texture Attachment Test")
, m_fbo(0)
, m_to(0)
{
/* Intentionally left blank. */
}
/** @brief Iterate Creation Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult TextureAttachmentTest::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;
try
{
glw::GLint max_color_attachments = 8 /* Specification minimum OpenGL 4.5 Core Profile p. 627 */;
gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed");
for (glw::GLuint i = 0; i < s_targets_count; ++i)
{
for (glw::GLuint j = 1; j <= MaxTextureLevels(s_targets[i]); ++j)
{
for (glw::GLint k = 0; k < max_color_attachments; ++k)
{
is_ok &= Test(GL_COLOR_ATTACHMENT0 + k, true, s_targets[i], GL_RGBA8, j);
Clean();
}
is_ok &= Test(GL_DEPTH_ATTACHMENT, false, s_targets[i], GL_DEPTH_COMPONENT24, j);
Clean();
is_ok &= Test(GL_STENCIL_ATTACHMENT, false, s_targets[i], GL_STENCIL_INDEX8, j);
Clean();
is_ok &= Test(GL_DEPTH_STENCIL_ATTACHMENT, false, s_targets[i], GL_DEPTH24_STENCIL8, j);
Clean();
}
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
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 Test functionality.
*
* @param [in] attachment Framebuffer attachment.
* @param [in] is_color_attachment Is color attachment tested.
* @param [in] texture_target Texture target.
* @param [in] internalformat Internal format ot be tested.
* @param [in] levels Number of levels.
*
* @return True if test succeeded, false otherwise.
*/
bool TextureAttachmentTest::Test(glw::GLenum attachment, bool is_color_attachment, glw::GLenum texture_target,
glw::GLenum internalformat, glw::GLuint levels)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* RBO creation. */
gl.genTextures(1, &m_to);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed");
gl.bindTexture(texture_target, m_to);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture has failed");
if (GL_TEXTURE_2D_MULTISAMPLE == texture_target)
{
gl.texStorage2DMultisample(texture_target, 1, internalformat, (glw::GLuint)std::pow((double)2, (double)levels),
(glw::GLuint)std::pow((double)2, (double)levels), GL_FALSE);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
}
else
{
gl.texStorage2D(texture_target, levels, internalformat, (glw::GLuint)std::pow((double)2, (double)levels),
(glw::GLuint)std::pow((double)2, (double)levels));
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
}
gl.bindTexture(texture_target, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer has failed");
/* FBO creation. */
gl.createFramebuffers(1, &m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateFramebuffers has failed");
for (glw::GLuint i = 0; i < levels; ++i)
{
gl.namedFramebufferTexture(m_fbo, attachment, m_to, i);
SubTestAttachmentError(attachment, texture_target, i, levels);
gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
if (is_color_attachment)
{
gl.drawBuffer(attachment);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffer has failed");
gl.readBuffer(attachment);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadBuffer has failed");
}
SubTestStatus(attachment, texture_target, i, levels);
if (GL_TEXTURE_2D_MULTISAMPLE != texture_target)
{
Clear();
if (!SubTestContent(attachment, texture_target, internalformat, i, levels))
{
return false;
}
}
gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
}
return true;
}
/** @brief Check error and log.
*
* @param [in] attachment Framebuffer attachment.
* @param [in] texture_target Texture target.
* @param [in] level Tested level.
* @param [in] levels Number of levels.
*
* @return True if no error, false otherwise.
*/
bool TextureAttachmentTest::SubTestAttachmentError(glw::GLenum attachment, glw::GLenum texture_target,
glw::GLuint level, glw::GLuint levels)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
if (glw::GLenum error = gl.getError())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "NamedFramebufferTexture for " << glu::getFramebufferAttachmentStr(attachment)
<< " attachment of " << glu::getTextureTargetStr(texture_target) << " texture and texture level " << level
<< " of texture with " << levels << " levels failed with error value " << glu::getErrorStr(error) << "."
<< tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Check status and log.
*
* @param [in] attachment Framebuffer attachment.
* @param [in] texture_target Texture target.
* @param [in] level Tested level.
* @param [in] levels Number of levels.
*
* @return True if FRAMEBUFFER_COMPLETE, false otherwise.
*/
bool TextureAttachmentTest::SubTestStatus(glw::GLenum attachment, glw::GLenum texture_target, glw::GLuint level,
glw::GLuint levels)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLenum status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
if (GL_FRAMEBUFFER_COMPLETE != status)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Named Framebuffer Texture Attachment test failed because of framebuffer "
<< glu::getFramebufferStatusStr(status) << " status with " << glu::getTextureTargetStr(texture_target)
<< " texture set up as " << glu::getFramebufferAttachmentStr(attachment) << " attachment and texture level "
<< level << " of texture with " << levels << " levels." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Check framebuffer content and log.
*
* @param [in] attachment Framebuffer attachment.
* @param [in] texture_target Texture target.
* @param [in] internalformat Tested internal format.
* @param [in] level Tested level.
* @param [in] levels Number of levels.
*
* @return True if FRAMEBUFFER_COMPLETE, false otherwise.
*/
bool TextureAttachmentTest::SubTestContent(glw::GLenum attachment, glw::GLenum texture_target,
glw::GLenum internalformat, glw::GLuint level, glw::GLuint levels)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Check framebuffer's color content. */
if (GL_RGBA8 == internalformat)
{
glw::GLfloat color[4] = { 0.f };
gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, color);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels has failed");
for (int i = 0; i < 4 /* color components */; ++i)
{
if (de::abs(s_reference_color[i] - color[i]) > 0.0625 /* precision */)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Named Framebuffer Texture Layer Attachment test failed with "
<< glu::getTextureTargetStr(texture_target) << " texture set up as "
<< glu::getFramebufferAttachmentStr(attachment) << " attachment and texture level " << level
<< " of texture with " << levels << " levels. The color content of the framebuffer was ["
<< color[0] << ", " << color[1] << ", " << color[2] << ", " << color[3] << "], but ["
<< s_reference_color[0] << ", " << s_reference_color[1] << ", " << s_reference_color[2] << ", "
<< s_reference_color[3] << "] was expected." << tcu::TestLog::EndMessage;
return false;
}
}
}
/* Check framebuffer's depth content. */
if ((GL_DEPTH_COMPONENT24 == internalformat) || (GL_DEPTH24_STENCIL8 == internalformat))
{
glw::GLfloat depth = 0.f;
gl.readPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels has failed");
if (de::abs(s_reference_depth - depth) > 0.0625 /* precision */)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Named Framebuffer Texture Layer Attachment test failed "
<< "with texture set up as " << glu::getFramebufferAttachmentStr(attachment)
<< " attachment and texture level " << level << " of texture with " << levels
<< " levels. The depth content of the framebuffer was [" << depth << "], but [" << s_reference_depth
<< "] was expected." << tcu::TestLog::EndMessage;
return false;
}
}
/* Check framebuffer's stencil content. */
if ((GL_STENCIL_INDEX8 == internalformat) || (GL_DEPTH24_STENCIL8 == internalformat))
{
glw::GLint stencil = 0;
gl.readPixels(0, 0, 1, 1, GL_STENCIL_INDEX, GL_INT, &stencil);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels has failed");
if (s_reference_stencil != stencil)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Named Framebuffer Texture Layer Attachment test failed "
<< "with texture set up as " << glu::getFramebufferAttachmentStr(attachment)
<< " attachment and texture level " << level << " of texture with " << levels
<< " levels. The stencil content of the framebuffer was [" << stencil << "], but ["
<< s_reference_stencil << "] was expected." << tcu::TestLog::EndMessage;
return false;
}
}
return true;
}
/** @brief Query max texture levels.
*
* @param [in] texture_target Texture target.
*
* @return Max texture levels.
*/
glw::GLuint TextureAttachmentTest::MaxTextureLevels(glw::GLenum texture_target)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLint max_texture_size = 1024 /* Specification default. */;
switch (texture_target)
{
case GL_TEXTURE_RECTANGLE:
case GL_TEXTURE_2D_MULTISAMPLE:
return 1;
case GL_TEXTURE_2D:
gl.getIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
return (glw::GLuint)std::log((double)max_texture_size);
case GL_TEXTURE_CUBE_MAP:
gl.getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_texture_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
return (glw::GLuint)std::log((double)max_texture_size);
default:
throw 0;
}
/* For compiler warnings only. */
return 0;
}
/** @brief Clear texture.
*/
void TextureAttachmentTest::Clear()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Setup clear values. */
gl.clearColor(s_reference_color[0], s_reference_color[1], s_reference_color[2], s_reference_color[3]);
gl.clearDepth(s_reference_depth);
gl.clearStencil(s_reference_stencil);
/* Clear rbo/fbo. */
gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
/** @brief Clean up GL state.
*/
void TextureAttachmentTest::Clean()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Cleanup. */
if (m_fbo)
{
gl.deleteFramebuffers(1, &m_fbo);
m_fbo = 0;
}
if (m_to)
{
gl.deleteTextures(1, &m_to);
m_to = 0;
}
/* Returning to default clear values. */
gl.clearColor(0.f, 0.f, 0.f, 0.f);
gl.clearDepth(1.f);
gl.clearStencil(0);
/* Errors clean up. */
while (gl.getError())
;
}
/** Tested targets. */
const glw::GLenum TextureAttachmentTest::s_targets[] = { GL_TEXTURE_RECTANGLE, GL_TEXTURE_2D, GL_TEXTURE_2D_MULTISAMPLE,
GL_TEXTURE_CUBE_MAP };
/** Tested targets count. */
const glw::GLuint TextureAttachmentTest::s_targets_count = sizeof(s_targets) / sizeof(s_targets[0]);
const glw::GLfloat TextureAttachmentTest::s_reference_color[4] = { 0.25, 0.5, 0.75, 1.0 }; //!< Reference color.
const glw::GLint TextureAttachmentTest::s_reference_color_integer[4] = { 1, 2, 3,
4 }; //!< Reference color for integer format.
const glw::GLfloat TextureAttachmentTest::s_reference_depth = 0.5; //!< Reference depth value.
const glw::GLint TextureAttachmentTest::s_reference_stencil = 7; //!< Reference stencil value.
/******************************** Framebuffer Texture Layer Attachment Test Implementation ********************************/
/** @brief Framebuffer Texture Layer Attachment Test constructor.
*
* @param [in] context OpenGL context.
*/
TextureLayerAttachmentTest::TextureLayerAttachmentTest(deqp::Context& context)
: deqp::TestCase(context, "framebuffers_texture_layer_attachment", "Framebuffer Texture Layer Attachment Test")
, m_fbo(0)
, m_to(0)
{
/* Intentionally left blank. */
}
/** @brief Iterate Framebuffer Texture Layer Attachment Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult TextureLayerAttachmentTest::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;
try
{
glw::GLint max_color_attachments = 8 /* Specification minimum OpenGL 4.5 Core Profile p. 627 */;
gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed");
for (glw::GLuint i = 0; i < s_targets_count; ++i)
{
glw::GLuint layers_counts[] = { (GL_TEXTURE_CUBE_MAP_ARRAY == (glw::GLuint)s_targets[i]) ? 6u : 1u,
(GL_TEXTURE_CUBE_MAP_ARRAY == (glw::GLuint)s_targets[i]) ? 192u : 192u,
MaxTextureLayers(s_targets[i]) };
glw::GLuint layers_counts_count = sizeof(layers_counts) / sizeof(layers_counts[0]);
for (glw::GLuint j = 1; j <= MaxTextureLevels(s_targets[i]); ++j)
{
for (glw::GLuint k = 0; k < layers_counts_count; ++k)
{
for (glw::GLint l = 0; l < max_color_attachments; ++l)
{
is_ok &= Test(GL_COLOR_ATTACHMENT0 + l, true, s_targets[i], GL_RGBA8, j, layers_counts[k]);
Clean();
}
if (GL_TEXTURE_3D != s_targets[i])
{
is_ok &=
Test(GL_DEPTH_ATTACHMENT, false, s_targets[i], GL_DEPTH_COMPONENT24, j, layers_counts[k]);
Clean();
is_ok &= Test(GL_DEPTH_STENCIL_ATTACHMENT, false, s_targets[i], GL_DEPTH24_STENCIL8, j,
layers_counts[k]);
Clean();
is_ok &=
Test(GL_STENCIL_ATTACHMENT, false, s_targets[i], GL_STENCIL_INDEX8, j, layers_counts[k]);
Clean();
}
}
}
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
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 Test texture layer attachment.
*
* @param [in] attachment Framebuffer attachment.
* @param [in] is_color_attachment Is color attachment tested.
* @param [in] texture_target Texture target.
* @param [in] internalformat Tested internal format.
* @param [in] level Tested level.
* @param [in] levels Number of levels.
* @param [in] layers Number of layers.
*
* @return True if test succeeded, false otherwise.
*/
bool TextureLayerAttachmentTest::Test(glw::GLenum attachment, bool is_color_attachment, glw::GLenum texture_target,
glw::GLenum internalformat, glw::GLuint levels, glw::GLint layers)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* RBO creation. */
gl.genTextures(1, &m_to);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed");
gl.bindTexture(texture_target, m_to);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture has failed");
// Lower the layers count when multiple levels are requested to limit the amount of memory required
layers = deMax32(1, (glw::GLint)((deUint64)layers / (1ull<<(deUint64)(2*(levels-1)))));
if (GL_TEXTURE_CUBE_MAP_ARRAY == texture_target)
{
layers = deMax32(6, (layers / 6) * 6);
}
if (GL_TEXTURE_2D_MULTISAMPLE_ARRAY == texture_target)
{
gl.texStorage3DMultisample(texture_target, 1, internalformat, (glw::GLuint)std::pow((double)2, (double)levels),
(glw::GLuint)std::pow((double)2, (double)levels), layers, GL_FALSE);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
}
else
{
gl.texStorage3D(texture_target, levels, internalformat, (glw::GLuint)std::pow((double)2, (double)levels),
(glw::GLuint)std::pow((double)2, (double)levels), layers);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
}
gl.bindTexture(texture_target, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer has failed");
/* FBO creation. */
gl.createFramebuffers(1, &m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateFramebuffers has failed");
for (glw::GLuint i = 0; i < levels; ++i)
{
glw::GLuint j = 0;
glw::GLuint k = 1;
/* 3D textures are mipmapped also in depth directio, so number of layers to be tested must be limited. */
glw::GLuint layers_at_level = (GL_TEXTURE_3D == texture_target) ?
(de::min(layers, layers / (glw::GLint)std::pow(2.0, (double)i))) :
layers;
while (j < layers_at_level) /* Only layers with Fibonacci number index are tested to reduce the test time. */
{
/* Attach texture layer. */
gl.namedFramebufferTextureLayer(m_fbo, attachment, m_to, i, j);
if (!SubTestAttachmentError(attachment, texture_target, i, j, levels, layers))
{
return false;
}
gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
if (is_color_attachment)
{
gl.drawBuffer(attachment);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffer has failed");
gl.readBuffer(attachment);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadBuffer has failed");
}
if (!SubTestStatus(attachment, texture_target, i, j, levels, layers))
{
return false;
}
if (GL_TEXTURE_2D_MULTISAMPLE_ARRAY != texture_target)
{
Clear();
if (!SubTestContent(attachment, texture_target, internalformat, i, j, levels, layers))
{
return false;
}
}
gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
/* Fibonacci number iteration. */
int l = j;
j = j + k;
k = l;
}
}
return true;
}
/** @brief Check error and log.
*
* @param [in] attachment Framebuffer attachment.
* @param [in] texture_target Texture target.
* @param [in] level Tested level.
* @param [in] layer Tested layer.
* @param [in] levels Number of levels.
* @param [in] layers Number of layers.
*
* @return True if no error, false otherwise.
*/
bool TextureLayerAttachmentTest::SubTestAttachmentError(glw::GLenum attachment, glw::GLenum texture_target,
glw::GLuint level, glw::GLint layer, glw::GLuint levels,
glw::GLint layers)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Check and log. */
if (glw::GLenum error = gl.getError())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "NamedFramebufferTexture for " << glu::getFramebufferAttachmentStr(attachment)
<< " attachment of " << glu::getTextureTargetStr(texture_target) << " texture at level " << level
<< " and at layer " << layer << " where texture has " << levels << " levels and " << layers
<< " layers failed with error value " << glu::getErrorStr(error) << "." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Check framebuffer completness.
*
* @param [in] attachment Framebuffer attachment.
* @param [in] texture_target Texture target.
* @param [in] level Tested level.
* @param [in] layer Tested layer.
* @param [in] levels Number of levels.
* @param [in] layers Number of layers.
*
* @return True if framebuffer is complete, false otherwise.
*/
bool TextureLayerAttachmentTest::SubTestStatus(glw::GLenum attachment, glw::GLenum texture_target, glw::GLuint level,
glw::GLint layer, glw::GLuint levels, glw::GLint layers)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Check framebuffer status. */
glw::GLenum status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
if (GL_FRAMEBUFFER_COMPLETE != status)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Named Framebuffer Texture Layer Attachment test failed because of framebuffer "
<< glu::getFramebufferStatusStr(status) << " with " << glu::getTextureTargetStr(texture_target)
<< " texture set up as " << glu::getFramebufferAttachmentStr(attachment) << " attachment and texture level "
<< level << " and texture layer " << layer << " of texture with " << levels << " levels and " << layers
<< " layers." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Check framebuffer cntent.
*
* @param [in] attachment Framebuffer attachment.
* @param [in] texture_target Texture target.
* @param [in] internalformat Tested internal format.
* @param [in] level Tested level.
* @param [in] layer Tested layer.
* @param [in] levels Number of levels.
* @param [in] layers Number of layers.
*
* @return True if framebuffer content is equal to the reference, false otherwise.
*/
bool TextureLayerAttachmentTest::SubTestContent(glw::GLenum attachment, glw::GLenum texture_target,
glw::GLenum internalformat, glw::GLuint level, glw::GLint layer,
glw::GLuint levels, glw::GLint layers)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Check framebuffer's color content. */
if (GL_RGBA8 == internalformat)
{
glw::GLfloat color[4] = { 0.f };
gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, color);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels has failed");
for (int i = 0; i < 4 /* color components */; ++i)
{
if (de::abs(s_reference_color[i] - color[i]) > 0.0625 /* precision */)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Named Framebuffer Texture Layer Attachment test failed with "
<< glu::getTextureTargetStr(texture_target) << " texture set up as "
<< glu::getFramebufferAttachmentStr(attachment) << " attachment and texture level " << level
<< " and texture layer " << layer << " of texture with " << levels << " levels and " << layers
<< " layers. The color content of the framebuffer was [" << color[0] << ", " << color[1] << ", "
<< color[2] << ", " << color[3] << "], but [" << s_reference_color[0] << ", "
<< s_reference_color[1] << ", " << s_reference_color[2] << ", " << s_reference_color[3]
<< "] was expected." << tcu::TestLog::EndMessage;
return false;
}
}
}
/* Check framebuffer's depth content. */
if ((GL_DEPTH_COMPONENT24 == internalformat) || (GL_DEPTH24_STENCIL8 == internalformat))
{
glw::GLfloat depth = 0.f;
gl.readPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels has failed");
if (de::abs(s_reference_depth - depth) > 0.0625 /* precision */)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Named Framebuffer Texture Layer Attachment test failed "
<< "with texture set up as " << glu::getFramebufferAttachmentStr(attachment)
<< " attachment and texture level " << level << " and texture layer " << layer << " of texture with "
<< levels << " levels and " << layers << " layers. The depth content of the framebuffer was [" << depth
<< "], but [" << s_reference_depth << "] was expected." << tcu::TestLog::EndMessage;
return false;
}
}
/* Check framebuffer's stencil content. */
if ((GL_STENCIL_INDEX8 == internalformat) || (GL_DEPTH24_STENCIL8 == internalformat))
{
glw::GLint stencil = 0;
gl.readPixels(0, 0, 1, 1, GL_STENCIL_INDEX, GL_INT, &stencil);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels has failed");
if (s_reference_stencil != stencil)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Named Framebuffer Texture Layer Attachment test failed "
<< "with texture set up as " << glu::getFramebufferAttachmentStr(attachment)
<< " attachment and texture level " << level << " and texture layer " << layer << " of texture with "
<< levels << " levels and " << layers << " layers. The stencil content of the framebuffer was ["
<< stencil << "], but [" << s_reference_stencil << "] was expected." << tcu::TestLog::EndMessage;
return false;
}
}
return true;
}
/** @brief Clear framebuffer.
*/
void TextureLayerAttachmentTest::Clear()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Setup clear values. */
gl.clearColor(s_reference_color[0], s_reference_color[1], s_reference_color[2], s_reference_color[3]);
gl.clearDepth(s_reference_depth);
gl.clearStencil(s_reference_stencil);
/* Clear rbo/fbo. */
gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
/** @brief Query maximum number of texture levels.
*
* @return True if max number of texture levels, false otherwise.
*/
glw::GLuint TextureLayerAttachmentTest::MaxTextureLevels(glw::GLenum texture_target)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLint max_texture_size = 1024 /* Specification default. */;
switch (texture_target)
{
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
return 1;
case GL_TEXTURE_2D_ARRAY:
gl.getIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
return (glw::GLuint)std::log((double)max_texture_size);
case GL_TEXTURE_CUBE_MAP_ARRAY:
gl.getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE , &max_texture_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
return (glw::GLuint)std::log((double)max_texture_size);
case GL_TEXTURE_3D:
gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max_texture_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
return (glw::GLuint)std::log((double)max_texture_size);
default:
throw 0;
}
/* For compiler warnings only. */
return 0;
}
/** @brief Query maximum number of texture layers.
*
* @return True if max number of texture layers, false otherwise.
*/
glw::GLuint TextureLayerAttachmentTest::MaxTextureLayers(glw::GLenum texture_target)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLint max_texture_size = 1024 /* Specification default. */;
switch (texture_target)
{
case GL_TEXTURE_3D:
gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max_texture_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
return max_texture_size;
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
case GL_TEXTURE_2D_ARRAY:
gl.getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &max_texture_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
return max_texture_size;
case GL_TEXTURE_CUBE_MAP_ARRAY:
gl.getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &max_texture_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
return (max_texture_size / 6) * 6; /* Make sure that max_texture_size is dividable by 6 */
default:
throw 0;
}
/* For compiler warnings only. */
return 0;
}
/** @brief Clean up GL state.
*/
void TextureLayerAttachmentTest::Clean()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Cleanup. */
if (m_fbo)
{
gl.deleteFramebuffers(1, &m_fbo);
m_fbo = 0;
}
if (m_to)
{
gl.deleteTextures(1, &m_to);
m_to = 0;
}
/* Returning to default clear values. */
gl.clearColor(0.f, 0.f, 0.f, 0.f);
gl.clearDepth(1.f);
gl.clearStencil(0);
/* Errors clean up. */
while (gl.getError())
;
}
const glw::GLenum TextureLayerAttachmentTest::s_targets[] = //!< Targets to be tested.
{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_3D };
const glw::GLuint TextureLayerAttachmentTest::s_targets_count =
sizeof(s_targets) / sizeof(s_targets[0]); //!< Number of tested targets.
const glw::GLfloat TextureLayerAttachmentTest::s_reference_color[4] = { 0.25, 0.5, 0.75, 1.0 }; //!< Reference color.
const glw::GLint TextureLayerAttachmentTest::s_reference_color_integer[4] = { 1, 2, 3,
4 }; //!< Reference integer color.
const glw::GLfloat TextureLayerAttachmentTest::s_reference_depth = 0.5; //!< Reference depth.
const glw::GLint TextureLayerAttachmentTest::s_reference_stencil = 7; //!< Reference stencil index.
/******************************** Named Framebuffer Read / Draw Buffer Test Implementation ********************************/
/** @brief Named Framebuffer Read / Draw Buffer Test constructor.
*
* @param [in] context OpenGL context.
*/
DrawReadBufferTest::DrawReadBufferTest(deqp::Context& context)
: deqp::TestCase(context, "framebuffers_read_draw_buffer", "Framebuffer Read and Draw Buffer Test")
{
/* Intentionally left blank. */
}
/** @brief Iterate Named Framebuffer Read / Draw Buffer Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult DrawReadBufferTest::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;
/* Framebuffers' objects */
glw::GLuint framebuffer = 0;
/* Get number of color attachments. */
glw::GLint max_color_attachments = 8 /* Specification minimum OpenGL 4.5 Core Profile p. 627 */;
gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed");
std::vector<glw::GLuint> renderbuffers(max_color_attachments);
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
renderbuffers[i] = 0;
}
try
{
/* Prepare framebuffer... */
gl.genFramebuffers(1, &framebuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed");
gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed");
gl.genRenderbuffers(max_color_attachments, &(renderbuffers[0]));
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed");
/* .. with renderbuffer color attachments. */
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffers[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer has failed");
gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER, renderbuffers[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed");
}
/* Check that framebuffer is complete. */
if (GL_FRAMEBUFFER_COMPLETE != gl.checkFramebufferStatus(GL_FRAMEBUFFER))
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "Framebuffer is unexpectedly incomplete."
<< tcu::TestLog::EndMessage;
throw 0;
}
/* Clear each of the framebuffer's attachments with unique color using NamedFramebufferDrawBuffer for attachment selection. */
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
gl.clearColor((float)i / (float)max_color_attachments, (float)i / (float)max_color_attachments,
(float)i / (float)max_color_attachments, (float)i / (float)max_color_attachments);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor has failed");
gl.namedFramebufferDrawBuffer(framebuffer, GL_COLOR_ATTACHMENT0 + i);
if (glw::GLenum error = gl.getError())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "NamedFramebufferDrawBuffer unexpectedly generated "
<< glu::getErrorStr(error) << " error with GL_COLOR_ATTACHMENT" << i << ". Test fails."
<< tcu::TestLog::EndMessage;
is_ok = false;
}
gl.clear(GL_COLOR_BUFFER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClear has failed");
}
/* Fetch framebuffer's content and compare it with reference using NamedFramebufferReadBuffer for attachment selection. */
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
gl.namedFramebufferReadBuffer(framebuffer, GL_COLOR_ATTACHMENT0 + i);
if (glw::GLenum error = gl.getError())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "NamedFramebufferReadBuffer unexpectedly generated "
<< glu::getErrorStr(error) << " error with GL_COLOR_ATTACHMENT" << i << ". Test fails."
<< tcu::TestLog::EndMessage;
is_ok = false;
}
glw::GLfloat rgba[4] = { -1.f, -1.f, -1.f, -1.f };
gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, rgba);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels has failed");
float expected_value = (float)i / (float)max_color_attachments;
for (glw::GLuint j = 0; j < 4 /* number of components */; ++j)
{
if (de::abs(expected_value - rgba[j]) > 0.0001 /* Precision */)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "Named Framebuffer Draw And Read Buffer failed because resulting color value was ["
<< rgba[0] << ", " << rgba[1] << ", " << rgba[2] << ", " << rgba[3] << "] but ["
<< expected_value << ", " << expected_value << ", " << expected_value << ", " << expected_value
<< "] had been expected." << tcu::TestLog::EndMessage;
is_ok = false;
break;
}
}
}
/* Check that NamedFramebufferDrawBuffer accepts GL_NONE as mode. */
gl.namedFramebufferDrawBuffer(framebuffer, GL_NONE);
if (glw::GLenum error = gl.getError())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "NamedFramebufferDrawBuffer unexpectedly generated "
<< glu::getErrorStr(error) << " error with GL_NONE mode. Test fails." << tcu::TestLog::EndMessage;
is_ok = false;
}
/* Check that NamedFramebufferReadBuffer accepts GL_NONE as mode. */
gl.namedFramebufferReadBuffer(framebuffer, GL_NONE);
if (glw::GLenum error = gl.getError())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "NamedFramebufferReadBuffer unexpectedly generated "
<< glu::getErrorStr(error) << " error with GL_NONE mode. Test fails." << tcu::TestLog::EndMessage;
is_ok = false;
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
if (framebuffer)
{
gl.deleteFramebuffers(1, &framebuffer);
framebuffer = 0;
}
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
if (renderbuffers[i])
{
gl.deleteRenderbuffers(1, &(renderbuffers[i]));
}
}
gl.clearColor(0.f, 0.f, 0.f, 0.f);
/* Errors clean up. */
while (gl.getError())
;
/* 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;
}
/******************************** Named Framebuffer Draw Buffers Test Implementation ********************************/
/** @brief Named Framebuffer Draw Buffers Test constructor.
*
* @param [in] context OpenGL context.
*/
DrawBuffersTest::DrawBuffersTest(deqp::Context& context)
: deqp::TestCase(context, "framebuffers_draw_buffers", "Framebuffer Draw Buffers Test")
{
/* Intentionally left blank. */
}
/** @brief Iterate Named Framebuffer Read / Draw Buffer Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult DrawBuffersTest::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;
/* Framebuffers' objects */
glw::GLuint framebuffer = 0;
/* Get number of color attachments. */
glw::GLint max_color_attachments = 8 /* Specification minimum OpenGL 4.5 Core Profile p. 627 */;
gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed");
std::vector<glw::GLuint> renderbuffers(max_color_attachments);
std::vector<glw::GLuint> color_attachments(max_color_attachments);
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
renderbuffers[i] = 0;
color_attachments[i] = GL_COLOR_ATTACHMENT0 + i;
}
try
{
/* Prepare framebuffer... */
gl.genFramebuffers(1, &framebuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed");
gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed");
gl.genRenderbuffers(max_color_attachments, &(renderbuffers[0]));
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed");
/* .. with renderbuffer color attachments. */
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffers[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer has failed");
gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER, renderbuffers[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed");
}
/* Check that framebuffer is complete. */
if (GL_FRAMEBUFFER_COMPLETE != gl.checkFramebufferStatus(GL_FRAMEBUFFER))
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "Framebuffer is unexpectedly incomplete."
<< tcu::TestLog::EndMessage;
throw 0;
}
/* Set up all attachments as draw buffer. */
gl.namedFramebufferDrawBuffers(framebuffer, max_color_attachments, &(color_attachments[0]));
if (glw::GLenum error = gl.getError())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "NamedFramebufferDrawBuffers unexpectedly generated "
<< glu::getErrorStr(error) << " error. Test fails." << tcu::TestLog::EndMessage;
is_ok = false;
}
/* Clear each of the framebuffer's attachments with unique color using NamedFramebufferDrawBuffer for attachment selection. */
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
gl.clearColor(s_rgba[0], s_rgba[1], s_rgba[2], s_rgba[3]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor has failed");
gl.clear(GL_COLOR_BUFFER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClear has failed");
}
/* Fetch framebuffer's content and compare it with reference using NamedFramebufferReadBuffer for attachment selection. */
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
gl.readBuffer(GL_COLOR_ATTACHMENT0 + i);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadBuffer has failed");
glw::GLfloat rgba[4] = { -1.f, -1.f, -1.f, -1.f };
gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, rgba);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels has failed");
for (glw::GLuint j = 0; j < 4 /* number of components */; ++j)
{
if (de::abs(s_rgba[j] - rgba[j]) > 0.0001 /* Precision */)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "Named Framebuffer Draw Buffers test have failed because resulting color value was ["
<< rgba[0] << ", " << rgba[1] << ", " << rgba[2] << ", " << rgba[3] << "] but [" << s_rgba[0]
<< ", " << s_rgba[1] << ", " << s_rgba[2] << ", " << s_rgba[3] << "] had been expected."
<< tcu::TestLog::EndMessage;
is_ok = false;
break;
}
}
}
/* Check that NamedFramebufferDrawBuffers accepts GL_NONE as mode. */
glw::GLenum none_bufs = GL_NONE;
gl.namedFramebufferDrawBuffers(framebuffer, 1, &none_bufs);
if (glw::GLenum error = gl.getError())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "NamedFramebufferDrawBuffers unexpectedly generated "
<< glu::getErrorStr(error) << " error with GL_NONE mode. Test fails." << tcu::TestLog::EndMessage;
is_ok = false;
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
if (framebuffer)
{
gl.deleteFramebuffers(1, &framebuffer);
framebuffer = 0;
}
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
if (renderbuffers[i])
{
gl.deleteRenderbuffers(1, &(renderbuffers[i]));
}
}
gl.clearColor(0.f, 0.f, 0.f, 0.f);
/* Errors clean up. */
while (gl.getError())
;
/* 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;
}
const glw::GLfloat DrawBuffersTest::s_rgba[4] = { 0.f, 0.25f, 0.5f, 0.75f };
/******************************** Named Framebuffer Invalidate Data Test Implementation ********************************/
/** @brief Named Framebuffer Invalidate Data Test constructor.
*
* @param [in] context OpenGL context.
*/
InvalidateDataTest::InvalidateDataTest(deqp::Context& context)
: deqp::TestCase(context, "framebuffers_invalidate_data", "Framebuffer Invalidate Data Test")
{
/* Intentionally left blank. */
}
/** @brief Iterate Named Framebuffer Read / Draw Buffer Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult InvalidateDataTest::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;
/* Framebuffers' objects */
glw::GLuint framebuffer = 0;
/* Get number of color attachments. */
glw::GLint max_color_attachments = 8 /* Specification minimum OpenGL 4.5 Core Profile p. 627 */;
gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed");
std::vector<glw::GLuint> renderbuffers(max_color_attachments);
std::vector<glw::GLuint> color_attachments(max_color_attachments);
static const glw::GLenum default_attachments[] = { GL_COLOR, GL_DEPTH, GL_STENCIL };
static const glw::GLuint default_attachments_count = sizeof(default_attachments) / sizeof(default_attachments[0]);
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
renderbuffers[i] = 0;
color_attachments[i] = GL_COLOR_ATTACHMENT0 + i;
}
try
{
/* Invalidate Default Framebuffer data */
gl.invalidateNamedFramebufferData(0, default_attachments_count, &(default_attachments[0]));
is_ok &= CheckErrorAndLog(default_attachments, default_attachments_count);
for (glw::GLuint i = 0; i < default_attachments_count; ++i)
{
gl.invalidateNamedFramebufferData(0, 1, &(default_attachments[i]));
is_ok &= CheckErrorAndLog(default_attachments[i]);
}
/* Prepare framebuffer... */
gl.genFramebuffers(1, &framebuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed");
gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed");
gl.genRenderbuffers(max_color_attachments, &(renderbuffers[0]));
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed");
/* .. with renderbuffer color attachments. */
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffers[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer has failed");
gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER, renderbuffers[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed");
}
/* Check that framebuffer is complete. */
if (GL_FRAMEBUFFER_COMPLETE != gl.checkFramebufferStatus(GL_FRAMEBUFFER))
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "Framebuffer is unexpectedly incomplete."
<< tcu::TestLog::EndMessage;
throw 0;
}
gl.invalidateNamedFramebufferData(framebuffer, max_color_attachments, &(color_attachments[0]));
is_ok &= CheckErrorAndLog(&(color_attachments[0]), max_color_attachments);
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
gl.invalidateNamedFramebufferData(framebuffer, 1, &(color_attachments[i]));
is_ok &= CheckErrorAndLog(color_attachments[i]);
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
if (framebuffer)
{
gl.deleteFramebuffers(1, &framebuffer);
framebuffer = 0;
}
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
if (renderbuffers[i])
{
gl.deleteRenderbuffers(1, &(renderbuffers[i]));
}
}
/* Errors clean up. */
while (gl.getError())
;
/* 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 Check error and log.
*
* @param [in] attachment Framebuffer attachment.
*
* @return True if no error, false otherwise.
*/
bool InvalidateDataTest::CheckErrorAndLog(const glw::GLenum attachment)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Check error. */
if (glw::GLenum error = gl.getError())
{
/* There is an error. Log. */
m_context.getTestContext().getLog() << tcu::TestLog::Message << "InvalidateDataTest unexpectedly generated "
<< glu::getErrorStr(error) << " error for attachment "
<< glu::getFramebufferAttachmentStr(attachment) << ". Test fails."
<< tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Check error and log.
*
* @param [in] attachments Framebuffer attachments.
* @param [in] attachments_count Framebuffer attachments count.
*
* @return True if no error, false otherwise.
*/
bool InvalidateDataTest::CheckErrorAndLog(const glw::GLenum attachments[], glw::GLuint count)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Check error. */
if (glw::GLenum error = gl.getError())
{
/* There is an error. Log. */
std::string attachments_names = "";
for (glw::GLuint i = 0; i < count; ++i)
{
attachments_names.append(glu::getFramebufferAttachmentStr(attachments[i]).toString());
if ((count - 1) != i)
{
attachments_names.append(", ");
}
}
m_context.getTestContext().getLog() << tcu::TestLog::Message << "InvalidateDataTest unexpectedly generated "
<< glu::getErrorStr(error) << " error for following attachments ["
<< attachments_names << "]. Test fails." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/******************************** Named Framebuffer Invalidate Sub Data Test Implementation ********************************/
/** @brief Named Framebuffer Invalidate Sub Data Test constructor.
*
* @param [in] context OpenGL context.
*/
InvalidateSubDataTest::InvalidateSubDataTest(deqp::Context& context)
: deqp::TestCase(context, "framebuffers_invalidate_subdata", "Framebuffer Invalidate Sub Data Test")
{
/* Intentionally left blank. */
}
/** @brief Iterate Named Framebuffer Read / Draw Buffer Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult InvalidateSubDataTest::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;
/* Framebuffers' objects */
glw::GLuint framebuffer = 0;
/* Get number of color attachments. */
glw::GLint max_color_attachments = 8 /* Specification minimum OpenGL 4.5 Core Profile p. 627 */;
gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed");
std::vector<glw::GLuint> renderbuffers(max_color_attachments);
std::vector<glw::GLuint> color_attachments(max_color_attachments);
static const glw::GLenum default_attachments[] = { GL_COLOR, GL_DEPTH, GL_STENCIL };
static const glw::GLuint default_attachments_count = sizeof(default_attachments) / sizeof(default_attachments[0]);
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
renderbuffers[i] = 0;
color_attachments[i] = GL_COLOR_ATTACHMENT0 + i;
}
try
{
/* Invalidate Default Framebuffer data */
gl.invalidateNamedFramebufferSubData(0, default_attachments_count, &(default_attachments[0]), 0, 0, 1, 1);
is_ok &= CheckErrorAndLog(default_attachments, default_attachments_count);
for (glw::GLuint i = 0; i < default_attachments_count; ++i)
{
gl.invalidateNamedFramebufferSubData(0, 1, &(default_attachments[i]), 0, 0, 1, 1);
is_ok &= CheckErrorAndLog(default_attachments[i]);
}
/* Prepare framebuffer... */
gl.genFramebuffers(1, &framebuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed");
gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed");
gl.genRenderbuffers(max_color_attachments, &(renderbuffers[0]));
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed");
/* .. with renderbuffer color attachments. */
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffers[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer has failed");
gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 4, 4);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER, renderbuffers[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed");
}
/* Check that framebuffer is complete. */
if (GL_FRAMEBUFFER_COMPLETE != gl.checkFramebufferStatus(GL_FRAMEBUFFER))
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "Framebuffer is unexpectedly incomplete."
<< tcu::TestLog::EndMessage;
throw 0;
}
gl.invalidateNamedFramebufferSubData(framebuffer, max_color_attachments, &(color_attachments[0]), 1, 1, 2, 2);
is_ok &= CheckErrorAndLog(&(color_attachments[0]), max_color_attachments);
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
gl.invalidateNamedFramebufferSubData(framebuffer, 1, &(color_attachments[i]), 1, 1, 2, 2);
is_ok &= CheckErrorAndLog(color_attachments[i]);
}
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
if (framebuffer)
{
gl.deleteFramebuffers(1, &framebuffer);
framebuffer = 0;
}
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
if (renderbuffers[i])
{
gl.deleteRenderbuffers(1, &(renderbuffers[i]));
}
}
/* Errors clean up. */
while (gl.getError())
;
/* 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 Check error and log.
*
* @param [in] attachment Framebuffer attachment.
*
* @return True if no error, false otherwise.
*/
bool InvalidateSubDataTest::CheckErrorAndLog(const glw::GLenum attachment)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Check error. */
if (glw::GLenum error = gl.getError())
{
/* There is an error. Log. */
m_context.getTestContext().getLog() << tcu::TestLog::Message << "InvalidateSubDataTest unexpectedly generated "
<< glu::getErrorStr(error) << " error for attachment "
<< glu::getFramebufferAttachmentStr(attachment) << ". Test fails."
<< tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Check error and log.
*
* @param [in] attachments Framebuffer attachments.
* @param [in] attachments_count Framebuffer attachments count.
*
* @return True if no error, false otherwise.
*/
bool InvalidateSubDataTest::CheckErrorAndLog(const glw::GLenum attachments[], glw::GLuint count)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Check error. */
if (glw::GLenum error = gl.getError())
{
/* There is an error. Log. */
std::string attachments_names = "";
for (glw::GLuint i = 0; i < count; ++i)
{
attachments_names.append(glu::getFramebufferAttachmentStr(attachments[i]).toString());
if ((count - 1) != i)
{
attachments_names.append(", ");
}
}
m_context.getTestContext().getLog() << tcu::TestLog::Message << "InvalidateSubDataTest unexpectedly generated "
<< glu::getErrorStr(error) << " error for following attachments ["
<< attachments_names << "]. Test fails." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/******************************** Clear Named Framebuffer Test Implementation ********************************/
/** @brief Clear Named Framebuffer Test constructor.
*
* @param [in] context OpenGL context.
*/
ClearTest::ClearTest(deqp::Context& context)
: deqp::TestCase(context, "framebuffers_clear", "Clear Named Framebuffer Test")
, m_fbo(0)
, m_renderbuffers(0)
, m_renderbuffers_count(0)
{
/* Intentionally left blank. */
}
/** @brief Compare two floats (template specialization).
*
* @param [in] first First float to be compared.
* @param [in] second Second float to be compared.
*
* @return True if floats are equal within +-(1.f/64.f) precision range, false otherwise.
*/
template <>
bool ClearTest::Compare<glw::GLfloat>(const glw::GLfloat first, const glw::GLfloat second)
{
return (de::abs(first - second) < (1.f / 64.f) /* Precission. */);
}
/** @brief Compare two objects (template general specialization).
*
* @param [in] first First objetc to be compared.
* @param [in] second Second object to be compared.
*
* @return True if floats are equal, false otherwise.
*/
template <typename T>
bool ClearTest::Compare(const T first, const T second)
{
return (first == second);
}
/** @brief Clear color buffer (float specialization), check errors and log.
*
* @param [in] buffer Buffer to be cleared.
* @param [in] drawbuffer Drawbuffer to be cleared.
* @param [in] value Value to be cleared with.
*
* @return True if succeeded without errors, false otherwise.
*/
template <>
bool ClearTest::ClearColor<glw::GLfloat>(glw::GLenum buffer, glw::GLint drawbuffer, glw::GLfloat value)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLfloat value_vector[4] = { value, 0, 0, 0 };
gl.clearNamedFramebufferfv(m_fbo, buffer, drawbuffer, value_vector);
if (glw::GLenum error = gl.getError())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "ClearNamedFramebufferfv unexpectedly generated " << glu::getErrorStr(error)
<< " error. Test fails." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Clear color buffer (int specialization), check errors and log.
*
* @param [in] buffer Buffer to be cleared.
* @param [in] drawbuffer Drawbuffer to be cleared.
* @param [in] value Value to be cleared with.
*
* @return True if succeeded without errors, false otherwise.
*/
template <>
bool ClearTest::ClearColor<glw::GLint>(glw::GLenum buffer, glw::GLint drawbuffer, glw::GLint value)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLint value_vector[4] = { value, 0, 0, 0 };
gl.clearNamedFramebufferiv(m_fbo, buffer, drawbuffer, value_vector);
if (glw::GLenum error = gl.getError())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "ClearNamedFramebufferiv unexpectedly generated " << glu::getErrorStr(error)
<< " error. Test fails." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Clear color buffer (uint specialization), check errors and log.
*
* @param [in] buffer Buffer to be cleared.
* @param [in] drawbuffer Drawbuffer to be cleared.
* @param [in] value Value to be cleared with.
*
* @return True if succeeded without errors, false otherwise.
*/
template <>
bool ClearTest::ClearColor<glw::GLuint>(glw::GLenum buffer, glw::GLint drawbuffer, glw::GLuint value)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLuint value_vector[4] = { value, 0, 0, 0 };
gl.clearNamedFramebufferuiv(m_fbo, buffer, drawbuffer, value_vector);
if (glw::GLenum error = gl.getError())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "ClearNamedFramebufferuiv unexpectedly generated " << glu::getErrorStr(error)
<< " error. Test fails." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** @brief Format of the buffer (float specialization).
*
* @return Format.
*/
template <>
glw::GLenum ClearTest::Format<GLfloat>()
{
return GL_RED;
}
/** @brief Format of the buffer (int and uint specialization).
*
* @return Format.
*/
template <typename T>
glw::GLenum ClearTest::Format()
{
return GL_RED_INTEGER;
}
/** @brief Type of the buffer (float specialization).
*
* @return Type.
*/
template <>
glw::GLenum ClearTest::Type<glw::GLfloat>()
{
return GL_FLOAT;
}
/** @brief Type of the buffer (int specialization).
*
* @return Type.
*/
template <>
glw::GLenum ClearTest::Type<glw::GLint>()
{
return GL_INT;
}
/** @brief Type of the buffer (uint specialization).
*
* @return Type.
*/
template <>
glw::GLenum ClearTest::Type<glw::GLuint>()
{
return GL_UNSIGNED_INT;
}
/** @brief Test DSA Clear function (color).
*
* @param [in] buffer Buffer to be cleared.
* @param [in] attachment Attachment to be tested.
* @param [in] value Value to be cleared with.
*
* @return True if test succeeded, false otherwise.
*/
template <typename T>
bool ClearTest::TestClearColor(glw::GLenum buffer, glw::GLenum attachment, T value)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.drawBuffer(attachment);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffer has failed");
/* Clear. */
if (ClearColor<T>(buffer, 0, value))
{
/* Fetching framebuffer content. */
T pixel = (T)0;
gl.readBuffer(attachment);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadBuffer has failed");
gl.readPixels(0, 0, 1, 1, Format<T>(), Type<T>(), &pixel);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixel has failed");
/* Comparison with reference value. */
if (Compare(pixel, value))
{
return true;
}
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "ClearNamedFramebuffer did not cleared color attachment "
<< glu::getFramebufferAttachmentStr(attachment) << " of the framebuffer." << tcu::TestLog::EndMessage;
}
return false;
}
/** @brief Test DSA Clear function (depth/stencil).
*
* @param [in] stencil Stencil value to be cleared with.
* @param [in] depth Depth value to be cleared with.
*
* @return True if test succeeded, false otherwise.
*/
bool ClearTest::TestClearDepthAndStencil(glw::GLfloat depth, glw::GLint stencil)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Clearing depth and stencil. */
gl.clearNamedFramebufferfi(m_fbo, GL_DEPTH_STENCIL, 0, depth, stencil);
if (glw::GLenum error = gl.getError())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "ClearNamedFramebufferufi unexpectedly generated " << glu::getErrorStr(error)
<< " error. Test fails." << tcu::TestLog::EndMessage;
return false;
}
/* Clear. */
/* Fetching framebuffer content. */
glw::GLfloat the_depth = 0.f;
glw::GLint the_stencil = 0;
gl.readPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &the_depth);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixel has failed");
gl.readPixels(0, 0, 1, 1, GL_STENCIL_INDEX, GL_INT, &the_stencil);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixel has failed");
/* Comparison with reference value. */
if (Compare(the_depth, depth) || Compare(the_stencil, stencil))
{
return true;
}
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "ClearNamedFramebufferfi did not cleared depth/stencil attachment of the framebuffer."
<< tcu::TestLog::EndMessage;
return true;
}
/** @brief Iterate Clear Named Framebuffer Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult ClearTest::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
{
/* Fixed point color test. */
PrepareFramebuffer(GL_COLOR, GL_R8);
for (glw::GLint i = 0; i < (glw::GLint)m_renderbuffers_count; ++i)
{
is_ok &= TestClearColor<glw::GLfloat>(GL_COLOR, GL_COLOR_ATTACHMENT0 + i, 0.5);
}
Clean();
/* Floating point color test. */
PrepareFramebuffer(GL_COLOR, GL_R32F);
for (glw::GLint i = 0; i < (glw::GLint)m_renderbuffers_count; ++i)
{
is_ok &= TestClearColor<glw::GLfloat>(GL_COLOR, GL_COLOR_ATTACHMENT0 + i, 0.5);
}
Clean();
/* Signed integer color test. */
PrepareFramebuffer(GL_COLOR, GL_R8I);
for (glw::GLint i = 0; i < (glw::GLint)m_renderbuffers_count; ++i)
{
is_ok &= TestClearColor<glw::GLint>(GL_COLOR, GL_COLOR_ATTACHMENT0 + i, -16);
}
Clean();
/* Unsigned integer color test. */
PrepareFramebuffer(GL_COLOR, GL_R8UI);
for (glw::GLint i = 0; i < (glw::GLint)m_renderbuffers_count; ++i)
{
is_ok &= TestClearColor<glw::GLuint>(GL_COLOR, GL_COLOR_ATTACHMENT0 + i, 16);
}
Clean();
/* Depth / stencil test. */
PrepareFramebuffer(GL_DEPTH_STENCIL, GL_DEPTH24_STENCIL8);
is_ok &= TestClearDepthAndStencil(1, 1);
Clean();
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
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 Prepare framebuffer.
*
* @param [in] buffer Buffer to be prepared.
* @param [in] internalformat Internal format to be prepared
*/
void ClearTest::PrepareFramebuffer(glw::GLenum buffer, glw::GLenum internalformat)
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Check that ther is no other fbo. */
if ((0 != m_fbo) || (DE_NULL != m_renderbuffers))
{
throw 0;
}
/* Prepare framebuffer... */
gl.genFramebuffers(1, &m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed");
gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed");
if (buffer == GL_COLOR)
{
glw::GLint max_color_attachments =
8; /* OpenGL 4.5 specification default (see Implementation Dependent Values tables). */
gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed");
m_renderbuffers = new glw::GLuint[max_color_attachments];
if (m_renderbuffers)
{
/* ... with renderbuffer color attachments. */
gl.genRenderbuffers(max_color_attachments, m_renderbuffers);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed");
m_renderbuffers_count = max_color_attachments;
for (glw::GLint i = 0; i < max_color_attachments; ++i)
{
gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffers[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer has failed");
gl.renderbufferStorage(GL_RENDERBUFFER, internalformat, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER,
m_renderbuffers[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed");
}
}
}
if (buffer == GL_DEPTH_STENCIL)
{
/* ... with depth and stencil attachments. */
m_renderbuffers = new glw::GLuint[1];
if (m_renderbuffers)
{
gl.genRenderbuffers(1, m_renderbuffers);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed");
gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffers[0]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer has failed");
m_renderbuffers_count = 1;
gl.renderbufferStorage(GL_RENDERBUFFER, internalformat, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
m_renderbuffers[0]);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed");
}
}
/* Check that framebuffer is complete. */
if (GL_FRAMEBUFFER_COMPLETE != gl.checkFramebufferStatus(GL_FRAMEBUFFER))
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "Framebuffer is unexpectedly incomplete."
<< tcu::TestLog::EndMessage;
throw 0;
}
}
/** @brief Clean up GL state.
*/
void ClearTest::Clean()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Releasing objects. */
if (m_fbo)
{
gl.deleteFramebuffers(1, &m_fbo);
m_fbo = 0;
}
if (DE_NULL != m_renderbuffers)
{
if (m_renderbuffers_count)
{
gl.deleteRenderbuffers(m_renderbuffers_count, m_renderbuffers);
}
delete[] m_renderbuffers;
m_renderbuffers = DE_NULL;
m_renderbuffers_count = 0;
}
/* Errors clean up. */
while (gl.getError())
;
}
/******************************** Blit Named Framebuffer Test Implementation ********************************/
/** @brief Named Framebuffer blit Test constructor.
*
* @param [in] context OpenGL context.
*/
BlitTest::BlitTest(deqp::Context& context)
: deqp::TestCase(context, "framebuffers_blit", "Framebuffer Blit Test")
, m_fbo_src(0)
, m_rbo_color_src(0)
, m_rbo_depth_stencil_src(0)
, m_fbo_dst(0)
, m_rbo_color_dst(0)
, m_rbo_depth_stencil_dst(0)
{
/* Intentionally left blank. */
}
/** @brief Iterate Named Framebuffer Blit Test cases.
*
* @return Iteration result.
*/
tcu::TestNode::IterateResult BlitTest::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;
try
{
PrepareFramebuffers();
is_ok = Test();
}
catch (...)
{
is_ok = false;
is_error = true;
}
/* Cleanup. */
Clean();
/* Errors clean up. */
while (gl.getError())
;
/* 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 Prepare framebuffer.
*/
void BlitTest::PrepareFramebuffers()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Prepare source framebuffer */
gl.genFramebuffers(1, &m_fbo_src);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed");
gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_src);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed");
gl.genRenderbuffers(1, &m_rbo_color_src);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed");
gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_color_src);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed");
gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 2, 2);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_color_src);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed");
gl.genRenderbuffers(1, &m_rbo_depth_stencil_src);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed");
gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_depth_stencil_src);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed");
gl.renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 2, 2);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo_depth_stencil_src);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed");
/* Check that framebuffer is complete. */
if (GL_FRAMEBUFFER_COMPLETE != gl.checkFramebufferStatus(GL_FRAMEBUFFER))
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "Framebuffer is unexpectedly incomplete."
<< tcu::TestLog::EndMessage;
throw 0;
}
/* Prepare destination framebuffer */
gl.genFramebuffers(1, &m_fbo_dst);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed");
gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_dst);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed");
gl.genRenderbuffers(1, &m_rbo_color_dst);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed");
gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_color_dst);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed");
gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 3, 2);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_color_dst);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed");
gl.genRenderbuffers(1, &m_rbo_depth_stencil_dst);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed");
gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_depth_stencil_dst);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed");
gl.renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 3, 2);
GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo_depth_stencil_dst);
GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed");
/* Check that framebuffer is complete. */
if (GL_FRAMEBUFFER_COMPLETE != gl.checkFramebufferStatus(GL_FRAMEBUFFER))
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "Framebuffer is unexpectedly incomplete."
<< tcu::TestLog::EndMessage;
throw 0;
}
}
/** @brief Do the blit test.
*/
bool BlitTest::Test()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_src);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
ClearFramebuffer(1.f, 0.f, 0.f, 0.5f, 1);
gl.blitNamedFramebuffer(m_fbo_src, m_fbo_dst, 0, 0, 1, 1, 0, 0, 1, 1,
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
if (CheckErrorAndLog())
{
ClearFramebuffer(0.f, 1.f, 0.f, 0.25f, 2);
gl.blitNamedFramebuffer(m_fbo_src, m_fbo_dst, 0, 0, 1, 1, 1, 0, 2, 1, GL_COLOR_BUFFER_BIT, GL_LINEAR);
gl.blitNamedFramebuffer(m_fbo_src, m_fbo_dst, 0, 0, 1, 1, 1, 0, 2, 1,
GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
if (CheckErrorAndLog())
{
ClearFramebuffer(0.f, 0.f, 1.f, 0.125f, 3);
gl.blitNamedFramebuffer(m_fbo_src, m_fbo_dst, 0, 0, 2, 2, 2, 0, 3, 1,
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
if (CheckErrorAndLog())
{
ClearFramebuffer(1.f, 1.f, 0.f, 0.0625f, 4);
gl.blitNamedFramebuffer(m_fbo_src, m_fbo_dst, 0, 0, 1, 1, 0, 1, 3, 2,
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
if (CheckErrorAndLog())
{
gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_dst);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
if (CheckColor() && CheckDepth() && CheckStencil())
{
return true;
}
}
}
}
}
return false;
}
/** @brief Check error and log.
*
* @return true if no error, false otherwise.
*/
bool BlitTest::CheckErrorAndLog()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Error query. */
if (glw::GLenum error = gl.getError())
{
/* Log. */
m_context.getTestContext().getLog() << tcu::TestLog::Message << "BlitNamedFramebuffer unexpectedly generated "
<< glu::getErrorStr(error) << " error." << tcu::TestLog::EndMessage;
/* Returning result. */
return false;
}
/* Returning result. */
return true;
}
/** @brief Check color and log.
*
* @return true if color matches reference, false otherwise.
*/
bool BlitTest::CheckColor()
{
/* Shortcut for GL functionality. */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reference values. */
static const glw::GLfloat reference[2][3][4] = {
{ { 1.f, 0.f, 0.f, 1.f }, { 0.f, 1.f, 0.f, 1.f }, { 0.f, 0.f, 1.f, 1.f } },
{ { 1.f, 1.f, 0.f, 1.f }, { 1.f, 1.f, 0.f, 1.f }, { 1.f, 1.f, 0.f, 1.f } }
};
/* Copy buffer. */
glw::GLfloat color[2][3][4] = { { { 0 } } };
/* Reading from GL. */
gl.readPixels(0, 0, 3, 2, GL_RGBA, GL_FLOAT, color);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels has failed");
/* Comparison against the reference. */
for (glw::GLuint j = 0; j < 2; ++j)
{
for (glw::GLuint i = 0; i < 3; ++i)
{
for (glw::GLuint k = 0; k < 4; ++k)
{
if (de::abs(reference[j][i][k] - color[j][i][k]) > (1.f / 64.f) /* Precision. */)
{
/* Log. */
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Blitted framebuffer color buffer contains [[" << color[0][0][0]
<< ", " << color[0][0][1] << ", " << color[0][0][2] << ", " << color[0][0][3] << "], ["
<< color[0][1][0] << ", " << color[0][1][1] << ", " << color[0][1][2] << ", " << color[0][1][3]
<< "], [" << color[0][2][0] << ", " << color[0][2][1] << ", " << color[0][2][2] << ", "
<< color[0][2][3] << "],\n[" << color[1][0][0] << ", " << color[1][0][1] << ", "
<< color[1][0][2] << ", " << color[1][0][3] << "], [" << color[1][1][0] << ", "
<< color[1][1][1] << ", " << color[1][1][2] << ", " << color[1][1][3] << "], ["
<< color[1][2][0] << ", " << color[1][2][1] << ", " << color[1][2][2] << ", " << color[1][2][3]
<< "]], but\n"
<< reference[0][0][0] << ", " << reference[0][0][1] << ", " << reference[0][0][2] << ", "
<< reference[0][0][3] << "], [" << reference[0][1][0] << ", " << reference[0][1][1] << ", "
<< reference[0][1][2] << ", " << reference[