/*-------------------------------------------------------------------------
 * 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 stencilbuffer tests.
 *//*--------------------------------------------------------------------*/

#include "es3fFramebufferBlitTests.hpp"
#include "es3fFboTestCase.hpp"
#include "es3fFboTestUtil.hpp"
#include "gluTextureUtil.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuVectorUtil.hpp"
#include "tcuTestLog.hpp"
#include "tcuImageCompare.hpp"
#include "tcuRenderTarget.hpp"
#include "sglrContextUtil.hpp"
#include "glwEnums.hpp"
#include "deStringUtil.hpp"

namespace deqp
{
namespace gles3
{
namespace Functional
{

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

class BlitRectCase : public FboTestCase
{
public:
	BlitRectCase (Context& context, const char* name, const char* desc, deUint32 filter, const IVec2& srcSize, const IVec4& srcRect, const IVec2& dstSize, const IVec4& dstRect, int cellSize = 8)
		: FboTestCase		(context, name, desc)
		, m_filter			(filter)
		, m_srcSize			(srcSize)
		, m_srcRect			(srcRect)
		, m_dstSize			(dstSize)
		, m_dstRect			(dstRect)
		, m_cellSize		(cellSize)
		, m_gridCellColorA	(0.2f, 0.7f, 0.1f, 1.0f)
		, m_gridCellColorB	(0.7f, 0.1f, 0.5f, 0.8f)
	{
	}

	void render (tcu::Surface& dst)
	{
		const deUint32			colorFormat		= GL_RGBA8;

		GradientShader			gradShader		(glu::TYPE_FLOAT_VEC4);
		Texture2DShader			texShader		(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
		deUint32				gradShaderID	= getCurrentContext()->createProgram(&gradShader);
		deUint32				texShaderID		= getCurrentContext()->createProgram(&texShader);

		deUint32				srcFbo = 0;
		deUint32				dstFbo = 0;
		deUint32				srcRbo = 0;
		deUint32				dstRbo = 0;

		// Setup shaders
		gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));
		texShader.setUniforms(*getCurrentContext(), texShaderID);

		// Create framebuffers.
		for (int ndx = 0; ndx < 2; ndx++)
		{
			deUint32&		fbo		= ndx ? dstFbo : srcFbo;
			deUint32&		rbo		= ndx ? dstRbo : srcRbo;
			const IVec2&	size	= ndx ? m_dstSize : m_srcSize;

			glGenFramebuffers(1, &fbo);
			glGenRenderbuffers(1, &rbo);

			glBindRenderbuffer(GL_RENDERBUFFER, rbo);
			glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, size.x(), size.y());

			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
			checkError();
			checkFramebufferStatus(GL_FRAMEBUFFER);
		}

		// Fill destination with gradient.
		glBindFramebuffer(GL_FRAMEBUFFER, dstFbo);
		glViewport(0, 0, m_dstSize.x(), m_dstSize.y());

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

		// Fill source with grid pattern.
		{
			const deUint32		format		= GL_RGBA;
			const deUint32		dataType	= GL_UNSIGNED_BYTE;
			const int			texW		= m_srcSize.x();
			const int			texH		= m_srcSize.y();
			deUint32			gridTex		= 0;
			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);

			tcu::fillWithGrid(data.getAccess(), m_cellSize, m_gridCellColorA, m_gridCellColorB);

			glGenTextures(1, &gridTex);
			glBindTexture(GL_TEXTURE_2D, gridTex);
			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());

			glBindFramebuffer(GL_FRAMEBUFFER, srcFbo);
			glViewport(0, 0, m_srcSize.x(), m_srcSize.y());
			sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		}

		// Perform copy.
		glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFbo);
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFbo);
		glBlitFramebuffer(m_srcRect.x(), m_srcRect.y(), m_srcRect.z(), m_srcRect.w(), m_dstRect.x(), m_dstRect.y(), m_dstRect.z(), m_dstRect.w(), GL_COLOR_BUFFER_BIT, m_filter);

		// Read back results.
		glBindFramebuffer(GL_READ_FRAMEBUFFER, dstFbo);
		readPixels(dst, 0, 0, m_dstSize.x(), m_dstSize.y(), glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f));
	}

	virtual bool compare (const tcu::Surface& reference, const tcu::Surface& result)
	{
		// Use pixel-threshold compare for rect cases since 1px off will mean failure.
		tcu::RGBA threshold = TestCase::m_context.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7);
		return tcu::pixelThresholdCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference, result, threshold, tcu::COMPARE_LOG_RESULT);
	}

protected:
	const deUint32	m_filter;
	const IVec2		m_srcSize;
	const IVec4		m_srcRect;
	const IVec2		m_dstSize;
	const IVec4		m_dstRect;
	const int		m_cellSize;
	const Vec4		m_gridCellColorA;
	const Vec4		m_gridCellColorB;
};

class BlitNearestFilterConsistencyCase : public BlitRectCase
{
public:
			BlitNearestFilterConsistencyCase	(Context& context, const char* name, const char* desc, const IVec2& srcSize, const IVec4& srcRect, const IVec2& dstSize, const IVec4& dstRect);

	bool	compare								(const tcu::Surface& reference, const tcu::Surface& result);
};

BlitNearestFilterConsistencyCase::BlitNearestFilterConsistencyCase (Context& context, const char* name, const char* desc, const IVec2& srcSize, const IVec4& srcRect, const IVec2& dstSize, const IVec4& dstRect)
	: BlitRectCase(context, name, desc, GL_NEAREST, srcSize, srcRect, dstSize, dstRect, 1)
{
}

bool BlitNearestFilterConsistencyCase::compare (const tcu::Surface& reference, const tcu::Surface& result)
{
	DE_ASSERT(reference.getWidth() == result.getWidth());
	DE_ASSERT(reference.getHeight() == result.getHeight());
	DE_UNREF(reference);

	// Image origin must be visible (for baseColor)
	DE_ASSERT(de::min(m_dstRect.x(), m_dstRect.z()) >= 0);
	DE_ASSERT(de::min(m_dstRect.y(), m_dstRect.w()) >= 0);

	const tcu::RGBA		cellColorA		(m_gridCellColorA);
	const tcu::RGBA		cellColorB		(m_gridCellColorB);
	const tcu::RGBA		threshold		= TestCase::m_context.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7);
	const tcu::IVec4	destinationArea	= tcu::IVec4(de::clamp(de::min(m_dstRect.x(), m_dstRect.z()), 0, result.getWidth()),
													 de::clamp(de::min(m_dstRect.y(), m_dstRect.w()), 0, result.getHeight()),
													 de::clamp(de::max(m_dstRect.x(), m_dstRect.z()), 0, result.getWidth()),
													 de::clamp(de::max(m_dstRect.y(), m_dstRect.w()), 0, result.getHeight()));
	const tcu::RGBA		baseColor		= result.getPixel(destinationArea.x(), destinationArea.y());
	const bool			signConfig		= tcu::compareThreshold(baseColor, cellColorA, threshold);

	bool				error			= false;
	tcu::Surface		errorMask		(result.getWidth(), result.getHeight());
	std::vector<bool>	horisontalSign	(destinationArea.z() - destinationArea.x());
	std::vector<bool>	verticalSign	(destinationArea.w() - destinationArea.y());

	tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));

	// Checking only area in our destination rect

	m_testCtx.getLog()
		<< tcu::TestLog::Message
		<< "Verifying consistency of NEAREST filtering. Verifying rect " << m_dstRect << ".\n"
		<< "Rounding direction of the NEAREST filter at the horisontal texel edge (x = n + 0.5) should not depend on the y-coordinate.\n"
		<< "Rounding direction of the NEAREST filter at the vertical texel edge (y = n + 0.5) should not depend on the x-coordinate.\n"
		<< "Blitting a grid (with uniform sized cells) should result in a grid (with non-uniform sized cells)."
		<< tcu::TestLog::EndMessage;

	// Verify that destination only contains valid colors

	for (int dy = 0; dy < destinationArea.w() - destinationArea.y(); ++dy)
	for (int dx = 0; dx < destinationArea.z() - destinationArea.x(); ++dx)
	{
		const tcu::RGBA	color	= result.getPixel(destinationArea.x() + dx, destinationArea.y() + dy);
		const bool isValidColor = tcu::compareThreshold(color, cellColorA, threshold) || tcu::compareThreshold(color, cellColorB, threshold);

		if (!isValidColor)
		{
			errorMask.setPixel(destinationArea.x() + dx, destinationArea.y() + dy, tcu::RGBA::red());
			error = true;
		}
	}
	if (error)
	{
		m_testCtx.getLog()
			<< tcu::TestLog::Message
			<< "Image verification failed, destination rect contains unexpected values. "
			<< "Expected either " << cellColorA << " or " << cellColorB << "."
			<< tcu::TestLog::EndMessage
			<< tcu::TestLog::ImageSet("Result", "Image verification result")
			<< tcu::TestLog::Image("Result",	"Result",		result)
			<< tcu::TestLog::Image("ErrorMask",	"Error mask",	errorMask)
			<< tcu::TestLog::EndImageSet;
		return false;
	}

	// Detect result edges by reading the first row and first column of the blitted area.
	// Blitting a grid should result in a grid-like image. ("sign changes" should be consistent)

	for (int dx = 0; dx < destinationArea.z() - destinationArea.x(); ++dx)
	{
		const tcu::RGBA color = result.getPixel(destinationArea.x() + dx, destinationArea.y());

		if (tcu::compareThreshold(color, cellColorA, threshold))
			horisontalSign[dx] = true;
		else if (tcu::compareThreshold(color, cellColorB, threshold))
			horisontalSign[dx] = false;
		else
			DE_ASSERT(DE_FALSE);
	}
	for (int dy = 0; dy < destinationArea.w() - destinationArea.y(); ++dy)
	{
		const tcu::RGBA color = result.getPixel(destinationArea.x(), destinationArea.y() + dy);

		if (tcu::compareThreshold(color, cellColorA, threshold))
			verticalSign[dy] = true;
		else if (tcu::compareThreshold(color, cellColorB, threshold))
			verticalSign[dy] = false;
		else
			DE_ASSERT(DE_FALSE);
	}

	// Verify grid-like image

	for (int dy = 0; dy < destinationArea.w() - destinationArea.y(); ++dy)
	for (int dx = 0; dx < destinationArea.z() - destinationArea.x(); ++dx)
	{
		const tcu::RGBA	color		= result.getPixel(destinationArea.x() + dx, destinationArea.y() + dy);
		const bool		resultSign	= tcu::compareThreshold(cellColorA, color, threshold);
		const bool		correctSign	= (horisontalSign[dx] == verticalSign[dy]) == signConfig;

		if (resultSign != correctSign)
		{
			errorMask.setPixel(destinationArea.x() + dx, destinationArea.y() + dy, tcu::RGBA::red());
			error = true;
		}
	}

	// Report result

	if (error)
	{
		m_testCtx.getLog()
			<< tcu::TestLog::Message
			<< "Image verification failed, nearest filter is not consistent."
			<< tcu::TestLog::EndMessage
			<< tcu::TestLog::ImageSet("Result", "Image verification result")
			<< tcu::TestLog::Image("Result",	"Result",		result)
			<< tcu::TestLog::Image("ErrorMask",	"Error mask",	errorMask)
			<< tcu::TestLog::EndImageSet;
	}
	else
	{
		m_testCtx.getLog()
			<< tcu::TestLog::Message
			<< "Image verification passed."
			<< tcu::TestLog::EndMessage
			<< tcu::TestLog::ImageSet("Result", "Image verification result")
			<< tcu::TestLog::Image("Result", "Result", result)
			<< tcu::TestLog::EndImageSet;
	}

	return !error;
}

static tcu::BVec4 getChannelMask (tcu::TextureFormat::ChannelOrder order)
{
	switch (order)
	{
		case tcu::TextureFormat::R:		return tcu::BVec4(true,	false,	false,	false);
		case tcu::TextureFormat::RG:	return tcu::BVec4(true,	true,	false,	false);
		case tcu::TextureFormat::RGB:	return tcu::BVec4(true,	true,	true,	false);
		case tcu::TextureFormat::RGBA:	return tcu::BVec4(true,	true,	true,	true);
		case tcu::TextureFormat::sRGB:	return tcu::BVec4(true,	true,	true,	false);
		case tcu::TextureFormat::sRGBA:	return tcu::BVec4(true,	true,	true,	true);
		default:
			DE_ASSERT(false);
			return tcu::BVec4(false);
	}
}

class BlitColorConversionCase : public FboTestCase
{
public:
	BlitColorConversionCase (Context& context, const char* name, const char* desc, deUint32 srcFormat, deUint32 dstFormat, const IVec2& size)
		: FboTestCase	(context, name, desc)
		, m_srcFormat	(srcFormat)
		, m_dstFormat	(dstFormat)
		, m_size		(size)
	{
	}

protected:
	void preCheck (void)
	{
		checkFormatSupport(m_srcFormat);
		checkFormatSupport(m_dstFormat);
	}

	void render (tcu::Surface& dst)
	{
		tcu::TextureFormat		srcFormat			= glu::mapGLInternalFormat(m_srcFormat);
		tcu::TextureFormat		dstFormat			= glu::mapGLInternalFormat(m_dstFormat);
		glu::DataType			srcOutputType		= getFragmentOutputType(srcFormat);
		glu::DataType			dstOutputType		= getFragmentOutputType(dstFormat);

		// Compute ranges \note Doesn't handle case where src or dest is not subset of the another!
		tcu::TextureFormatInfo	srcFmtRangeInfo		= tcu::getTextureFormatInfo(srcFormat);
		tcu::TextureFormatInfo	dstFmtRangeInfo		= tcu::getTextureFormatInfo(dstFormat);
		tcu::BVec4				copyMask			= tcu::logicalAnd(getChannelMask(srcFormat.order), getChannelMask(dstFormat.order));
		tcu::BVec4				srcIsGreater		= tcu::greaterThan(srcFmtRangeInfo.valueMax-srcFmtRangeInfo.valueMin, dstFmtRangeInfo.valueMax-dstFmtRangeInfo.valueMin);
		tcu::TextureFormatInfo	srcRangeInfo		(tcu::select(dstFmtRangeInfo.valueMin,		srcFmtRangeInfo.valueMin,		tcu::logicalAnd(copyMask, srcIsGreater)),
													 tcu::select(dstFmtRangeInfo.valueMax,		srcFmtRangeInfo.valueMax,		tcu::logicalAnd(copyMask, srcIsGreater)),
													 tcu::select(dstFmtRangeInfo.lookupScale,	srcFmtRangeInfo.lookupScale,	tcu::logicalAnd(copyMask, srcIsGreater)),
													 tcu::select(dstFmtRangeInfo.lookupBias,	srcFmtRangeInfo.lookupBias,		tcu::logicalAnd(copyMask, srcIsGreater)));
		tcu::TextureFormatInfo	dstRangeInfo		(tcu::select(dstFmtRangeInfo.valueMin,		srcFmtRangeInfo.valueMin,		tcu::logicalOr(tcu::logicalNot(copyMask), srcIsGreater)),
													 tcu::select(dstFmtRangeInfo.valueMax,		srcFmtRangeInfo.valueMax,		tcu::logicalOr(tcu::logicalNot(copyMask), srcIsGreater)),
													 tcu::select(dstFmtRangeInfo.lookupScale,	srcFmtRangeInfo.lookupScale,	tcu::logicalOr(tcu::logicalNot(copyMask), srcIsGreater)),
													 tcu::select(dstFmtRangeInfo.lookupBias,	srcFmtRangeInfo.lookupBias,		tcu::logicalOr(tcu::logicalNot(copyMask), srcIsGreater)));

		// Shaders.
		GradientShader			gradientToSrcShader	(srcOutputType);
		GradientShader			gradientToDstShader	(dstOutputType);

		deUint32				gradShaderSrcID		= getCurrentContext()->createProgram(&gradientToSrcShader);
		deUint32				gradShaderDstID		= getCurrentContext()->createProgram(&gradientToDstShader);

		deUint32				srcFbo, dstFbo;
		deUint32				srcRbo, dstRbo;

		// Create framebuffers.
		for (int ndx = 0; ndx < 2; ndx++)
		{
			deUint32&	fbo		= ndx ? dstFbo : srcFbo;
			deUint32&	rbo		= ndx ? dstRbo : srcRbo;
			deUint32	format	= ndx ? m_dstFormat : m_srcFormat;

			glGenFramebuffers(1, &fbo);
			glGenRenderbuffers(1, &rbo);

			glBindRenderbuffer(GL_RENDERBUFFER, rbo);
			glRenderbufferStorage(GL_RENDERBUFFER, format, m_size.x(), m_size.y());

			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
			checkError();
			checkFramebufferStatus(GL_FRAMEBUFFER);
		}

		glViewport(0, 0, m_size.x(), m_size.y());

		// Render gradients.
		for (int ndx = 0; ndx < 2; ndx++)
		{
			glBindFramebuffer(GL_FRAMEBUFFER, ndx ? dstFbo : srcFbo);

			if (ndx)
			{
				gradientToDstShader.setGradient(*getCurrentContext(), gradShaderDstID, dstRangeInfo.valueMax, dstRangeInfo.valueMin);
				sglr::drawQuad(*getCurrentContext(), gradShaderDstID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
			}
			else
			{
				gradientToSrcShader.setGradient(*getCurrentContext(), gradShaderSrcID, srcRangeInfo.valueMin, dstRangeInfo.valueMax);
				sglr::drawQuad(*getCurrentContext(), gradShaderSrcID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
			}
		}

		// Execute copy.
		glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFbo);
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFbo);
		glBlitFramebuffer(0, 0, m_size.x(), m_size.y(), 0, 0, m_size.x(), m_size.y(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
		checkError();

		// Read results.
		glBindFramebuffer(GL_READ_FRAMEBUFFER, dstFbo);
		readPixels(dst, 0, 0, m_size.x(), m_size.y(), dstFormat, dstRangeInfo.lookupScale, dstRangeInfo.lookupBias);
	}

	bool compare (const tcu::Surface& reference, const tcu::Surface& result)
	{
		const tcu::TextureFormat	srcFormat	= glu::mapGLInternalFormat(m_srcFormat);
		const tcu::TextureFormat	dstFormat	= glu::mapGLInternalFormat(m_dstFormat);
		const bool					srcIsSRGB	= tcu::isSRGB(srcFormat);
		const bool					dstIsSRGB	= tcu::isSRGB(dstFormat);

		tcu::RGBA					threshold;

		if (dstIsSRGB)
		{
			threshold = getToSRGBConversionThreshold(srcFormat, dstFormat);
		}
		else
		{
			const tcu::RGBA	srcMaxDiff	= getFormatThreshold(srcFormat) * (srcIsSRGB ? 2 : 1);
			const tcu::RGBA	dstMaxDiff	= getFormatThreshold(dstFormat);

			threshold = tcu::max(srcMaxDiff, dstMaxDiff);
		}

		m_testCtx.getLog() << tcu::TestLog::Message << "threshold = " << threshold << tcu::TestLog::EndMessage;
		return tcu::pixelThresholdCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference, result, threshold, tcu::COMPARE_LOG_RESULT);
	}

private:
	deUint32		m_srcFormat;
	deUint32		m_dstFormat;
	IVec2			m_size;
};

class BlitDepthStencilCase : public FboTestCase
{
public:
	BlitDepthStencilCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 srcBuffers, const IVec2& srcSize, const IVec4& srcRect, deUint32 dstBuffers, const IVec2& dstSize, const IVec4& dstRect, deUint32 copyBuffers)
		: FboTestCase	(context, name, desc)
		, m_format		(format)
		, m_srcBuffers	(srcBuffers)
		, m_srcSize		(srcSize)
		, m_srcRect		(srcRect)
		, m_dstBuffers	(dstBuffers)
		, m_dstSize		(dstSize)
		, m_dstRect		(dstRect)
		, m_copyBuffers	(copyBuffers)
	{
	}

protected:
	void preCheck (void)
	{
		checkFormatSupport(m_format);
	}

	void render (tcu::Surface& dst)
	{
		const deUint32			colorFormat			= GL_RGBA8;

		GradientShader			gradShader			(glu::TYPE_FLOAT_VEC4);
		Texture2DShader			texShader			(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
		FlatColorShader			flatShader			(glu::TYPE_FLOAT_VEC4);

		deUint32				flatShaderID		= getCurrentContext()->createProgram(&flatShader);
		deUint32				texShaderID			= getCurrentContext()->createProgram(&texShader);
		deUint32				gradShaderID		= getCurrentContext()->createProgram(&gradShader);

		deUint32				srcFbo				= 0;
		deUint32				dstFbo				= 0;
		deUint32				srcColorRbo			= 0;
		deUint32				dstColorRbo			= 0;
		deUint32				srcDepthStencilRbo	= 0;
		deUint32				dstDepthStencilRbo	= 0;

		// setup shaders
		gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));
		texShader.setUniforms(*getCurrentContext(), texShaderID);

		// Create framebuffers.
		for (int ndx = 0; ndx < 2; ndx++)
		{
			deUint32&		fbo				= ndx ? dstFbo : srcFbo;
			deUint32&		colorRbo		= ndx ? dstColorRbo : srcColorRbo;
			deUint32&		depthStencilRbo	= ndx ? dstDepthStencilRbo : srcDepthStencilRbo;
			deUint32		bufs			= ndx ? m_dstBuffers : m_srcBuffers;
			const IVec2&	size			= ndx ? m_dstSize : m_srcSize;

			glGenFramebuffers(1, &fbo);
			glGenRenderbuffers(1, &colorRbo);
			glGenRenderbuffers(1, &depthStencilRbo);

			glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
			glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, size.x(), size.y());

			glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo);
			glRenderbufferStorage(GL_RENDERBUFFER, m_format, size.x(), size.y());

			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);

			if (bufs & GL_DEPTH_BUFFER_BIT)
				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
			if (bufs & GL_STENCIL_BUFFER_BIT)
				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);

			checkError();
			checkFramebufferStatus(GL_FRAMEBUFFER);

			// Clear depth to 1 and stencil to 0.
			glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0);
		}

		// Fill source with gradient, depth = [-1..1], stencil = 7
		glBindFramebuffer(GL_FRAMEBUFFER, srcFbo);
		glViewport(0, 0, m_srcSize.x(), m_srcSize.y());
		glEnable(GL_DEPTH_TEST);
		glEnable(GL_STENCIL_TEST);
		glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc(GL_ALWAYS, 7, 0xffu);

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

		// Fill destination with grid pattern, depth = 0 and stencil = 1
		{
			const deUint32		format		= GL_RGBA;
			const deUint32		dataType	= GL_UNSIGNED_BYTE;
			const int			texW		= m_srcSize.x();
			const int			texH		= m_srcSize.y();
			deUint32			gridTex		= 0;
			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);

			tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f));

			glGenTextures(1, &gridTex);
			glBindTexture(GL_TEXTURE_2D, gridTex);
			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());

			glBindFramebuffer(GL_FRAMEBUFFER, dstFbo);
			glViewport(0, 0, m_dstSize.x(), m_dstSize.y());
			glStencilFunc(GL_ALWAYS, 1, 0xffu);
			sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
		}

		// Perform copy.
		glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFbo);
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFbo);
		glBlitFramebuffer(m_srcRect.x(), m_srcRect.y(), m_srcRect.z(), m_srcRect.w(), m_dstRect.x(), m_dstRect.y(), m_dstRect.z(), m_dstRect.w(), m_copyBuffers, GL_NEAREST);

		// Render blue color where depth < 0, decrement on depth failure.
		glBindFramebuffer(GL_FRAMEBUFFER, dstFbo);
		glViewport(0, 0, m_dstSize.x(), m_dstSize.y());
		glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
		glStencilFunc(GL_ALWAYS, 0, 0xffu);

		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));

		if (m_dstBuffers & GL_STENCIL_BUFFER_BIT)
		{
			// Render green color where stencil == 6.
			glDisable(GL_DEPTH_TEST);
			glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
			glStencilFunc(GL_EQUAL, 6, 0xffu);

			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));
		}

		readPixels(dst, 0, 0, m_dstSize.x(), m_dstSize.y(), glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f));
	}

private:
	deUint32	m_format;
	deUint32	m_srcBuffers;
	IVec2		m_srcSize;
	IVec4		m_srcRect;
	deUint32	m_dstBuffers;
	IVec2		m_dstSize;
	IVec4		m_dstRect;
	deUint32	m_copyBuffers;
};

class BlitDefaultFramebufferCase : public FboTestCase
{
public:
	BlitDefaultFramebufferCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 filter)
		: FboTestCase	(context, name, desc)
		, m_format		(format)
		, m_filter		(filter)
	{
	}

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

		checkFormatSupport(m_format);
	}

	virtual void render (tcu::Surface& dst)
	{
		tcu::TextureFormat		colorFormat		= glu::mapGLInternalFormat(m_format);
		glu::TransferFormat		transferFmt		= glu::getTransferFormat(colorFormat);
		GradientShader			gradShader		(glu::TYPE_FLOAT_VEC4);
		Texture2DShader			texShader		(DataTypes() << glu::getSampler2DType(colorFormat), glu::TYPE_FLOAT_VEC4);
		deUint32				gradShaderID	= getCurrentContext()->createProgram(&gradShader);
		deUint32				texShaderID		= getCurrentContext()->createProgram(&texShader);
		deUint32				fbo				= 0;
		deUint32				tex				= 0;
		const int				texW			= 128;
		const int				texH			= 128;

		// Setup shaders
		gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));
		texShader.setUniforms(*getCurrentContext(), texShaderID);

		// FBO
		glGenFramebuffers(1, &fbo);
		glGenTextures(1, &tex);

		glBindTexture(GL_TEXTURE_2D, tex);
		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	m_filter);
		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	m_filter);
		glTexImage2D(GL_TEXTURE_2D, 0, m_format, texW, texH, 0, transferFmt.format, transferFmt.dataType, DE_NULL);

		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
		checkError();
		checkFramebufferStatus(GL_FRAMEBUFFER);

		// Render gradient to screen.
		glBindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());

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

		// Blit gradient from screen to fbo.
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
		glBlitFramebuffer(0, 0, getWidth(), getHeight(), 0, 0, texW, texH, GL_COLOR_BUFFER_BIT, m_filter);

		// Fill left half of viewport with quad that uses texture.
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
		glClearBufferfv(GL_COLOR, 0, Vec4(1.0f, 0.0f, 0.0f, 1.0f).getPtr());
		sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));

		// Blit fbo to right half.
		glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
		glBlitFramebuffer(0, 0, texW, texH, getWidth()/2, 0, getWidth(), getHeight(), GL_COLOR_BUFFER_BIT, m_filter);

		glBindFramebuffer(GL_READ_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
		readPixels(dst, 0, 0, getWidth(), getHeight());
	}

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

		m_testCtx.getLog() << TestLog::Message << "Comparing images, threshold: " << threshold << TestLog::EndMessage;

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

protected:
	const deUint32	m_format;
	const deUint32	m_filter;
};

class DefaultFramebufferBlitCase : public BlitDefaultFramebufferCase
{
public:
	enum BlitDirection
	{
		BLIT_DEFAULT_TO_TARGET,
		BLIT_TO_DEFAULT_FROM_TARGET,

		BLIT_LAST
	};
	enum BlitArea
	{
		AREA_SCALE,
		AREA_OUT_OF_BOUNDS,

		AREA_LAST
	};

	DefaultFramebufferBlitCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 filter, BlitDirection dir, BlitArea area)
		: BlitDefaultFramebufferCase	(context, name, desc, format, filter)
		, m_blitDir						(dir)
		, m_blitArea					(area)
		, m_srcRect						(-1, -1, -1, -1)
		, m_dstRect						(-1, -1, -1, -1)
		, m_interestingArea				(-1, -1, -1, -1)
	{
		DE_ASSERT(dir < BLIT_LAST);
		DE_ASSERT(area < AREA_LAST);
	}

	void init (void)
	{
		// requirements
		const int minViewportSize = 128;
		if (m_context.getRenderTarget().getWidth() < minViewportSize || m_context.getRenderTarget().getHeight() < minViewportSize)
			throw tcu::NotSupportedError("Viewport size " + de::toString(minViewportSize) + "x" + de::toString(minViewportSize) + " required");

		// prevent viewport randoming
		m_viewportWidth = m_context.getRenderTarget().getWidth();
		m_viewportHeight = m_context.getRenderTarget().getHeight();

		// set proper areas
		if (m_blitArea == AREA_SCALE)
		{
			m_srcRect = IVec4( 10,  20,  65, 100);
			m_dstRect = IVec4( 25,  30, 125,  94);
			m_interestingArea = IVec4(0, 0, 128, 128);
		}
		else if (m_blitArea == AREA_OUT_OF_BOUNDS)
		{
			const tcu::IVec2 ubound = (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (tcu::IVec2(128, 128)) : (tcu::IVec2(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight()));

			m_srcRect = IVec4(-10, -15, 100,  63);
			m_dstRect = ubound.swizzle(0, 1, 0, 1) + IVec4(-75, -99, 8, 16);
			m_interestingArea = IVec4(ubound.x() - 128, ubound.y() - 128, ubound.x(), ubound.y());
		}
		else
			DE_ASSERT(false);
	}

	void render (tcu::Surface& dst)
	{
		const tcu::TextureFormat		colorFormat		= glu::mapGLInternalFormat(m_format);
		const glu::TransferFormat		transferFmt		= glu::getTransferFormat(colorFormat);
		const tcu::TextureChannelClass	targetClass		= (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (tcu::getTextureChannelClass(colorFormat.type)) : (tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT);
		deUint32						fbo				= 0;
		deUint32						fboTex			= 0;
		const int						fboTexW			= 128;
		const int						fboTexH			= 128;
		const int						sourceWidth		= (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (getWidth()) : (fboTexW);
		const int						sourceHeight	= (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (getHeight()) : (fboTexH);
		const int						gridRenderWidth	= de::min(256, sourceWidth);
		const int						gridRenderHeight= de::min(256, sourceHeight);

		int								targetFbo		= -1;
		int								sourceFbo		= -1;

		// FBO
		glGenFramebuffers(1, &fbo);
		glGenTextures(1, &fboTex);

		glBindTexture(GL_TEXTURE_2D, fboTex);
		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	m_filter);
		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	m_filter);
		glTexImage2D(GL_TEXTURE_2D, 0, m_format, fboTexW, fboTexH, 0, transferFmt.format, transferFmt.dataType, DE_NULL);

		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
		checkError();
		checkFramebufferStatus(GL_FRAMEBUFFER);

		targetFbo = (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (fbo) : (m_context.getRenderContext().getDefaultFramebuffer());
		sourceFbo = (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (m_context.getRenderContext().getDefaultFramebuffer()) : (fbo);

		// Render grid to source framebuffer
		{
			Texture2DShader		texShader		(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
			const deUint32		texShaderID		= getCurrentContext()->createProgram(&texShader);
			const deUint32		internalFormat	= GL_RGBA8;
			const deUint32		format			= GL_RGBA;
			const deUint32		dataType		= GL_UNSIGNED_BYTE;
			const int			gridTexW		= 128;
			const int			gridTexH		= 128;
			deUint32			gridTex			= 0;
			tcu::TextureLevel	data			(glu::mapGLTransferFormat(format, dataType), gridTexW, gridTexH, 1);

			tcu::fillWithGrid(data.getAccess(), 9, tcu::Vec4(0.9f, 0.5f, 0.1f, 0.9f), tcu::Vec4(0.2f, 0.8f, 0.2f, 0.7f));

			glGenTextures(1, &gridTex);
			glBindTexture(GL_TEXTURE_2D, gridTex);
			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
			glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, gridTexW, gridTexH, 0, format, dataType, data.getAccess().getDataPtr());

			glBindFramebuffer(GL_FRAMEBUFFER, sourceFbo);
			glViewport(0, 0, gridRenderWidth, gridRenderHeight);
			glClearBufferfv(GL_COLOR, 0, Vec4(1.0f, 0.0f, 0.0f, 1.0f).getPtr());

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

		// Blit source framebuffer to destination

		glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFbo);
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, targetFbo);
		checkError();

		if (targetClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || targetClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || targetClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
			glClearBufferfv(GL_COLOR, 0, Vec4(1.0f, 1.0f, 0.0f, 1.0f).getPtr());
		else if (targetClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
			glClearBufferiv(GL_COLOR, 0, IVec4(0, 0, 0, 0).getPtr());
		else if (targetClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
			glClearBufferuiv(GL_COLOR, 0, UVec4(0, 0, 0, 0).getPtr());
		else
			DE_ASSERT(false);

		glBlitFramebuffer(m_srcRect.x(), m_srcRect.y(), m_srcRect.z(), m_srcRect.w(), m_dstRect.x(), m_dstRect.y(), m_dstRect.z(), m_dstRect.w(), GL_COLOR_BUFFER_BIT, m_filter);
		checkError();

		// Read target

		glBindFramebuffer(GL_FRAMEBUFFER, targetFbo);

		if (m_blitDir == BLIT_TO_DEFAULT_FROM_TARGET)
			readPixels(dst, m_interestingArea.x(), m_interestingArea.y(), m_interestingArea.z() - m_interestingArea.x(), m_interestingArea.w() - m_interestingArea.y());
		else
			readPixels(dst, m_interestingArea.x(), m_interestingArea.y(), m_interestingArea.z() - m_interestingArea.x(), m_interestingArea.w() - m_interestingArea.y(), colorFormat, tcu::Vec4(1.0f), tcu::Vec4(0.0f));

		checkError();
	}

private:
	const BlitDirection	m_blitDir;
	const BlitArea		m_blitArea;
	tcu::IVec4			m_srcRect;
	tcu::IVec4			m_dstRect;
	tcu::IVec4			m_interestingArea;
};

FramebufferBlitTests::FramebufferBlitTests (Context& context)
	: TestCaseGroup(context, "blit", "Framebuffer blit tests")
{
}

FramebufferBlitTests::~FramebufferBlitTests (void)
{
}

void FramebufferBlitTests::init (void)
{
	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
	};

	static const deUint32 depthStencilFormats[] =
	{
		GL_DEPTH_COMPONENT32F,
		GL_DEPTH_COMPONENT24,
		GL_DEPTH_COMPONENT16,
		GL_DEPTH32F_STENCIL8,
		GL_DEPTH24_STENCIL8,
		GL_STENCIL_INDEX8
	};

	// .rect
	{
		static const struct
		{
			const char*	name;
			IVec4		srcRect;
			IVec4		dstRect;
		} copyRects[] =
		{
			{ "basic",						IVec4( 10,  20,  65, 100),		IVec4( 45,   5, 100,  85) },
			{ "scale",						IVec4( 10,  20,  65, 100),		IVec4( 25,  30, 125,  94) },
			{ "out_of_bounds",				IVec4(-10, -15, 100,  63),		IVec4( 50,  30, 136, 144) },
		};

		static const struct
		{
			const char*	name;
			IVec4		srcRect;
			IVec4		dstRect;
		} filterConsistencyRects[] =
		{
			{ "mag",						IVec4( 20,  10,  74, 88),		IVec4( 10,  10,  91, 101) },
			{ "min",						IVec4( 10,  20,  78, 100),		IVec4( 20,  20,  71,  80) },
			{ "out_of_bounds_mag",			IVec4( 21,  10,  73, 82),		IVec4( 11,  43, 141, 151) },
			{ "out_of_bounds_min",			IVec4( 11,  21,  77, 97),		IVec4( 80,  82, 135, 139) },
		};

		static const struct
		{
			const char* name;
			IVec4		srcSwizzle;
			IVec4		dstSwizzle;
		} swizzles[] =
		{
			{ DE_NULL,				IVec4(0,1,2,3),	IVec4(0,1,2,3) },
			{ "reverse_src_x",		IVec4(2,1,0,3), IVec4(0,1,2,3) },
			{ "reverse_src_y",		IVec4(0,3,2,1), IVec4(0,1,2,3) },
			{ "reverse_dst_x",		IVec4(0,1,2,3), IVec4(2,1,0,3) },
			{ "reverse_dst_y",		IVec4(0,1,2,3), IVec4(0,3,2,1) },
			{ "reverse_src_dst_x",	IVec4(2,1,0,3), IVec4(2,1,0,3) },
			{ "reverse_src_dst_y",	IVec4(0,3,2,1), IVec4(0,3,2,1) }
		};

		const IVec2 srcSize(127, 119);
		const IVec2 dstSize(132, 128);

		// Blit rectangle tests.
		tcu::TestCaseGroup* rectGroup = new tcu::TestCaseGroup(m_testCtx, "rect", "Blit rectangle tests");
		addChild(rectGroup);
		for (int rectNdx = 0; rectNdx < DE_LENGTH_OF_ARRAY(copyRects); rectNdx++)
		{
			for (int swzNdx = 0; swzNdx < DE_LENGTH_OF_ARRAY(swizzles); swzNdx++)
			{
				string		name	= string(copyRects[rectNdx].name) + (swizzles[swzNdx].name ? (string("_") + swizzles[swzNdx].name) : string());
				IVec4		srcSwz	= swizzles[swzNdx].srcSwizzle;
				IVec4		dstSwz	= swizzles[swzNdx].dstSwizzle;
				IVec4		srcRect	= copyRects[rectNdx].srcRect.swizzle(srcSwz[0], srcSwz[1], srcSwz[2], srcSwz[3]);
				IVec4		dstRect	= copyRects[rectNdx].dstRect.swizzle(dstSwz[0], dstSwz[1], dstSwz[2], dstSwz[3]);

				rectGroup->addChild(new BlitRectCase(m_context, (name + "_nearest").c_str(),	"", GL_NEAREST,	srcSize, srcRect, dstSize, dstRect));
				rectGroup->addChild(new BlitRectCase(m_context, (name + "_linear").c_str(),		"", GL_LINEAR,	srcSize, srcRect, dstSize, dstRect));
			}
		}

		// Nearest filter tests
		for (int rectNdx = 0; rectNdx < DE_LENGTH_OF_ARRAY(filterConsistencyRects); rectNdx++)
		{
			for (int swzNdx = 0; swzNdx < DE_LENGTH_OF_ARRAY(swizzles); swzNdx++)
			{
				string		name	= string("nearest_consistency_") + filterConsistencyRects[rectNdx].name + (swizzles[swzNdx].name ? (string("_") + swizzles[swzNdx].name) : string());
				IVec4		srcSwz	= swizzles[swzNdx].srcSwizzle;
				IVec4		dstSwz	= swizzles[swzNdx].dstSwizzle;
				IVec4		srcRect	= filterConsistencyRects[rectNdx].srcRect.swizzle(srcSwz[0], srcSwz[1], srcSwz[2], srcSwz[3]);
				IVec4		dstRect	= filterConsistencyRects[rectNdx].dstRect.swizzle(dstSwz[0], dstSwz[1], dstSwz[2], dstSwz[3]);

				rectGroup->addChild(new BlitNearestFilterConsistencyCase(m_context, name.c_str(), "Test consistency of the nearest filter", srcSize, srcRect, dstSize, dstRect));
			}
		}
	}

	// .conversion
	{
		tcu::TestCaseGroup* conversionGroup = new tcu::TestCaseGroup(m_testCtx, "conversion", "Color conversion tests");
		addChild(conversionGroup);

		for (int srcFmtNdx = 0; srcFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); srcFmtNdx++)
		{
			for (int dstFmtNdx = 0; dstFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); dstFmtNdx++)
			{
				deUint32					srcFormat	= colorFormats[srcFmtNdx];
				tcu::TextureFormat			srcTexFmt	= glu::mapGLInternalFormat(srcFormat);
				tcu::TextureChannelClass	srcType		= tcu::getTextureChannelClass(srcTexFmt.type);
				deUint32					dstFormat	= colorFormats[dstFmtNdx];
				tcu::TextureFormat			dstTexFmt	= glu::mapGLInternalFormat(dstFormat);
				tcu::TextureChannelClass	dstType		= tcu::getTextureChannelClass(dstTexFmt.type);

				if (((srcType == tcu::TEXTURECHANNELCLASS_FLOATING_POINT || srcType == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) !=
					 (dstType == tcu::TEXTURECHANNELCLASS_FLOATING_POINT || dstType == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)) ||
					((srcType == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) != (dstType == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)) ||
					((srcType == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) != (dstType == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)))
					continue; // Conversion not supported.

				string						name		= string(getFormatName(srcFormat)) + "_to_" + getFormatName(dstFormat);

				conversionGroup->addChild(new BlitColorConversionCase(m_context, name.c_str(), "", srcFormat, dstFormat, IVec2(127, 113)));
			}
		}
	}

	// .depth_stencil
	{
		tcu::TestCaseGroup* depthStencilGroup = new tcu::TestCaseGroup(m_testCtx, "depth_stencil", "Depth and stencil blits");
		addChild(depthStencilGroup);

		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
		{
			deUint32			format		= depthStencilFormats[fmtNdx];
			tcu::TextureFormat	texFmt		= glu::mapGLInternalFormat(format);
			string				fmtName		= getFormatName(format);
			bool				depth		= texFmt.order == tcu::TextureFormat::D || texFmt.order == tcu::TextureFormat::DS;
			bool				stencil		= texFmt.order == tcu::TextureFormat::S || texFmt.order == tcu::TextureFormat::DS;
			deUint32			buffers		= (depth ? GL_DEPTH_BUFFER_BIT : 0) | (stencil ? GL_STENCIL_BUFFER_BIT : 0);

			depthStencilGroup->addChild(new BlitDepthStencilCase(m_context, (fmtName + "_basic").c_str(), "", format, buffers, IVec2(128, 128), IVec4(0, 0, 128, 128), buffers, IVec2(128, 128), IVec4(0, 0, 128, 128), buffers));
			depthStencilGroup->addChild(new BlitDepthStencilCase(m_context, (fmtName + "_scale").c_str(), "", format, buffers, IVec2(127, 119), IVec4(10, 30, 100, 70), buffers, IVec2(111, 130), IVec4(20, 5, 80, 130), buffers));

			if (depth && stencil)
			{
				depthStencilGroup->addChild(new BlitDepthStencilCase(m_context, (fmtName + "_depth_only").c_str(),		"", format, buffers, IVec2(128, 128), IVec4(0, 0, 128, 128), buffers, IVec2(128, 128), IVec4(0, 0, 128, 128), GL_DEPTH_BUFFER_BIT));
				depthStencilGroup->addChild(new BlitDepthStencilCase(m_context, (fmtName + "_stencil_only").c_str(),	"", format, buffers, IVec2(128, 128), IVec4(0, 0, 128, 128), buffers, IVec2(128, 128), IVec4(0, 0, 128, 128), GL_STENCIL_BUFFER_BIT));
			}
		}
	}

	// .default_framebuffer
	{
		static const struct
		{
			const char*								name;
			DefaultFramebufferBlitCase::BlitArea	area;
		} areas[] =
		{
			{ "scale",						DefaultFramebufferBlitCase::AREA_SCALE			},
			{ "out_of_bounds",				DefaultFramebufferBlitCase::AREA_OUT_OF_BOUNDS	},
		};

		tcu::TestCaseGroup* defaultFbGroup = new tcu::TestCaseGroup(m_testCtx, "default_framebuffer", "Blits with default framebuffer");
		addChild(defaultFbGroup);

		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
		{
			const deUint32					format		= colorFormats[fmtNdx];
			const tcu::TextureFormat		texFmt		= glu::mapGLInternalFormat(format);
			const tcu::TextureChannelClass	fmtClass	= tcu::getTextureChannelClass(texFmt.type);
			const deUint32					filter		= glu::isGLInternalColorFormatFilterable(format) ? GL_LINEAR : GL_NEAREST;
			const bool						filterable	= glu::isGLInternalColorFormatFilterable(format);

			if (fmtClass != tcu::TEXTURECHANNELCLASS_FLOATING_POINT &&
				fmtClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT &&
				fmtClass != tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT)
				continue; // Conversion not supported.

			defaultFbGroup->addChild(new BlitDefaultFramebufferCase(m_context, getFormatName(format), "", format, filter));

			for (int areaNdx = 0; areaNdx < DE_LENGTH_OF_ARRAY(areas); areaNdx++)
			{
				const string	name				= string(areas[areaNdx].name);
				const bool		addLinear			= filterable;
				const bool		addNearest			= !addLinear || (areas[areaNdx].area != DefaultFramebufferBlitCase::AREA_OUT_OF_BOUNDS); // No need to check out-of-bounds with different filtering

				if (addNearest)
				{
					defaultFbGroup->addChild(new DefaultFramebufferBlitCase(m_context, (std::string(getFormatName(format)) + "_nearest_" + name + "_blit_from_default").c_str(), "", format, GL_NEAREST, DefaultFramebufferBlitCase::BLIT_DEFAULT_TO_TARGET, areas[areaNdx].area));
					defaultFbGroup->addChild(new DefaultFramebufferBlitCase(m_context, (std::string(getFormatName(format)) + "_nearest_" + name + "_blit_to_default").c_str(), "", format, GL_NEAREST, DefaultFramebufferBlitCase::BLIT_TO_DEFAULT_FROM_TARGET, areas[areaNdx].area));
				}

				if (addLinear)
				{
					defaultFbGroup->addChild(new DefaultFramebufferBlitCase(m_context, (std::string(getFormatName(format)) + "_linear_" + name + "_blit_from_default").c_str(), "", format, GL_LINEAR, DefaultFramebufferBlitCase::BLIT_DEFAULT_TO_TARGET, areas[areaNdx].area));
					defaultFbGroup->addChild(new DefaultFramebufferBlitCase(m_context, (std::string(getFormatName(format)) + "_linear_" + name + "_blit_to_default").c_str(), "", format, GL_LINEAR, DefaultFramebufferBlitCase::BLIT_TO_DEFAULT_FROM_TARGET, areas[areaNdx].area));
				}
			}
		}
	}
}

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