text: /*-------------------------------------------------------------------------
   * 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], &parameter_legacy);
  		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFramebufferParameteriv has failed");
  
  		gl.getNamedFramebufferParameteriv(0, pnames[i], &parameter_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], &parameter_legacy);
  		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFramebufferParameteriv has failed");
  
  		gl.getNamedFramebufferParameteriv(m_fbo, pnames[i], &parameter_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,
  											   &parameter_legacy);
  		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFramebufferParameteriv has failed");
  
  		gl.getNamedFramebufferAttachmentParameteriv(0, attachments[j], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
  													&parameter_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,
  											   &parameter_legacy);
  		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFramebufferParameteriv has failed");
  
  		gl.getNamedFramebufferAttachmentParameteriv(m_fbo, attachments[j], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
  													&parameter_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,
  											   &parameter_legacy);
  		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFramebufferParameteriv has failed");
  
  		gl.getNamedFramebufferAttachmentParameteriv(m_fbo, attachments[j], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
  													&parameter_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_unused_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_unused_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_unused_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_unused_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_unused_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_unused_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_unused_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_unused_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_unused_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_unused_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_unused_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_unused_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_unused_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], &parameter_legacy);
  				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetRenderbufferParameteriv has failed");
  
  				gl.getNamedRenderbufferParameteriv(renderbuffer, pnames[j], &parameter_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_unused_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_unused_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_unused_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
  