| /*------------------------------------------------------------------------- |
| * 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[0][1][3] << "], [" << reference[0][2][0] << ", " |
| << reference[0][2][1] << ", " << reference[0][2][2] << ", " << reference[0][2][3] << "],\n[" |
| << reference[1][0][0] << ", " << reference[1][0][1] << ", " << reference[1][0][2] << ", " |
| << reference[1][0][3] << "], [" << reference[1][1][0] << ", " << reference[1][1][1] << ", " |
| << reference[1][1][2] << ", " << reference[1][1][3] << "], [" << reference[1][2][0] << ", " |
| << reference[1][2][1] << ", " << reference[1][2][2] << ", " << reference[1][2][3] |
| << "]] was expected.\n" |
| << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| /** @brief Check depth and log. |
| * |
| * @return true if depth matches reference, false otherwise. |
| */ |
| bool BlitTest::CheckDepth() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Reference values. */ |
| static const glw::GLfloat reference[2][3] = { { 0.5, 0.25, 0.125 }, { 0.0625, 0.0625, 0.0625 } }; |
| |
| /* Copy buffer. */ |
| glw::GLfloat depth[2][3] = { { 0 } }; |
| |
| /* Reading from GL. */ |
| gl.readPixels(0, 0, 3, 2, GL_DEPTH_COMPONENT, GL_FLOAT, depth); |
| 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) |
| { |
| if (de::abs(reference[j][i] - depth[j][i]) > (1.f / 64.f) /* Precision. */) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Blitted framebuffer depth buffer contains [" << depth[0][0] << ", " |
| << depth[0][1] << ", " << depth[0][2] << ", \n" |
| << depth[1][0] << ", " << depth[1][1] << ", " << depth[1][2] << "], but " << reference[0][0] << ", " |
| << reference[0][1] << ", " << reference[0][2] << ", \n" |
| << reference[1][0] << ", " << reference[1][1] << ", " << reference[1][2] << "] was expected." |
| << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| /** @brief Check stencil and log. |
| * |
| * @return true if stencil matches reference, false otherwise. |
| */ |
| bool BlitTest::CheckStencil() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Reference values. */ |
| static const glw::GLint reference[2][3] = { { 1, 2, 3 }, { 4, 4, 4 } }; |
| |
| /* Copy buffer. */ |
| glw::GLint stencil[2][3] = { { 0 } }; |
| |
| /* Reading from GL. */ |
| gl.readPixels(0, 0, 3, 2, GL_STENCIL_INDEX, GL_INT, stencil); |
| 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) |
| { |
| if (reference[j][i] != stencil[j][i]) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Blitted framebuffer stencil buffer contains [" << stencil[0][0] << ", " |
| << stencil[0][1] << ", " << stencil[0][2] << ", \n" |
| << stencil[1][0] << ", " << stencil[1][1] << ", " << stencil[1][2] << "], but " << reference[0][0] |
| << ", " << reference[0][1] << ", " << reference[0][2] << ", \n" |
| << reference[1][0] << ", " << reference[1][1] << ", " << reference[1][2] << "] was expected." |
| << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| /** @brief Clear framebuffer. |
| * |
| * @param [in] red Color component. |
| * @param [in] green Color component. |
| * @param [in] blue Color component. |
| * @param [in] alpha Color component. |
| * @param [in] depth Depth component. |
| * @param [in] stencil Stencil index. |
| */ |
| void BlitTest::ClearFramebuffer(glw::GLfloat red, glw::GLfloat green, glw::GLfloat blue, glw::GLfloat depth, |
| glw::GLint stencil) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Setup clear values. */ |
| gl.clearColor(red, green, blue, 1.f); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor has failed"); |
| |
| gl.clearDepth(depth); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor has failed"); |
| |
| gl.clearStencil(stencil); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor has failed"); |
| |
| /* Clearing. */ |
| gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor has failed"); |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void BlitTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Releasing objects. */ |
| if (m_fbo_src) |
| { |
| gl.deleteFramebuffers(1, &m_fbo_src); |
| |
| m_fbo_src = 0; |
| } |
| |
| if (m_fbo_dst) |
| { |
| gl.deleteFramebuffers(1, &m_fbo_dst); |
| |
| m_fbo_dst = 0; |
| } |
| |
| if (m_rbo_color_src) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_color_src); |
| |
| m_rbo_color_src = 0; |
| } |
| |
| if (m_rbo_color_dst) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_color_dst); |
| |
| m_rbo_color_dst = 0; |
| } |
| |
| if (m_rbo_depth_stencil_src) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_depth_stencil_src); |
| |
| m_rbo_depth_stencil_src = 0; |
| } |
| |
| if (m_rbo_depth_stencil_dst) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_depth_stencil_dst); |
| |
| m_rbo_depth_stencil_dst = 0; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| /******************************** Framebuffer Check Status Test Implementation ********************************/ |
| |
| /** @brief Check Status Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| CheckStatusTest::CheckStatusTest(deqp::Context& context) |
| : deqp::TestCase(context, "framebuffers_check_status", "Framebuffer Check Status Test") |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Check Status Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult CheckStatusTest::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 maybe_ok = true; |
| bool is_error = false; |
| |
| try |
| { |
| /* The specification is not clear about framebuffer completness. OpenGL 4.5 core profile |
| specification in chapter 9.4.2 says: |
| "The framebuffer object bound to target is said to be framebuffer complete if all |
| the following conditions are true [...]" |
| It does not say that framebuffer is incomplete when any of the conditions are not met. |
| Due to this wording, except for obvious cases (incomplete attachment and missing attachments) |
| other tests ar optional and may result in QP_TEST_RESULT_COMPATIBILITY_WARNING when fail. */ |
| is_ok &= IncompleteAttachmentTestCase(); |
| is_ok &= MissingAttachmentTestCase(); |
| |
| maybe_ok &= IncompleteMultisampleRenderbufferTestCase(); |
| maybe_ok &= IncompleteMultisampleTextureTestCase(); |
| maybe_ok &= IncompleteLayerTargetsTestCase(); |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| if (maybe_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Pass with Compatibility Warning"); |
| } |
| } |
| else |
| { |
| if (is_error) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| } |
| |
| return STOP; |
| } |
| |
| /** Incomplete Attachment Test Case |
| * |
| * @return True if test case succeeded, false otherwise. |
| */ |
| bool CheckStatusTest::IncompleteAttachmentTestCase() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Test result */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| /* Test objects. */ |
| glw::GLuint fbo = 0; |
| glw::GLuint rbo = 0; |
| |
| try |
| { |
| gl.genFramebuffers(1, &fbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, fbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed"); |
| |
| gl.genRenderbuffers(1, &rbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, rbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed"); |
| |
| glw::GLenum status = 0; |
| |
| /* Check that framebuffer is complete. */ |
| if (GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT != (status = gl.checkNamedFramebufferStatus(fbo, GL_FRAMEBUFFER))) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "CheckNamedFramebufferStatus did not return FRAMEBUFFER_INCOMPLETE_ATTACHMENT value. " |
| << glu::getFramebufferStatusStr(status) << " was observed instead." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Releasing obnjects. */ |
| if (fbo) |
| { |
| gl.deleteFramebuffers(1, &fbo); |
| } |
| |
| if (rbo) |
| { |
| gl.deleteRenderbuffers(1, &rbo); |
| } |
| |
| if (is_error) |
| { |
| throw 0; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** Missing Attachment Test Case |
| * |
| * @return True if test case succeeded, false otherwise. |
| */ |
| bool CheckStatusTest::MissingAttachmentTestCase() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Test result */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| /* Test objects. */ |
| glw::GLuint fbo = 0; |
| |
| try |
| { |
| gl.genFramebuffers(1, &fbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, fbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed"); |
| |
| glw::GLenum status = 0; |
| |
| /* Check that framebuffer is complete. */ |
| if (GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT != |
| (status = gl.checkNamedFramebufferStatus(fbo, GL_FRAMEBUFFER))) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "CheckNamedFramebufferStatus did not return FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT value. " |
| << glu::getFramebufferStatusStr(status) << " was observed instead." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Releasing obnjects. */ |
| if (fbo) |
| { |
| gl.deleteRenderbuffers(1, &fbo); |
| } |
| |
| if (is_error) |
| { |
| throw 0; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** Incomplete Multisample Renderbuffer Test Case |
| * |
| * @return True if test case succeeded, false otherwise. |
| */ |
| bool CheckStatusTest::IncompleteMultisampleRenderbufferTestCase() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Test result */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| /* Test objects. */ |
| glw::GLuint fbo = 0; |
| glw::GLuint rbo[2] = { 0 }; |
| |
| try |
| { |
| gl.genFramebuffers(1, &fbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, fbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed"); |
| |
| gl.genRenderbuffers(2, rbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, rbo[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed"); |
| |
| gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_R8, 1, 1); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, rbo[1]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed"); |
| |
| gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_R8, 1, 1); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rbo[1]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed"); |
| |
| glw::GLenum status = 0; |
| |
| /* Check that framebuffer is complete. */ |
| if (GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE != (status = gl.checkNamedFramebufferStatus(fbo, GL_FRAMEBUFFER))) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "CheckNamedFramebufferStatus did not return FRAMEBUFFER_INCOMPLETE_MULTISAMPLE value. " |
| << glu::getFramebufferStatusStr(status) << " was observed instead." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Releasing obnjects. */ |
| if (fbo) |
| { |
| gl.deleteFramebuffers(1, &fbo); |
| } |
| |
| for (glw::GLuint i = 0; i < 2; ++i) |
| { |
| if (rbo[i]) |
| { |
| gl.deleteRenderbuffers(1, &rbo[i]); |
| } |
| } |
| |
| if (is_error) |
| { |
| throw 0; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** Incomplete Multisample Texture Test Case |
| * |
| * @return True if test case succeeded, false otherwise. |
| */ |
| bool CheckStatusTest::IncompleteMultisampleTextureTestCase() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Test result */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| /* Test objects. */ |
| glw::GLuint fbo = 0; |
| glw::GLuint rbo = 0; |
| glw::GLuint to[2] = { 0 }; |
| |
| try |
| { |
| gl.genFramebuffers(1, &fbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, fbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed"); |
| |
| gl.genTextures(2, to); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed"); |
| |
| gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture has failed"); |
| |
| gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_R8, 1, 1, GL_FALSE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample has failed"); |
| |
| gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, to[0], 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to[1]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture has failed"); |
| |
| gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_R8, 1, 1, GL_TRUE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample has failed"); |
| |
| gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, to[1], 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| gl.genRenderbuffers(1, &rbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, rbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed"); |
| |
| gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_R8, 1, 1); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, rbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed"); |
| |
| glw::GLenum status = 0; |
| |
| /* Check that framebuffer is complete. */ |
| if (GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE != (status = gl.checkNamedFramebufferStatus(fbo, GL_FRAMEBUFFER))) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "CheckNamedFramebufferStatus did not return FRAMEBUFFER_INCOMPLETE_MULTISAMPLE value. " |
| << glu::getFramebufferStatusStr(status) << " was observed instead." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Releasing obnjects. */ |
| if (fbo) |
| { |
| gl.deleteFramebuffers(1, &fbo); |
| } |
| |
| for (glw::GLuint i = 0; i < 2; ++i) |
| { |
| if (to[i]) |
| { |
| gl.deleteTextures(1, &to[i]); |
| } |
| } |
| |
| if (rbo) |
| { |
| gl.deleteRenderbuffers(1, &rbo); |
| } |
| |
| if (is_error) |
| { |
| throw 0; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** Incomplete Layer Targets Test Case |
| * |
| * @return True if test case succeeded, false otherwise. |
| */ |
| bool CheckStatusTest::IncompleteLayerTargetsTestCase() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Test result */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| /* Test objects. */ |
| glw::GLuint fbo = 0; |
| glw::GLuint to[2] = { 0 }; |
| |
| try |
| { |
| gl.genFramebuffers(1, &fbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, fbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed"); |
| |
| gl.genTextures(2, to); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed"); |
| |
| gl.bindTexture(GL_TEXTURE_3D, to[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture has failed"); |
| |
| gl.texStorage3D(GL_TEXTURE_3D, 1, GL_R8, 2, 2, 2); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample has failed"); |
| |
| gl.framebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, to[0], 0, 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| gl.bindTexture(GL_TEXTURE_2D, to[1]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture has failed"); |
| |
| gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R8, 1, 1); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample has failed"); |
| |
| gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, to[1], 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed"); |
| |
| glw::GLenum status = 0; |
| |
| /* Check that framebuffer is complete. */ |
| if (GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS != (status = gl.checkNamedFramebufferStatus(fbo, GL_FRAMEBUFFER))) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "CheckNamedFramebufferStatus did not return FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS value. " |
| << glu::getFramebufferStatusStr(status) << " was observed instead." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Releasing obnjects. */ |
| if (fbo) |
| { |
| gl.deleteFramebuffers(1, &fbo); |
| } |
| |
| for (glw::GLuint i = 0; i < 2; ++i) |
| { |
| if (to[i]) |
| { |
| gl.deleteTextures(1, &to[i]); |
| } |
| } |
| |
| if (is_error) |
| { |
| throw 0; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /******************************** Get Named Framebuffer Parameters Test Implementation ********************************/ |
| |
| /** @brief Get Named Framebuffer Parameters Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| GetParametersTest::GetParametersTest(deqp::Context& context) |
| : deqp::TestCase(context, "framebuffers_get_parameters", "Get Named Framebuffer Parameters Test") |
| , m_fbo(0) |
| , m_rbo(0) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Check Status Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult GetParametersTest::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 |
| { |
| gl.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed"); |
| |
| is_ok &= TestDefaultFramebuffer(); |
| |
| PrepareFramebuffer(); |
| |
| is_ok &= TestCustomFramebuffer(); |
| } |
| 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 Prepare framebuffer. |
| */ |
| void GetParametersTest::PrepareFramebuffer() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| 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"); |
| |
| 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(), "glBindRenderbuffers has failed"); |
| |
| gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, 1, 2); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| /* Check that framebuffer is complete. */ |
| if (GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus(GL_FRAMEBUFFER)) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Unexpectedly framebuffer was incomplete." |
| << tcu::TestLog::EndMessage; |
| |
| throw 0; |
| } |
| } |
| |
| /** Default framebuffer Test Case |
| * |
| * @return True if test case succeeded, false otherwise. |
| */ |
| bool GetParametersTest::TestDefaultFramebuffer() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Result. */ |
| bool is_ok = true; |
| |
| static const glw::GLenum pnames[] = { GL_DOUBLEBUFFER, |
| GL_IMPLEMENTATION_COLOR_READ_FORMAT, |
| GL_IMPLEMENTATION_COLOR_READ_TYPE, |
| GL_SAMPLES, |
| GL_SAMPLE_BUFFERS, |
| GL_STEREO }; |
| |
| static const glw::GLchar* pnames_strings[] = { "GL_DOUBLEBUFFER", |
| "GL_IMPLEMENTATION_COLOR_READ_FORMAT", |
| "GL_IMPLEMENTATION_COLOR_READ_TYPE", |
| "GL_SAMPLES", |
| "GL_SAMPLE_BUFFERS", |
| "GL_STEREO" }; |
| |
| glw::GLuint pnames_count = sizeof(pnames) / sizeof(pnames[0]); |
| |
| for (glw::GLuint i = 0; i < pnames_count; ++i) |
| { |
| glw::GLint parameter_legacy = 0; |
| glw::GLint parameter_dsa = 0; |
| |
| gl.getFramebufferParameteriv(GL_FRAMEBUFFER, pnames[i], ¶meter_legacy); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFramebufferParameteriv has failed"); |
| |
| gl.getNamedFramebufferParameteriv(0, pnames[i], ¶meter_dsa); |
| |
| if (glw::GLenum error = gl.getError()) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferParameteriv unexpectedly generated " |
| << glu::getErrorStr(error) << " error when called with " << pnames_strings[i] |
| << " parameter name for default framebuffer." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| |
| if (parameter_legacy != parameter_dsa) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "GetNamedFramebufferParameteriv returned " |
| << parameter_dsa << ", but " << parameter_legacy << " was expected for " |
| << pnames_strings[i] << " parameter name of default object." |
| << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| } |
| |
| return is_ok; |
| } |
| |
| /** Framebuffer Object Test Case |
| * |
| * @return True if test case succeeded, false otherwise. |
| */ |
| bool GetParametersTest::TestCustomFramebuffer() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Result. */ |
| bool is_ok = true; |
| |
| static const glw::GLenum pnames[] = { GL_DOUBLEBUFFER, |
| GL_IMPLEMENTATION_COLOR_READ_FORMAT, |
| GL_IMPLEMENTATION_COLOR_READ_TYPE, |
| GL_SAMPLES, |
| GL_SAMPLE_BUFFERS, |
| GL_STEREO, |
| GL_FRAMEBUFFER_DEFAULT_WIDTH, |
| GL_FRAMEBUFFER_DEFAULT_HEIGHT, |
| GL_FRAMEBUFFER_DEFAULT_LAYERS, |
| GL_FRAMEBUFFER_DEFAULT_SAMPLES, |
| GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS }; |
| |
| static const glw::GLchar* pnames_strings[] = { "GL_DOUBLEBUFFER", |
| "GL_IMPLEMENTATION_COLOR_READ_FORMAT", |
| "GL_IMPLEMENTATION_COLOR_READ_TYPE", |
| "GL_SAMPLES", |
| "GL_SAMPLE_BUFFERS", |
| "GL_STEREO", |
| "FRAMEBUFFER_DEFAULT_WIDTH", |
| "FRAMEBUFFER_DEFAULT_HEIGHT", |
| "FRAMEBUFFER_DEFAULT_LAYERS", |
| "FRAMEBUFFER_DEFAULT_SAMPLES", |
| "FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS" }; |
| |
| glw::GLuint pnames_count = sizeof(pnames) / sizeof(pnames[0]); |
| |
| for (glw::GLuint i = 0; i < pnames_count; ++i) |
| { |
| glw::GLint parameter_legacy = 0; |
| glw::GLint parameter_dsa = 0; |
| |
| gl.getFramebufferParameteriv(GL_FRAMEBUFFER, pnames[i], ¶meter_legacy); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFramebufferParameteriv has failed"); |
| |
| gl.getNamedFramebufferParameteriv(m_fbo, pnames[i], ¶meter_dsa); |
| |
| if (glw::GLenum error = gl.getError()) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferParameteriv unexpectedly generated " |
| << glu::getErrorStr(error) << " error when called with " << pnames_strings[i] |
| << " parameter name for framebuffer object." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| |
| if (parameter_legacy != parameter_dsa) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "GetNamedFramebufferParameteriv returned " |
| << parameter_dsa << ", but " << parameter_legacy << " was expected for " |
| << pnames_strings[i] << " parameter name of framebuffer object." |
| << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void GetParametersTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Releasing obnjects. */ |
| 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()) |
| ; |
| } |
| |
| /******************************** Get Named Framebuffer Attachment Parameters Test Implementation ********************************/ |
| |
| /** @brief Get Named Framebuffer Parameters Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| GetAttachmentParametersTest::GetAttachmentParametersTest(deqp::Context& context) |
| : deqp::TestCase(context, "framebuffers_get_attachment_parameters", |
| "Get Named Framebuffer Attachment Parameters Test") |
| , m_fbo(0) |
| { |
| memset(m_rbo, 0, sizeof(m_rbo)); |
| memset(m_to, 0, sizeof(m_to)); |
| } |
| |
| /** @brief Iterate Get Named Framebuffer Attachment Parameters Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult GetAttachmentParametersTest::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 |
| { |
| /* Default framebuffer. */ |
| gl.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers has failed"); |
| |
| is_ok &= TestDefaultFramebuffer(); |
| |
| /* Framebuffer object with renderbuffer attachments (depth only). */ |
| CreateRenderbufferFramebuffer(true, false); |
| |
| is_ok &= TestRenderbufferFramebuffer(false); |
| |
| Clean(); |
| |
| /* Framebuffer object with renderbuffer attachments (stencil only). */ |
| CreateRenderbufferFramebuffer(false, true); |
| |
| is_ok &= TestRenderbufferFramebuffer(false); |
| |
| Clean(); |
| |
| /* Framebuffer object with renderbuffer attachments (depth-stencil merged). */ |
| CreateRenderbufferFramebuffer(true, true); |
| |
| is_ok &= TestRenderbufferFramebuffer(true); |
| |
| Clean(); |
| |
| /* Framebuffer object with texture attachments (depth only). */ |
| CreateTextureFramebuffer(true, false); |
| |
| is_ok &= TestTextureFramebuffer(false); |
| |
| Clean(); |
| |
| /* Framebuffer object with texture attachments (stencil only). */ |
| CreateTextureFramebuffer(false, true); |
| |
| is_ok &= TestTextureFramebuffer(false); |
| |
| Clean(); |
| |
| /* Framebuffer object with texture attachments (depth-stencil merged). */ |
| CreateTextureFramebuffer(true, true); |
| |
| is_ok &= TestTextureFramebuffer(true); |
| |
| Clean(); |
| } |
| 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; |
| } |
| |
| /** Create framebuffer with renderbuffer |
| * |
| * @param [in] depth Prepare framebuffer with depth buffer. |
| * @param [in] stencil Prepare framebuffer with stencil buffer. |
| * |
| * @note If both depth and stencil, the joined dept_stencil buffer will be created. |
| */ |
| void GetAttachmentParametersTest::CreateRenderbufferFramebuffer(bool depth, bool stencil) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| 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"); |
| |
| gl.genRenderbuffers(2, m_rbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed"); |
| |
| gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 2); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| if (depth && (!stencil)) |
| { |
| gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo[1]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed"); |
| |
| gl.renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 1, 2); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rbo[1]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| } |
| |
| if ((!depth) && stencil) |
| { |
| gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo[1]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed"); |
| |
| gl.renderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 1, 2); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo[1]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| } |
| |
| if (depth && stencil) |
| { |
| gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo[1]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed"); |
| |
| gl.renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 1, 2); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo[1]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| } |
| |
| /* Check that framebuffer is complete. */ |
| if (GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus(GL_FRAMEBUFFER)) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Unexpectedly framebuffer was incomplete." |
| << tcu::TestLog::EndMessage; |
| |
| throw 0; |
| } |
| } |
| |
| /** Create framebuffer with tetxure |
| * |
| * @param [in] depth Prepare framebuffer with depth buffer. |
| * @param [in] stencil Prepare framebuffer with stencil buffer. |
| * |
| * @note If both depth and stencil, the joined dept_stencil buffer will be created. |
| */ |
| void GetAttachmentParametersTest::CreateTextureFramebuffer(bool depth, bool stencil) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| 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"); |
| |
| gl.genTextures(2, m_to); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed"); |
| |
| gl.bindTexture(GL_TEXTURE_2D, m_to[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed"); |
| |
| gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 2); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to[0], 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| if (depth && (!stencil)) |
| { |
| gl.bindTexture(GL_TEXTURE_2D, m_to[1]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed"); |
| |
| gl.texStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT24, 1, 2); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_to[1], 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| } |
| |
| if ((!depth) && stencil) |
| { |
| gl.bindTexture(GL_TEXTURE_2D, m_to[1]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed"); |
| |
| gl.texStorage2D(GL_TEXTURE_2D, 1, GL_STENCIL_INDEX8, 1, 2); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_to[1], 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| } |
| |
| if (depth && stencil) |
| { |
| gl.bindTexture(GL_TEXTURE_2D, m_to[1]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffers has failed"); |
| |
| gl.texStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, 1, 2); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_to[1], 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| } |
| |
| /* Check that framebuffer is complete. */ |
| if (GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus(GL_FRAMEBUFFER)) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Unexpectedly framebuffer was incomplete." |
| << tcu::TestLog::EndMessage; |
| |
| throw 0; |
| } |
| } |
| |
| /** Test default framebuffer. |
| * |
| * @return True if test succeeded, false otherwise. |
| */ |
| bool GetAttachmentParametersTest::TestDefaultFramebuffer() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Result. */ |
| bool is_ok = true; |
| |
| static const glw::GLenum attachments[] = { GL_FRONT_LEFT, GL_FRONT_RIGHT, GL_BACK_LEFT, |
| GL_BACK_RIGHT, GL_DEPTH, GL_STENCIL }; |
| |
| static const glw::GLchar* attachments_strings[] = { "GL_FRONT_LEFT", "GL_FRONT_RIGHT", "GL_BACK_LEFT", |
| "GL_BACK_RIGHT", "GL_DEPTH", "GL_STENCIL" }; |
| |
| static const glw::GLuint attachments_count = sizeof(attachments) / sizeof(attachments[0]); |
| |
| for (glw::GLuint j = 0; j < attachments_count; ++j) |
| { |
| glw::GLint parameter_legacy = 0; |
| glw::GLint parameter_dsa = 0; |
| |
| gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, attachments[j], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, |
| ¶meter_legacy); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFramebufferParameteriv has failed"); |
| |
| gl.getNamedFramebufferAttachmentParameteriv(0, attachments[j], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, |
| ¶meter_dsa); |
| |
| /* Error check. */ |
| if (glw::GLenum error = gl.getError()) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferAttachmentParameteriv unexpectedly generated " |
| << glu::getErrorStr(error) |
| << " error when called with GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE parameter name for " |
| << attachments_strings[j] << " attachment of default framebuffer." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| |
| if (parameter_legacy != parameter_dsa) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferAttachmentParameteriv returned " << parameter_dsa |
| << ", but " << parameter_legacy |
| << " was expected for GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE parameter name of default framebuffer." |
| << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| |
| if (parameter_dsa != GL_NONE) |
| { |
| static const glw::GLenum optional_pnames[] = { |
| GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING |
| }; |
| |
| static const glw::GLchar* optional_pnames_strings[] = { |
| "GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE", "GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE", |
| "GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE", "GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE", |
| "GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE", "GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE", |
| "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE", "GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING" |
| }; |
| |
| static const glw::GLuint optional_pnames_count = sizeof(optional_pnames) / sizeof(optional_pnames[0]); |
| |
| for (glw::GLuint i = 0; i < optional_pnames_count; ++i) |
| { |
| glw::GLint optional_parameter_legacy = 0; |
| glw::GLint optional_parameter_dsa = 0; |
| |
| gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, attachments[j], optional_pnames[i], |
| &optional_parameter_legacy); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFramebufferParameteriv has failed"); |
| |
| gl.getNamedFramebufferAttachmentParameteriv(0, attachments[j], optional_pnames[i], |
| &optional_parameter_dsa); |
| |
| if (glw::GLenum error = gl.getError()) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferAttachmentParameteriv unexpectedly generated " |
| << glu::getErrorStr(error) << " error when called with " << optional_pnames_strings[i] |
| << " parameter name for " << attachments_strings[j] |
| << " attachment of default framebuffer. The GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was " |
| << parameter_legacy << "." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| |
| if (optional_parameter_legacy != optional_parameter_dsa) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferAttachmentParameteriv returned " |
| << optional_parameter_dsa << ", but " << optional_parameter_legacy << " was expected for " |
| << optional_pnames_strings << " parameter name for " << attachments_strings[j] |
| << " attachment of default framebuffer." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| } |
| } |
| } |
| |
| return is_ok; |
| } |
| |
| /** Test framebuffer object (with renderbuffer). |
| * |
| * @param [in] depth_stencil Has framebuffer depth_stencil attachment. |
| * |
| * @return True if test succeeded, false otherwise. |
| */ |
| bool GetAttachmentParametersTest::TestRenderbufferFramebuffer(bool depth_stencil) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Result. */ |
| bool is_ok = true; |
| |
| static const glw::GLenum attachments[] = { GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL_ATTACHMENT, |
| GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; |
| |
| static const glw::GLchar* attachments_strings[] = { "GL_DEPTH_ATTACHMENT", "GL_STENCIL_ATTACHMENT", |
| "GL_DEPTH_STENCIL_ATTACHMENT", "GL_COLOR_ATTACHMENT0", |
| "GL_COLOR_ATTACHMENT1" }; |
| |
| static const glw::GLuint attachments_count = sizeof(attachments) / sizeof(attachments[0]); |
| |
| for (glw::GLuint j = 0; j < attachments_count; ++j) |
| { |
| glw::GLint parameter_legacy = 0; |
| glw::GLint parameter_dsa = 0; |
| |
| /* Omit DEPTH_STENCIL_ATTACHMENT attachment if the renderbuffer is not depth-stencil. */ |
| if (attachments[j] == GL_DEPTH_STENCIL_ATTACHMENT) |
| { |
| if (!depth_stencil) |
| { |
| continue; |
| } |
| } |
| |
| gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, attachments[j], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, |
| ¶meter_legacy); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFramebufferParameteriv has failed"); |
| |
| gl.getNamedFramebufferAttachmentParameteriv(m_fbo, attachments[j], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, |
| ¶meter_dsa); |
| |
| /* Error check. */ |
| if (glw::GLenum error = gl.getError()) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferAttachmentParameteriv unexpectedly generated " |
| << glu::getErrorStr(error) |
| << " error when called with GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE parameter name for " |
| << attachments_strings[j] << " attachment of renderbuffer framebuffer object." |
| << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| |
| if (parameter_legacy != parameter_dsa) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferAttachmentParameteriv returned " << parameter_dsa |
| << ", but " << parameter_legacy << " was expected for GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE parameter " |
| "name of renderbuffer framebuffer object." |
| << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| |
| if (parameter_dsa != GL_NONE) |
| { |
| static const glw::GLenum optional_pnames[] = { |
| GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, |
| GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING |
| }; |
| |
| static const glw::GLchar* optional_pnames_strings[] = { |
| "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME", "GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE", |
| "GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE", "GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE", |
| "GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE", "GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE", |
| "GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE", "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE", |
| "GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING" |
| }; |
| |
| static const glw::GLuint optional_pnames_count = sizeof(optional_pnames) / sizeof(optional_pnames[0]); |
| |
| for (glw::GLuint i = 0; i < optional_pnames_count; ++i) |
| { |
| /* Omit FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE pname when DEPTH_STENCIL_ATTACHMENT attachment is used. */ |
| if (attachments[j] == GL_DEPTH_STENCIL_ATTACHMENT) |
| { |
| if (optional_pnames[i] == GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE) |
| { |
| continue; |
| } |
| } |
| |
| glw::GLint optional_parameter_legacy = 0; |
| glw::GLint optional_parameter_dsa = 0; |
| |
| gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, attachments[j], optional_pnames[i], |
| &optional_parameter_legacy); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFramebufferParameteriv has failed"); |
| |
| gl.getNamedFramebufferAttachmentParameteriv(m_fbo, attachments[j], optional_pnames[i], |
| &optional_parameter_dsa); |
| |
| if (glw::GLenum error = gl.getError()) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferAttachmentParameteriv unexpectedly generated " |
| << glu::getErrorStr(error) << " error when called with " << optional_pnames_strings[i] |
| << " parameter name for " << attachments_strings[j] |
| << " attachment of renderbuffer framebuffer object. The GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE " |
| "was " |
| << parameter_legacy << "." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| |
| if (optional_parameter_legacy != optional_parameter_dsa) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferAttachmentParameteriv returned " |
| << optional_parameter_dsa << ", but " << optional_parameter_legacy << " was expected for " |
| << optional_pnames_strings << " parameter name for " << attachments_strings[j] |
| << " attachment of renderbuffer framebuffer object." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| } |
| } |
| } |
| |
| return is_ok; |
| } |
| |
| /** Test framebuffer object (with texture). |
| * |
| * @param [in] depth_stencil Has framebuffer depth_stencil attachment. |
| * |
| * @return True if test succeeded, false otherwise. |
| */ |
| bool GetAttachmentParametersTest::TestTextureFramebuffer(bool depth_stencil) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Result. */ |
| bool is_ok = true; |
| |
| static const glw::GLenum attachments[] = { GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL_ATTACHMENT, |
| GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; |
| |
| static const glw::GLchar* attachments_strings[] = { "GL_DEPTH_ATTACHMENT", "GL_STENCIL_ATTACHMENT", |
| "GL_DEPTH_STENCIL_ATTACHMENT", "GL_COLOR_ATTACHMENT0", |
| "GL_COLOR_ATTACHMENT1" }; |
| |
| static const glw::GLuint attachments_count = sizeof(attachments) / sizeof(attachments[0]); |
| |
| for (glw::GLuint j = 0; j < attachments_count; ++j) |
| { |
| /* Omit DEPTH_STENCIL_ATTACHMENT attachment if the renderbuffer is not depth-stencil. */ |
| if (attachments[j] == GL_DEPTH_STENCIL_ATTACHMENT) |
| { |
| if (!depth_stencil) |
| { |
| continue; |
| } |
| } |
| |
| glw::GLint parameter_legacy = 0; |
| glw::GLint parameter_dsa = 0; |
| |
| gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, attachments[j], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, |
| ¶meter_legacy); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFramebufferParameteriv has failed"); |
| |
| gl.getNamedFramebufferAttachmentParameteriv(m_fbo, attachments[j], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, |
| ¶meter_dsa); |
| |
| /* Error check. */ |
| if (glw::GLenum error = gl.getError()) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferAttachmentParameteriv unexpectedly generated " |
| << glu::getErrorStr(error) |
| << " error when called with GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE parameter name for " |
| << attachments_strings[j] << " attachment of texture framebuffer object." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| |
| if (parameter_legacy != parameter_dsa) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferAttachmentParameteriv returned " << parameter_dsa |
| << ", but " << parameter_legacy << " was expected for GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE parameter " |
| "name of texture framebuffer object." |
| << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| |
| if (parameter_dsa != GL_NONE) |
| { |
| static const glw::GLenum optional_pnames[] = { GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, |
| GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, |
| GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, |
| GL_FRAMEBUFFER_ATTACHMENT_LAYERED, |
| GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, |
| GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, |
| GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING }; |
| |
| static const glw::GLchar* optional_pnames_strings[] = { "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME", |
| "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL", |
| "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE", |
| "GL_FRAMEBUFFER_ATTACHMENT_LAYERED", |
| "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER", |
| "GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE", |
| "GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE", |
| "GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE", |
| "GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE", |
| "GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE", |
| "GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE", |
| "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE", |
| "GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING" }; |
| |
| static const glw::GLuint optional_pnames_count = sizeof(optional_pnames) / sizeof(optional_pnames[0]); |
| |
| for (glw::GLuint i = 0; i < optional_pnames_count; ++i) |
| { |
| /* Omit FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE pname when DEPTH_STENCIL_ATTACHMENT attachment is used. */ |
| if (attachments[j] == GL_DEPTH_STENCIL_ATTACHMENT) |
| { |
| if (optional_pnames[i] == GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE) |
| { |
| continue; |
| } |
| } |
| |
| glw::GLint optional_parameter_legacy = 0; |
| glw::GLint optional_parameter_dsa = 0; |
| |
| gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, attachments[j], optional_pnames[i], |
| &optional_parameter_legacy); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFramebufferParameteriv has failed"); |
| |
| gl.getNamedFramebufferAttachmentParameteriv(m_fbo, attachments[j], optional_pnames[i], |
| &optional_parameter_dsa); |
| |
| if (glw::GLenum error = gl.getError()) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferAttachmentParameteriv unexpectedly generated " |
| << glu::getErrorStr(error) << " error when called with " << optional_pnames_strings[i] |
| << " parameter name for " << attachments_strings[j] |
| << " attachment of texture framebuffer object. The GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was " |
| << parameter_legacy << "." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| |
| if (optional_parameter_legacy != optional_parameter_dsa) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedFramebufferAttachmentParameteriv returned " |
| << optional_parameter_dsa << ", but " << optional_parameter_legacy << " was expected for " |
| << optional_pnames_strings << " parameter name for " << attachments_strings[j] |
| << " attachment of texture framebuffer object." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| } |
| } |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void GetAttachmentParametersTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Releasing obnjects. */ |
| if (m_fbo) |
| { |
| gl.deleteFramebuffers(1, &m_fbo); |
| |
| m_fbo = 0; |
| } |
| |
| /* Releasing renderbuffers. */ |
| for (glw::GLuint i = 0; i < 2; ++i) |
| { |
| if (m_rbo[i]) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo[i]); |
| |
| m_rbo[i] = 0; |
| } |
| } |
| |
| /* Releasing textures. */ |
| for (glw::GLuint i = 0; i < 2; ++i) |
| { |
| if (m_to[i]) |
| { |
| gl.deleteTextures(1, &m_to[i]); |
| |
| m_to[i] = 0; |
| } |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| /******************************** Framebuffer Creation Errors Test Implementation ********************************/ |
| |
| /** @brief Creation Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| CreationErrorsTest::CreationErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "framebuffers_creation_errors", "Framebuffer Objects Creation Errors Test") |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Creation Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult CreationErrorsTest::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; |
| |
| /* Framebuffer object */ |
| glw::GLuint framebuffer = 0; |
| |
| /* Check direct state creation of negative numbers of framebuffers. */ |
| gl.createFramebuffers(-1, &framebuffer); |
| |
| glw::GLenum error = GL_NO_ERROR; |
| |
| if (GL_INVALID_VALUE != (error = gl.getError())) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "CreateFramebuffers generated " << glu::getErrorStr(error) |
| << " error when called with negative number of framebuffers, but GL_INVALID_VALUE was expected." |
| << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| |
| /* Cleanup (sanity). */ |
| if (framebuffer) |
| { |
| gl.deleteFramebuffers(1, &framebuffer); |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /******************************** Renderbuffer Attachment Errors Test Implementation ********************************/ |
| |
| /** @brief Renderbuffer Attachment Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| RenderbufferAttachmentErrorsTest::RenderbufferAttachmentErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "framebuffers_renderbuffer_attachment_errors", "Renderbuffer Attachment Errors Test") |
| , m_fbo_valid(0) |
| , m_rbo_valid(0) |
| , m_fbo_invalid(0) |
| , m_rbo_invalid(0) |
| , m_color_attachment_invalid(0) |
| , m_attachment_invalid(0) |
| , m_renderbuffer_target_invalid(0) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Renderbuffer Attachment Errors Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult RenderbufferAttachmentErrorsTest::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 |
| { |
| /* Prepare objects. */ |
| PrepareObjects(); |
| |
| /* Invalid Framebuffer ID. */ |
| gl.namedFramebufferRenderbuffer(m_fbo_invalid, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_valid); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, false, true, false, true, true); |
| |
| /* Invalid color attachment. */ |
| gl.namedFramebufferRenderbuffer(m_fbo_valid, m_color_attachment_invalid, GL_RENDERBUFFER, m_rbo_valid); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, true, false, true, true, true); |
| |
| /* Invalid attachment. */ |
| gl.namedFramebufferRenderbuffer(m_fbo_valid, m_attachment_invalid, GL_RENDERBUFFER, m_rbo_valid); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, true, false, false, true, true); |
| |
| /* Invalid Renderbuffer Target. */ |
| gl.namedFramebufferRenderbuffer(m_fbo_valid, GL_COLOR_ATTACHMENT0, m_renderbuffer_target_invalid, m_rbo_valid); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, true, true, false, false, true); |
| |
| /* Invalid Renderbuffer ID. */ |
| gl.namedFramebufferRenderbuffer(m_fbo_valid, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_invalid); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, true, true, false, true, false); |
| } |
| 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; |
| } |
| |
| /** Prepare test objects. |
| */ |
| void RenderbufferAttachmentErrorsTest::PrepareObjects() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Valid objects. */ |
| gl.genFramebuffers(1, &m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| gl.genRenderbuffers(1, &m_rbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| /* Invalid objects. */ |
| while (gl.isFramebuffer(++m_fbo_invalid)) |
| ; |
| while (gl.isRenderbuffer(++m_rbo_invalid)) |
| ; |
| |
| /* Max color attachments query. */ |
| glw::GLint max_color_attachments = 8; /* Spec default. */ |
| gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed"); |
| |
| /* Invalid color attachment */ |
| m_color_attachment_invalid = GL_COLOR_ATTACHMENT0 + max_color_attachments; |
| |
| /* Invalid attachment. */ |
| bool is_attachment = true; |
| |
| while (is_attachment) |
| { |
| ++m_attachment_invalid; |
| |
| is_attachment = false; |
| |
| if ((GL_DEPTH_ATTACHMENT == m_attachment_invalid) || (GL_STENCIL_ATTACHMENT == m_attachment_invalid) || |
| (GL_DEPTH_STENCIL_ATTACHMENT == m_attachment_invalid)) |
| { |
| is_attachment = true; |
| } |
| |
| if (GL_COLOR_ATTACHMENT0 < m_attachment_invalid) |
| { |
| /* If this unlikely happen this mean that we cannot create invalid attachment which is not DEPTH_ATTACHMENT, STENCIL_ATTACHMENT, DEPTH_STENCIL_ATTACHMENT and |
| GL_COLOR_ATTACHMENTm where m IS any positive integer number (for m < MAX_COLOR_ATTACHMENTS attachments are valid, and for m >= MAX_COLOR_ATTACHMENTS is invalid, but |
| INVALID_OPERATION shall be generated instead of INVALID_ENUM. Such a situation may need change in the test or in the specification. */ |
| throw 0; |
| } |
| } |
| |
| /* Invalid renderbuffer target. */ |
| m_renderbuffer_target_invalid = GL_RENDERBUFFER + 1; |
| } |
| |
| /** Check if error is equal to the expected, log if not. |
| * |
| * @param [in] expected_error Error to be expected. |
| * @param [in] framebuffer Framebuffer name to be logged. |
| * @param [in] attachment Attachment name to be logged. |
| * @param [in] renderbuffertarget Renderbuffertarget name to be logged. |
| * @param [in] renderbuffer Renderbuffer name to be logged. |
| * |
| * @return True if test succeeded, false otherwise. |
| */ |
| bool RenderbufferAttachmentErrorsTest::ExpectError(glw::GLenum expected_error, bool framebuffer, bool attachment, |
| bool color_attachment, bool renderbuffertarget, bool renderbuffer) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| bool is_ok = true; |
| |
| glw::GLenum error = GL_NO_ERROR; |
| |
| if (expected_error != (error = gl.getError())) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "NamedFramebufferRenderbuffer called with " |
| << (framebuffer ? "valid" : "invalid") << " framebuffer, " << (attachment ? "valid" : "invalid") |
| << (color_attachment ? " color" : "") << " attachment, " << (renderbuffertarget ? "valid" : "invalid") |
| << " renderbuffer target, " << (renderbuffer ? "valid" : "invalid") |
| << " renderbuffer was expected to generate " << glu::getErrorStr(expected_error) << ", but " |
| << glu::getErrorStr(error) << " was observed instead." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| |
| /* Clean additional possible errors. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void RenderbufferAttachmentErrorsTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release GL objects. */ |
| if (m_fbo_valid) |
| { |
| gl.deleteFramebuffers(1, &m_fbo_valid); |
| m_fbo_valid = 0; |
| } |
| |
| if (m_rbo_valid) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_valid); |
| m_rbo_valid = 0; |
| } |
| |
| /* Set initial values - all test shall have the same environment. */ |
| m_fbo_invalid = 0; |
| m_rbo_invalid = 0; |
| m_attachment_invalid = 0; |
| m_color_attachment_invalid = 0; |
| m_renderbuffer_target_invalid = 0; |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| /******************************** Texture Attachment Errors Test Implementation ********************************/ |
| |
| /** @brief Texture Attachment Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| TextureAttachmentErrorsTest::TextureAttachmentErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "framebuffers_texture_attachment_errors", "Texture Attachment Errors Test") |
| , m_fbo_valid(0) |
| , m_to_valid(0) |
| , m_to_3d_valid(0) |
| , m_to_array_valid(0) |
| , m_to_cubearray_valid(0) |
| , m_tbo_valid(0) |
| , m_fbo_invalid(0) |
| , m_to_invalid(0) |
| , m_to_layer_invalid(0) |
| , m_color_attachment_invalid(0) |
| , m_attachment_invalid(0) |
| , m_level_invalid(0) |
| , m_max_3d_texture_size(2048) /* OpenGL 4.5 Core Profile default values (Table 23.53). */ |
| , m_max_3d_texture_depth(2048) /* == m_max_3d_texture_size or value of GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV. */ |
| , m_max_array_texture_layers(2048) /* OpenGL 4.5 Core Profile default values (Table 23.53). */ |
| , m_max_cube_map_texture_size(16384) /* OpenGL 4.5 Core Profile default values (Table 23.53). */ |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Texture Attachment Errors Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult TextureAttachmentErrorsTest::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 |
| { |
| /* Prepare objects. */ |
| PrepareObjects(); |
| |
| /********** NamedFramebufferTexture **************/ |
| |
| /* Invalid Framebuffer ID. */ |
| gl.namedFramebufferTexture(m_fbo_invalid, GL_COLOR_ATTACHMENT0, m_to_valid, 0); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferTexture", false, true, false, true, true, "", true); |
| |
| /* Invalid Color Attachment. */ |
| gl.namedFramebufferTexture(m_fbo_valid, m_color_attachment_invalid, m_to_valid, 0); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferTexture", true, false, true, true, true, "", true); |
| |
| /* Invalid Attachment. */ |
| gl.namedFramebufferTexture(m_fbo_valid, m_attachment_invalid, m_to_valid, 0); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedFramebufferTexture", true, false, false, true, true, "", true); |
| |
| /* Invalid Texture ID. */ |
| gl.namedFramebufferTexture(m_fbo_valid, GL_COLOR_ATTACHMENT0, m_to_invalid, 0); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "NamedFramebufferTexture", true, true, false, false, true, "", true); |
| |
| /* Invalid Level. */ |
| gl.namedFramebufferTexture(m_fbo_valid, GL_COLOR_ATTACHMENT0, m_to_valid, m_level_invalid); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "NamedFramebufferTexture", true, true, false, true, false, "", true); |
| |
| /* Buffer texture. */ |
| gl.namedFramebufferTexture(m_fbo_valid, GL_COLOR_ATTACHMENT0, m_tbo_valid, 0); |
| |
| is_ok &= |
| ExpectError(GL_INVALID_OPERATION, "NamedFramebufferTexture", true, true, false, true, true, "buffer", true); |
| |
| /********** NamedFramebufferTextureLayer **************/ |
| |
| /* Invalid Framebuffer ID. */ |
| gl.namedFramebufferTextureLayer(m_fbo_invalid, GL_COLOR_ATTACHMENT0, m_to_array_valid, 0, 0); |
| |
| is_ok &= |
| ExpectError(GL_INVALID_OPERATION, "NamedFramebufferTextureLayer", false, true, false, true, true, "", true); |
| |
| /* Invalid Color Attachment. */ |
| gl.namedFramebufferTextureLayer(m_fbo_valid, m_color_attachment_invalid, m_to_array_valid, 0, 0); |
| |
| is_ok &= |
| ExpectError(GL_INVALID_OPERATION, "NamedFramebufferTextureLayer", true, false, true, true, true, "", true); |
| |
| /* Invalid Attachment. */ |
| gl.namedFramebufferTextureLayer(m_fbo_valid, m_attachment_invalid, m_to_array_valid, 0, 0); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedFramebufferTextureLayer", true, false, false, true, true, "", true); |
| |
| /* Invalid Texture ID. */ |
| gl.namedFramebufferTextureLayer(m_fbo_valid, GL_COLOR_ATTACHMENT0, m_to_invalid, 0, 0); |
| |
| is_ok &= |
| ExpectError(GL_INVALID_OPERATION, "NamedFramebufferTextureLayer", true, true, false, false, true, "", true); |
| |
| /* Invalid Level. */ |
| gl.namedFramebufferTextureLayer(m_fbo_valid, GL_COLOR_ATTACHMENT0, m_to_array_valid, m_level_invalid, 0); |
| |
| is_ok &= |
| ExpectError(GL_INVALID_VALUE, "NamedFramebufferTextureLayer", true, true, false, true, false, "", true); |
| |
| /* Buffer texture. */ |
| gl.namedFramebufferTextureLayer(m_fbo_valid, GL_COLOR_ATTACHMENT0, m_tbo_valid, 0, 0); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferTextureLayer", true, true, false, true, true, |
| "buffer", true); |
| |
| /* Check that INVALID_VALUE error is generated by NamedFramebufferTextureLayer if texture is a three-dimensional |
| texture, and layer is larger than the value of MAX_3D_TEXTURE_SIZE or GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV (if available) minus one. */ |
| gl.namedFramebufferTextureLayer(m_fbo_valid, GL_COLOR_ATTACHMENT0, m_to_3d_valid, 0, m_max_3d_texture_depth); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "NamedFramebufferTextureLayer", true, true, false, true, true, |
| "3D texture", false); |
| |
| /* Check that INVALID_VALUE error is generated by NamedFramebufferTextureLayer if texture is an array texture, |
| and layer is larger than the value of MAX_ARRAY_TEXTURE_LAYERS minus one. */ |
| gl.namedFramebufferTextureLayer(m_fbo_valid, GL_COLOR_ATTACHMENT0, m_to_array_valid, 0, |
| m_max_array_texture_layers); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "NamedFramebufferTextureLayer", true, true, false, true, true, "array", |
| false); |
| |
| /* Check that INVALID_VALUE error is generated by NamedFramebufferTextureLayer if texture is a cube map array texture, |
| and (layer / 6) is larger than the value of MAX_CUBE_MAP_TEXTURE_SIZE minus one (see section 9.8). |
| Check that INVALID_VALUE error is generated by NamedFramebufferTextureLayer if texture is non-zero |
| and layer is negative. */ |
| gl.namedFramebufferTextureLayer(m_fbo_valid, GL_COLOR_ATTACHMENT0, m_to_cubearray_valid, 0, |
| m_max_cube_map_texture_size); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "NamedFramebufferTextureLayer", true, true, false, true, true, |
| "cuba map array", false); |
| |
| /* Check that INVALID_OPERATION error is generated by NamedFramebufferTextureLayer if texture is non-zero |
| and is not the name of a three-dimensional, two-dimensional multisample array, one- or two-dimensional array, |
| or cube map array texture. */ |
| gl.namedFramebufferTextureLayer(m_fbo_valid, GL_COLOR_ATTACHMENT0, m_to_layer_invalid, 0, 0); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferTextureLayer", true, true, false, false, true, |
| "rectangle", true); |
| } |
| 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; |
| } |
| |
| /** Prepare test GL objects. |
| */ |
| void TextureAttachmentErrorsTest::PrepareObjects() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Valid objects. */ |
| gl.genFramebuffers(1, &m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| gl.genTextures(1, &m_to_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed"); |
| |
| gl.bindTexture(GL_TEXTURE_2D, m_to_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed"); |
| |
| gl.genTextures(1, &m_tbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed"); |
| |
| gl.bindTexture(GL_TEXTURE_BUFFER, m_tbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| gl.genTextures(1, &m_to_3d_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed"); |
| |
| gl.bindTexture(GL_TEXTURE_3D, m_to_3d_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| gl.genTextures(1, &m_to_array_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed"); |
| |
| gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_array_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| gl.genTextures(1, &m_to_cubearray_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed"); |
| |
| gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_to_cubearray_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| gl.genTextures(1, &m_to_layer_invalid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed"); |
| |
| gl.bindTexture(GL_TEXTURE_RECTANGLE, m_to_layer_invalid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| /* Invalid objects. */ |
| while (gl.isFramebuffer(++m_fbo_invalid)) |
| ; |
| while (gl.isTexture(++m_to_invalid)) |
| ; |
| |
| /* Max color attachments query. */ |
| glw::GLint max_color_attachments = 8; /* Spec default. */ |
| gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed"); |
| |
| /* Invalid color attachment */ |
| m_color_attachment_invalid = GL_COLOR_ATTACHMENT0 + max_color_attachments; |
| |
| /* Invalid attachment. */ |
| bool is_attachment = true; |
| |
| while (is_attachment) |
| { |
| ++m_attachment_invalid; |
| |
| is_attachment = false; |
| |
| if ((GL_DEPTH_ATTACHMENT == m_attachment_invalid) || (GL_STENCIL_ATTACHMENT == m_attachment_invalid) || |
| (GL_DEPTH_STENCIL_ATTACHMENT == m_attachment_invalid)) |
| { |
| is_attachment = true; |
| } |
| |
| for (glw::GLint i = 0; i < max_color_attachments; ++i) |
| { |
| if (GL_COLOR_ATTACHMENT0 == m_attachment_invalid) |
| { |
| is_attachment = true; |
| } |
| } |
| } |
| |
| /* Maximum values */ |
| gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &m_max_3d_texture_size); |
| gl.getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &m_max_array_texture_layers); |
| gl.getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &m_max_cube_map_texture_size); |
| |
| if (m_context.getContextInfo().isExtensionSupported("GL_NV_deep_texture3D")) |
| { |
| gl.getIntegerv(GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV, &m_max_3d_texture_depth); |
| } |
| else |
| { |
| m_max_3d_texture_depth = m_max_3d_texture_size; |
| } |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed"); |
| |
| /* Invalid level. */ |
| m_level_invalid = -1; |
| } |
| |
| /** Check if error is equal to the expected, log if not. |
| * |
| * @param [in] expected_error Error to be expected. |
| * @param [in] framebuffer Framebuffer name to be logged. |
| * @param [in] attachment Attachment name to be logged. |
| * @param [in] texture Texture name to be logged. |
| * @param [in] level Level # to be logged. |
| * @param [in] buffer_texture Is this buffer texture (special logging case). |
| * |
| * @return True if test succeeded, false otherwise. |
| */ |
| bool TextureAttachmentErrorsTest::ExpectError(glw::GLenum expected_error, const glw::GLchar* function_name, |
| bool framebuffer, bool attachment, bool color_attachment, bool texture, |
| bool level, const glw::GLchar* texture_type, bool layer) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| bool is_ok = true; |
| |
| glw::GLenum error = GL_NO_ERROR; |
| |
| if (expected_error != (error = gl.getError())) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << function_name << " called with " << (framebuffer ? "valid" : "invalid") |
| << " framebuffer, " << (attachment ? "valid" : "invalid") << (color_attachment ? " color" : "") |
| << " attachment, " << (texture ? "valid " : "invalid ") << texture_type << " texture, " |
| << (level ? "valid" : "invalid") << " level" << (layer ? "" : ", with invalid layer number") |
| << " was expected to generate " << glu::getErrorStr(expected_error) << ", but " << glu::getErrorStr(error) |
| << " was observed instead." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| |
| /* Clean additional possible errors. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void TextureAttachmentErrorsTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release GL objects. */ |
| if (m_fbo_valid) |
| { |
| gl.deleteFramebuffers(1, &m_fbo_valid); |
| m_fbo_valid = 0; |
| } |
| |
| if (m_to_valid) |
| { |
| gl.deleteTextures(1, &m_to_valid); |
| m_to_valid = 0; |
| } |
| |
| if (m_tbo_valid) |
| { |
| gl.deleteTextures(1, &m_tbo_valid); |
| m_tbo_valid = 0; |
| } |
| |
| if (m_to_3d_valid) |
| { |
| gl.deleteTextures(1, &m_to_3d_valid); |
| m_to_3d_valid = 0; |
| } |
| |
| if (m_to_array_valid) |
| { |
| gl.deleteTextures(1, &m_to_array_valid); |
| m_to_array_valid = 0; |
| } |
| |
| if (m_to_cubearray_valid) |
| { |
| gl.deleteTextures(1, &m_to_cubearray_valid); |
| m_to_cubearray_valid = 0; |
| } |
| |
| if (m_to_layer_invalid) |
| { |
| gl.deleteTextures(1, &m_to_layer_invalid); |
| m_to_layer_invalid = 0; |
| } |
| |
| /* Set initial values - all test shall have the same environment. */ |
| m_fbo_invalid = 0; |
| m_to_invalid = 0; |
| m_attachment_invalid = 0; |
| m_level_invalid = 0; |
| |
| m_max_3d_texture_size = 2048; |
| m_max_3d_texture_depth = m_max_3d_texture_size; |
| m_max_array_texture_layers = 2048; |
| m_max_cube_map_texture_size = 16384; |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| /******************************** Draw Read Buffers Errors Test Implementation ********************************/ |
| |
| /** @brief Draw Read Buffers Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| DrawReadBuffersErrorsTest::DrawReadBuffersErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "framebuffers_draw_read_buffers_errors", "Draw Read Buffers Errors Test Test") |
| , m_fbo_valid(0) |
| , m_fbo_invalid(0) |
| , m_attachment_color(GL_COLOR_ATTACHMENT0) |
| , m_attachment_back_left(GL_BACK_LEFT) |
| , m_attachment_right(GL_RIGHT) |
| , m_attachment_left(GL_LEFT) |
| , m_attachment_front(GL_FRONT) |
| , m_attachment_front_and_back(GL_FRONT_AND_BACK) |
| , m_attachment_back(GL_BACK) |
| , m_attachment_invalid(0) |
| , m_max_color_attachments(8) /* GL 4.5 default, updated later */ |
| { |
| m_attachments_invalid[0] = 0; |
| m_attachments_invalid[1] = 0; |
| |
| m_attachments_back_invalid[0] = GL_BACK_LEFT; |
| m_attachments_back_invalid[1] = GL_BACK; |
| |
| m_attachments_too_many_count = 0; |
| |
| m_attachments_too_many = DE_NULL; |
| } |
| |
| /** @brief Iterate Draw Read Buffers Errors Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult DrawReadBuffersErrorsTest::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 |
| { |
| /* Prepare objects. */ |
| PrepareObjects(); |
| |
| /* Check that INVALID_OPERATION error is generated by |
| NamedFramebufferDrawBuffer if framebuffer is not zero or the name of an |
| existing framebuffer object. */ |
| gl.namedFramebufferDrawBuffer(m_fbo_invalid, m_attachment_color); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferDrawBuffer", |
| "framebuffer is not zero or the name of an existing framebuffer object."); |
| |
| /* Check that INVALID_ENUM is generated by NamedFramebufferDrawBuffer if |
| buf is not an accepted value. */ |
| gl.namedFramebufferDrawBuffer(m_fbo_valid, m_attachment_invalid); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedFramebufferDrawBuffer", "buf is not an accepted value."); |
| |
| /* Check that INVALID_OPERATION is generated by NamedFramebufferDrawBuffer |
| if the GL is bound to a draw framebuffer object and the ith argument is |
| a value other than COLOR_ATTACHMENTi or NONE. */ |
| gl.namedFramebufferDrawBuffer(m_fbo_valid, m_attachment_back_left); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferDrawBuffer", |
| "the GL is bound to a draw framebuffer object and the ith argument is a value other than " |
| "COLOR_ATTACHMENTi or NONE."); |
| |
| /* Check that INVALID_OPERATION error is generated by |
| NamedFramebufferDrawBuffers if framebuffer is not zero or the name of an |
| existing framebuffer object. */ |
| gl.namedFramebufferDrawBuffers(m_fbo_invalid, 1, &m_attachment_color); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferDrawBuffers", |
| "framebuffer is not zero or the name of an existing framebuffer object."); |
| |
| /* Check that INVALID_VALUE is generated by NamedFramebufferDrawBuffers if n |
| is less than 0. */ |
| gl.namedFramebufferDrawBuffers(m_fbo_valid, -1, &m_attachment_color); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "NamedFramebufferDrawBuffers", "n is less than 0."); |
| |
| /* Check that INVALID_VALUE is generated by NamedFramebufferDrawBuffers if |
| n is greater than MAX_DRAW_BUFFERS. */ |
| gl.namedFramebufferDrawBuffers(m_fbo_valid, m_attachments_too_many_count, m_attachments_too_many); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "NamedFramebufferDrawBuffers", "n is greater than MAX_DRAW_BUFFERS."); |
| |
| /* Check that INVALID_ENUM is generated by NamedFramebufferDrawBuffers if |
| one of the values in bufs is not an accepted value. */ |
| gl.namedFramebufferDrawBuffers(m_fbo_valid, 1, &m_attachment_invalid); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedFramebufferDrawBuffers", |
| "one of the values in bufs is not an accepted value."); |
| |
| /* Check that INVALID_OPERATION is generated by NamedFramebufferDrawBuffers |
| if a symbolic constant other than GL_NONE appears more than once in |
| bufs. */ |
| gl.namedFramebufferDrawBuffers(m_fbo_valid, 2, m_attachments_invalid); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferDrawBuffers", |
| "a symbolic constant other than GL_NONE appears more than once in bufs."); |
| |
| /* Check that INVALID_ENUM error is generated by NamedFramebufferDrawBuffers if any value in bufs is FRONT, LEFT, RIGHT, or FRONT_AND_BACK. |
| This restriction applies to both the default framebuffer and framebuffer objects, and exists because these constants may themselves |
| refer to multiple buffers, as shown in table 17.4. */ |
| gl.namedFramebufferDrawBuffers(m_fbo_valid, 1, &m_attachment_front); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedFramebufferDrawBuffers", |
| "a framebuffer object is tested and a value in bufs is FRONT."); |
| |
| gl.namedFramebufferDrawBuffers(m_fbo_valid, 1, &m_attachment_left); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedFramebufferDrawBuffers", |
| "a framebuffer object is tested and a value in bufs is LEFT."); |
| |
| gl.namedFramebufferDrawBuffers(m_fbo_valid, 1, &m_attachment_right); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedFramebufferDrawBuffers", |
| "a framebuffer object is tested and a value in bufs is RIGHT."); |
| |
| gl.namedFramebufferDrawBuffers(m_fbo_valid, 1, &m_attachment_front_and_back); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedFramebufferDrawBuffers", |
| "a framebuffer object is tested and a value in bufs is FRONT_AND_BACK."); |
| |
| gl.namedFramebufferDrawBuffers(0, 1, &m_attachment_front); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedFramebufferDrawBuffers", |
| "a default framebuffer is tested and a value in bufs is FRONT."); |
| |
| gl.namedFramebufferDrawBuffers(0, 1, &m_attachment_left); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedFramebufferDrawBuffers", |
| "a default framebuffer is tested and a value in bufs is LEFT."); |
| |
| gl.namedFramebufferDrawBuffers(0, 1, &m_attachment_right); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedFramebufferDrawBuffers", |
| "a default framebuffer is tested and a value in bufs is RIGHT."); |
| |
| gl.namedFramebufferDrawBuffers(0, 1, &m_attachment_front_and_back); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedFramebufferDrawBuffers", |
| "a default framebuffer is tested and a value in bufs is FRONT_AND_BACK."); |
| |
| /* Check that INVALID_OPERATION is generated by NamedFramebufferDrawBuffers |
| if any value in bufs is BACK, and n is not one. */ |
| gl.namedFramebufferDrawBuffers(0, 2, m_attachments_back_invalid); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferDrawBuffers", |
| "any value in bufs is BACK, and n is not one."); |
| |
| /* Check that INVALID_OPERATION is generated by NamedFramebufferDrawBuffers if |
| the API call refers to a framebuffer object and one or more of the |
| values in bufs is anything other than NONE or one of the |
| COLOR_ATTACHMENTn tokens. */ |
| gl.namedFramebufferDrawBuffers(m_fbo_valid, 1, &m_attachment_back_left); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferDrawBuffers", |
| "the API call refers to a framebuffer object and one or more of the values in bufs is " |
| "anything other than NONE or one of the COLOR_ATTACHMENTn tokens."); |
| |
| /* Check that INVALID_OPERATION is generated by NamedFramebufferDrawBuffers if |
| the API call refers to the default framebuffer and one or more of the |
| values in bufs is one of the COLOR_ATTACHMENTn tokens. */ |
| gl.namedFramebufferDrawBuffers(0, 1, &m_attachment_color); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferDrawBuffers", |
| "the API call refers to the default framebuffer and one or more of the values in bufs is " |
| "one of the COLOR_ATTACHMENTn tokens."); |
| |
| /* Check that INVALID_OPERATION is generated by NamedFramebufferReadBuffer |
| if framebuffer is not zero or the name of an existing framebuffer |
| object. */ |
| gl.namedFramebufferReadBuffer(m_fbo_invalid, m_attachment_color); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferReadBuffer", |
| "framebuffer is not zero or the name of an existing framebuffer object."); |
| |
| /* Check that INVALID_ENUM is generated by NamedFramebufferReadBuffer if |
| src is not one of the accepted values (tables 17.4 and 17.5 of OpenGL 4.5 Core Profile Specification). */ |
| gl.namedFramebufferReadBuffer(m_fbo_valid, m_attachment_invalid); |
| |
| is_ok &= ExpectError( |
| GL_INVALID_ENUM, "NamedFramebufferReadBuffer", |
| "src is not one of the accepted values (tables 17.4 and 17.5 of OpenGL 4.5 Core Profile Specification)."); |
| |
| /* Check that INVALID_OPERATION error is generated by NamedFramebufferReadBuffer if the default framebuffer is |
| affected and src is a value (other than NONE) that does not indicate any of the |
| color buffers allocated to the default framebuffer. */ |
| gl.namedFramebufferReadBuffer(0, GL_COLOR_ATTACHMENT0); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferReadBuffer", |
| "the default framebuffer is affected and src is a value (other than NONE) that does not " |
| "indicate any of the color buffers allocated to the default framebuffer."); |
| |
| /* Check that INVALID_OPERATION error is generated by NamedFramebufferReadBuffer if a framebuffer object is |
| affected, and src is one of the constants from table 17.4 (other than NONE, or COLOR_ATTACHMENTm where m |
| is greater than or equal to the value of MAX_COLOR_ATTACHMENTS). */ |
| gl.namedFramebufferReadBuffer(m_fbo_valid, m_attachment_front_and_back); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferReadBuffer", |
| "a framebuffer object is affected, and src is one of the constants from table 17.4."); |
| |
| gl.namedFramebufferReadBuffer(m_fbo_valid, GL_COLOR_ATTACHMENT0 + m_max_color_attachments); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedFramebufferReadBuffer", |
| "a framebuffer object is affected, and src is one of the COLOR_ATTACHMENTm where mis " |
| "greater than or equal to the value of MAX_COLOR_ATTACHMENTS."); |
| } |
| 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; |
| } |
| |
| /** Check Prepare test's GL objects. |
| */ |
| void DrawReadBuffersErrorsTest::PrepareObjects() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Valid objects. */ |
| gl.genFramebuffers(1, &m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| /* Invalid objects. */ |
| while (gl.isFramebuffer(++m_fbo_invalid)) |
| ; |
| |
| /* Invalid attachment. */ |
| gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &m_max_color_attachments); |
| |
| bool is_attachment = true; |
| |
| while (is_attachment) |
| { |
| ++m_attachment_invalid; |
| |
| is_attachment = false; |
| |
| /* Valid attachments are those from tables 17.4, 17.5 and a 17.6 (valid for various functions and framebuffer types). |
| (see OpenGL 4.5 Core Profile Specification) */ |
| switch (m_attachment_invalid) |
| { |
| case GL_NONE: |
| case GL_FRONT_LEFT: |
| case GL_FRONT_RIGHT: |
| case GL_BACK_LEFT: |
| case GL_BACK_RIGHT: |
| case GL_FRONT: |
| case GL_BACK: |
| case GL_LEFT: |
| case GL_RIGHT: |
| case GL_FRONT_AND_BACK: |
| is_attachment = true; |
| }; |
| |
| for (glw::GLint i = 0; i < m_max_color_attachments; ++i) |
| { |
| if ((glw::GLenum)(GL_COLOR_ATTACHMENT0 + i) == m_attachment_invalid) |
| { |
| is_attachment = true; |
| break; |
| } |
| } |
| } |
| |
| m_attachments_invalid[0] = GL_COLOR_ATTACHMENT0; |
| m_attachments_invalid[1] = GL_COLOR_ATTACHMENT0; |
| |
| glw::GLint max_draw_buffers = 8; /* Spec default. */ |
| gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers); |
| |
| m_attachments_too_many_count = max_draw_buffers + 1; |
| |
| m_attachments_too_many = new glw::GLenum[m_attachments_too_many_count]; |
| |
| m_attachments_too_many[0] = GL_COLOR_ATTACHMENT0; |
| |
| for (glw::GLint i = 1; i < m_attachments_too_many_count; ++i) |
| { |
| m_attachments_too_many[i] = GL_NONE; |
| } |
| } |
| |
| /** Check if error is equal to the expected, log if not. |
| * |
| * @param [in] expected_error Error to be expected. |
| * @param [in] function Function name which is being tested (to be logged). |
| * @param [in] conditions Conditions when the expected error shall occure (to be logged). |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool DrawReadBuffersErrorsTest::ExpectError(glw::GLenum expected_error, const glw::GLchar* function, |
| const glw::GLchar* conditions) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| bool is_ok = true; |
| |
| glw::GLenum error = GL_NO_ERROR; |
| |
| if (expected_error != (error = gl.getError())) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << function << " was expected to generate " |
| << glu::getErrorStr(expected_error) << ", but " << glu::getErrorStr(error) |
| << " was observed instead when " << conditions << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| |
| /* Clean additional possible errors. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void DrawReadBuffersErrorsTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release GL objects. */ |
| if (m_fbo_valid) |
| { |
| gl.deleteFramebuffers(1, &m_fbo_valid); |
| m_fbo_valid = 0; |
| } |
| |
| /* Set initial values - all test shall have the same environment. */ |
| m_fbo_invalid = 0; |
| m_attachment_invalid = 0; |
| m_attachments_invalid[0] = 0; |
| m_attachments_invalid[1] = 0; |
| |
| delete[] m_attachments_too_many; |
| |
| m_attachments_too_many = DE_NULL; |
| |
| m_attachments_too_many_count = 0; |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| /******************************** Invalidate Data and SubData Errors Test Implementation ********************************/ |
| |
| /** @brief Invalidate SubData Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| InvalidateDataAndSubDataErrorsTest::InvalidateDataAndSubDataErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "invalidate_data_and_subdata_errors", "Invalidate Data and SubData Errors Test") |
| , m_fbo_valid(0) |
| , m_rbo(0) |
| , m_fbo_invalid(0) |
| , m_fbo_attachment_valid(0) |
| , m_fbo_attachment_invalid(0) |
| , m_color_attachment_invalid(0) |
| , m_default_attachment_invalid(0) |
| |
| { |
| } |
| |
| /** @brief Iterate Invalidate Data and SubData Errors Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult InvalidateDataAndSubDataErrorsTest::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 |
| { |
| /* Prepare objects. */ |
| PrepareObjects(); |
| |
| /******* InvalidateNamedFramebufferData *******/ |
| |
| /* Check that INVALID_OPERATION error is generated by InvalidateNamedFramebufferData if framebuffer is not zero or the name of an existing framebuffer object. */ |
| gl.invalidateNamedFramebufferData(m_fbo_invalid, 1, &m_fbo_attachment_valid); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "InvalidateNamedFramebufferData", |
| "framebuffer is not zero or the name of an existing framebuffer object."); |
| |
| /* Check that INVALID_ENUM error is generated by InvalidateNamedFramebufferData if a framebuffer object is affected, and |
| any element of of attachments is not one of the values in table {COLOR_ATTACHMENTi, DEPTH_ATTACHMENT, STENCIL_ATTACHMENT, DEPTH_STENCIL_ATTACHMENT }. */ |
| gl.invalidateNamedFramebufferData(m_fbo_valid, 1, &m_fbo_attachment_invalid); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "InvalidateNamedFramebufferData", |
| "a framebuffer object is affected, and any element of of attachments is not one of the " |
| "values in table { COLOR_ATTACHMENTi, DEPTH_ATTACHMENT, STENCIL_ATTACHMENT, " |
| "DEPTH_STENCIL_ATTACHMENT }."); |
| |
| /* Check that INVALID_OPERATION error is generated by InvalidateNamedFramebufferData if attachments contains COLOR_ATTACHMENTm |
| where m is greater than or equal to the value of MAX_COLOR_ATTACHMENTS. */ |
| gl.invalidateNamedFramebufferData(m_fbo_valid, 1, &m_color_attachment_invalid); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "InvalidateNamedFramebufferData", |
| "attachments contains COLOR_ATTACHMENTm where m is greater than or equal to the value of " |
| "MAX_COLOR_ATTACHMENTS"); |
| |
| /* Check that INVALID_ENUM error is generated by |
| InvalidateNamedFramebufferData if the default framebuffer is affected, |
| and any elements of attachments are not one of: |
| - FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, and BACK_RIGHT, identifying that |
| specific buffer, |
| - COLOR, which is treated as BACK_LEFT for a double-buffered context |
| and FRONT_LEFT for a single-buffered context, |
| - DEPTH, identifying the depth buffer, |
| - STENCIL, identifying the stencil buffer. */ |
| gl.invalidateNamedFramebufferData(0, 1, &m_default_attachment_invalid); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "InvalidateNamedFramebufferData", |
| "the default framebuffer is affected, and any elements of attachments are not one of " |
| "FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, COLOR, DEPTH, STENCIL."); |
| |
| /******* InvalidateNamedFramebufferSubData *******/ |
| |
| /* Check that INVALID_OPERATION error is generated by InvalidateNamedFramebufferSubData if framebuffer is not zero or the name of an existing framebuffer object. */ |
| gl.invalidateNamedFramebufferSubData(m_fbo_invalid, 1, &m_fbo_attachment_valid, 0, 0, 1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "InvalidateNamedFramebufferSubData", |
| "framebuffer is not zero or the name of an existing framebuffer object."); |
| |
| /* Check that INVALID_VALUE error is generated by InvalidateNamedFramebufferSubData if numAttachments, width, or height is negative. */ |
| gl.invalidateNamedFramebufferSubData(m_fbo_valid, -1, &m_fbo_attachment_valid, 0, 0, 1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "InvalidateNamedFramebufferSubData", "numAttachments is negative."); |
| |
| gl.invalidateNamedFramebufferSubData(m_fbo_valid, 1, &m_fbo_attachment_valid, 0, 0, -1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "InvalidateNamedFramebufferSubData", "width is negative."); |
| |
| gl.invalidateNamedFramebufferSubData(m_fbo_valid, 1, &m_fbo_attachment_valid, 0, 0, 1, -1); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "InvalidateNamedFramebufferSubData", "height is negative."); |
| |
| /* Check that INVALID_ENUM error is generated by InvalidateNamedFramebufferSubData if a framebuffer object is affected, and |
| any element of of attachments is not one of the values in table {COLOR_ATTACHMENTi, DEPTH_ATTACHMENT, STENCIL_ATTACHMENT, DEPTH_STENCIL_ATTACHMENT }. */ |
| gl.invalidateNamedFramebufferSubData(m_fbo_valid, 1, &m_fbo_attachment_invalid, 0, 0, 1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "InvalidateNamedFramebufferSubData", |
| "a framebuffer object is affected, and any element of of attachments is not one of the " |
| "values in table { COLOR_ATTACHMENTi, DEPTH_ATTACHMENT, STENCIL_ATTACHMENT, " |
| "DEPTH_STENCIL_ATTACHMENT }."); |
| |
| /* Check that INVALID_OPERATION error is generated by InvalidateNamedFramebufferSubData if attachments contains COLOR_ATTACHMENTm |
| where m is greater than or equal to the value of MAX_COLOR_ATTACHMENTS. */ |
| gl.invalidateNamedFramebufferSubData(m_fbo_valid, 1, &m_color_attachment_invalid, 0, 0, 1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "InvalidateNamedFramebufferSubData", |
| "attachments contains COLOR_ATTACHMENTm where m is greater than or equal to the value of " |
| "MAX_COLOR_ATTACHMENTS"); |
| |
| /* Check that INVALID_ENUM error is generated by InvalidateNamedFramebufferSubData if the default framebuffer is affected, |
| and any elements of attachments are not one of: |
| - FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, and BACK_RIGHT, identifying that |
| specific buffer, |
| - COLOR, which is treated as BACK_LEFT for a double-buffered context |
| and FRONT_LEFT for a single-buffered context, |
| - DEPTH, identifying the depth buffer, |
| - STENCIL, identifying the stencil buffer. */ |
| gl.invalidateNamedFramebufferSubData(0, 1, &m_default_attachment_invalid, 0, 0, 1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "InvalidateNamedFramebufferSubData", |
| "the default framebuffer is affected, and any elements of attachments are not one of " |
| "FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, COLOR, DEPTH, STENCIL."); |
| } |
| 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; |
| } |
| |
| /** Check Prepare test's GL objects. |
| */ |
| void InvalidateDataAndSubDataErrorsTest::PrepareObjects() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Valid attachments. */ |
| m_fbo_attachment_valid = GL_COLOR_ATTACHMENT0; |
| |
| /* Valid objects. */ |
| gl.genFramebuffers(1, &m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| 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, GL_RGBA8, 1, 1); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, m_fbo_attachment_valid, GL_RENDERBUFFER, m_rbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| if (GL_FRAMEBUFFER_COMPLETE != gl.checkFramebufferStatus(GL_FRAMEBUFFER)) |
| { |
| throw 0; |
| } |
| |
| /* Invalid objects. */ |
| while (gl.isFramebuffer(++m_fbo_invalid)) |
| ; |
| |
| /* Invalid framebuffer object attachment. */ |
| while (true) |
| { |
| if (GL_COLOR_ATTACHMENT0 < m_fbo_attachment_invalid) |
| { |
| /* If this unlikely happen this mean that we cannot create invalid attachment which is not DEPTH_ATTACHMENT, STENCIL_ATTACHMENT, DEPTH_STENCIL_ATTACHMENT and |
| GL_COLOR_ATTACHMENTm where m IS any number (for m < MAX_COLOR_ATTACHMENTS attachments are valid, and for m >= MAX_COLOR_ATTACHMENTS is invalid, but |
| INVALID_OPERATION shall be generated instead of INVALID_ENUM. Such a situation may need change in the test or in the specification. */ |
| throw 0; |
| } |
| |
| switch (++m_fbo_attachment_invalid) |
| { |
| case GL_DEPTH_ATTACHMENT: |
| case GL_STENCIL_ATTACHMENT: |
| case GL_DEPTH_STENCIL_ATTACHMENT: |
| continue; |
| }; |
| |
| break; |
| }; |
| |
| /* Invalid color attachment. */ |
| glw::GLint max_color_attachments = 8; /* Spec default. */ |
| |
| gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed"); |
| |
| m_color_attachment_invalid = GL_COLOR_ATTACHMENT0 + max_color_attachments; |
| |
| /* Invalid default attachment. */ |
| while (true) |
| { |
| switch (++m_default_attachment_invalid) |
| { |
| case GL_FRONT_LEFT: |
| case GL_FRONT_RIGHT: |
| case GL_BACK_LEFT: |
| case GL_BACK_RIGHT: |
| case GL_COLOR: |
| case GL_DEPTH: |
| case GL_STENCIL: |
| continue; |
| }; |
| |
| break; |
| } |
| } |
| |
| /** Check if error is equal to the expected, log if not. |
| * |
| * @param [in] expected_error Error to be expected. |
| * @param [in] function Function name which is being tested (to be logged). |
| * @param [in] conditions Conditions when the expected error shall occure (to be logged). |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool InvalidateDataAndSubDataErrorsTest::ExpectError(glw::GLenum expected_error, const glw::GLchar* function, |
| const glw::GLchar* conditions) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| bool is_ok = true; |
| |
| glw::GLenum error = GL_NO_ERROR; |
| |
| if (expected_error != (error = gl.getError())) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << function << " was expected to generate " |
| << glu::getErrorStr(expected_error) << ", but " << glu::getErrorStr(error) |
| << " was observed instead when " << conditions << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| |
| /* Clean additional possible errors. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void InvalidateDataAndSubDataErrorsTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release GL objects. */ |
| if (m_fbo_valid) |
| { |
| gl.deleteFramebuffers(1, &m_fbo_valid); |
| m_fbo_valid = 0; |
| } |
| |
| if (m_rbo) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo); |
| |
| m_rbo = 0; |
| } |
| |
| /* Set initial values - all test shall have the same environment. */ |
| m_fbo_invalid = 0; |
| m_fbo_attachment_valid = 0; |
| m_fbo_attachment_invalid = 0; |
| m_default_attachment_invalid = 0; |
| m_color_attachment_invalid = 0; |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| /******************************** Clear Named Framebuffer Errors Test Implementation ********************************/ |
| |
| /** @brief Clear Named Framebuffer Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| ClearNamedFramebufferErrorsTest::ClearNamedFramebufferErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "framebuffers_clear_errors", "Clear Named Framebuffer Errors Test") |
| , m_fbo_valid(0) |
| , m_rbo_color(0) |
| , m_rbo_depth_stencil(0) |
| , m_fbo_invalid(0) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Clear Named Framebuffer Errors Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult ClearNamedFramebufferErrorsTest::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 |
| { |
| /* Prepare objects. */ |
| PrepareObjects(); |
| |
| glw::GLint icolor[4] = {}; |
| glw::GLuint ucolor[4] = {}; |
| glw::GLfloat fcolor[4] = {}; |
| |
| /* Check that INVALID_OPERATION is generated by ClearNamedFramebuffer* if |
| framebuffer is not zero or the name of an existing framebuffer object. */ |
| gl.clearNamedFramebufferiv(m_fbo_invalid, GL_COLOR, 0, icolor); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "ClearNamedFramebufferiv", |
| "framebuffer is not zero or the name of an existing framebuffer object."); |
| |
| gl.clearNamedFramebufferuiv(m_fbo_invalid, GL_COLOR, 0, ucolor); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "ClearNamedFramebufferuiv", |
| "framebuffer is not zero or the name of an existing framebuffer object."); |
| |
| gl.clearNamedFramebufferfv(m_fbo_invalid, GL_COLOR, 0, fcolor); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "ClearNamedFramebufferfv", |
| "framebuffer is not zero or the name of an existing framebuffer object."); |
| |
| gl.clearNamedFramebufferfi(m_fbo_invalid, GL_DEPTH_STENCIL, 0, fcolor[0], icolor[0]); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "ClearNamedFramebufferfi", |
| "framebuffer is not zero or the name of an existing framebuffer object."); |
| |
| /* Check that INVALID_ENUM is generated by ClearNamedFramebufferiv if buffer |
| is not COLOR or STENCIL. */ |
| gl.clearNamedFramebufferiv(m_fbo_valid, GL_DEPTH, 0, icolor); |
| |
| is_ok &= |
| ExpectError(GL_INVALID_ENUM, "ClearNamedFramebufferiv", "buffer is not COLOR or STENCIL (it is DEPTH)."); |
| |
| /* Check that INVALID_ENUM is generated by ClearNamedFramebufferuiv if buffer |
| is not COLOR. */ |
| gl.clearNamedFramebufferuiv(m_fbo_valid, GL_DEPTH, 0, ucolor); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "ClearNamedFramebufferuiv", "buffer is not COLOR (it is DEPTH)."); |
| |
| /* Check that INVALID_ENUM is generated by ClearNamedFramebufferfv buffer |
| is not COLOR or DEPTH. */ |
| gl.clearNamedFramebufferfv(m_fbo_valid, GL_STENCIL, 0, fcolor); |
| |
| is_ok &= |
| ExpectError(GL_INVALID_ENUM, "ClearNamedFramebufferfv", "buffer is not COLOR or DEPTH (it is STENCIL)."); |
| |
| /* Check that INVALID_ENUM is generated by ClearNamedFramebufferfi if buffer |
| is not DEPTH_STENCIL. */ |
| gl.clearNamedFramebufferfi(m_fbo_valid, GL_COLOR, 0, fcolor[0], icolor[0]); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "ClearNamedFramebufferfi", "buffer is not DEPTH_STENCIL."); |
| |
| /* Check that INVALID_VALUE is generated by ClearNamedFramebuffer* if buffer is COLOR drawbuffer is |
| negative, or greater than the value of MAX_DRAW_BUFFERS minus one. */ |
| gl.clearNamedFramebufferiv(m_fbo_valid, GL_COLOR, -1, icolor); |
| |
| is_ok &= ExpectError( |
| GL_INVALID_VALUE, "ClearNamedFramebufferiv", |
| "buffer is COLOR drawbuffer is negative, or greater than the value of MAX_DRAW_BUFFERS minus one."); |
| |
| gl.clearNamedFramebufferuiv(m_fbo_valid, GL_COLOR, -1, ucolor); |
| |
| is_ok &= ExpectError( |
| GL_INVALID_VALUE, "ClearNamedFramebufferuiv", |
| "buffer is COLOR drawbuffer is negative, or greater than the value of MAX_DRAW_BUFFERS minus one."); |
| |
| /* Check that INVALID_VALUE is generated by ClearNamedFramebuffer* if buffer is DEPTH, STENCIL or |
| DEPTH_STENCIL and drawbuffer is not zero. */ |
| |
| gl.clearNamedFramebufferiv(m_fbo_valid, GL_STENCIL, 1, icolor); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "ClearNamedFramebufferiv", |
| "buffer is DEPTH, STENCIL or DEPTH_STENCIL and drawbuffer is not zero."); |
| |
| gl.clearNamedFramebufferfv(m_fbo_valid, GL_DEPTH, 1, fcolor); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "ClearNamedFramebufferfv", |
| "buffer is DEPTH, STENCIL or DEPTH_STENCIL and drawbuffer is not zero."); |
| |
| gl.clearNamedFramebufferfi(m_fbo_valid, GL_DEPTH_STENCIL, 1, fcolor[0], icolor[0]); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "ClearNamedFramebufferfi", |
| "buffer is DEPTH, STENCIL or DEPTH_STENCIL and drawbuffer is not zero."); |
| } |
| 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; |
| } |
| |
| /** Check Prepare test's GL objects. |
| */ |
| void ClearNamedFramebufferErrorsTest::PrepareObjects() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Valid objects. */ |
| gl.genFramebuffers(1, &m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| gl.genRenderbuffers(1, &m_rbo_color); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_color); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, 1, 1); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_color); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| gl.genRenderbuffers(1, &m_rbo_depth_stencil); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_depth_stencil); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| gl.renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 1, 1); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo_depth_stencil); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| /* Invalid objects. */ |
| while (gl.isFramebuffer(++m_fbo_invalid)) |
| ; |
| } |
| |
| /** Check if error is equal to the expected, log if not. |
| * |
| * @param [in] expected_error Error to be expected. |
| * @param [in] function Function name which is being tested (to be logged). |
| * @param [in] conditions Conditions when the expected error shall occure (to be logged). |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool ClearNamedFramebufferErrorsTest::ExpectError(glw::GLenum expected_error, const glw::GLchar* function, |
| const glw::GLchar* conditions) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| bool is_ok = true; |
| |
| glw::GLenum error = GL_NO_ERROR; |
| |
| if (expected_error != (error = gl.getError())) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << function << " was expected to generate " |
| << glu::getErrorStr(expected_error) << ", but " << glu::getErrorStr(error) |
| << " was observed instead when " << conditions << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| |
| /* Clean additional possible errors. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void ClearNamedFramebufferErrorsTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release GL objects. */ |
| if (m_fbo_valid) |
| { |
| gl.deleteFramebuffers(1, &m_fbo_valid); |
| m_fbo_valid = 0; |
| } |
| |
| if (m_rbo_color) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_color); |
| m_rbo_color = 0; |
| } |
| |
| if (m_rbo_depth_stencil) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_depth_stencil); |
| m_rbo_depth_stencil = 0; |
| } |
| |
| /* Set initial values - all test shall have the same environment. */ |
| m_fbo_invalid = 0; |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| /******************************** Check Status Errors Test Implementation ********************************/ |
| |
| /** @brief Clear Named Framebuffer Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| CheckStatusErrorsTest::CheckStatusErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "framebuffers_check_status_errors", "Check Status Errors Test") |
| , m_fbo_valid(0) |
| , m_fbo_invalid(0) |
| , m_target_invalid(0) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Clear Named Framebuffer Errors Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult CheckStatusErrorsTest::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 |
| { |
| /* Prepare objects. */ |
| PrepareObjects(); |
| |
| /* Check that INVALID_ENUM is generated by CheckNamedFramebufferStatus if |
| target is not DRAW_FRAMEBUFFER, READ_FRAMEBUFFER or FRAMEBUFFER. */ |
| gl.checkNamedFramebufferStatus(m_fbo_valid, m_target_invalid); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "CheckNamedFramebufferStatus", |
| "target is not DRAW_FRAMEBUFFER, READ_FRAMEBUFFER or FRAMEBUFFER."); |
| |
| /* Check that INVALID_OPERATION is generated by CheckNamedFramebufferStatus |
| if framebuffer is not zero or the name of an existing framebuffer |
| object. */ |
| gl.checkNamedFramebufferStatus(m_fbo_invalid, GL_FRAMEBUFFER); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "CheckNamedFramebufferStatus", |
| "framebuffer is not zero or the name of an existing framebuffer object."); |
| } |
| 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; |
| } |
| |
| /** Check Prepare test's GL objects. |
| */ |
| void CheckStatusErrorsTest::PrepareObjects() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Valid objects. */ |
| gl.genFramebuffers(1, &m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| /* Invalid target. */ |
| bool is_target = true; |
| |
| while (is_target) |
| { |
| is_target = false; |
| |
| ++m_target_invalid; |
| |
| if (GL_FRAMEBUFFER == m_target_invalid) |
| { |
| is_target = true; |
| } |
| |
| if (GL_READ_FRAMEBUFFER == m_target_invalid) |
| { |
| is_target = true; |
| } |
| |
| if (GL_DRAW_FRAMEBUFFER == m_target_invalid) |
| { |
| is_target = true; |
| } |
| } |
| /* Invalid objects. */ |
| while (gl.isFramebuffer(++m_fbo_invalid)) |
| ; |
| } |
| |
| /** Check if error is equal to the expected, log if not. |
| * |
| * @param [in] expected_error Error to be expected. |
| * @param [in] function Function name which is being tested (to be logged). |
| * @param [in] conditions Conditions when the expected error shall occure (to be logged). |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool CheckStatusErrorsTest::ExpectError(glw::GLenum expected_error, const glw::GLchar* function, |
| const glw::GLchar* conditions) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| bool is_ok = true; |
| |
| glw::GLenum error = GL_NO_ERROR; |
| |
| if (expected_error != (error = gl.getError())) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << function << " was expected to generate " |
| << glu::getErrorStr(expected_error) << ", but " << glu::getErrorStr(error) |
| << " was observed instead when " << conditions << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| |
| /* Clean additional possible errors. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void CheckStatusErrorsTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release GL objects. */ |
| if (m_fbo_valid) |
| { |
| gl.deleteFramebuffers(1, &m_fbo_valid); |
| m_fbo_valid = 0; |
| } |
| |
| /* Set initial values - all test shall have the same environment. */ |
| m_fbo_invalid = 0; |
| m_target_invalid = 0; |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| /******************************** Get Parameter Errors Test Implementation ********************************/ |
| |
| /** @brief Get Parameter Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| GetParameterErrorsTest::GetParameterErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "framebuffers_get_parameter_errors", "Get Parameter Errors Test") |
| , m_fbo_valid(0) |
| , m_fbo_invalid(0) |
| , m_parameter_invalid(0) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Get Parameter Errors Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult GetParameterErrorsTest::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 |
| { |
| /* Prepare objects. */ |
| PrepareObjects(); |
| |
| glw::GLint return_values_dummy_storage[4]; |
| |
| /* Check that INVALID_OPERATION is generated by |
| GetNamedFramebufferParameteriv if framebuffer is not zero or the name of |
| an existing framebuffer object. */ |
| gl.getNamedFramebufferParameteriv(m_fbo_invalid, GL_SAMPLES, return_values_dummy_storage); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "GetNamedFramebufferParameteriv", |
| "framebuffer is not zero or the name of an existing framebuffer object."); |
| |
| /* Check that INVALID_ENUM is generated by GetNamedFramebufferParameteriv |
| if pname is not one of the accepted parameter names. */ |
| gl.getNamedFramebufferParameteriv(m_fbo_valid, m_parameter_invalid, return_values_dummy_storage); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "GetNamedFramebufferParameteriv", |
| "pname is not one of the accepted parameter names."); |
| |
| /* Check that INVALID_OPERATION is generated if a default framebuffer is |
| queried, and pname is not one of DOUBLEBUFFER, |
| IMPLEMENTATION_COLOR_READ_FORMAT, IMPLEMENTATION_COLOR_READ_TYPE, |
| SAMPLES, SAMPLE_BUFFERS or STEREO. */ |
| gl.getNamedFramebufferParameteriv(0, GL_FRAMEBUFFER_DEFAULT_WIDTH, return_values_dummy_storage); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "GetNamedFramebufferParameteriv", |
| "a default framebuffer is queried, and pname is not one of DOUBLEBUFFER, " |
| "IMPLEMENTATION_COLOR_READ_FORMAT, IMPLEMENTATION_COLOR_READ_TYPE, SAMPLES, " |
| "SAMPLE_BUFFERS or STEREO."); |
| } |
| 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; |
| } |
| |
| /** Check Prepare test's GL objects. |
| */ |
| void GetParameterErrorsTest::PrepareObjects() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Valid objects. */ |
| gl.genFramebuffers(1, &m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| /* Invalid target. */ |
| bool is_parameter = true; |
| |
| while (is_parameter) |
| { |
| is_parameter = false; |
| |
| ++m_parameter_invalid; |
| |
| static const glw::GLenum valid_parameters[] = { GL_FRAMEBUFFER_DEFAULT_WIDTH, |
| GL_FRAMEBUFFER_DEFAULT_HEIGHT, |
| GL_FRAMEBUFFER_DEFAULT_LAYERS, |
| GL_FRAMEBUFFER_DEFAULT_SAMPLES, |
| GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS, |
| GL_DOUBLEBUFFER, |
| GL_IMPLEMENTATION_COLOR_READ_FORMAT, |
| GL_IMPLEMENTATION_COLOR_READ_TYPE, |
| GL_SAMPLES, |
| GL_SAMPLE_BUFFERS, |
| GL_STEREO }; |
| |
| static const glw::GLuint valid_parameters_count = sizeof(valid_parameters) / sizeof(valid_parameters[0]); |
| |
| for (glw::GLuint i = 0; i < valid_parameters_count; ++i) |
| { |
| if (valid_parameters[i] == m_parameter_invalid) |
| { |
| is_parameter = true; |
| } |
| } |
| } |
| |
| /* Invalid objects. */ |
| while (gl.isFramebuffer(++m_fbo_invalid)) |
| ; |
| } |
| |
| /** Check if error is equal to the expected, log if not. |
| * |
| * @param [in] expected_error Error to be expected. |
| * @param [in] function Function name which is being tested (to be logged). |
| * @param [in] conditions Conditions when the expected error shall occure (to be logged). |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool GetParameterErrorsTest::ExpectError(glw::GLenum expected_error, const glw::GLchar* function, |
| const glw::GLchar* conditions) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| bool is_ok = true; |
| |
| glw::GLenum error = GL_NO_ERROR; |
| |
| if (expected_error != (error = gl.getError())) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << function << " was expected to generate " |
| << glu::getErrorStr(expected_error) << ", but " << glu::getErrorStr(error) |
| << " was observed instead when " << conditions << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| |
| /* Clean additional possible errors. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void GetParameterErrorsTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release GL objects. */ |
| if (m_fbo_valid) |
| { |
| gl.deleteFramebuffers(1, &m_fbo_valid); |
| m_fbo_valid = 0; |
| } |
| |
| /* Set initial values - all test shall have the same environment. */ |
| m_fbo_invalid = 0; |
| m_parameter_invalid = 0; |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| /******************************** Get Attachment Parameter Errors Test Implementation ********************************/ |
| |
| /** @brief Get Attachment Parameter Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| GetAttachmentParameterErrorsTest::GetAttachmentParameterErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "framebuffers_get_attachment_parameter_errors", "Get Attachment Parameter Errors Test") |
| , m_fbo_valid(0) |
| , m_rbo_color(0) |
| , m_rbo_depth_stencil(0) |
| , m_fbo_invalid(0) |
| , m_parameter_invalid(0) |
| , m_attachment_invalid(0) |
| , m_default_attachment_invalid(0) |
| , m_max_color_attachments(8) /* Spec default. */ |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Get Attachment Parameter Errors Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult GetAttachmentParameterErrorsTest::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 |
| { |
| /* Prepare objects. */ |
| PrepareObjects(); |
| |
| glw::GLint return_values_dummy_storage[4]; |
| |
| /* Check that GL_INVALID_OPERATION is generated by |
| GetNamedFramebufferAttachmentParameteriv if framebuffer is not zero or |
| the name of an existing framebuffer object. */ |
| gl.getNamedFramebufferAttachmentParameteriv( |
| m_fbo_invalid, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, return_values_dummy_storage); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "GetNamedFramebufferAttachmentParameteriv", |
| "framebuffer is not zero or the name of an existing framebuffer object."); |
| |
| /* Check that INVALID_ENUM is generated by |
| GetNamedFramebufferAttachmentParameteriv if pname is not valid for the |
| value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, as described above. */ |
| gl.getNamedFramebufferAttachmentParameteriv( |
| m_fbo_valid, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, return_values_dummy_storage); |
| |
| is_ok &= ExpectError( |
| GL_INVALID_ENUM, "GetNamedFramebufferAttachmentParameteriv", |
| "pname is not valid for the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, as described above."); |
| |
| /* Check that INVALID_ENUM error is generated if a framebuffer object is queried, attachment |
| is not one of the attachments in table 9.2 (COLOR_ATTACHMENTi, DEPTH_ATTACHMENT, STENCIL_ATTACHMENT, DEPTH_STENCIL_ATTACHMENT), and attachment is not |
| COLOR_ATTACHMENTm where m is greater than or equal to the value of MAX_COLOR_ATTACHMENTS. */ |
| gl.getNamedFramebufferAttachmentParameteriv( |
| m_fbo_valid, m_attachment_invalid, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, return_values_dummy_storage); |
| |
| is_ok &= ExpectError( |
| GL_INVALID_ENUM, "GetNamedFramebufferAttachmentParameteriv", |
| "attachment is not one of the accepted framebuffer attachment points, as described in specification."); |
| |
| /* Check that INVALID_OPERATION is generated by |
| GetNamedFramebufferAttachmentParameteriv if the value of |
| FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE and pname is not |
| FRAMEBUFFER_ATTACHMENT_OBJECT_NAME or |
| FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE. */ |
| gl.getNamedFramebufferAttachmentParameteriv( |
| m_fbo_valid, GL_COLOR_ATTACHMENT1, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, return_values_dummy_storage); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "GetNamedFramebufferAttachmentParameteriv", |
| "the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE and pname is not " |
| "FRAMEBUFFER_ATTACHMENT_OBJECT_NAME or FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE."); |
| |
| /* Check that INVALID_OPERATION is generated by |
| GetNamedFramebufferAttachmentParameteriv if attachment is |
| DEPTH_STENCIL_ATTACHMENT and pname is FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE. */ |
| gl.getNamedFramebufferAttachmentParameteriv(m_fbo_valid, GL_DEPTH_STENCIL_ATTACHMENT, |
| GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, |
| return_values_dummy_storage); |
| |
| is_ok &= |
| ExpectError(GL_INVALID_OPERATION, "GetNamedFramebufferAttachmentParameteriv", |
| "attachment is DEPTH_STENCIL_ATTACHMENT and pname is FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE."); |
| |
| /* Check that an INVALID_ENUM error is generated if the default framebuffer is |
| queried and attachment is not one the values FRONT, FRONT_LEFT, FRONT_RIGHT, |
| BACK, BACK_LEFT, BACK_RIGHT, DEPTH, STENCIL. */ |
| gl.getNamedFramebufferAttachmentParameteriv( |
| 0, m_default_attachment_invalid, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, return_values_dummy_storage); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "GetNamedFramebufferAttachmentParameteriv", |
| "the default framebuffer is queried and attachment is not one the values FRONT, " |
| "FRONT_LEFT, FRONT_RIGHT, BACK, BACK_LEFT, BACK_RIGHT, DEPTH, STENCIL."); |
| |
| /* Check that an INVALID_OPERATION error is generated if a framebuffer object is |
| bound to target and attachment is COLOR_ATTACHMENTm where m is greater than or |
| equal to the value of MAX_COLOR_ATTACHMENTS. */ |
| gl.getNamedFramebufferAttachmentParameteriv(m_fbo_valid, GL_COLOR_ATTACHMENT0 + m_max_color_attachments, |
| GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, |
| return_values_dummy_storage); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "GetNamedFramebufferAttachmentParameteriv", |
| "a framebuffer object is bound to target and attachment is COLOR_ATTACHMENTm where m is " |
| "equal to the value of MAX_COLOR_ATTACHMENTS."); |
| |
| gl.getNamedFramebufferAttachmentParameteriv(m_fbo_valid, GL_COLOR_ATTACHMENT0 + m_max_color_attachments + 1, |
| GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, |
| return_values_dummy_storage); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "GetNamedFramebufferAttachmentParameteriv", |
| "a framebuffer object is bound to target and attachment is COLOR_ATTACHMENTm where m is " |
| "greater than the value of MAX_COLOR_ATTACHMENTS."); |
| } |
| 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; |
| } |
| |
| /** Check Prepare test's GL objects. |
| */ |
| void GetAttachmentParameterErrorsTest::PrepareObjects() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Valid objects. */ |
| gl.genFramebuffers(1, &m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| gl.genRenderbuffers(1, &m_rbo_color); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_color); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, 1, 1); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_color); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| gl.genRenderbuffers(1, &m_rbo_depth_stencil); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_depth_stencil); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| gl.renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 1, 1); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo_depth_stencil); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); |
| |
| /* Max color attachments. */ |
| gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &m_max_color_attachments); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv has failed"); |
| |
| /* Invalid attachment. */ |
| bool is_attachment = true; |
| |
| while (is_attachment) |
| { |
| is_attachment = false; |
| |
| if ((GL_DEPTH_ATTACHMENT == m_attachment_invalid) || (GL_STENCIL_ATTACHMENT == m_attachment_invalid) || |
| (GL_DEPTH_STENCIL_ATTACHMENT == m_attachment_invalid)) |
| { |
| ++m_attachment_invalid; |
| is_attachment = true; |
| } |
| |
| if (GL_COLOR_ATTACHMENT0 < m_attachment_invalid) |
| { |
| /* If this unlikely happen this mean that we cannot create invalid attachment which is not DEPTH_ATTACHMENT, STENCIL_ATTACHMENT, DEPTH_STENCIL_ATTACHMENT and |
| GL_COLOR_ATTACHMENTm where m IS any number (for m < MAX_COLOR_ATTACHMENTS attachments are valid, and for m >= MAX_COLOR_ATTACHMENTS is invalid, but |
| INVALID_OPERATION shall be generated instead of INVALID_ENUM. Such a situation may need change in the test or in the specification. */ |
| throw 0; |
| } |
| } |
| |
| /* Invalid default framebuffer attachment. */ |
| bool is_default_attachment = true; |
| |
| while (is_default_attachment) |
| { |
| is_default_attachment = false; |
| |
| static const glw::GLenum valid_values[] = { GL_FRONT, GL_FRONT_LEFT, GL_FRONT_RIGHT, GL_BACK, |
| GL_BACK_LEFT, GL_BACK_RIGHT, GL_DEPTH, GL_STENCIL }; |
| |
| static const glw::GLuint valid_values_count = sizeof(valid_values) / sizeof(valid_values[0]); |
| |
| for (glw::GLuint i = 0; i < valid_values_count; ++i) |
| { |
| if (valid_values[i] == m_default_attachment_invalid) |
| { |
| m_default_attachment_invalid++; |
| is_default_attachment = true; |
| break; |
| } |
| } |
| } |
| |
| /* Invalid parameter. */ |
| bool is_parameter = true; |
| |
| while (is_parameter) |
| { |
| is_parameter = false; |
| |
| ++m_parameter_invalid; |
| |
| static const glw::GLenum valid_parameters[] = { GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, |
| GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, |
| GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, |
| GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, |
| GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, |
| GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, |
| GL_FRAMEBUFFER_ATTACHMENT_LAYERED, |
| GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER }; |
| |
| static const glw::GLuint valid_parameters_count = sizeof(valid_parameters) / sizeof(valid_parameters[0]); |
| |
| for (glw::GLuint i = 0; i < valid_parameters_count; ++i) |
| { |
| if (valid_parameters[i] == m_parameter_invalid) |
| { |
| is_parameter = true; |
| } |
| } |
| } |
| |
| /* Invalid objects. */ |
| while (gl.isFramebuffer(++m_fbo_invalid)) |
| ; |
| } |
| |
| /** Check if error is equal to the expected, log if not. |
| * |
| * @param [in] expected_error Error to be expected. |
| * @param [in] function Function name which is being tested (to be logged). |
| * @param [in] conditions Conditions when the expected error shall occure (to be logged). |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool GetAttachmentParameterErrorsTest::ExpectError(glw::GLenum expected_error, const glw::GLchar* function, |
| const glw::GLchar* conditions) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| bool is_ok = true; |
| |
| glw::GLenum error = GL_NO_ERROR; |
| |
| if (expected_error != (error = gl.getError())) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << function << " was expected to generate " |
| << glu::getErrorStr(expected_error) << ", but " << glu::getErrorStr(error) |
| << " was observed instead when " << conditions << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| |
| /* Clean additional possible errors. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void GetAttachmentParameterErrorsTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release GL objects. */ |
| if (m_fbo_valid) |
| { |
| gl.deleteFramebuffers(1, &m_fbo_valid); |
| m_fbo_valid = 0; |
| } |
| |
| if (m_rbo_color) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_color); |
| m_rbo_color = 0; |
| } |
| |
| if (m_rbo_depth_stencil) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_depth_stencil); |
| m_rbo_depth_stencil = 0; |
| } |
| |
| /* Set initial values - all test shall have the same environment. */ |
| m_fbo_invalid = 0; |
| m_parameter_invalid = 0; |
| m_attachment_invalid = 0; |
| m_default_attachment_invalid = 0; |
| m_max_color_attachments = 8; |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| /******************************** Functional Test Implementation ********************************/ |
| |
| /** @brief Get Attachment Parameter Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| FunctionalTest::FunctionalTest(deqp::Context& context) |
| : deqp::TestCase(context, "framebuffers_renderbuffers_functional", "Functional Test") |
| , m_fbo_1st(0) |
| , m_fbo_2nd(0) |
| , m_rbo_color(0) |
| , m_rbo_depth_stencil(0) |
| , m_to_color(0) |
| , m_po(0) |
| , m_vao_stencil_pass_quad(0) |
| , m_vao_depth_pass_quad(0) |
| , m_vao_color_pass_quad(0) |
| , m_bo_stencil_pass_quad(0) |
| , m_bo_depth_pass_quad(0) |
| , m_bo_color_pass_quad(0) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Get Attachment Parameter Errors 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 |
| { |
| /* Test. */ |
| is_ok &= PrepareFirstFramebuffer(); |
| is_ok &= PrepareSecondFramebuffer(); |
| is_ok &= ClearFramebuffers(); |
| PrepareProgram(); |
| PrepareBuffersAndVertexArrays(); |
| is_ok &= DrawAndBlit(); |
| is_ok &= CheckSecondFramebufferContent(); |
| } |
| 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; |
| } |
| |
| /** Prepare first framebuffer. |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool FunctionalTest::PrepareFirstFramebuffer() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Failure of this part shall result in test failure (it is DSA functionality failure). */ |
| try |
| { |
| gl.createFramebuffers(1, &m_fbo_1st); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateFramebuffers has failed"); |
| |
| gl.createRenderbuffers(1, &m_rbo_color); |
| gl.createRenderbuffers(1, &m_rbo_depth_stencil); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateRenderbuffers has failed"); |
| |
| gl.namedRenderbufferStorage(m_rbo_color, GL_R8, 8, 8); |
| gl.namedRenderbufferStorage(m_rbo_depth_stencil, GL_DEPTH24_STENCIL8, 8, 8); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedRenderbufferStorage has failed"); |
| |
| gl.namedFramebufferRenderbuffer(m_fbo_1st, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_color); |
| gl.namedFramebufferRenderbuffer(m_fbo_1st, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo_depth_stencil); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedFramebufferRenderbuffer has failed"); |
| |
| if (GL_FRAMEBUFFER_COMPLETE != gl.checkNamedFramebufferStatus(m_fbo_1st, GL_FRAMEBUFFER)) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "CheckNamedFramebufferStatus is incomplete." |
| << tcu::TestLog::EndMessage; |
| |
| throw 0; |
| } |
| } |
| catch (...) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** Prepare second framebuffer. |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool FunctionalTest::PrepareSecondFramebuffer() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Failure of this part shall result in test internal error (it does not test the DSA functionality). */ |
| gl.genTextures(1, &m_to_color); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed"); |
| |
| gl.bindTexture(GL_TEXTURE_2D, m_to_color); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture has failed"); |
| |
| gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R8, 4, 3); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D has failed"); |
| |
| /* Failure of this part shall result in test failure (it is DSA functionality failure). */ |
| try |
| { |
| gl.createFramebuffers(1, &m_fbo_2nd); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateFramebuffers has failed"); |
| |
| gl.namedFramebufferTexture(m_fbo_2nd, GL_COLOR_ATTACHMENT0, m_to_color, 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedFramebufferTexture has failed"); |
| |
| if (GL_FRAMEBUFFER_COMPLETE != gl.checkNamedFramebufferStatus(m_fbo_2nd, GL_FRAMEBUFFER)) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "CheckNamedFramebufferStatus is incomplete." |
| << tcu::TestLog::EndMessage; |
| |
| throw 0; |
| } |
| } |
| catch (...) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** Clear framebuffers. |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool FunctionalTest::ClearFramebuffers() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Failure of this part shall result in test failure (it is DSA functionality failure). */ |
| try |
| { |
| glw::GLfloat color_value[] = { 0.f, 0.f, 0.f, 0.f }; |
| glw::GLfloat depth_value = 0.f; |
| glw::GLint stencil_value = 0; |
| |
| /* 1st framebuffer. */ |
| gl.clearNamedFramebufferfv(m_fbo_1st, GL_COLOR, 0, color_value); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glClearNamedFramebufferfv has failed"); |
| |
| gl.clearNamedFramebufferfi(m_fbo_1st, GL_DEPTH_STENCIL, 0, depth_value, stencil_value); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glClearNamedFramebufferfi has failed"); |
| |
| /* 2nd framebuffer. */ |
| gl.clearNamedFramebufferfv(m_fbo_1st, GL_COLOR, 0, color_value); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glClearNamedFramebufferfv has failed"); |
| } |
| catch (...) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** Prepare test's GLSL program. |
| */ |
| 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 (0 == m_po) |
| { |
| throw 0; |
| } |
| } |
| |
| /** Prepare Vertex Array Objects (one for each draw pass). |
| */ |
| void FunctionalTest::PrepareBuffersAndVertexArrays() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Query program attribute. */ |
| glw::GLuint program_attribute = gl.getAttribLocation(m_po, s_attribute); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); |
| |
| /* Create stencil pass buffer. */ |
| gl.genVertexArrays(1, &m_vao_stencil_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); |
| |
| gl.bindVertexArray(m_vao_stencil_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); |
| |
| gl.genBuffers(1, &m_bo_stencil_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); |
| |
| gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_stencil_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers call failed."); |
| |
| gl.bufferData(GL_ARRAY_BUFFER, s_stencil_pass_quad_size, s_stencil_pass_quad, GL_STATIC_DRAW); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); |
| |
| gl.vertexAttribPointer(program_attribute, 3, GL_FLOAT, GL_FALSE, 0, NULL); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); |
| |
| gl.enableVertexAttribArray(program_attribute); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); |
| |
| /* Create depth pass buffer. */ |
| gl.genVertexArrays(1, &m_vao_depth_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); |
| |
| gl.bindVertexArray(m_vao_depth_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); |
| |
| gl.genBuffers(1, &m_bo_depth_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); |
| |
| gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_depth_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers call failed."); |
| |
| gl.bufferData(GL_ARRAY_BUFFER, s_depth_pass_quad_size, s_depth_pass_quad, GL_STATIC_DRAW); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); |
| |
| gl.vertexAttribPointer(program_attribute, 3, GL_FLOAT, GL_FALSE, 0, NULL); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); |
| |
| gl.enableVertexAttribArray(program_attribute); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); |
| |
| /* Create color pass buffer. */ |
| gl.genVertexArrays(1, &m_vao_color_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); |
| |
| gl.bindVertexArray(m_vao_color_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); |
| |
| gl.genBuffers(1, &m_bo_color_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); |
| |
| gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_color_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers call failed."); |
| |
| gl.bufferData(GL_ARRAY_BUFFER, s_color_pass_quad_size, s_color_pass_quad, GL_STATIC_DRAW); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); |
| |
| gl.vertexAttribPointer(program_attribute, 3, GL_FLOAT, GL_FALSE, 0, NULL); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); |
| |
| gl.enableVertexAttribArray(program_attribute); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); |
| } |
| |
| /** Do the test draww/blit calls. |
| * |
| * @return True if there is no error in DSA functionality, false otherwise. |
| */ |
| bool FunctionalTest::DrawAndBlit() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| gl.useProgram(m_po); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_1st); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); |
| |
| gl.viewport(0, 0, 8, 8); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed."); |
| |
| /* Draw to stencil buffer. */ |
| gl.bindVertexArray(m_vao_stencil_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); |
| |
| gl.stencilFunc(GL_NEVER, 0, 0xff); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glStencilFunc call failed."); |
| |
| gl.stencilOp(GL_INCR, GL_KEEP, GL_KEEP); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glStencilOp call failed."); |
| |
| gl.stencilMask(0xff); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glStencilMask call failed."); |
| |
| gl.colorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glColorMask call failed."); |
| |
| gl.depthMask(GL_FALSE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDepthMask call failed."); |
| |
| gl.enable(GL_STENCIL_TEST); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); |
| |
| gl.disable(GL_DEPTH_TEST); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); |
| |
| gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); |
| |
| /* Draw to depth buffer. */ |
| gl.bindVertexArray(m_vao_depth_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); |
| |
| gl.stencilFunc(GL_ALWAYS, 0, 0xff); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glStencilFunc call failed."); |
| |
| gl.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glStencilOp call failed."); |
| |
| gl.stencilMask(0xff); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glStencilMask call failed."); |
| |
| gl.depthFunc(GL_ALWAYS); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDepthFunc call failed."); |
| |
| gl.disable(GL_STENCIL_TEST); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); |
| |
| gl.enable(GL_DEPTH_TEST); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); |
| |
| gl.depthMask(GL_TRUE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDepthMask call failed."); |
| |
| gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); |
| |
| /* Draw to color buffer. */ |
| gl.bindVertexArray(m_vao_color_pass_quad); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); |
| |
| gl.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glColorMask call failed."); |
| |
| gl.stencilFunc(GL_EQUAL, 1, 0xff); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glStencilFunc call failed."); |
| |
| gl.enable(GL_STENCIL_TEST); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); |
| |
| gl.enable(GL_DEPTH_TEST); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); |
| |
| gl.depthFunc(GL_GREATER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDepthFunc call failed."); |
| |
| gl.depthMask(GL_FALSE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDepthMask call failed."); |
| |
| gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); |
| |
| /* Blit framebuffer content. */ |
| gl.blitNamedFramebuffer(m_fbo_1st, m_fbo_2nd, 0, 0, 8, 8, 0, 0, 4, 3, GL_COLOR_BUFFER_BIT, GL_NEAREST); |
| |
| if (gl.getError()) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** Check resulting framebuffer content. |
| * |
| * @return True if content matches the reference false otherwise. |
| */ |
| bool FunctionalTest::CheckSecondFramebufferContent() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_2nd); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); |
| |
| glw::GLubyte framebuffer_values[3][4] = { |
| { 0 } /* , ... */ |
| }; |
| |
| static const glw::GLubyte reference_values[3][4] = { { 0, 0, 0, 0 }, { 0, 0, 255, 0 }, { 0, 0, 0, 0 } }; |
| |
| gl.readPixels(0, 0, 4, 3, GL_RED, GL_UNSIGNED_BYTE, framebuffer_values); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); |
| |
| for (glw::GLuint j = 0; j < 3; ++j) |
| { |
| for (glw::GLuint i = 0; i < 4; ++i) |
| { |
| if (reference_values[j][i] != framebuffer_values[j][i]) |
| { |
| return false; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void FunctionalTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Releas GL objects. */ |
| if (m_fbo_1st) |
| { |
| gl.deleteFramebuffers(1, &m_fbo_1st); |
| |
| m_fbo_1st = 0; |
| } |
| |
| if (m_fbo_2nd) |
| { |
| gl.deleteFramebuffers(1, &m_fbo_2nd); |
| |
| m_fbo_2nd = 0; |
| } |
| |
| if (m_rbo_color) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_color); |
| |
| m_rbo_color = 0; |
| } |
| |
| if (m_rbo_depth_stencil) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_depth_stencil); |
| |
| m_rbo_depth_stencil = 0; |
| } |
| |
| if (m_to_color) |
| { |
| gl.deleteTextures(1, &m_to_color); |
| |
| m_to_color = 0; |
| } |
| |
| if (m_po) |
| { |
| gl.useProgram(0); |
| |
| gl.deleteProgram(m_po); |
| |
| m_po = 0; |
| } |
| |
| if (m_vao_stencil_pass_quad) |
| { |
| gl.deleteBuffers(1, &m_vao_stencil_pass_quad); |
| |
| m_vao_stencil_pass_quad = 0; |
| } |
| |
| if (m_vao_depth_pass_quad) |
| { |
| gl.deleteBuffers(1, &m_vao_depth_pass_quad); |
| |
| m_vao_depth_pass_quad = 0; |
| } |
| |
| if (m_vao_color_pass_quad) |
| { |
| gl.deleteBuffers(1, &m_vao_color_pass_quad); |
| |
| m_vao_color_pass_quad = 0; |
| } |
| |
| if (m_bo_stencil_pass_quad) |
| { |
| gl.deleteBuffers(1, &m_bo_stencil_pass_quad); |
| |
| m_bo_stencil_pass_quad = 0; |
| } |
| |
| if (m_bo_depth_pass_quad) |
| { |
| gl.deleteBuffers(1, &m_bo_depth_pass_quad); |
| |
| m_bo_depth_pass_quad = 0; |
| } |
| |
| if (m_bo_color_pass_quad) |
| { |
| gl.deleteBuffers(1, &m_bo_color_pass_quad); |
| |
| m_bo_color_pass_quad = 0; |
| } |
| |
| /* Reseting state. */ |
| gl.stencilFunc(GL_ALWAYS, 0, 0xff); |
| gl.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP); |
| gl.stencilMask(0xff); |
| gl.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| gl.depthFunc(GL_LESS); |
| gl.depthMask(GL_TRUE); |
| gl.disable(GL_STENCIL_TEST); |
| gl.disable(GL_DEPTH_TEST); |
| |
| /* Clean errors. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| /** Vertex shader source code. */ |
| const glw::GLchar FunctionalTest::s_vertex_shader[] = "#version 330\n" |
| "\n" |
| "in vec3 position;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(position, 1.0);\n" |
| "}\n"; |
| |
| /** Fragment shader source code. */ |
| const glw::GLchar FunctionalTest::s_fragment_shader[] = "#version 330\n" |
| "\n" |
| "out vec4 color;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " color = vec4(1.0);\n" |
| "}\n"; |
| |
| /** Vertex shader source code attribute name. */ |
| const glw::GLchar FunctionalTest::s_attribute[] = "position"; |
| |
| /** Stencil pass' geometry to be passed to vertex shader attribute. */ |
| const glw::GLfloat FunctionalTest::s_stencil_pass_quad[] = { -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, |
| 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f }; |
| |
| /** Depth pass' geometry to be passed to vertex shader attribute. */ |
| const glw::GLfloat FunctionalTest::s_depth_pass_quad[] = { -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, |
| 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f }; |
| |
| /** Color pass' geometry to be passed to vertex shader attribute. */ |
| const glw::GLfloat FunctionalTest::s_color_pass_quad[] = { -1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, |
| 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f }; |
| |
| const glw::GLuint FunctionalTest::s_stencil_pass_quad_size = |
| sizeof(s_stencil_pass_quad); //!< Size of stencil pass' geometry. |
| const glw::GLuint FunctionalTest::s_depth_pass_quad_size = |
| sizeof(s_depth_pass_quad); //!< Size of depth pass' geometry. |
| const glw::GLuint FunctionalTest::s_color_pass_quad_size = |
| sizeof(s_color_pass_quad); //!< Size of color pass' geometry. |
| |
| } // namespace Framebuffers |
| |
| namespace Renderbuffers |
| { |
| /******************************** Renderbuffer Creation Test Implementation ********************************/ |
| |
| /** @brief Creation Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| CreationTest::CreationTest(deqp::Context& context) |
| : deqp::TestCase(context, "renderbuffers_creation", "Renderbuffer 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; |
| |
| /* Renderbuffers' objects */ |
| static const glw::GLuint renderbuffers_count = 2; |
| |
| glw::GLuint renderbuffers_legacy[renderbuffers_count] = {}; |
| glw::GLuint renderbuffers_dsa[renderbuffers_count] = {}; |
| |
| try |
| { |
| /* Check legacy state creation. */ |
| gl.genRenderbuffers(renderbuffers_count, renderbuffers_legacy); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed"); |
| |
| for (glw::GLuint i = 0; i < renderbuffers_count; ++i) |
| { |
| if (gl.isRenderbuffer(renderbuffers_legacy[i])) |
| { |
| is_ok = false; |
| |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "GenRenderbuffers has created default objects, but it should create only a names." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| |
| /* Check direct state creation. */ |
| gl.createRenderbuffers(renderbuffers_count, renderbuffers_dsa); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateRenderbuffers has failed"); |
| |
| for (glw::GLuint i = 0; i < renderbuffers_count; ++i) |
| { |
| if (!gl.isRenderbuffer(renderbuffers_dsa[i])) |
| { |
| is_ok = false; |
| |
| /* Log. */ |
| m_context.getTestContext().getLog() << tcu::TestLog::Message |
| << "CreateRenderbuffers has not created default objects." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Cleanup. */ |
| for (glw::GLuint i = 0; i < renderbuffers_count; ++i) |
| { |
| if (renderbuffers_legacy[i]) |
| { |
| gl.deleteRenderbuffers(1, &renderbuffers_legacy[i]); |
| |
| renderbuffers_legacy[i] = 0; |
| } |
| |
| if (renderbuffers_dsa[i]) |
| { |
| gl.deleteRenderbuffers(1, &renderbuffers_dsa[i]); |
| |
| renderbuffers_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; |
| } |
| |
| /******************************** Renderbuffer Storage Test Implementation ********************************/ |
| |
| /** @brief Renderbuffer Storage Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| StorageTest::StorageTest(deqp::Context& context) |
| : deqp::TestCase(context, "renderbuffers_storage", "Renderbuffer Objects Storage Test"), m_fbo(0), m_rbo(0) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Creation Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult StorageTest::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_renderbuffer_size = 16384 /* Specification minimum. */; |
| |
| gl.getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &max_renderbuffer_size); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); |
| |
| const struct |
| { |
| glw::GLuint width; |
| glw::GLuint height; |
| } test_cases[] = { { 1, 1 }, |
| { 256, 512 }, |
| { 1280, 720 }, |
| { (glw::GLuint)max_renderbuffer_size, 1 }, |
| { 1, (glw::GLuint)max_renderbuffer_size } }; |
| |
| const glw::GLuint test_cases_count = sizeof(test_cases) / sizeof(test_cases[0]); |
| |
| for (glw::GLuint i = 0; i < test_cases_count; ++i) |
| { |
| for (glw::GLuint j = 0; j < s_renderbuffer_internalformat_configuration_count; ++j) |
| { |
| if (PrepareRenderbuffer(s_renderbuffer_internalformat_configuration[j], test_cases[i].width, |
| test_cases[i].height)) |
| { |
| Clear(s_renderbuffer_internalformat_configuration[j].isColorIntegralFormat); |
| is_ok &= Check(s_renderbuffer_internalformat_configuration[j], test_cases[i].width, |
| test_cases[i].height); |
| } |
| else |
| { |
| is_ok = false; |
| } |
| |
| Clean(); |
| } |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| |
| 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; |
| } |
| |
| /** Prepare renderbuffer. |
| * |
| * @param [in] format Internal format to be prepared. |
| * @param [in] width Width of the framebuffer. |
| * @param [in] height Height of the framebuffer. |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool StorageTest::PrepareRenderbuffer(StorageTest::RenderbufferInternalFormatConfiguration format, glw::GLuint width, |
| glw::GLuint height) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| 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(), "glBindFramebuffer call failed."); |
| |
| gl.createRenderbuffers(1, &m_rbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateRenderbuffers call failed."); |
| |
| gl.namedRenderbufferStorage(m_rbo, format.internalformat, width, height); |
| |
| if (glw::GLenum error = gl.getError()) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Renderbuffer storage test failed because NamedRenderbufferStorage generated " |
| << glu::getErrorStr(error) << " error value. Renderbuffers format was " |
| << glu::getInternalFormatParameterStr(format.internalformat) << ", width was " << width << ", height was " |
| << height << "." << tcu::TestLog::EndMessage; |
| return false; |
| } |
| |
| if (format.hasRedComponent || format.hasGreenComponent || format.hasBlueComponent || format.hasAlphaComponent) |
| { |
| gl.namedFramebufferRenderbuffer(m_fbo, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo); |
| } |
| |
| if (format.hasDepthComponent) |
| { |
| gl.namedFramebufferRenderbuffer(m_fbo, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rbo); |
| } |
| |
| if (format.hasStencilComponent) |
| { |
| gl.namedFramebufferRenderbuffer(m_fbo, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo); |
| } |
| |
| if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "Renderbuffer storage test failed due to incomplete framebuffer status. Renderbuffers format was " |
| << glu::getInternalFormatParameterStr(format.internalformat) << ", width was " << width << ", height was " |
| << height << "." << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** Clear renderbuffer. |
| * |
| * @param [in] isColorIntegralFormat Is this color integral format. |
| */ |
| void StorageTest::Clear(bool isColorIntegralFormat) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| if (isColorIntegralFormat) |
| { |
| gl.clearBufferiv(GL_COLOR, 0, s_reference_color_integer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferiv has failed"); |
| } |
| else |
| { |
| /* 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); |
| } |
| } |
| |
| /** Check renderbuffer's content. |
| * |
| * @param [in] format Internal format to be prepared. |
| * @param [in] width Width of the framebuffer. |
| * @param [in] height Height of the framebuffer. |
| * |
| * @return True if content matches the reference, false otherwise. |
| */ |
| bool StorageTest::Check(StorageTest::RenderbufferInternalFormatConfiguration format, glw::GLuint width, |
| glw::GLuint height) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| glw::GLuint size = width * height; |
| |
| if (format.hasRedComponent || format.hasGreenComponent || format.hasBlueComponent || format.hasAlphaComponent) |
| { |
| if (format.isColorIntegralFormat) |
| { |
| std::vector<glw::GLint> color(size * 4); |
| |
| gl.readPixels(0, 0, width, height, GL_RGBA_INTEGER, GL_INT, &color[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); |
| |
| const bool hasComponent[] = { format.hasRedComponent, format.hasGreenComponent, format.hasBlueComponent, |
| format.hasAlphaComponent }; |
| |
| static const char* componentName[] = { "red", "green", "blue", "alpha" }; |
| |
| for (glw::GLuint i = 0; i < size; ++i) |
| { |
| if (hasComponent[i % 4 /* color components count*/]) |
| { |
| if (de::abs(s_reference_color_integer[i % 4 /* color components count*/] - color[i]) > |
| 2 /* Precision */) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Renderbuffer storage was cleared with color " |
| << componentName[i % 4 /* color components count*/] << " component equal to " |
| << s_reference_color_integer << ", but fetched value " << color[i] |
| << " is not the same. Renderbuffers format was " << format.internalformat_name |
| << ", width was " << width << ", height was " << height << "." << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| } |
| } |
| } |
| else |
| { |
| std::vector<glw::GLfloat> color(size * 4); |
| |
| gl.readPixels(0, 0, width, height, GL_RGBA, GL_FLOAT, &color[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); |
| |
| const bool hasComponent[] = { format.hasRedComponent, format.hasGreenComponent, format.hasBlueComponent, |
| format.hasAlphaComponent }; |
| |
| static const char* componentName[] = { "red", "green", "blue", "alpha" }; |
| |
| for (glw::GLuint i = 0; i < size; ++i) |
| { |
| if (hasComponent[i % 4 /* color components count*/]) |
| { |
| if (de::abs(s_reference_color[i % 4 /* color components count*/] - color[i]) > |
| 0.0625 /* precision */) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Renderbuffer storage was cleared with color " |
| << componentName[i % 4 /* color components count*/] << " component equal to " |
| << s_reference_color[i % 4 /* color components count*/] << ", but fetched value " |
| << color[i] << " is not the same. Renderbuffers format was " << format.internalformat_name |
| << ", width was " << width << ", height was " << height << "." << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| } |
| } |
| } |
| } |
| |
| if (format.hasDepthComponent) |
| { |
| std::vector<glw::GLfloat> depth(size); |
| |
| gl.readPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, &depth[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); |
| |
| for (glw::GLuint i = 0; i < size; ++i) |
| { |
| if (de::abs(s_reference_depth - depth[i]) > 0.0625 /* 1/16 precision */) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Renderbuffer storage was cleared with depth component equal to " |
| << s_reference_depth << ", but fetched value " << depth[i] |
| << " is not the same. Renderbuffers format was " << format.internalformat_name << ", width was " |
| << width << ", height was " << height << "." << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| } |
| } |
| |
| if (format.hasStencilComponent) |
| { |
| std::vector<glw::GLint> stencil(size); |
| |
| gl.readPixels(0, 0, width, height, GL_STENCIL_INDEX, GL_INT, &stencil[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); |
| |
| for (glw::GLuint i = 0; i < size; ++i) |
| { |
| if (s_reference_stencil != stencil[i]) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Renderbuffer storage was cleared with alpha component equal to " |
| << s_reference_stencil << ", but fetched value " << stencil[i] |
| << " is not the same. Renderbuffers format was " << format.internalformat_name << ", width was " |
| << width << ", height was " << height << "." << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void StorageTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release objects. */ |
| if (m_rbo) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo); |
| |
| m_rbo = 0; |
| } |
| |
| if (m_fbo) |
| { |
| gl.deleteFramebuffers(1, &m_fbo); |
| |
| m_fbo = 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()) |
| ; |
| } |
| |
| /** Internal formats to be tested*/ |
| const struct StorageTest::RenderbufferInternalFormatConfiguration |
| StorageTest::s_renderbuffer_internalformat_configuration[] = { |
| { GL_R8, "GL_R8", true, false, false, false, false, false, false }, |
| { GL_R16, "GL_R16", true, false, false, false, false, false, false }, |
| { GL_RG8, "GL_RG8", true, true, false, false, false, false, false }, |
| { GL_RG16, "GL_RG16", true, true, false, false, false, false, false }, |
| { GL_RGB565, "GL_RGB56", true, true, true, false, false, false, false }, |
| { GL_RGBA4, "GL_RGBA4", true, true, true, true, false, false, false }, |
| { GL_RGB5_A1, "GL_RGB5_A1", true, true, true, true, false, false, false }, |
| { GL_RGBA8, "GL_RGBA8", true, true, true, true, false, false, false }, |
| { GL_RGB10_A2, "GL_RGB10_A2", true, true, true, true, false, false, false }, |
| { GL_RGB10_A2UI, "GL_RGB10_A2UI", true, true, true, true, false, false, true }, |
| { GL_RGBA16, "GL_RGBA16", true, true, true, true, false, false, false }, |
| { GL_SRGB8_ALPHA8, "GL_SRGB8_ALPHA8", true, true, true, true, false, false, false }, |
| { GL_R16F, "GL_R16F", true, false, false, false, false, false, false }, |
| { GL_RG16F, "GL_RG16F", true, true, false, false, false, false, false }, |
| { GL_RGBA16F, "GL_RGBA16F", true, true, true, true, false, false, false }, |
| { GL_R32F, "GL_R32F", true, false, false, false, false, false, false }, |
| { GL_RG32F, "GL_RG32F", true, true, false, false, false, false, false }, |
| { GL_RGBA32F, "GL_RGBA32F", true, true, true, true, false, false, false }, |
| { GL_R11F_G11F_B10F, "GL_R11F_G11F_B10F", true, true, true, false, false, false, false }, |
| { GL_R8I, "GL_R8I", true, false, false, false, false, false, true }, |
| { GL_R8UI, "GL_R8UI", true, false, false, false, false, false, true }, |
| { GL_R16I, "GL_R16I", true, false, false, false, false, false, true }, |
| { GL_R16UI, "GL_R16UI", true, false, false, false, false, false, true }, |
| { GL_R32I, "GL_R32I", true, false, false, false, false, false, true }, |
| { GL_R32UI, "GL_R32UI", true, false, false, false, false, false, true }, |
| { GL_RG8I, "GL_RG8I", true, true, false, false, false, false, true }, |
| { GL_RG8UI, "GL_RG8UI", true, true, false, false, false, false, true }, |
| { GL_RG16I, "GL_RG16I", true, true, false, false, false, false, true }, |
| { GL_RG16UI, "GL_RG16UI", true, true, false, false, false, false, true }, |
| { GL_RG32I, "GL_RG32I", true, true, false, false, false, false, true }, |
| { GL_RG32UI, "GL_RG32UI", true, true, false, false, false, false, true }, |
| { GL_RGBA8I, "GL_RGBA8I", true, true, true, true, false, false, true }, |
| { GL_RGBA8UI, "GL_RGBA8UI", true, true, true, true, false, false, true }, |
| { GL_RGBA16I, "GL_RGBA16I", true, true, true, true, false, false, true }, |
| { GL_RGBA16UI, "GL_RGBA16UI", true, true, true, true, false, false, true }, |
| { GL_RGBA32I, "GL_RGBA32I", true, true, true, true, false, false, true }, |
| { GL_RGBA32UI, "GL_RGBA32UI", true, true, true, true, false, false, true }, |
| { GL_DEPTH_COMPONENT16, "GL_DEPTH_COMPONENT16", false, false, false, false, true, false, false }, |
| { GL_DEPTH_COMPONENT24, "GL_DEPTH_COMPONENT24", false, false, false, false, true, false, false }, |
| { GL_DEPTH_COMPONENT32F, "GL_DEPTH_COMPONENT32F", false, false, false, false, true, false, false }, |
| { GL_DEPTH24_STENCIL8, "GL_DEPTH24_STENCIL8", false, false, false, false, true, true, false }, |
| { GL_DEPTH32F_STENCIL8, "GL_DEPTH32F_STENCIL8", false, false, false, false, true, true, false }, |
| { GL_STENCIL_INDEX8, "GL_STENCIL_INDEX8", false, false, false, false, false, true, false } |
| }; |
| |
| /** Internal formats count */ |
| const glw::GLuint StorageTest::s_renderbuffer_internalformat_configuration_count = |
| sizeof(s_renderbuffer_internalformat_configuration) / sizeof(s_renderbuffer_internalformat_configuration[0]); |
| |
| const glw::GLfloat StorageTest::s_reference_color[4] = { 0.25, 0.5, 0.75, 1.0 }; //!< Reference color. |
| const glw::GLint StorageTest::s_reference_color_integer[4] = { 1, 2, 3, 4 }; //!< Reference integral color. |
| const glw::GLfloat StorageTest::s_reference_depth = 0.5; //!< Reference depth. |
| const glw::GLint StorageTest::s_reference_stencil = 7; //!< Reference stencil. |
| |
| /***************************** Renderbuffer Storage Multisample Test Implementation ***************************/ |
| |
| /** @brief Renderbuffer Storage Multisample Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| StorageMultisampleTest::StorageMultisampleTest(deqp::Context& context) |
| : deqp::TestCase(context, "renderbuffers_storage_multisample", "Renderbuffer Objects Storage Multisample Test") |
| { |
| for (glw::GLuint i = 0; i < 2; ++i) |
| { |
| m_fbo[i] = 0; |
| m_rbo[i] = 0; |
| } |
| } |
| |
| /** @brief Iterate Creation Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult StorageMultisampleTest::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_renderbuffer_size = 16384 /* Specification minimum. */; |
| |
| gl.getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &max_renderbuffer_size); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); |
| |
| const struct |
| { |
| glw::GLuint width; |
| glw::GLuint height; |
| } test_cases[] = { { 1, 1 }, |
| { (glw::GLuint)max_renderbuffer_size / 2, 1 }, |
| { 1, (glw::GLuint)max_renderbuffer_size / 2 } }; |
| |
| const glw::GLuint test_cases_count = sizeof(test_cases) / sizeof(test_cases[0]); |
| |
| for (glw::GLuint i = 0; i < test_cases_count; ++i) |
| { |
| for (glw::GLuint j = 0; j < s_renderbuffer_internalformat_configuration_count; ++j) |
| { |
| glw::GLint max_integer_samples = GetMaxConformantSampleCount( |
| GL_RENDERBUFFER, s_renderbuffer_internalformat_configuration[j].internalformat); |
| for (glw::GLint k = 0; k <= max_integer_samples; ++k) |
| { |
| if (PrepareRenderbuffer(s_renderbuffer_internalformat_configuration[j], test_cases[i].width, |
| test_cases[i].height, k)) |
| { |
| Bind(GL_DRAW_FRAMEBUFFER, 0); |
| Clear(s_renderbuffer_internalformat_configuration[j].isColorIntegralFormat); |
| Bind(GL_READ_FRAMEBUFFER, 0); |
| Bind(GL_DRAW_FRAMEBUFFER, 1); |
| Blit(test_cases[i].width, test_cases[i].height); |
| Bind(GL_READ_FRAMEBUFFER, 1); |
| is_ok &= Check(s_renderbuffer_internalformat_configuration[j], test_cases[i].width, |
| test_cases[i].height); |
| } |
| else |
| { |
| is_ok = false; |
| } |
| |
| Clean(); |
| } |
| } |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| |
| 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; |
| } |
| |
| /** Prepare renderbuffer. |
| * |
| * @param [in] format Internal format to be prepared. |
| * @param [in] width Width of the framebuffer. |
| * @param [in] height Height of the framebuffer. |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool StorageMultisampleTest::PrepareRenderbuffer(StorageMultisampleTest::RenderbufferInternalFormatConfiguration format, |
| glw::GLuint width, glw::GLuint height, glw::GLsizei samples) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| gl.genFramebuffers(2, m_fbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.createRenderbuffers(2, m_rbo); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateRenderbuffers call failed."); |
| |
| for (glw::GLuint i = 0; i < 2; ++i) |
| { |
| gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo[i]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); |
| |
| if (i) |
| { |
| /* 2nd is not multisampled. */ |
| gl.namedRenderbufferStorageMultisample(m_rbo[i], 0, format.internalformat, width, height); |
| |
| if (glw::GLenum error = gl.getError()) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Renderbuffer storage multisample test failed because " |
| "NamedRenderbufferStorageMultisample generated " |
| << glu::getErrorStr(error) << " error value. Renderbuffers format was " |
| << format.internalformat_name << ", samples was " << 0 << ", width was " << width << ", height was " |
| << height << "." << tcu::TestLog::EndMessage; |
| return false; |
| } |
| } |
| else |
| { |
| /* 1st is multisampled. */ |
| gl.namedRenderbufferStorageMultisample(m_rbo[i], samples, format.internalformat, width, height); |
| |
| if (glw::GLenum error = gl.getError()) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Renderbuffer storage multisample test failed because " |
| "NamedRenderbufferStorageMultisample generated " |
| << glu::getErrorStr(error) << " error value. Renderbuffers format was " |
| << format.internalformat_name << ", samples was " << samples << ", width was " << width |
| << ", height was " << height << "." << tcu::TestLog::EndMessage; |
| return false; |
| } |
| } |
| |
| if (format.hasRedComponent || format.hasGreenComponent || format.hasBlueComponent || format.hasAlphaComponent) |
| { |
| gl.namedFramebufferRenderbuffer(m_fbo[i], GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo[i]); |
| } |
| |
| if (format.hasDepthComponent) |
| { |
| gl.namedFramebufferRenderbuffer(m_fbo[i], GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rbo[i]); |
| } |
| |
| if (format.hasStencilComponent) |
| { |
| gl.namedFramebufferRenderbuffer(m_fbo[i], GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo[i]); |
| } |
| |
| glw::GLenum status = gl.checkFramebufferStatus(GL_FRAMEBUFFER); |
| if (status != GL_FRAMEBUFFER_COMPLETE) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Renderbuffer storage multisample test failed due to " |
| << glu::getFramebufferStatusStr(status) << " framebuffer status. Renderbuffers format was " |
| << format.internalformat_name << ", samples was " << (i ? 0 : samples) << ", width was " << width |
| << ", height was " << height << "." << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| /** Bind framebuffer to the target. |
| * |
| * @param [in] target Bind to target. |
| * @param [in] selector Index of the framebuffer in framebuffers' arrays. |
| */ |
| void StorageMultisampleTest::Bind(glw::GLenum target, glw::GLuint selector) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Binding framebuffer. */ |
| gl.bindFramebuffer(target, m_fbo[selector]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); |
| } |
| |
| /** Blit one framebuffer to the second. |
| * |
| * @param [in] width Width of the framebuffer. |
| * @param [in] height Height of the framebuffer. |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| void StorageMultisampleTest::Blit(glw::GLuint width, glw::GLuint height) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Binding framebuffer. */ |
| gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, |
| GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); |
| } |
| |
| /** Clear framebuffer. |
| * |
| * @param [in] isColorIntegralFormat Is framebuffer a color integral type. |
| */ |
| void StorageMultisampleTest::Clear(bool isColorIntegralFormat) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (isColorIntegralFormat) |
| { |
| gl.clearBufferiv(GL_COLOR, 0, s_reference_color_integer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferiv has failed"); |
| } |
| else |
| { |
| /* 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); |
| } |
| } |
| |
| /** Check renderbuffer's content. |
| * |
| * @param [in] format Internal format to be prepared. |
| * @param [in] width Width of the framebuffer. |
| * @param [in] height Height of the framebuffer. |
| * |
| * @return True if content matches the reference, false otherwise. |
| */ |
| bool StorageMultisampleTest::Check(StorageMultisampleTest::RenderbufferInternalFormatConfiguration format, |
| glw::GLuint width, glw::GLuint height) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| glw::GLuint size = width * height; |
| |
| if (format.hasRedComponent || format.hasGreenComponent || format.hasBlueComponent || format.hasAlphaComponent) |
| { |
| if (format.isColorIntegralFormat) |
| { |
| std::vector<glw::GLint> color(size * 4); |
| |
| gl.readPixels(0, 0, width, height, GL_RGBA_INTEGER, GL_INT, &color[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); |
| |
| const bool hasComponent[] = { format.hasRedComponent, format.hasGreenComponent, format.hasBlueComponent, |
| format.hasAlphaComponent }; |
| |
| static const char* componentName[] = { "red", "green", "blue", "alpha" }; |
| |
| for (glw::GLuint i = 0; i < size; ++i) |
| { |
| if (hasComponent[i % 4 /* color components count*/]) |
| { |
| if (de::abs(s_reference_color_integer[i % 4 /* color components count*/] - color[i]) > |
| 2 /* Precision */) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Renderbuffer storage multisample was cleared with color " |
| << componentName[i % 4 /* color components count*/] << " component equal to " |
| << s_reference_color_integer << ", but fetched value " << color[i] |
| << " is not the same. Renderbuffers format was " << format.internalformat_name |
| << ", width was " << width << ", height was " << height << "." << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| } |
| } |
| } |
| else |
| { |
| std::vector<glw::GLfloat> color(size * 4); |
| |
| gl.readPixels(0, 0, width, height, GL_RGBA, GL_FLOAT, &color[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); |
| |
| const bool hasComponent[] = { format.hasRedComponent, format.hasGreenComponent, format.hasBlueComponent, |
| format.hasAlphaComponent }; |
| |
| static const char* componentName[] = { "red", "green", "blue", "alpha" }; |
| |
| for (glw::GLuint i = 0; i < size; ++i) |
| { |
| if (hasComponent[i % 4 /* color components count*/]) |
| { |
| if (de::abs(s_reference_color[i % 4 /* color components count*/] - color[i]) > |
| 0.0625 /* precision */) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Renderbuffer storage multisample was cleared with color " |
| << componentName[i % 4 /* color components count*/] << " component equal to " |
| << s_reference_color[i % 4 /* color components count*/] << ", but fetched value " |
| << color[i] << " is not the same. Renderbuffers format was " << format.internalformat_name |
| << ", width was " << width << ", height was " << height << "." << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| } |
| } |
| } |
| } |
| |
| if (format.hasDepthComponent) |
| { |
| std::vector<glw::GLfloat> depth(size); |
| |
| gl.readPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, &depth[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); |
| |
| for (glw::GLuint i = 0; i < size; ++i) |
| { |
| if (de::abs(s_reference_depth - depth[i]) > 0.0625 /* 1/16 precision */) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "Renderbuffer storage multisample was cleared with depth component equal to " |
| << s_reference_depth << ", but fetched value " << depth[i] |
| << " is not the same. Renderbuffers format was " << format.internalformat_name << ", width was " |
| << width << ", height was " << height << "." << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| } |
| } |
| |
| if (format.hasStencilComponent) |
| { |
| std::vector<glw::GLint> stencil(size); |
| |
| gl.readPixels(0, 0, width, height, GL_STENCIL_INDEX, GL_INT, &stencil[0]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); |
| |
| for (glw::GLuint i = 0; i < size; ++i) |
| { |
| if (s_reference_stencil != stencil[i]) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "Renderbuffer storage multisample was cleared with alpha component equal to " |
| << s_reference_stencil << ", but fetched value " << stencil[i] |
| << " is not the same. Renderbuffers format was " << format.internalformat_name << ", width was " |
| << width << ", height was " << height << "." << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void StorageMultisampleTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release objects. */ |
| for (glw::GLuint i = 0; i < 2; ++i) |
| { |
| if (m_rbo[i]) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo[i]); |
| |
| m_rbo[i] = 0; |
| } |
| |
| if (m_fbo[i]) |
| { |
| gl.deleteFramebuffers(1, &m_fbo[i]); |
| |
| m_fbo[i] = 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()) |
| ; |
| } |
| |
| /** @brief Retrieve max conformant sample count when GL_NV_internalformat_sample_query is supported |
| * |
| * @param [in] target Target indicating usage of internal format |
| * @param [in] internalFormat Internal format about which to retrieve information |
| * |
| * @return Max conformant sample count |
| */ |
| glw::GLint StorageMultisampleTest::GetMaxConformantSampleCount(glw::GLenum target, glw::GLenum internalFormat) |
| { |
| glw::GLint max_conformant_samples = 0; |
| |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return the max conformant sample count if extension is supported */ |
| if (m_context.getContextInfo().isExtensionSupported("GL_NV_internalformat_sample_query")) |
| { |
| glw::GLint gl_sample_counts = 0; |
| gl.getInternalformativ(target, internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &gl_sample_counts); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed for GL_NUM_SAMPLE_COUNTS pname"); |
| |
| /* Check and return the max conformant sample count */ |
| glw::GLint* gl_supported_samples = new glw::GLint[gl_sample_counts]; |
| if (gl_supported_samples) |
| { |
| gl.getInternalformativ(target, internalFormat, GL_SAMPLES, gl_sample_counts, gl_supported_samples); |
| |
| for (glw::GLint i = 0; i < gl_sample_counts; i++) |
| { |
| glw::GLint isConformant = 0; |
| gl.getInternalformatSampleivNV(target, internalFormat, gl_supported_samples[i], GL_CONFORMANT_NV, 1, |
| &isConformant); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformatSampleivNV() call(s) failed"); |
| |
| if (isConformant && gl_supported_samples[i] > max_conformant_samples) |
| { |
| max_conformant_samples = gl_supported_samples[i]; |
| } |
| } |
| delete[] gl_supported_samples; |
| } |
| } |
| else |
| { |
| /* Otherwise return GL_MAX_INTEGER_SAMPLES */ |
| gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &max_conformant_samples); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_INTEGER_SAMPLES pname."); |
| } |
| |
| return max_conformant_samples; |
| } |
| |
| /** Tested internal format */ |
| const struct StorageMultisampleTest::RenderbufferInternalFormatConfiguration |
| StorageMultisampleTest::s_renderbuffer_internalformat_configuration[] = { |
| { GL_R8, "GL_R8", true, false, false, false, false, false, false }, |
| { GL_R16, "GL_R16", true, false, false, false, false, false, false }, |
| { GL_RG8, "GL_RG8", true, true, false, false, false, false, false }, |
| { GL_RG16, "GL_RG16", true, true, false, false, false, false, false }, |
| { GL_RGB565, "GL_RGB56", true, true, true, false, false, false, false }, |
| { GL_RGBA4, "GL_RGBA4", true, true, true, true, false, false, false }, |
| { GL_RGB5_A1, "GL_RGB5_A1", true, true, true, true, false, false, false }, |
| { GL_RGBA8, "GL_RGBA8", true, true, true, true, false, false, false }, |
| { GL_RGB10_A2, "GL_RGB10_A2", true, true, true, true, false, false, false }, |
| { GL_RGB10_A2UI, "GL_RGB10_A2UI", true, true, true, true, false, false, true }, |
| { GL_RGBA16, "GL_RGBA16", true, true, true, true, false, false, false }, |
| { GL_SRGB8_ALPHA8, "GL_SRGB8_ALPHA8", true, true, true, true, false, false, false }, |
| { GL_R16F, "GL_R16F", true, false, false, false, false, false, false }, |
| { GL_RG16F, "GL_RG16F", true, true, false, false, false, false, false }, |
| { GL_RGBA16F, "GL_RGBA16F", true, true, true, true, false, false, false }, |
| { GL_R32F, "GL_R32F", true, false, false, false, false, false, false }, |
| { GL_RG32F, "GL_RG32F", true, true, false, false, false, false, false }, |
| { GL_RGBA32F, "GL_RGBA32F", true, true, true, true, false, false, false }, |
| { GL_R11F_G11F_B10F, "GL_R11F_G11F_B10F", true, true, true, false, false, false, false }, |
| { GL_R8I, "GL_R8I", true, false, false, false, false, false, true }, |
| { GL_R8UI, "GL_R8UI", true, false, false, false, false, false, true }, |
| { GL_R16I, "GL_R16I", true, false, false, false, false, false, true }, |
| { GL_R16UI, "GL_R16UI", true, false, false, false, false, false, true }, |
| { GL_R32I, "GL_R32I", true, false, false, false, false, false, true }, |
| { GL_R32UI, "GL_R32UI", true, false, false, false, false, false, true }, |
| { GL_RG8I, "GL_RG8I", true, true, false, false, false, false, true }, |
| { GL_RG8UI, "GL_RG8UI", true, true, false, false, false, false, true }, |
| { GL_RG16I, "GL_RG16I", true, true, false, false, false, false, true }, |
| { GL_RG16UI, "GL_RG16UI", true, true, false, false, false, false, true }, |
| { GL_RG32I, "GL_RG32I", true, true, false, false, false, false, true }, |
| { GL_RG32UI, "GL_RG32UI", true, true, false, false, false, false, true }, |
| { GL_RGBA8I, "GL_RGBA8I", true, true, true, true, false, false, true }, |
| { GL_RGBA8UI, "GL_RGBA8UI", true, true, true, true, false, false, true }, |
| { GL_RGBA16I, "GL_RGBA16I", true, true, true, true, false, false, true }, |
| { GL_RGBA16UI, "GL_RGBA16UI", true, true, true, true, false, false, true }, |
| { GL_RGBA32I, "GL_RGBA32I", true, true, true, true, false, false, true }, |
| { GL_RGBA32UI, "GL_RGBA32UI", true, true, true, true, false, false, true }, |
| { GL_DEPTH_COMPONENT16, "GL_DEPTH_COMPONENT16", false, false, false, false, true, false, false }, |
| { GL_DEPTH_COMPONENT24, "GL_DEPTH_COMPONENT24", false, false, false, false, true, false, false }, |
| { GL_DEPTH_COMPONENT32F, "GL_DEPTH_COMPONENT32F", false, false, false, false, true, false, false }, |
| { GL_DEPTH24_STENCIL8, "GL_DEPTH24_STENCIL8", false, false, false, false, true, true, false }, |
| { GL_DEPTH32F_STENCIL8, "GL_DEPTH32F_STENCIL8", false, false, false, false, true, true, false }, |
| { GL_STENCIL_INDEX8, "GL_STENCIL_INDEX8", false, false, false, false, false, true, false } |
| }; |
| |
| /** Tesetd internal format count */ |
| const glw::GLuint StorageMultisampleTest::s_renderbuffer_internalformat_configuration_count = |
| sizeof(s_renderbuffer_internalformat_configuration) / sizeof(s_renderbuffer_internalformat_configuration[0]); |
| |
| const glw::GLfloat StorageMultisampleTest::s_reference_color[4] = { 0.25, 0.5, 0.75, 1.0 }; //!< Reference color value. |
| const glw::GLint StorageMultisampleTest::s_reference_color_integer[4] = { |
| 1, 2, 3, 4 |
| }; //!< Reference color value for integral color internal formats. |
| const glw::GLfloat StorageMultisampleTest::s_reference_depth = 0.5; //!< Reference depth value. |
| const glw::GLint StorageMultisampleTest::s_reference_stencil = 7; //!< Reference stencil value. |
| |
| /******************************** Get Named Renderbuffer Parameters Test Implementation ********************************/ |
| |
| /** @brief Get Named Renderbuffer Parameters Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| GetParametersTest::GetParametersTest(deqp::Context& context) |
| : deqp::TestCase(context, "renderbuffers_get_parameters", "Get Named Renderbuffer Parameters Test") |
| , m_fbo(0) |
| , m_rbo(0) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Check Status Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult GetParametersTest::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; |
| |
| /* Test renderbuffer. */ |
| glw::GLuint renderbuffer = 0; |
| |
| /* Test. */ |
| try |
| { |
| static const glw::GLenum internalformats[] = { GL_RGBA8, GL_DEPTH_COMPONENT24, GL_STENCIL_INDEX8, |
| GL_DEPTH24_STENCIL8 }; |
| |
| static const glw::GLuint internalformats_count = sizeof(internalformats) / sizeof(internalformats[0]); |
| |
| for (glw::GLuint i = 0; i < internalformats_count; ++i) |
| { |
| gl.genRenderbuffers(1, &renderbuffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer has failed"); |
| |
| gl.renderbufferStorage(GL_RENDERBUFFER, internalformats[i], 1, 2); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); |
| |
| static const glw::GLenum pnames[] = { GL_RENDERBUFFER_WIDTH, GL_RENDERBUFFER_HEIGHT, |
| GL_RENDERBUFFER_INTERNAL_FORMAT, GL_RENDERBUFFER_SAMPLES, |
| GL_RENDERBUFFER_RED_SIZE, GL_RENDERBUFFER_GREEN_SIZE, |
| GL_RENDERBUFFER_BLUE_SIZE, GL_RENDERBUFFER_ALPHA_SIZE, |
| GL_RENDERBUFFER_DEPTH_SIZE, GL_RENDERBUFFER_STENCIL_SIZE }; |
| |
| static const glw::GLchar* pnames_strings[] = { |
| "GL_RENDERBUFFER_WIDTH", "GL_RENDERBUFFER_HEIGHT", "GL_RENDERBUFFER_INTERNAL_FORMAT", |
| "GL_RENDERBUFFER_SAMPLES", "GL_RENDERBUFFER_RED_SIZE", "GL_RENDERBUFFER_GREEN_SIZE", |
| "GL_RENDERBUFFER_BLUE_SIZE", "GL_RENDERBUFFER_ALPHA_SIZE", "GL_RENDERBUFFER_DEPTH_SIZE", |
| "GL_RENDERBUFFER_STENCIL_SIZE" |
| }; |
| |
| for (glw::GLuint j = 0; j < internalformats_count; ++j) |
| { |
| glw::GLint parameter_legacy = 0; |
| glw::GLint parameter_dsa = 0; |
| |
| gl.getRenderbufferParameteriv(GL_RENDERBUFFER, pnames[j], ¶meter_legacy); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetRenderbufferParameteriv has failed"); |
| |
| gl.getNamedRenderbufferParameteriv(renderbuffer, pnames[j], ¶meter_dsa); |
| |
| if (glw::GLenum error = gl.getError()) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedRenderbufferParameteriv unexpectedly generated " |
| << glu::getErrorStr(error) << " error when called with " << pnames_strings[i] |
| << " parameter name of renderbuffer with internalformat = " |
| << glu::getInternalFormatParameterStr(internalformats[i]) << ", width = 1, height = 2." |
| << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| continue; |
| } |
| |
| if (parameter_legacy != parameter_dsa) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "GetNamedRenderbufferParameteriv returned " << parameter_dsa |
| << ", but " << parameter_legacy << " was expected for " << pnames_strings[i] |
| << " parameter name of renderbuffer with internalformat = " |
| << glu::getInternalFormatParameterStr(internalformats[i]) << ", width = 1, height = 2." |
| << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| } |
| |
| gl.deleteRenderbuffers(1, &renderbuffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteRenderbuffers has failed"); |
| |
| renderbuffer = 0; |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Clean up. */ |
| if (renderbuffer) |
| { |
| gl.deleteRenderbuffers(1, &renderbuffer); |
| } |
| |
| 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; |
| } |
| |
| /******************************** Renderbuffer Creation Errors Test Implementation ********************************/ |
| |
| /** @brief Creation Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| CreationErrorsTest::CreationErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "renderbuffers_creation_errors", "Renderbuffer Objects Creation Errors Test") |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Creation Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult CreationErrorsTest::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; |
| |
| /* Framebuffer object */ |
| glw::GLuint renderbuffer = 0; |
| |
| /* Check direct state creation of negative numbers of framebuffers. */ |
| gl.createRenderbuffers(-1, &renderbuffer); |
| |
| glw::GLenum error = GL_NO_ERROR; |
| |
| if (GL_INVALID_VALUE != (error = gl.getError())) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "CreateRenderbuffers generated " << glu::getErrorStr(error) |
| << " error when called with negative number of renderbuffers, but GL_INVALID_VALUE was expected." |
| << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| |
| /* Cleanup (sanity). */ |
| if (renderbuffer) |
| { |
| gl.deleteRenderbuffers(1, &renderbuffer); |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /******************************** Storage Errors Test Implementation ********************************/ |
| |
| /** @brief Storage Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| StorageErrorsTest::StorageErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "renderbuffers_storage_errors", "Storage Errors Test") |
| , m_rbo_valid(0) |
| , m_rbo_invalid(0) |
| , m_internalformat_invalid(0) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Creation Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult StorageErrorsTest::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 |
| { |
| /* Prepare objects. */ |
| PrepareObjects(); |
| |
| /* Check that INVALID_OPERATION is generated by NamedRenderbufferStorage if |
| renderbuffer is not the name of an existing renderbuffer object. */ |
| gl.namedRenderbufferStorage(m_rbo_invalid, GL_RGBA8, 1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedRenderbufferStorage", |
| "renderbuffer is not the name of an existing renderbuffer object."); |
| |
| /* Check that INVALID_VALUE is generated by NamedRenderbufferStorage if |
| either of width or height is negative, or greater than the value of |
| MAX_RENDERBUFFER_SIZE. */ |
| gl.namedRenderbufferStorage(m_rbo_valid, GL_RGBA8, -1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "NamedRenderbufferStorage", "either of width is negative."); |
| |
| gl.namedRenderbufferStorage(m_rbo_valid, GL_RGBA8, 1, -1); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "NamedRenderbufferStorage", "either of height is negative."); |
| |
| /* Check that INVALID_ENUM is generated by NamedRenderbufferStorage if |
| internalformat is not a color-renderable, depth-renderable, or |
| stencil-renderable format. */ |
| gl.namedRenderbufferStorage(m_rbo_valid, m_internalformat_invalid, 1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedRenderbufferStorage", "internalformat is not a color-renderable, " |
| "depth-renderable, or stencil-renderable " |
| "format (it is COMPRESSED_RED)."); |
| } |
| 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; |
| } |
| |
| /** Check Prepare test's GL objects. |
| */ |
| void StorageErrorsTest::PrepareObjects() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Valid objects. */ |
| gl.genRenderbuffers(1, &m_rbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| /* Invalid objects. */ |
| while (gl.isRenderbuffer(++m_rbo_invalid)) |
| ; |
| } |
| |
| /** Check if error is equal to the expected, log if not. |
| * |
| * @param [in] expected_error Error to be expected. |
| * @param [in] function Function name which is being tested (to be logged). |
| * @param [in] conditions Conditions when the expected error shall occure (to be logged). |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool StorageErrorsTest::ExpectError(glw::GLenum expected_error, const glw::GLchar* function, |
| const glw::GLchar* conditions) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| bool is_ok = true; |
| |
| glw::GLenum error = GL_NO_ERROR; |
| |
| if (expected_error != (error = gl.getError())) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << function << " was expected to generate " |
| << glu::getErrorStr(expected_error) << ", but " << glu::getErrorStr(error) |
| << " was observed instead when " << conditions << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| |
| /* Clean additional possible errors. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void StorageErrorsTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release GL objects. */ |
| if (m_rbo_valid) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_valid); |
| m_rbo_valid = 0; |
| } |
| |
| /* COmpressed internal formats are not color renderable (OpenGL 4.5 Core PRofile SPecification Chapter 9.4 )*/ |
| m_internalformat_invalid = GL_COMPRESSED_RED; |
| |
| /* Set initial values - all test shall have the same environment. */ |
| m_rbo_valid = 0; |
| m_rbo_invalid = 0; |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| /******************************** Storage Multisample Errors Test Implementation ********************************/ |
| |
| /** @brief Storage Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| StorageMultisampleErrorsTest::StorageMultisampleErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "renderbuffers_storage_multisample_errors", "Storage Multisample Errors Test") |
| , m_rbo_valid(0) |
| , m_rbo_invalid(0) |
| , m_internalformat_invalid(0) |
| , m_max_samples(0) |
| , m_max_integer_samples(0) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Creation Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult StorageMultisampleErrorsTest::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 |
| { |
| /* Prepare objects. */ |
| PrepareObjects(); |
| |
| /* Check that INVALID_OPERATION is generated by NamedRenderbufferStorage if |
| renderbuffer is not the name of an existing renderbuffer object. */ |
| gl.namedRenderbufferStorageMultisample(m_rbo_invalid, 1, GL_RGBA8, 1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedRenderbufferStorageMultisample", |
| "renderbuffer is not the name of an existing renderbuffer object."); |
| |
| /* Check that INVALID_VALUE is generated by |
| NamedRenderbufferStorageMultisample if samples is greater than |
| the maximum number of SAMPLES reported for GL_RGBA8. */ |
| gl.namedRenderbufferStorageMultisample(m_rbo_valid, m_max_samples + 1, GL_RGBA8, 1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedRenderbufferStorageMultisample", |
| "samples is greater than MAX_SAMPLES."); |
| |
| /* Check that INVALID_VALUE is generated by NamedRenderbufferStorage if |
| either of width or height is negative, or greater than the value of |
| MAX_RENDERBUFFER_SIZE. */ |
| gl.namedRenderbufferStorageMultisample(m_rbo_valid, 1, GL_RGBA8, -1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "NamedRenderbufferStorageMultisample", "either of width is negative."); |
| |
| gl.namedRenderbufferStorageMultisample(m_rbo_valid, 1, GL_RGBA8, 1, -1); |
| |
| is_ok &= ExpectError(GL_INVALID_VALUE, "NamedRenderbufferStorageMultisample", "either of height is negative."); |
| |
| /* Check that INVALID_OPERATION is generated by |
| NamedRenderbufferStorageMultisample if internalformat is a signed or |
| unsigned integer format and samples is greater than the maximum number |
| of samples reported for GL_RGB10_A2UI */ |
| gl.namedRenderbufferStorageMultisample(m_rbo_valid, m_max_integer_samples + 1, GL_RGB10_A2UI, 1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "NamedRenderbufferStorageMultisample", |
| "internalformat is a signed or unsigned integer format and samples is greater than the " |
| "value of MAX_INTEGER_SAMPLES."); |
| |
| /* Check that INVALID_ENUM is generated by NamedRenderbufferStorage if |
| internalformat is not a color-renderable, depth-renderable, or |
| stencil-renderable format. */ |
| gl.namedRenderbufferStorageMultisample(m_rbo_valid, 1, m_internalformat_invalid, 1, 1); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "NamedRenderbufferStorageMultisample", |
| "internalformat is not a color-renderable, depth-renderable, or stencil-renderable format " |
| "(it is COMPRESSED_RED)."); |
| } |
| 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; |
| } |
| |
| /** Check Prepare test's GL objects. |
| */ |
| void StorageMultisampleErrorsTest::PrepareObjects() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Valid objects. */ |
| gl.genRenderbuffers(1, &m_rbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| /* Limits. */ |
| gl.getInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, 1, &m_max_samples); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ has failed"); |
| |
| gl.getInternalformativ(GL_RENDERBUFFER, GL_RGB10_A2UI, GL_SAMPLES, 1, &m_max_integer_samples); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ has failed"); |
| |
| /* Invalid objects. */ |
| while (gl.isRenderbuffer(++m_rbo_invalid)) |
| ; |
| } |
| |
| /** Check if error is equal to the expected, log if not. |
| * |
| * @param [in] expected_error Error to be expected. |
| * @param [in] function Function name which is being tested (to be logged). |
| * @param [in] conditions Conditions when the expected error shall occure (to be logged). |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool StorageMultisampleErrorsTest::ExpectError(glw::GLenum expected_error, const glw::GLchar* function, |
| const glw::GLchar* conditions) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| bool is_ok = true; |
| |
| glw::GLenum error = GL_NO_ERROR; |
| |
| if (expected_error != (error = gl.getError())) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << function << " was expected to generate " |
| << glu::getErrorStr(expected_error) << ", but " << glu::getErrorStr(error) |
| << " was observed instead when " << conditions << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| |
| /* Clean additional possible errors. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void StorageMultisampleErrorsTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release GL objects. */ |
| if (m_rbo_valid) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_valid); |
| m_rbo_valid = 0; |
| } |
| |
| /* COmpressed internal formats are not color renderable (OpenGL 4.5 Core PRofile SPecification Chapter 9.4 )*/ |
| m_internalformat_invalid = GL_COMPRESSED_RED; |
| |
| /* Set initial values - all test shall have the same environment. */ |
| m_rbo_valid = 0; |
| m_rbo_invalid = 0; |
| m_max_samples = 0; |
| m_max_integer_samples = 0; |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| /******************************** Get Parameter Errors Test Implementation ********************************/ |
| |
| /** @brief Parameter Errors Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| GetParameterErrorsTest::GetParameterErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "renderbuffers_get_parameters_errors", "Get Parameter Errors Test") |
| , m_rbo_valid(0) |
| , m_rbo_invalid(0) |
| , m_parameter_invalid(0) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Parameter Errors Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult GetParameterErrorsTest::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 |
| { |
| /* Prepare objects. */ |
| PrepareObjects(); |
| |
| glw::GLint return_value_dummy_storage; |
| |
| /* Check that INVALID_OPERATION is generated by |
| GetNamedRenderbufferParameteriv if renderbuffer is not the name of an |
| existing renderbuffer object. */ |
| gl.getNamedRenderbufferParameteriv(m_rbo_invalid, GL_RENDERBUFFER_WIDTH, &return_value_dummy_storage); |
| |
| is_ok &= ExpectError(GL_INVALID_OPERATION, "GetNamedRenderbufferParameteriv", |
| "renderbuffer is not the name of an existing renderbuffer object."); |
| |
| /* Check that INVALID_ENUM is generated by GetNamedRenderbufferParameteriv |
| if parameter name is not one of the accepted parameter names described |
| in specification. */ |
| gl.getNamedRenderbufferParameteriv(m_rbo_valid, m_parameter_invalid, &return_value_dummy_storage); |
| |
| is_ok &= ExpectError(GL_INVALID_ENUM, "GetNamedRenderbufferParameteriv", |
| "parameter name is not one of the accepted parameter names described in specification."); |
| } |
| 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; |
| } |
| |
| /** Check Prepare test's GL objects. |
| */ |
| void GetParameterErrorsTest::PrepareObjects() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Valid objects. */ |
| gl.genRenderbuffers(1, &m_rbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); |
| |
| gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_valid); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); |
| |
| /* Invalid parameter. */ |
| bool is_parameter = true; |
| |
| while (is_parameter) |
| { |
| is_parameter = false; |
| |
| ++m_parameter_invalid; |
| |
| static const glw::GLenum valid_parameters[] = { GL_RENDERBUFFER_WIDTH, GL_RENDERBUFFER_HEIGHT, |
| GL_RENDERBUFFER_INTERNAL_FORMAT, GL_RENDERBUFFER_SAMPLES, |
| GL_RENDERBUFFER_RED_SIZE, GL_RENDERBUFFER_GREEN_SIZE, |
| GL_RENDERBUFFER_BLUE_SIZE, GL_RENDERBUFFER_ALPHA_SIZE, |
| GL_RENDERBUFFER_DEPTH_SIZE, GL_RENDERBUFFER_STENCIL_SIZE }; |
| |
| static const glw::GLuint valid_parameters_count = sizeof(valid_parameters) / sizeof(valid_parameters[0]); |
| |
| for (glw::GLuint i = 0; i < valid_parameters_count; ++i) |
| { |
| if (valid_parameters[i] == m_parameter_invalid) |
| { |
| is_parameter = true; |
| } |
| } |
| } |
| |
| /* Invalid objects. */ |
| while (gl.isRenderbuffer(++m_rbo_invalid)) |
| ; |
| } |
| |
| /** Check if error is equal to the expected, log if not. |
| * |
| * @param [in] expected_error Error to be expected. |
| * @param [in] function Function name which is being tested (to be logged). |
| * @param [in] conditions Conditions when the expected error shall occure (to be logged). |
| * |
| * @return True if there is no error, false otherwise. |
| */ |
| bool GetParameterErrorsTest::ExpectError(glw::GLenum expected_error, const glw::GLchar* function, |
| const glw::GLchar* conditions) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| bool is_ok = true; |
| |
| glw::GLenum error = GL_NO_ERROR; |
| |
| if (expected_error != (error = gl.getError())) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << function << " was expected to generate " |
| << glu::getErrorStr(expected_error) << ", but " << glu::getErrorStr(error) |
| << " was observed instead when " << conditions << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| } |
| |
| /* Clean additional possible errors. */ |
| while (gl.getError()) |
| ; |
| |
| return is_ok; |
| } |
| |
| /** @brief Clean up GL state. |
| */ |
| void GetParameterErrorsTest::Clean() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release GL objects. */ |
| if (m_rbo_valid) |
| { |
| gl.deleteRenderbuffers(1, &m_rbo_valid); |
| m_rbo_valid = 0; |
| } |
| |
| /* Set initial values - all test shall have the same environment. */ |
| m_rbo_valid = 0; |
| m_rbo_invalid = 0; |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| } // namespace Renderbuffers |
| } // namespace DirectStateAccess |
| } // namespace gl4cts |