/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.0 Module
 * -------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * 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 FBO invalidate tests.
 *//*--------------------------------------------------------------------*/

#include "es3fFboInvalidateTests.hpp"
#include "es3fFboTestCase.hpp"
#include "es3fFboTestUtil.hpp"
#include "gluTextureUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuTextureUtil.hpp"
#include "sglrContextUtil.hpp"

#include "glwEnums.hpp"

#include <algorithm>

namespace deqp
{
namespace gles3
{
namespace Functional
{

using std::string;
using std::vector;
using tcu::Vec2;
using tcu::Vec3;
using tcu::Vec4;
using tcu::IVec2;
using tcu::IVec3;
using tcu::IVec4;
using tcu::UVec4;
using namespace FboTestUtil;

static std::vector<deUint32> getDefaultFBDiscardAttachments (deUint32 discardBufferBits)
{
	vector<deUint32> attachments;

	if (discardBufferBits & GL_COLOR_BUFFER_BIT)
		attachments.push_back(GL_COLOR);

	if (discardBufferBits & GL_DEPTH_BUFFER_BIT)
		attachments.push_back(GL_DEPTH);

	if (discardBufferBits & GL_STENCIL_BUFFER_BIT)
		attachments.push_back(GL_STENCIL);

	return attachments;
}

static std::vector<deUint32> getFBODiscardAttachments (deUint32 discardBufferBits)
{
	vector<deUint32> attachments;

	if (discardBufferBits & GL_COLOR_BUFFER_BIT)
		attachments.push_back(GL_COLOR_ATTACHMENT0);

	// \note DEPTH_STENCIL_ATTACHMENT is allowed when discarding FBO, but not with default FB
	if ((discardBufferBits & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) == (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT))
		attachments.push_back(GL_DEPTH_STENCIL_ATTACHMENT);
	else if (discardBufferBits & GL_DEPTH_BUFFER_BIT)
		attachments.push_back(GL_DEPTH_ATTACHMENT);
	else if (discardBufferBits & GL_STENCIL_BUFFER_BIT)
		attachments.push_back(GL_STENCIL_ATTACHMENT);

	return attachments;
}

static inline bool hasAttachment (const std::vector<deUint32>& attachmentList, deUint32 attachment)
{
	return std::find(attachmentList.begin(), attachmentList.end(), attachment) != attachmentList.end();
}

static deUint32 getCompatibleColorFormat (const tcu::RenderTarget& renderTargetInfo)
{
	const tcu::PixelFormat& pxFmt = renderTargetInfo.getPixelFormat();
	DE_ASSERT(de::inBounds(pxFmt.redBits,	0, 0xff) &&
			  de::inBounds(pxFmt.greenBits,	0, 0xff) &&
			  de::inBounds(pxFmt.blueBits,	0, 0xff) &&
			  de::inBounds(pxFmt.alphaBits,	0, 0xff));

#define PACK_FMT(R, G, B, A) (((R) << 24) | ((G) << 16) | ((B) << 8) | (A))

	// \note [pyry] This may not hold true on some implementations - best effort guess only.
	switch (PACK_FMT(pxFmt.redBits, pxFmt.greenBits, pxFmt.blueBits, pxFmt.alphaBits))
	{
		case PACK_FMT(8,8,8,8):		return GL_RGBA8;
		case PACK_FMT(8,8,8,0):		return GL_RGB8;
		case PACK_FMT(4,4,4,4):		return GL_RGBA4;
		case PACK_FMT(5,5,5,1):		return GL_RGB5_A1;
		case PACK_FMT(5,6,5,0):		return GL_RGB565;
		default:					return GL_NONE;
	}

#undef PACK_FMT
}

static deUint32 getCompatibleDepthStencilFormat (const tcu::RenderTarget& renderTargetInfo)
{
	const int	depthBits		= renderTargetInfo.getDepthBits();
	const int	stencilBits		= renderTargetInfo.getStencilBits();
	const bool	hasDepth		= depthBits > 0;
	const bool	hasStencil		= stencilBits > 0;

	if (!hasDepth || !hasStencil || (stencilBits != 8))
		return GL_NONE;

	if (depthBits == 32)
		return GL_DEPTH32F_STENCIL8;
	else if (depthBits == 24)
		return GL_DEPTH24_STENCIL8;
	else
		return GL_NONE;
}

class InvalidateDefaultFramebufferRenderCase : public FboTestCase
{
public:
	InvalidateDefaultFramebufferRenderCase (Context& context, const char* name, const char* description, deUint32 buffers, deUint32 fboTarget = GL_FRAMEBUFFER)
		: FboTestCase	(context, name, description)
		, m_buffers		(buffers)
		, m_fboTarget	(fboTarget)
	{
	}

	void render (tcu::Surface& dst)
	{
		FlatColorShader		flatShader	(glu::TYPE_FLOAT_VEC4);
		vector<deUint32>	attachments	= getDefaultFBDiscardAttachments(m_buffers);
		deUint32			flatShaderID= getCurrentContext()->createProgram(&flatShader);

		glClearColor	(0.0f, 0.0f, 0.0f, 1.0f);
		glClear			(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		glEnable		(GL_DEPTH_TEST);
		glEnable		(GL_STENCIL_TEST);
		glStencilOp		(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc	(GL_ALWAYS, 1, 0xff);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));

		glInvalidateFramebuffer(m_fboTarget, (int)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0]);

		if ((m_buffers & GL_COLOR_BUFFER_BIT) != 0)
		{
			// Color was not preserved - fill with green.
			glDisable(GL_DEPTH_TEST);
			glDisable(GL_STENCIL_TEST);

			flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
			sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

			glEnable(GL_DEPTH_TEST);
			glEnable(GL_STENCIL_TEST);
		}

		if ((m_buffers & GL_DEPTH_BUFFER_BIT) != 0)
		{
			// Depth was not preserved.
			glDepthFunc(GL_ALWAYS);
		}

		if ((m_buffers & GL_STENCIL_BUFFER_BIT) == 0)
		{
			// Stencil was preserved.
			glStencilFunc(GL_EQUAL, 1, 0xff);
		}

		glEnable		(GL_BLEND);
		glBlendFunc		(GL_ONE, GL_ONE);
		glBlendEquation	(GL_FUNC_ADD);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		readPixels(dst, 0, 0, getWidth(), getHeight());
	}

private:
	deUint32 m_buffers;
	deUint32 m_fboTarget;
};

class InvalidateDefaultFramebufferBindCase : public FboTestCase
{
public:
	InvalidateDefaultFramebufferBindCase (Context& context, const char* name, const char* description, deUint32 buffers)
		: FboTestCase	(context, name, description)
		, m_buffers		(buffers)
	{
	}

	void render (tcu::Surface& dst)
	{
		deUint32			fbo			= 0;
		deUint32			tex			= 0;
		FlatColorShader		flatShader	(glu::TYPE_FLOAT_VEC4);
		Texture2DShader		texShader	(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
		GradientShader		gradShader	(glu::TYPE_FLOAT_VEC4);
		vector<deUint32>	attachments	= getDefaultFBDiscardAttachments(m_buffers);
		deUint32			flatShaderID= getCurrentContext()->createProgram(&flatShader);
		deUint32			texShaderID = getCurrentContext()->createProgram(&texShader);
		deUint32			gradShaderID= getCurrentContext()->createProgram(&gradShader);

		glClearColor	(0.0f, 0.0f, 0.0f, 1.0f);
		glClear			(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		// Create fbo.
		glGenFramebuffers		(1, &fbo);
		glGenTextures			(1, &tex);
		glBindTexture			(GL_TEXTURE_2D, tex);
		glTexImage2D			(GL_TEXTURE_2D, 0, GL_RGBA8, getWidth(), getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
		glTexParameteri			(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glBindFramebuffer		(GL_FRAMEBUFFER, fbo);
		glFramebufferTexture2D	(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
		glBindTexture			(GL_TEXTURE_2D, 0);
		checkFramebufferStatus	(GL_FRAMEBUFFER);

		glBindFramebuffer		(GL_FRAMEBUFFER, 0);

		glEnable		(GL_DEPTH_TEST);
		glEnable		(GL_STENCIL_TEST);
		glStencilOp		(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc	(GL_ALWAYS, 1, 0xff);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));

		glInvalidateFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0]);

		// Switch to fbo and render gradient into it.
		glDisable			(GL_DEPTH_TEST);
		glDisable			(GL_STENCIL_TEST);
		glBindFramebuffer	(GL_FRAMEBUFFER, fbo);

		gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));
		sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		// Restore default fbo.
		glBindFramebuffer	(GL_FRAMEBUFFER, 0);

		if ((m_buffers & GL_COLOR_BUFFER_BIT) != 0)
		{
			// Color was not preserved - fill with green.
			flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
			sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		}

		if ((m_buffers & GL_DEPTH_BUFFER_BIT) != 0)
		{
			// Depth was not preserved.
			glDepthFunc(GL_ALWAYS);
		}

		if ((m_buffers & GL_STENCIL_BUFFER_BIT) == 0)
		{
			// Stencil was preserved.
			glStencilFunc(GL_EQUAL, 1, 0xff);
		}

		glEnable		(GL_DEPTH_TEST);
		glEnable		(GL_STENCIL_TEST);
		glEnable		(GL_BLEND);
		glBlendFunc		(GL_ONE, GL_ONE);
		glBlendEquation	(GL_FUNC_ADD);
		glBindTexture	(GL_TEXTURE_2D, tex);

		texShader.setUniforms(*getCurrentContext(), texShaderID);
		sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		readPixels(dst, 0, 0, getWidth(), getHeight());
	}

private:
	deUint32 m_buffers;
};

class InvalidateDefaultSubFramebufferRenderCase : public FboTestCase
{
public:
	InvalidateDefaultSubFramebufferRenderCase (Context& context, const char* name, const char* description, deUint32 buffers)
		: FboTestCase	(context, name, description)
		, m_buffers		(buffers)
	{
	}

	void render (tcu::Surface& dst)
	{
		int					invalidateX		= getWidth()	/ 4;
		int					invalidateY		= getHeight()	/ 4;
		int					invalidateW		= getWidth()	/ 2;
		int					invalidateH		= getHeight()	/ 2;
		FlatColorShader		flatShader		(glu::TYPE_FLOAT_VEC4);
		vector<deUint32>	attachments		= getDefaultFBDiscardAttachments(m_buffers);
		deUint32			flatShaderID	= getCurrentContext()->createProgram(&flatShader);

		glClearColor	(0.0f, 0.0f, 0.0f, 1.0f);
		glClear			(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		glEnable		(GL_DEPTH_TEST);
		glEnable		(GL_STENCIL_TEST);
		glStencilOp		(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc	(GL_ALWAYS, 1, 0xff);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));

		glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0], invalidateX, invalidateY, invalidateW, invalidateH);

		// Clear invalidated buffers.
		glClearColor	(0.0f, 1.0f, 0.0f, 1.0f);
		glClearStencil	(1);
		glScissor		(invalidateX, invalidateY, invalidateW, invalidateH);
		glEnable		(GL_SCISSOR_TEST);
		glClear			(m_buffers);
		glDisable		(GL_SCISSOR_TEST);

		glEnable		(GL_BLEND);
		glBlendFunc		(GL_ONE, GL_ONE);
		glBlendEquation	(GL_FUNC_ADD);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		readPixels(dst, 0, 0, getWidth(), getHeight());
	}

private:
	deUint32 m_buffers;
};

class InvalidateDefaultSubFramebufferBindCase : public FboTestCase
{
public:
	InvalidateDefaultSubFramebufferBindCase (Context& context, const char* name, const char* description, deUint32 buffers)
		: FboTestCase	(context, name, description)
		, m_buffers		(buffers)
	{
	}

	void render (tcu::Surface& dst)
	{
		deUint32			fbo				= 0;
		deUint32			tex				= 0;
		FlatColorShader		flatShader		(glu::TYPE_FLOAT_VEC4);
		Texture2DShader		texShader		(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
		GradientShader		gradShader		(glu::TYPE_FLOAT_VEC4);
		vector<deUint32>	attachments		= getDefaultFBDiscardAttachments(m_buffers);
		deUint32			flatShaderID	= getCurrentContext()->createProgram(&flatShader);
		deUint32			texShaderID		= getCurrentContext()->createProgram(&texShader);
		deUint32			gradShaderID	= getCurrentContext()->createProgram(&gradShader);

		int				invalidateX		= getWidth()	/ 4;
		int				invalidateY		= getHeight()	/ 4;
		int				invalidateW		= getWidth()	/ 2;
		int				invalidateH		= getHeight()	/ 2;


		flatShader.setColor   (*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
		texShader.setUniforms (*getCurrentContext(), texShaderID);
		gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));

		glClearColor	(0.0f, 0.0f, 0.0f, 1.0f);
		glClear			(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		// Create fbo.
		glGenFramebuffers		(1, &fbo);
		glGenTextures			(1, &tex);
		glBindTexture			(GL_TEXTURE_2D, tex);
		glTexImage2D			(GL_TEXTURE_2D, 0, GL_RGBA8, getWidth(), getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
		glTexParameteri			(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glBindFramebuffer		(GL_FRAMEBUFFER, fbo);
		glFramebufferTexture2D	(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
		glBindTexture			(GL_TEXTURE_2D, 0);
		checkFramebufferStatus	(GL_FRAMEBUFFER);

		glBindFramebuffer		(GL_FRAMEBUFFER, 0);

		glEnable		(GL_DEPTH_TEST);
		glEnable		(GL_STENCIL_TEST);
		glStencilOp		(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc	(GL_ALWAYS, 1, 0xff);

		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));

		glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0], invalidateX, invalidateY, invalidateW, invalidateH);

		// Switch to fbo and render gradient into it.
		glDisable			(GL_DEPTH_TEST);
		glDisable			(GL_STENCIL_TEST);
		glBindFramebuffer	(GL_FRAMEBUFFER, fbo);

		sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		// Restore default fbo.
		glBindFramebuffer	(GL_FRAMEBUFFER, 0);

		// Clear invalidated buffers.
		glClearColor	(0.0f, 1.0f, 0.0f, 1.0f);
		glClearStencil	(1);
		glScissor		(invalidateX, invalidateY, invalidateW, invalidateH);
		glEnable		(GL_SCISSOR_TEST);
		glClear			(m_buffers);
		glDisable		(GL_SCISSOR_TEST);

		glEnable		(GL_DEPTH_TEST);
		glEnable		(GL_STENCIL_TEST);
		glEnable		(GL_BLEND);
		glBlendFunc		(GL_ONE, GL_ONE);
		glBlendEquation	(GL_FUNC_ADD);
		glBindTexture	(GL_TEXTURE_2D, tex);

		sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		readPixels(dst, 0, 0, getWidth(), getHeight());
	}

private:
	deUint32 m_buffers;
};

class InvalidateFboRenderCase : public FboTestCase
{
public:
	InvalidateFboRenderCase (Context& context, const char* name, const char* description, deUint32 colorFmt, deUint32 depthStencilFmt, deUint32 invalidateBuffers)
		: FboTestCase			(context, name, description)
		, m_colorFmt			(colorFmt)
		, m_depthStencilFmt		(depthStencilFmt)
		, m_invalidateBuffers	(invalidateBuffers)
	{
	}

protected:
	void preCheck (void)
	{
		if (m_colorFmt != GL_NONE)			checkFormatSupport(m_colorFmt);
		if (m_depthStencilFmt != GL_NONE)	checkFormatSupport(m_depthStencilFmt);
	}

	void render (tcu::Surface& dst)
	{
		tcu::TextureFormat		colorFmt				= glu::mapGLInternalFormat(m_colorFmt);
		tcu::TextureFormat		depthStencilFmt			= m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat();
		tcu::TextureFormatInfo	colorFmtInfo			= tcu::getTextureFormatInfo(colorFmt);
		bool					depth					= depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS;
		bool					stencil					= depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS;
		const tcu::Vec4&		cBias					= colorFmtInfo.valueMin;
		tcu::Vec4				cScale					= colorFmtInfo.valueMax-colorFmtInfo.valueMin;
		deUint32				fbo						= 0;
		deUint32				colorRbo				= 0;
		deUint32				depthStencilRbo			= 0;
		FlatColorShader			flatShader				(glu::TYPE_FLOAT_VEC4);
		vector<deUint32>		attachments				= getFBODiscardAttachments(m_invalidateBuffers);
		deUint32				flatShaderID			= getCurrentContext()->createProgram(&flatShader);

		// Create fbo.
		glGenRenderbuffers		(1, &colorRbo);
		glBindRenderbuffer		(GL_RENDERBUFFER, colorRbo);
		glRenderbufferStorage	(GL_RENDERBUFFER, m_colorFmt, getWidth(), getHeight());

		if (m_depthStencilFmt != GL_NONE)
		{
			glGenRenderbuffers		(1, &depthStencilRbo);
			glBindRenderbuffer		(GL_RENDERBUFFER, depthStencilRbo);
			glRenderbufferStorage	(GL_RENDERBUFFER, m_depthStencilFmt, getWidth(), getHeight());
		}

		glGenFramebuffers			(1, &fbo);
		glBindFramebuffer			(GL_FRAMEBUFFER, fbo);
		glFramebufferRenderbuffer	(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);

		if (depth)
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);

		if (stencil)
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);

		checkFramebufferStatus		(GL_FRAMEBUFFER);

		glClearColor	(0.0f, 0.0f, 0.0f, 1.0f);
		glClear			(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		glEnable		(GL_DEPTH_TEST);
		glEnable		(GL_STENCIL_TEST);
		glStencilOp		(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc	(GL_ALWAYS, 1, 0xff);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias);
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));

		glInvalidateFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0]);

		if ((m_invalidateBuffers & GL_COLOR_BUFFER_BIT) != 0)
		{
			// Color was not preserved - fill with green.
			glDisable(GL_DEPTH_TEST);
			glDisable(GL_STENCIL_TEST);

			flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias);
			sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

			glEnable(GL_DEPTH_TEST);
			glEnable(GL_STENCIL_TEST);
		}

		if ((m_invalidateBuffers & GL_DEPTH_BUFFER_BIT) != 0)
		{
			// Depth was not preserved.
			glDepthFunc(GL_ALWAYS);
		}

		if ((m_invalidateBuffers & GL_STENCIL_BUFFER_BIT) == 0)
		{
			// Stencil was preserved.
			glStencilFunc(GL_EQUAL, 1, 0xff);
		}

		glEnable		(GL_BLEND);
		glBlendFunc		(GL_ONE, GL_ONE);
		glBlendEquation	(GL_FUNC_ADD);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)*cScale + cBias);
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		readPixels(dst, 0, 0, getWidth(), getHeight(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
	}

private:
	deUint32	m_colorFmt;
	deUint32	m_depthStencilFmt;
	deUint32	m_invalidateBuffers;
};

class InvalidateFboUnbindReadCase : public FboTestCase
{
public:
	InvalidateFboUnbindReadCase (Context& context, const char* name, const char* description, deUint32 colorFmt, deUint32 depthStencilFmt, deUint32 invalidateBuffers)
		: FboTestCase			(context, name, description)
		, m_colorFmt			(colorFmt)
		, m_depthStencilFmt		(depthStencilFmt)
		, m_invalidateBuffers	(invalidateBuffers)
	{
		DE_ASSERT((m_invalidateBuffers & (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)) != (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT));
	}

protected:
	void preCheck (void)
	{
		if (m_colorFmt != GL_NONE)			checkFormatSupport(m_colorFmt);
		if (m_depthStencilFmt != GL_NONE)	checkFormatSupport(m_depthStencilFmt);
	}

	void render (tcu::Surface& dst)
	{
		tcu::TextureFormat		colorFmt				= glu::mapGLInternalFormat(m_colorFmt);
		tcu::TextureFormat		depthStencilFmt			= m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat();
		tcu::TextureFormatInfo	colorFmtInfo			= tcu::getTextureFormatInfo(colorFmt);
		bool					depth					= depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS;
		bool					stencil					= depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS;
		deUint32				fbo						= 0;
		deUint32				colorTex				= 0;
		deUint32				depthStencilTex			= 0;
		GradientShader			gradShader				(getFragmentOutputType(colorFmt));
		vector<deUint32>		attachments				= getFBODiscardAttachments(m_invalidateBuffers);
		deUint32				gradShaderID			= getCurrentContext()->createProgram(&gradShader);

		// Create fbo.
		{
			glu::TransferFormat transferFmt = glu::getTransferFormat(colorFmt);

			glGenTextures	(1, &colorTex);
			glBindTexture	(GL_TEXTURE_2D, colorTex);
			glTexImage2D	(GL_TEXTURE_2D, 0, m_colorFmt, getWidth(), getHeight(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
			glTexParameteri	(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		}

		if (m_depthStencilFmt != GL_NONE)
		{
			glu::TransferFormat transferFmt = glu::getTransferFormat(depthStencilFmt);

			glGenTextures	(1, &depthStencilTex);
			glBindTexture	(GL_TEXTURE_2D, depthStencilTex);
			glTexImage2D	(GL_TEXTURE_2D, 0, m_depthStencilFmt, getWidth(), getHeight(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
			glTexParameteri	(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			glTexParameteri	(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		}

		glGenFramebuffers		(1, &fbo);
		glBindFramebuffer		(GL_FRAMEBUFFER, fbo);
		glFramebufferTexture2D	(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);

		if (depth)
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthStencilTex, 0);

		if (stencil)
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthStencilTex, 0);

		checkFramebufferStatus		(GL_FRAMEBUFFER);

		glClearColor	(0.0f, 0.0f, 0.0f, 1.0f);
		glClear			(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		glEnable		(GL_DEPTH_TEST);
		glEnable		(GL_STENCIL_TEST);
		glStencilOp		(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc	(GL_ALWAYS, 1, 0xff);

		gradShader.setGradient(*getCurrentContext(), gradShaderID, colorFmtInfo.valueMin, colorFmtInfo.valueMax);
		sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));

		glInvalidateFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0]);

		glBindFramebuffer	(GL_FRAMEBUFFER, 0);
		glDisable			(GL_DEPTH_TEST);
		glDisable			(GL_STENCIL_TEST);

		if ((m_invalidateBuffers & GL_DEPTH_BUFFER_BIT) != 0)
		{
			// Render color.
			Texture2DShader texShader(DataTypes() << glu::getSampler2DType(colorFmt), glu::TYPE_FLOAT_VEC4);
			deUint32		texShaderID = getCurrentContext()->createProgram(&texShader);

			texShader.setTexScaleBias(0, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
			texShader.setUniforms(*getCurrentContext(), texShaderID);

			glBindTexture(GL_TEXTURE_2D, colorTex);
			sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		}
		else
		{
			// Render depth.
			Texture2DShader texShader(DataTypes() << glu::getSampler2DType(depthStencilFmt), glu::TYPE_FLOAT_VEC4);
			deUint32		texShaderID = getCurrentContext()->createProgram(&texShader);

			texShader.setUniforms(*getCurrentContext(), texShaderID);

			glBindTexture(GL_TEXTURE_2D, depthStencilTex);
			sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		}

		readPixels(dst, 0, 0, getWidth(), getHeight());
	}

private:
	deUint32	m_colorFmt;
	deUint32	m_depthStencilFmt;
	deUint32	m_invalidateBuffers;
};

class InvalidateFboUnbindBlitCase : public FboTestCase
{
public:
	InvalidateFboUnbindBlitCase (Context& context, const char* name, const char* description, int numSamples, deUint32 invalidateBuffers)
		: FboTestCase			(context, name, description, numSamples > 0)	// \note Use fullscreen viewport when multisampling - we can't allow GLES3Context do its
																				//		 behing-the-scenes viewport position randomization, because with glBlitFramebuffer,
																				//		 source and destination rectangles must match when multisampling.
		, m_colorFmt			(0)
		, m_depthStencilFmt		(0)
		, m_numSamples			(numSamples)
		, m_invalidateBuffers	(invalidateBuffers)
	{
		// Figure out formats that are compatible with default framebuffer.
		m_colorFmt			= getCompatibleColorFormat(m_context.getRenderTarget());
		m_depthStencilFmt	= getCompatibleDepthStencilFormat(m_context.getRenderTarget());
	}

protected:
	void preCheck (void)
	{
		if (m_context.getRenderTarget().getNumSamples() > 0)
			throw tcu::NotSupportedError("Not supported in MSAA config");

		if (m_colorFmt == GL_NONE)
			throw tcu::NotSupportedError("Unsupported color format");

		if (m_depthStencilFmt == GL_NONE)
			throw tcu::NotSupportedError("Unsupported depth/stencil format");

		checkFormatSupport(m_colorFmt);
		checkFormatSupport(m_depthStencilFmt);
	}

	void render (tcu::Surface& dst)
	{
		// \note When using fullscreen viewport (when m_numSamples > 0), still only use a 128x128 pixel quad at most.
		IVec2					quadSizePixels			(m_numSamples == 0 ? getWidth() : de::min(128, getWidth()),
														 m_numSamples == 0 ? getHeight() : de::min(128, getHeight()));
		Vec2					quadNDCLeftBottomXY		(-1.0f, -1.0f);
		Vec2					quadNDCSize				(2.0f*quadSizePixels.x()/getWidth(), 2.0f*quadSizePixels.y()/getHeight());
		Vec2					quadNDCRightTopXY		= quadNDCLeftBottomXY + quadNDCSize;
		tcu::TextureFormat		depthStencilFmt			= m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat();
		bool					depth					= depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS;
		bool					stencil					= depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS;
		deUint32				fbo						= 0;
		deUint32				colorRbo				= 0;
		deUint32				depthStencilRbo			= 0;
		FlatColorShader			flatShader				(glu::TYPE_FLOAT_VEC4);
		vector<deUint32>		attachments				= getFBODiscardAttachments(m_invalidateBuffers);
		deUint32				flatShaderID			= getCurrentContext()->createProgram(&flatShader);

		glClearColor	(0.0f, 0.0f, 0.0f, 1.0f);
		glClear			(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		// Create fbo.
		glGenRenderbuffers					(1, &colorRbo);
		glBindRenderbuffer					(GL_RENDERBUFFER, colorRbo);
		glRenderbufferStorageMultisample	(GL_RENDERBUFFER, m_numSamples, m_colorFmt, quadSizePixels.x(), quadSizePixels.y());

		if (m_depthStencilFmt != GL_NONE)
		{
			glGenRenderbuffers					(1, &depthStencilRbo);
			glBindRenderbuffer					(GL_RENDERBUFFER, depthStencilRbo);
			glRenderbufferStorageMultisample	(GL_RENDERBUFFER, m_numSamples, m_depthStencilFmt, quadSizePixels.x(), quadSizePixels.y());
		}

		glGenFramebuffers			(1, &fbo);
		glBindFramebuffer			(GL_FRAMEBUFFER, fbo);
		glFramebufferRenderbuffer	(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);

		if (depth)
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);

		if (stencil)
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);

		checkFramebufferStatus		(GL_FRAMEBUFFER);

		glClear			(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		glEnable		(GL_DEPTH_TEST);
		glEnable		(GL_STENCIL_TEST);
		glStencilOp		(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc	(GL_ALWAYS, 1, 0xff);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), -1.0f), Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 1.0f));

		glInvalidateFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0]);

		// Set default framebuffer as draw framebuffer and blit preserved buffers.
		glBindFramebuffer	(GL_DRAW_FRAMEBUFFER, 0);
		glBlitFramebuffer	(0, 0, quadSizePixels.x(), quadSizePixels.y(),
							 0, 0, quadSizePixels.x(), quadSizePixels.y(),
							 (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT) & ~m_invalidateBuffers, GL_NEAREST);
		glBindFramebuffer	(GL_READ_FRAMEBUFFER, 0);

		if ((m_invalidateBuffers & GL_COLOR_BUFFER_BIT) != 0)
		{
			// Color was not preserved - fill with green.
			glDisable(GL_DEPTH_TEST);
			glDisable(GL_STENCIL_TEST);

			flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
			sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), 0.0f), Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 0.0f));

			glEnable(GL_DEPTH_TEST);
			glEnable(GL_STENCIL_TEST);
		}

		if ((m_invalidateBuffers & GL_DEPTH_BUFFER_BIT) != 0)
		{
			// Depth was not preserved.
			glDepthFunc(GL_ALWAYS);
		}

		if ((m_invalidateBuffers & GL_STENCIL_BUFFER_BIT) == 0)
		{
			// Stencil was preserved.
			glStencilFunc(GL_EQUAL, 1, 0xff);
		}

		glEnable		(GL_BLEND);
		glBlendFunc		(GL_ONE, GL_ONE);
		glBlendEquation	(GL_FUNC_ADD);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), 0.0f), Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 0.0f));

		readPixels(dst, 0, 0, quadSizePixels.x(), quadSizePixels.y());
	}

private:
	deUint32	m_colorFmt;
	deUint32	m_depthStencilFmt;
	int			m_numSamples;
	deUint32	m_invalidateBuffers;
};

class InvalidateSubFboRenderCase : public FboTestCase
{
public:
	InvalidateSubFboRenderCase (Context& context, const char* name, const char* description, deUint32 colorFmt, deUint32 depthStencilFmt, deUint32 invalidateBuffers)
		: FboTestCase			(context, name, description)
		, m_colorFmt			(colorFmt)
		, m_depthStencilFmt		(depthStencilFmt)
		, m_invalidateBuffers	(invalidateBuffers)
	{
	}

protected:
	void preCheck (void)
	{
		if (m_colorFmt != GL_NONE)			checkFormatSupport(m_colorFmt);
		if (m_depthStencilFmt != GL_NONE)	checkFormatSupport(m_depthStencilFmt);
	}

	void render (tcu::Surface& dst)
	{
		tcu::TextureFormat		colorFmt				= glu::mapGLInternalFormat(m_colorFmt);
		tcu::TextureFormat		depthStencilFmt			= m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat();
		tcu::TextureFormatInfo	colorFmtInfo			= tcu::getTextureFormatInfo(colorFmt);
		bool					depth					= depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS;
		bool					stencil					= depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS;
		const tcu::Vec4&		cBias					= colorFmtInfo.valueMin;
		tcu::Vec4				cScale					= colorFmtInfo.valueMax-colorFmtInfo.valueMin;
		deUint32				fbo						= 0;
		deUint32				colorRbo				= 0;
		deUint32				depthStencilRbo			= 0;
		int						invalidateX				= getWidth()	/ 4;
		int						invalidateY				= getHeight()	/ 4;
		int						invalidateW				= getWidth()	/ 2;
		int						invalidateH				= getHeight()	/ 2;
		FlatColorShader			flatShader				(glu::TYPE_FLOAT_VEC4);
		vector<deUint32>		attachments				= getFBODiscardAttachments(m_invalidateBuffers);
		deUint32				flatShaderID			= getCurrentContext()->createProgram(&flatShader);

		// Create fbo.
		glGenRenderbuffers		(1, &colorRbo);
		glBindRenderbuffer		(GL_RENDERBUFFER, colorRbo);
		glRenderbufferStorage	(GL_RENDERBUFFER, m_colorFmt, getWidth(), getHeight());

		if (m_depthStencilFmt != GL_NONE)
		{
			glGenRenderbuffers		(1, &depthStencilRbo);
			glBindRenderbuffer		(GL_RENDERBUFFER, depthStencilRbo);
			glRenderbufferStorage	(GL_RENDERBUFFER, m_depthStencilFmt, getWidth(), getHeight());
		}

		glGenFramebuffers			(1, &fbo);
		glBindFramebuffer			(GL_FRAMEBUFFER, fbo);
		glFramebufferRenderbuffer	(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);

		if (depth)
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);

		if (stencil)
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);

		checkFramebufferStatus		(GL_FRAMEBUFFER);

		glClearBufferfv	(GL_COLOR, 0, (Vec4(0.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias).getPtr());
		glClearBufferfi	(GL_DEPTH_STENCIL, 0, 1.0f, 0);

		glEnable		(GL_DEPTH_TEST);
		glEnable		(GL_STENCIL_TEST);
		glStencilOp		(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc	(GL_ALWAYS, 1, 0xff);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias);
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));

		glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0], invalidateX, invalidateY, invalidateW, invalidateH);

		// Clear invalidated buffers.
		glScissor	(invalidateX, invalidateY, invalidateW, invalidateH);
		glEnable	(GL_SCISSOR_TEST);

		if (m_invalidateBuffers & GL_COLOR_BUFFER_BIT)
			glClearBufferfv(GL_COLOR, 0, (Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias).getPtr());

		glClear		(m_invalidateBuffers & ~GL_COLOR_BUFFER_BIT);
		glDisable	(GL_SCISSOR_TEST);

		glEnable		(GL_BLEND);
		glBlendFunc		(GL_ONE, GL_ONE);
		glBlendEquation	(GL_FUNC_ADD);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)*cScale + cBias);
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		readPixels(dst, 0, 0, getWidth(), getHeight(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
	}

private:
	deUint32	m_colorFmt;
	deUint32	m_depthStencilFmt;
	deUint32	m_invalidateBuffers;
};

class InvalidateSubFboUnbindReadCase : public FboTestCase
{
public:
	InvalidateSubFboUnbindReadCase (Context& context, const char* name, const char* description, deUint32 colorFmt, deUint32 depthStencilFmt, deUint32 invalidateBuffers)
		: FboTestCase			(context, name, description)
		, m_colorFmt			(colorFmt)
		, m_depthStencilFmt		(depthStencilFmt)
		, m_invalidateBuffers	(invalidateBuffers)
	{
		DE_ASSERT((m_invalidateBuffers & (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)) != (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT));
	}

protected:
	void preCheck (void)
	{
		if (m_colorFmt != GL_NONE)			checkFormatSupport(m_colorFmt);
		if (m_depthStencilFmt != GL_NONE)	checkFormatSupport(m_depthStencilFmt);
	}

	void render (tcu::Surface& dst)
	{
		tcu::TextureFormat		colorFmt				= glu::mapGLInternalFormat(m_colorFmt);
		tcu::TextureFormat		depthStencilFmt			= m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat();
		tcu::TextureFormatInfo	colorFmtInfo			= tcu::getTextureFormatInfo(colorFmt);
		bool					depth					= depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS;
		bool					stencil					= depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS;
		deUint32				fbo						= 0;
		deUint32				colorTex				= 0;
		deUint32				depthStencilTex			= 0;
		int						invalidateX				= 0;
		int						invalidateY				= 0;
		int						invalidateW				= getWidth()/2;
		int						invalidateH				= getHeight();
		int						readX					= invalidateW;
		int						readY					= 0;
		int						readW					= getWidth()/2;
		int						readH					= getHeight();
		GradientShader			gradShader				(getFragmentOutputType(colorFmt));
		vector<deUint32>		attachments				= getFBODiscardAttachments(m_invalidateBuffers);
		deUint32				gradShaderID			= getCurrentContext()->createProgram(&gradShader);

		// Create fbo.
		{
			glu::TransferFormat transferFmt = glu::getTransferFormat(colorFmt);

			glGenTextures	(1, &colorTex);
			glBindTexture	(GL_TEXTURE_2D, colorTex);
			glTexImage2D	(GL_TEXTURE_2D, 0, m_colorFmt, getWidth(), getHeight(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
			glTexParameteri	(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			glTexParameteri	(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		}

		if (m_depthStencilFmt != GL_NONE)
		{
			glu::TransferFormat transferFmt = glu::getTransferFormat(depthStencilFmt);

			glGenTextures	(1, &depthStencilTex);
			glBindTexture	(GL_TEXTURE_2D, depthStencilTex);
			glTexImage2D	(GL_TEXTURE_2D, 0, m_depthStencilFmt, getWidth(), getHeight(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
			glTexParameteri	(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			glTexParameteri	(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		}

		glGenFramebuffers		(1, &fbo);
		glBindFramebuffer		(GL_FRAMEBUFFER, fbo);
		glFramebufferTexture2D	(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);

		if (depth)
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthStencilTex, 0);

		if (stencil)
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthStencilTex, 0);

		checkFramebufferStatus		(GL_FRAMEBUFFER);

		clearColorBuffer(colorFmt, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
		glClear			(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		glEnable		(GL_DEPTH_TEST);
		glEnable		(GL_STENCIL_TEST);
		glStencilOp		(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc	(GL_ALWAYS, 1, 0xff);

		gradShader.setGradient(*getCurrentContext(), gradShaderID, colorFmtInfo.valueMin, colorFmtInfo.valueMax);
		sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));

		glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0], invalidateX, invalidateY, invalidateW, invalidateH);

		glBindFramebuffer	(GL_FRAMEBUFFER, 0);
		glDisable			(GL_DEPTH_TEST);
		glDisable			(GL_STENCIL_TEST);

		glClearColor		(0.25f, 0.5f, 0.75f, 1.0f);
		glClear				(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		// Limit read area using scissor.
		glScissor			(readX, readY, readW, readH);
		glEnable			(GL_SCISSOR_TEST);

		if ((m_invalidateBuffers & GL_COLOR_BUFFER_BIT) != 0)
		{
			// Render color.
			Texture2DShader texShader(DataTypes() << glu::getSampler2DType(colorFmt), glu::TYPE_FLOAT_VEC4);
			deUint32		texShaderID = getCurrentContext()->createProgram(&texShader);

			texShader.setTexScaleBias(0, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
			texShader.setUniforms(*getCurrentContext(), texShaderID);

			glBindTexture(GL_TEXTURE_2D, colorTex);
			sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		}
		else
		{
			// Render depth.
			Texture2DShader texShader(DataTypes() << glu::getSampler2DType(depthStencilFmt), glu::TYPE_FLOAT_VEC4);
			deUint32		texShaderID = getCurrentContext()->createProgram(&texShader);

			texShader.setUniforms(*getCurrentContext(), texShaderID);

			glBindTexture(GL_TEXTURE_2D, depthStencilTex);
			sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		}

		readPixels(dst, 0, 0, getWidth(), getHeight());
	}

	bool compare (const tcu::Surface& reference, const tcu::Surface& result)
	{
		const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_colorFmt), tcu::RGBA(12, 12, 12, 12)));

		return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
	}

private:
	deUint32	m_colorFmt;
	deUint32	m_depthStencilFmt;
	deUint32	m_invalidateBuffers;
};

class InvalidateSubFboUnbindBlitCase : public FboTestCase
{
public:
	InvalidateSubFboUnbindBlitCase (Context& context, const char* name, const char* description, int numSamples, deUint32 invalidateBuffers)
		: FboTestCase			(context, name, description, numSamples > 0)	// \note Use fullscreen viewport when multisampling - we can't allow GLES3Context do its
																				//		 behing-the-scenes viewport position randomization, because with glBlitFramebuffer,
																				//		 source and destination rectangles must match when multisampling.
		, m_colorFmt			(0)
		, m_depthStencilFmt		(0)
		, m_numSamples			(numSamples)
		, m_invalidateBuffers	(invalidateBuffers)
	{
		// Figure out formats that are compatible with default framebuffer.
		m_colorFmt			= getCompatibleColorFormat(m_context.getRenderTarget());
		m_depthStencilFmt	= getCompatibleDepthStencilFormat(m_context.getRenderTarget());
	}

protected:
	void preCheck (void)
	{
		if (m_context.getRenderTarget().getNumSamples() > 0)
			throw tcu::NotSupportedError("Not supported in MSAA config");

		if (m_colorFmt == GL_NONE)
			throw tcu::NotSupportedError("Unsupported color format");

		if (m_depthStencilFmt == GL_NONE)
			throw tcu::NotSupportedError("Unsupported depth/stencil format");

		checkFormatSupport(m_colorFmt);
		checkFormatSupport(m_depthStencilFmt);
	}

	void render (tcu::Surface& dst)
	{
		// \note When using fullscreen viewport (when m_numSamples > 0), still only use a 128x128 pixel quad at most.
		IVec2					quadSizePixels			(m_numSamples == 0 ? getWidth() : de::min(128, getWidth()),
														 m_numSamples == 0 ? getHeight() : de::min(128, getHeight()));
		Vec2					quadNDCLeftBottomXY		(-1.0f, -1.0f);
		Vec2					quadNDCSize				(2.0f*quadSizePixels.x()/getWidth(), 2.0f*quadSizePixels.y()/getHeight());
		Vec2					quadNDCRightTopXY		= quadNDCLeftBottomXY + quadNDCSize;
		tcu::TextureFormat		depthStencilFmt			= m_depthStencilFmt != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFmt) : tcu::TextureFormat();
		bool					depth					= depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS;
		bool					stencil					= depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS;
		deUint32				fbo						= 0;
		deUint32				colorRbo				= 0;
		deUint32				depthStencilRbo			= 0;
		int						invalidateX				= 0;
		int						invalidateY				= 0;
		int						invalidateW				= quadSizePixels.x()/2;
		int						invalidateH				= quadSizePixels.y();
		int						blitX0					= invalidateW;
		int						blitY0					= 0;
		int						blitX1					= blitX0 + quadSizePixels.x()/2;
		int						blitY1					= blitY0 + quadSizePixels.y();
		FlatColorShader			flatShader				(glu::TYPE_FLOAT_VEC4);
		vector<deUint32>		attachments				= getFBODiscardAttachments(m_invalidateBuffers);
		deUint32				flatShaderID			= getCurrentContext()->createProgram(&flatShader);

		glClearColor	(0.0f, 0.0f, 0.0f, 1.0f);
		glClear			(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		// Create fbo.
		glGenRenderbuffers					(1, &colorRbo);
		glBindRenderbuffer					(GL_RENDERBUFFER, colorRbo);
		glRenderbufferStorageMultisample	(GL_RENDERBUFFER, m_numSamples, m_colorFmt, quadSizePixels.x(), quadSizePixels.y());

		if (m_depthStencilFmt != GL_NONE)
		{
			glGenRenderbuffers					(1, &depthStencilRbo);
			glBindRenderbuffer					(GL_RENDERBUFFER, depthStencilRbo);
			glRenderbufferStorageMultisample	(GL_RENDERBUFFER, m_numSamples, m_depthStencilFmt, quadSizePixels.x(), quadSizePixels.y());
		}

		glGenFramebuffers			(1, &fbo);
		glBindFramebuffer			(GL_FRAMEBUFFER, fbo);
		glFramebufferRenderbuffer	(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);

		if (depth)
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);

		if (stencil)
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);

		checkFramebufferStatus		(GL_FRAMEBUFFER);

		glClear			(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		glEnable		(GL_DEPTH_TEST);
		glEnable		(GL_STENCIL_TEST);
		glStencilOp		(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc	(GL_ALWAYS, 1, 0xff);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), -1.0f), Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 1.0f));

		glInvalidateSubFramebuffer(GL_FRAMEBUFFER, (int)attachments.size(), &attachments[0], invalidateX, invalidateY, invalidateW, invalidateH);

		// Set default framebuffer as draw framebuffer and blit preserved buffers.
		glBindFramebuffer	(GL_DRAW_FRAMEBUFFER, 0);
		glBlitFramebuffer	(blitX0, blitY0, blitX1, blitY1, blitX0, blitY0, blitX1, blitY1, (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT) & ~m_invalidateBuffers, GL_NEAREST);
		glBindFramebuffer	(GL_READ_FRAMEBUFFER, 0);

		if ((m_invalidateBuffers & GL_COLOR_BUFFER_BIT) != 0)
		{
			// Color was not preserved - fill with green.
			glDisable(GL_DEPTH_TEST);
			glDisable(GL_STENCIL_TEST);

			flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
			sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), 0.0f), Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 0.0f));

			glEnable(GL_DEPTH_TEST);
			glEnable(GL_STENCIL_TEST);
		}

		if ((m_invalidateBuffers & GL_DEPTH_BUFFER_BIT) != 0)
		{
			// Depth was not preserved.
			glDepthFunc(GL_ALWAYS);
		}

		if ((m_invalidateBuffers & GL_STENCIL_BUFFER_BIT) == 0)
		{
			// Stencil was preserved.
			glStencilFunc(GL_EQUAL, 1, 0xff);
		}

		glEnable		(GL_BLEND);
		glBlendFunc		(GL_ONE, GL_ONE);
		glBlendEquation	(GL_FUNC_ADD);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(quadNDCLeftBottomXY.x(), quadNDCLeftBottomXY.y(), 0.0f), Vec3(quadNDCRightTopXY.x(), quadNDCRightTopXY.y(), 0.0f));

		readPixels(dst, 0, 0, quadSizePixels.x(), quadSizePixels.y());
	}

private:
	deUint32	m_colorFmt;
	deUint32	m_depthStencilFmt;
	int			m_numSamples;
	deUint32	m_invalidateBuffers;
};

class InvalidateFboTargetCase : public FboTestCase
{
public:
	InvalidateFboTargetCase (Context& context, const char* name, const char* description, deUint32 boundTarget, deUint32 invalidateTarget, const deUint32* invalidateAttachments, int numAttachments)
		: FboTestCase				(context, name, description)
		, m_boundTarget				(boundTarget)
		, m_invalidateTarget		(invalidateTarget)
		, m_invalidateAttachments	(invalidateAttachments, invalidateAttachments+numAttachments)
	{
	}

protected:
	void render (tcu::Surface& dst)
	{
		const deUint32					colorFormat				= GL_RGBA8;
		const deUint32					depthStencilFormat		= GL_DEPTH24_STENCIL8;
		const tcu::TextureFormat		colorFmt				= glu::mapGLInternalFormat(colorFormat);
		const tcu::TextureFormatInfo	colorFmtInfo			= tcu::getTextureFormatInfo(colorFmt);
		const tcu::Vec4&				cBias					= colorFmtInfo.valueMin;
		const tcu::Vec4					cScale					= colorFmtInfo.valueMax-colorFmtInfo.valueMin;
		const bool						isDiscarded				= (m_boundTarget == GL_FRAMEBUFFER) ||
																  (m_invalidateTarget == GL_FRAMEBUFFER && m_boundTarget == GL_DRAW_FRAMEBUFFER) ||
																  (m_invalidateTarget == m_boundTarget);
		const bool						isColorDiscarded		= isDiscarded && hasAttachment(m_invalidateAttachments, GL_COLOR_ATTACHMENT0);
		const bool						isDepthDiscarded		= isDiscarded && (hasAttachment(m_invalidateAttachments, GL_DEPTH_ATTACHMENT) || hasAttachment(m_invalidateAttachments, GL_DEPTH_STENCIL_ATTACHMENT));
		const bool						isStencilDiscarded		= isDiscarded && (hasAttachment(m_invalidateAttachments, GL_STENCIL_ATTACHMENT) || hasAttachment(m_invalidateAttachments, GL_DEPTH_STENCIL_ATTACHMENT));

		deUint32						fbo						= 0;
		deUint32						colorRbo				= 0;
		deUint32						depthStencilRbo			= 0;
		FlatColorShader					flatShader				(glu::TYPE_FLOAT_VEC4);
		deUint32						flatShaderID			= getCurrentContext()->createProgram(&flatShader);

		// Create fbo.
		glGenRenderbuffers		(1, &colorRbo);
		glBindRenderbuffer		(GL_RENDERBUFFER, colorRbo);
		glRenderbufferStorage	(GL_RENDERBUFFER, colorFormat, getWidth(), getHeight());

		glGenRenderbuffers		(1, &depthStencilRbo);
		glBindRenderbuffer		(GL_RENDERBUFFER, depthStencilRbo);
		glRenderbufferStorage	(GL_RENDERBUFFER, depthStencilFormat, getWidth(), getHeight());

		glGenFramebuffers			(1, &fbo);
		glBindFramebuffer			(GL_FRAMEBUFFER, fbo);
		glFramebufferRenderbuffer	(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
		glFramebufferRenderbuffer	(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
		glFramebufferRenderbuffer	(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);

		checkFramebufferStatus		(GL_FRAMEBUFFER);

		glClearColor	(0.0f, 0.0f, 0.0f, 1.0f);
		glClear			(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		glEnable		(GL_DEPTH_TEST);
		glEnable		(GL_STENCIL_TEST);
		glStencilOp		(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc	(GL_ALWAYS, 1, 0xff);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias);
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));

		// Bound FBO to test target and default to other
		if (m_boundTarget != GL_FRAMEBUFFER)
		{
			// Dummy fbo is used as complemeting target (read when discarding draw for example).
			// \note Framework takes care of deleting objects at the end of test case.
			const deUint32	dummyTarget		= m_boundTarget == GL_DRAW_FRAMEBUFFER ?  GL_READ_FRAMEBUFFER : GL_DRAW_FRAMEBUFFER;
			deUint32		dummyFbo		= 0;
			deUint32		dummyColorRbo	= 0;

			glGenRenderbuffers			(1, &dummyColorRbo);
			glBindRenderbuffer			(GL_RENDERBUFFER, dummyColorRbo);
			glRenderbufferStorage		(GL_RENDERBUFFER, GL_RGBA8, 64, 64);
			glGenFramebuffers			(1, &dummyFbo);
			glBindFramebuffer			(dummyTarget, dummyFbo);
			glFramebufferRenderbuffer	(dummyTarget, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, dummyColorRbo);

			glBindFramebuffer			(m_boundTarget, fbo);
		}

		glInvalidateFramebuffer(m_invalidateTarget, (int)m_invalidateAttachments.size(), m_invalidateAttachments.empty() ? DE_NULL : &m_invalidateAttachments[0]);

		if (m_boundTarget != GL_FRAMEBUFFER)
			glBindFramebuffer(GL_FRAMEBUFFER, fbo);

		if (isColorDiscarded)
		{
			// Color was not preserved - fill with green.
			glDisable(GL_DEPTH_TEST);
			glDisable(GL_STENCIL_TEST);

			flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias);
			sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

			glEnable(GL_DEPTH_TEST);
			glEnable(GL_STENCIL_TEST);
		}

		if (isDepthDiscarded)
		{
			// Depth was not preserved.
			glDepthFunc(GL_ALWAYS);
		}

		if (!isStencilDiscarded)
		{
			// Stencil was preserved.
			glStencilFunc(GL_EQUAL, 1, 0xff);
		}

		glEnable		(GL_BLEND);
		glBlendFunc		(GL_ONE, GL_ONE);
		glBlendEquation	(GL_FUNC_ADD);

		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)*cScale + cBias);
		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));

		readPixels(dst, 0, 0, getWidth(), getHeight(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
	}

private:
	deUint32				m_boundTarget;
	deUint32				m_invalidateTarget;
	std::vector<deUint32>	m_invalidateAttachments;
};

FboInvalidateTests::FboInvalidateTests (Context& context)
	: TestCaseGroup(context, "invalidate", "Framebuffer invalidate tests")
{
}

FboInvalidateTests::~FboInvalidateTests (void)
{
}

void FboInvalidateTests::init (void)
{
	// invalidate.default.
	{
		tcu::TestCaseGroup* defaultFbGroup = new tcu::TestCaseGroup(m_testCtx, "default", "Default framebuffer invalidate tests");
		addChild(defaultFbGroup);

		defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase		(m_context,	"render_none",				"Invalidating no framebuffers (ref)",						0));
		defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase		(m_context,	"render_color",				"Rendering after invalidating colorbuffer",					GL_COLOR_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase		(m_context,	"render_depth",				"Rendering after invalidating depthbuffer",					GL_DEPTH_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase		(m_context,	"render_stencil",			"Rendering after invalidating stencilbuffer",				GL_STENCIL_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase		(m_context,	"render_depth_stencil",		"Rendering after invalidating depth- and stencilbuffers",	GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase		(m_context,	"render_all",				"Rendering after invalidating all buffers",					GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));

		defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase		(m_context,	"bind_color",				"Binding fbo after invalidating colorbuffer",				GL_COLOR_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase		(m_context,	"bind_depth",				"Binding fbo after invalidating depthbuffer",				GL_DEPTH_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase		(m_context,	"bind_stencil",				"Binding fbo after invalidating stencilbuffer",				GL_STENCIL_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase		(m_context,	"bind_depth_stencil",		"Binding fbo after invalidating depth- and stencilbuffers",	GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultFramebufferBindCase		(m_context,	"bind_all",					"Binding fbo after invalidating all buffers",				GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));

		defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase	(m_context,	"sub_render_color",			"Rendering after invalidating colorbuffer",					GL_COLOR_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase	(m_context,	"sub_render_depth",			"Rendering after invalidating depthbuffer",					GL_DEPTH_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase	(m_context,	"sub_render_stencil",		"Rendering after invalidating stencilbuffer",				GL_STENCIL_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase	(m_context,	"sub_render_depth_stencil",	"Rendering after invalidating depth- and stencilbuffers",	GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferRenderCase	(m_context,	"sub_render_all",			"Rendering after invalidating all buffers",					GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));

		defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase	(m_context,	"sub_bind_color",			"Binding fbo after invalidating colorbuffer",				GL_COLOR_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase	(m_context,	"sub_bind_depth",			"Binding fbo after invalidating depthbuffer",				GL_DEPTH_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase	(m_context,	"sub_bind_stencil",			"Binding fbo after invalidating stencilbuffer",				GL_STENCIL_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase	(m_context,	"sub_bind_depth_stencil",	"Binding fbo after invalidating depth- and stencilbuffers",	GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));
		defaultFbGroup->addChild(new InvalidateDefaultSubFramebufferBindCase	(m_context,	"sub_bind_all",				"Binding fbo after invalidating all buffers",				GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));

		defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase		(m_context,	"draw_framebuffer_color",	"Invalidating GL_COLOR in GL_DRAW_FRAMEBUFFER",				GL_COLOR_BUFFER_BIT,											GL_DRAW_FRAMEBUFFER));
		defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase		(m_context,	"draw_framebuffer_all",		"Invalidating all in GL_DRAW_FRAMEBUFFER",					GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT,	GL_DRAW_FRAMEBUFFER));
		defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase		(m_context,	"read_framebuffer_color",	"Invalidating GL_COLOR in GL_READ_FRAMEBUFFER",				GL_COLOR_BUFFER_BIT,											GL_READ_FRAMEBUFFER));
		defaultFbGroup->addChild(new InvalidateDefaultFramebufferRenderCase		(m_context,	"read_framebuffer_all",		"Invalidating all in GL_READ_FRAMEBUFFER",					GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT,	GL_READ_FRAMEBUFFER));
	}

	// invalidate.whole.
	{
		tcu::TestCaseGroup* wholeFboGroup = new tcu::TestCaseGroup(m_testCtx, "whole", "Invalidating whole framebuffer object");
		addChild(wholeFboGroup);

		wholeFboGroup->addChild(new InvalidateFboRenderCase		(m_context, "render_none",						"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	0));
		wholeFboGroup->addChild(new InvalidateFboRenderCase		(m_context, "render_color",						"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_COLOR_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboRenderCase		(m_context, "render_depth",						"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_DEPTH_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboRenderCase		(m_context, "render_stencil",					"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_STENCIL_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboRenderCase		(m_context, "render_depth_stencil",				"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboRenderCase		(m_context, "render_all",						"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));

		wholeFboGroup->addChild(new InvalidateFboUnbindReadCase	(m_context, "unbind_read_color",				"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_COLOR_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboUnbindReadCase	(m_context, "unbind_read_depth",				"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_DEPTH_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboUnbindReadCase	(m_context, "unbind_read_stencil",				"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_STENCIL_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboUnbindReadCase	(m_context, "unbind_read_depth_stencil",		"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboUnbindReadCase	(m_context, "unbind_read_color_stencil",		"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));

		wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase	(m_context, "unbind_blit_color",				"",		0,	GL_COLOR_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase	(m_context, "unbind_blit_depth",				"",		0,	GL_DEPTH_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase	(m_context, "unbind_blit_stencil",				"",		0,	GL_STENCIL_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase	(m_context, "unbind_blit_depth_stencil",		"",		0,	GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));

		wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase	(m_context, "unbind_blit_msaa_color",			"",		4,	GL_COLOR_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase	(m_context, "unbind_blit_msaa_depth",			"",		4,	GL_DEPTH_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase	(m_context, "unbind_blit_msaa_stencil",			"",		4,	GL_STENCIL_BUFFER_BIT));
		wholeFboGroup->addChild(new InvalidateFboUnbindBlitCase	(m_context, "unbind_blit_msaa_depth_stencil",	"",		4,	GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));
	}

	// invalidate.sub.
	{
		tcu::TestCaseGroup* subFboGroup = new tcu::TestCaseGroup(m_testCtx, "sub", "Invalidating subsection of framebuffer object");
		addChild(subFboGroup);

		subFboGroup->addChild(new InvalidateSubFboRenderCase	(m_context, "render_none",						"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	0));
		subFboGroup->addChild(new InvalidateSubFboRenderCase	(m_context, "render_color",						"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_COLOR_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboRenderCase	(m_context, "render_depth",						"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_DEPTH_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboRenderCase	(m_context, "render_stencil",					"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_STENCIL_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboRenderCase	(m_context, "render_depth_stencil",				"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboRenderCase	(m_context, "render_all",						"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));

		subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_color",				"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_COLOR_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_depth",				"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_DEPTH_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_stencil",				"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_STENCIL_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_depth_stencil",		"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, "unbind_read_color_stencil",		"",		GL_RGBA8,		GL_DEPTH24_STENCIL8,	GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));

		subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_color",				"",		0,	GL_COLOR_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_depth",				"",		0,	GL_DEPTH_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_stencil",				"",		0,	GL_STENCIL_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_depth_stencil",		"",		0,	GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));

		subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_msaa_color",			"",		4,	GL_COLOR_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_msaa_depth",			"",		4,	GL_DEPTH_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_msaa_stencil",			"",		4,	GL_STENCIL_BUFFER_BIT));
		subFboGroup->addChild(new InvalidateSubFboUnbindBlitCase(m_context, "unbind_blit_msaa_depth_stencil",	"",		4,	GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));
	}

	// invalidate.format.
	{
		tcu::TestCaseGroup* formatGroup = new tcu::TestCaseGroup(m_testCtx, "format", "Invalidating framebuffers with selected formats");
		addChild(formatGroup);

		// Color buffer formats.
		static const deUint32 colorFormats[] =
		{
			// RGBA formats
			GL_RGBA32I,
			GL_RGBA32UI,
			GL_RGBA16I,
			GL_RGBA16UI,
			GL_RGBA8,
			GL_RGBA8I,
			GL_RGBA8UI,
			GL_SRGB8_ALPHA8,
			GL_RGB10_A2,
			GL_RGB10_A2UI,
			GL_RGBA4,
			GL_RGB5_A1,

			// RGB formats
			GL_RGB8,
			GL_RGB565,

			// RG formats
			GL_RG32I,
			GL_RG32UI,
			GL_RG16I,
			GL_RG16UI,
			GL_RG8,
			GL_RG8I,
			GL_RG8UI,

			// R formats
			GL_R32I,
			GL_R32UI,
			GL_R16I,
			GL_R16UI,
			GL_R8,
			GL_R8I,
			GL_R8UI,

			// GL_EXT_color_buffer_float
			GL_RGBA32F,
			GL_RGBA16F,
			GL_R11F_G11F_B10F,
			GL_RG32F,
			GL_RG16F,
			GL_R32F,
			GL_R16F
		};

		// Depth/stencilbuffer formats.
		static const deUint32 depthStencilFormats[] =
		{
			GL_DEPTH_COMPONENT32F,
			GL_DEPTH_COMPONENT24,
			GL_DEPTH_COMPONENT16,
			GL_DEPTH32F_STENCIL8,
			GL_DEPTH24_STENCIL8,
			GL_STENCIL_INDEX8
		};

		// Colorbuffer tests use invalidate, unbind, read test.
		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
			formatGroup->addChild(new InvalidateSubFboUnbindReadCase(m_context, getFormatName(colorFormats[ndx]), "", colorFormats[ndx], GL_NONE, GL_COLOR_BUFFER_BIT));

		// Depth/stencilbuffer tests use invalidate, render test.
		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
			formatGroup->addChild(new InvalidateSubFboRenderCase(m_context, getFormatName(depthStencilFormats[ndx]), "", GL_RGBA8, depthStencilFormats[ndx], GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));
	}

	// invalidate.target
	{
		tcu::TestCaseGroup* targetGroup = new tcu::TestCaseGroup(m_testCtx, "target", "Invalidate target");
		addChild(targetGroup);

		static const struct
		{
			const char*		name;
			deUint32		invalidateTarget;
			deUint32		boundTarget;
		} s_targetCases[] =
		{
			{ "framebuffer_framebuffer",			GL_FRAMEBUFFER,			GL_FRAMEBUFFER		},
			{ "framebuffer_read_framebuffer",		GL_FRAMEBUFFER,			GL_READ_FRAMEBUFFER },
			{ "framebuffer_draw_framebuffer",		GL_FRAMEBUFFER,			GL_DRAW_FRAMEBUFFER },
			{ "read_framebuffer_framebuffer",		GL_READ_FRAMEBUFFER,	GL_FRAMEBUFFER		},
			{ "read_framebuffer_read_framebuffer",	GL_READ_FRAMEBUFFER,	GL_READ_FRAMEBUFFER },
			{ "read_framebuffer_draw_framebuffer",	GL_READ_FRAMEBUFFER,	GL_DRAW_FRAMEBUFFER },
			{ "draw_framebuffer_framebuffer",		GL_DRAW_FRAMEBUFFER,	GL_FRAMEBUFFER		},
			{ "draw_framebuffer_read_framebuffer",	GL_DRAW_FRAMEBUFFER,	GL_READ_FRAMEBUFFER },
			{ "draw_framebuffer_draw_framebuffer",	GL_DRAW_FRAMEBUFFER,	GL_DRAW_FRAMEBUFFER },
		};

		static const deUint32 colorAttachment[]			= { GL_COLOR_ATTACHMENT0 };
		static const deUint32 depthStencilAttachment[]	= { GL_DEPTH_STENCIL_ATTACHMENT };
		static const deUint32 allAttachments[]			= { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT };

		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_targetCases); caseNdx++)
		{
			const std::string	baseName		= s_targetCases[caseNdx].name;
			const deUint32		invalidateT		= s_targetCases[caseNdx].invalidateTarget;
			const deUint32		boundT			= s_targetCases[caseNdx].boundTarget;

			targetGroup->addChild(new InvalidateFboTargetCase(m_context, (baseName + "_color").c_str(),			"",	boundT, invalidateT, &colorAttachment[0],			DE_LENGTH_OF_ARRAY(colorAttachment)));
			targetGroup->addChild(new InvalidateFboTargetCase(m_context, (baseName + "_depth_stencil").c_str(),	"",	boundT, invalidateT, &depthStencilAttachment[0],	DE_LENGTH_OF_ARRAY(depthStencilAttachment)));
			targetGroup->addChild(new InvalidateFboTargetCase(m_context, (baseName + "_all").c_str(),			"",	boundT, invalidateT, &allAttachments[0],			DE_LENGTH_OF_ARRAY(allAttachments)));
		}
	}
}

} // Functional
} // gles3
} // deqp
