Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.0 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief FBO stencilbuffer tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es3fFramebufferBlitTests.hpp"
     25 #include "es3fFboTestCase.hpp"
     26 #include "es3fFboTestUtil.hpp"
     27 #include "gluTextureUtil.hpp"
     28 #include "tcuTextureUtil.hpp"
     29 #include "tcuVectorUtil.hpp"
     30 #include "tcuTestLog.hpp"
     31 #include "tcuImageCompare.hpp"
     32 #include "tcuRenderTarget.hpp"
     33 #include "sglrContextUtil.hpp"
     34 #include "glwEnums.hpp"
     35 #include "deStringUtil.hpp"
     36 
     37 namespace deqp
     38 {
     39 namespace gles3
     40 {
     41 namespace Functional
     42 {
     43 
     44 using std::string;
     45 using tcu::TestLog;
     46 using tcu::Vec2;
     47 using tcu::Vec3;
     48 using tcu::Vec4;
     49 using tcu::IVec2;
     50 using tcu::IVec3;
     51 using tcu::IVec4;
     52 using tcu::UVec4;
     53 using namespace FboTestUtil;
     54 
     55 class BlitRectCase : public FboTestCase
     56 {
     57 public:
     58 	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)
     59 		: FboTestCase		(context, name, desc)
     60 		, m_filter			(filter)
     61 		, m_srcSize			(srcSize)
     62 		, m_srcRect			(srcRect)
     63 		, m_dstSize			(dstSize)
     64 		, m_dstRect			(dstRect)
     65 		, m_cellSize		(cellSize)
     66 		, m_gridCellColorA	(0.2f, 0.7f, 0.1f, 1.0f)
     67 		, m_gridCellColorB	(0.7f, 0.1f, 0.5f, 0.8f)
     68 	{
     69 	}
     70 
     71 	void render (tcu::Surface& dst)
     72 	{
     73 		const deUint32			colorFormat		= GL_RGBA8;
     74 
     75 		GradientShader			gradShader		(glu::TYPE_FLOAT_VEC4);
     76 		Texture2DShader			texShader		(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
     77 		deUint32				gradShaderID	= getCurrentContext()->createProgram(&gradShader);
     78 		deUint32				texShaderID		= getCurrentContext()->createProgram(&texShader);
     79 
     80 		deUint32				srcFbo, dstFbo;
     81 		deUint32				srcRbo, dstRbo;
     82 
     83 		// Setup shaders
     84 		gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));
     85 		texShader.setUniforms(*getCurrentContext(), texShaderID);
     86 
     87 		// Create framebuffers.
     88 		for (int ndx = 0; ndx < 2; ndx++)
     89 		{
     90 			deUint32&		fbo		= ndx ? dstFbo : srcFbo;
     91 			deUint32&		rbo		= ndx ? dstRbo : srcRbo;
     92 			const IVec2&	size	= ndx ? m_dstSize : m_srcSize;
     93 
     94 			glGenFramebuffers(1, &fbo);
     95 			glGenRenderbuffers(1, &rbo);
     96 
     97 			glBindRenderbuffer(GL_RENDERBUFFER, rbo);
     98 			glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, size.x(), size.y());
     99 
    100 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    101 			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
    102 			checkError();
    103 			checkFramebufferStatus(GL_FRAMEBUFFER);
    104 		}
    105 
    106 		// Fill destination with gradient.
    107 		glBindFramebuffer(GL_FRAMEBUFFER, dstFbo);
    108 		glViewport(0, 0, m_dstSize.x(), m_dstSize.y());
    109 
    110 		sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    111 
    112 		// Fill source with grid pattern.
    113 		{
    114 			const deUint32		format		= GL_RGBA;
    115 			const deUint32		dataType	= GL_UNSIGNED_BYTE;
    116 			const int			texW		= m_srcSize.x();
    117 			const int			texH		= m_srcSize.y();
    118 			deUint32			gridTex		= 0;
    119 			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
    120 
    121 			tcu::fillWithGrid(data.getAccess(), m_cellSize, m_gridCellColorA, m_gridCellColorB);
    122 
    123 			glGenTextures(1, &gridTex);
    124 			glBindTexture(GL_TEXTURE_2D, gridTex);
    125 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    126 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    127 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
    128 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
    129 			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
    130 
    131 			glBindFramebuffer(GL_FRAMEBUFFER, srcFbo);
    132 			glViewport(0, 0, m_srcSize.x(), m_srcSize.y());
    133 			sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    134 		}
    135 
    136 		// Perform copy.
    137 		glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFbo);
    138 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFbo);
    139 		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);
    140 
    141 		// Read back results.
    142 		glBindFramebuffer(GL_READ_FRAMEBUFFER, dstFbo);
    143 		readPixels(dst, 0, 0, m_dstSize.x(), m_dstSize.y(), glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f));
    144 	}
    145 
    146 	virtual bool compare (const tcu::Surface& reference, const tcu::Surface& result)
    147 	{
    148 		// Use pixel-threshold compare for rect cases since 1px off will mean failure.
    149 		tcu::RGBA threshold = TestCase::m_context.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7);
    150 		return tcu::pixelThresholdCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference, result, threshold, tcu::COMPARE_LOG_RESULT);
    151 	}
    152 
    153 protected:
    154 	const deUint32	m_filter;
    155 	const IVec2		m_srcSize;
    156 	const IVec4		m_srcRect;
    157 	const IVec2		m_dstSize;
    158 	const IVec4		m_dstRect;
    159 	const int		m_cellSize;
    160 	const Vec4		m_gridCellColorA;
    161 	const Vec4		m_gridCellColorB;
    162 };
    163 
    164 class BlitNearestFilterConsistencyCase : public BlitRectCase
    165 {
    166 public:
    167 			BlitNearestFilterConsistencyCase	(Context& context, const char* name, const char* desc, const IVec2& srcSize, const IVec4& srcRect, const IVec2& dstSize, const IVec4& dstRect);
    168 
    169 	bool	compare								(const tcu::Surface& reference, const tcu::Surface& result);
    170 };
    171 
    172 BlitNearestFilterConsistencyCase::BlitNearestFilterConsistencyCase (Context& context, const char* name, const char* desc, const IVec2& srcSize, const IVec4& srcRect, const IVec2& dstSize, const IVec4& dstRect)
    173 	: BlitRectCase(context, name, desc, GL_NEAREST, srcSize, srcRect, dstSize, dstRect, 1)
    174 {
    175 }
    176 
    177 bool BlitNearestFilterConsistencyCase::compare (const tcu::Surface& reference, const tcu::Surface& result)
    178 {
    179 	DE_ASSERT(reference.getWidth() == result.getWidth());
    180 	DE_ASSERT(reference.getHeight() == result.getHeight());
    181 	DE_UNREF(reference);
    182 
    183 	// Image origin must be visible (for baseColor)
    184 	DE_ASSERT(de::min(m_dstRect.x(), m_dstRect.z()) >= 0);
    185 	DE_ASSERT(de::min(m_dstRect.y(), m_dstRect.w()) >= 0);
    186 
    187 	const tcu::RGBA		cellColorA		(m_gridCellColorA);
    188 	const tcu::RGBA		cellColorB		(m_gridCellColorB);
    189 	const tcu::RGBA		threshold		= TestCase::m_context.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7);
    190 	const tcu::IVec4	destinationArea	= tcu::IVec4(de::clamp(de::min(m_dstRect.x(), m_dstRect.z()), 0, result.getWidth()),
    191 													 de::clamp(de::min(m_dstRect.y(), m_dstRect.w()), 0, result.getHeight()),
    192 													 de::clamp(de::max(m_dstRect.x(), m_dstRect.z()), 0, result.getWidth()),
    193 													 de::clamp(de::max(m_dstRect.y(), m_dstRect.w()), 0, result.getHeight()));
    194 	const tcu::RGBA		baseColor		= result.getPixel(destinationArea.x(), destinationArea.y());
    195 	const bool			signConfig		= tcu::compareThreshold(baseColor, cellColorA, threshold);
    196 
    197 	bool				error			= false;
    198 	tcu::Surface		errorMask		(result.getWidth(), result.getHeight());
    199 	std::vector<bool>	horisontalSign	(destinationArea.z() - destinationArea.x());
    200 	std::vector<bool>	verticalSign	(destinationArea.w() - destinationArea.y());
    201 
    202 	tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
    203 
    204 	// Checking only area in our destination rect
    205 
    206 	m_testCtx.getLog()
    207 		<< tcu::TestLog::Message
    208 		<< "Verifying consistency of NEAREST filtering. Verifying rect " << m_dstRect << ".\n"
    209 		<< "Rounding direction of the NEAREST filter at the horisontal texel edge (x = n + 0.5) should not depend on the y-coordinate.\n"
    210 		<< "Rounding direction of the NEAREST filter at the vertical texel edge (y = n + 0.5) should not depend on the x-coordinate.\n"
    211 		<< "Blitting a grid (with uniform sized cells) should result in a grid (with non-uniform sized cells)."
    212 		<< tcu::TestLog::EndMessage;
    213 
    214 	// Verify that destination only contains valid colors
    215 
    216 	for (int dy = 0; dy < destinationArea.w() - destinationArea.y(); ++dy)
    217 	for (int dx = 0; dx < destinationArea.z() - destinationArea.x(); ++dx)
    218 	{
    219 		const tcu::RGBA	color	= result.getPixel(destinationArea.x() + dx, destinationArea.y() + dy);
    220 		const bool isValidColor = tcu::compareThreshold(color, cellColorA, threshold) || tcu::compareThreshold(color, cellColorB, threshold);
    221 
    222 		if (!isValidColor)
    223 		{
    224 			errorMask.setPixel(destinationArea.x() + dx, destinationArea.y() + dy, tcu::RGBA::red());
    225 			error = true;
    226 		}
    227 	}
    228 	if (error)
    229 	{
    230 		m_testCtx.getLog()
    231 			<< tcu::TestLog::Message
    232 			<< "Image verification failed, destination rect contains unexpected values. "
    233 			<< "Expected either " << cellColorA << " or " << cellColorB << "."
    234 			<< tcu::TestLog::EndMessage
    235 			<< tcu::TestLog::ImageSet("Result", "Image verification result")
    236 			<< tcu::TestLog::Image("Result",	"Result",		result)
    237 			<< tcu::TestLog::Image("ErrorMask",	"Error mask",	errorMask)
    238 			<< tcu::TestLog::EndImageSet;
    239 		return false;
    240 	}
    241 
    242 	// Detect result edges by reading the first row and first column of the blitted area.
    243 	// Blitting a grid should result in a grid-like image. ("sign changes" should be consistent)
    244 
    245 	for (int dx = 0; dx < destinationArea.z() - destinationArea.x(); ++dx)
    246 	{
    247 		const tcu::RGBA color = result.getPixel(destinationArea.x() + dx, destinationArea.y());
    248 
    249 		if (tcu::compareThreshold(color, cellColorA, threshold))
    250 			horisontalSign[dx] = true;
    251 		else if (tcu::compareThreshold(color, cellColorB, threshold))
    252 			horisontalSign[dx] = false;
    253 		else
    254 			DE_ASSERT(DE_FALSE);
    255 	}
    256 	for (int dy = 0; dy < destinationArea.w() - destinationArea.y(); ++dy)
    257 	{
    258 		const tcu::RGBA color = result.getPixel(destinationArea.x(), destinationArea.y() + dy);
    259 
    260 		if (tcu::compareThreshold(color, cellColorA, threshold))
    261 			verticalSign[dy] = true;
    262 		else if (tcu::compareThreshold(color, cellColorB, threshold))
    263 			verticalSign[dy] = false;
    264 		else
    265 			DE_ASSERT(DE_FALSE);
    266 	}
    267 
    268 	// Verify grid-like image
    269 
    270 	for (int dy = 0; dy < destinationArea.w() - destinationArea.y(); ++dy)
    271 	for (int dx = 0; dx < destinationArea.z() - destinationArea.x(); ++dx)
    272 	{
    273 		const tcu::RGBA	color		= result.getPixel(destinationArea.x() + dx, destinationArea.y() + dy);
    274 		const bool		resultSign	= tcu::compareThreshold(cellColorA, color, threshold);
    275 		const bool		correctSign	= (horisontalSign[dx] == verticalSign[dy]) == signConfig;
    276 
    277 		if (resultSign != correctSign)
    278 		{
    279 			errorMask.setPixel(destinationArea.x() + dx, destinationArea.y() + dy, tcu::RGBA::red());
    280 			error = true;
    281 		}
    282 	}
    283 
    284 	// Report result
    285 
    286 	if (error)
    287 	{
    288 		m_testCtx.getLog()
    289 			<< tcu::TestLog::Message
    290 			<< "Image verification failed, nearest filter is not consistent."
    291 			<< tcu::TestLog::EndMessage
    292 			<< tcu::TestLog::ImageSet("Result", "Image verification result")
    293 			<< tcu::TestLog::Image("Result",	"Result",		result)
    294 			<< tcu::TestLog::Image("ErrorMask",	"Error mask",	errorMask)
    295 			<< tcu::TestLog::EndImageSet;
    296 	}
    297 	else
    298 	{
    299 		m_testCtx.getLog()
    300 			<< tcu::TestLog::Message
    301 			<< "Image verification passed."
    302 			<< tcu::TestLog::EndMessage
    303 			<< tcu::TestLog::ImageSet("Result", "Image verification result")
    304 			<< tcu::TestLog::Image("Result", "Result", result)
    305 			<< tcu::TestLog::EndImageSet;
    306 	}
    307 
    308 	return !error;
    309 }
    310 
    311 static tcu::BVec4 getChannelMask (tcu::TextureFormat::ChannelOrder order)
    312 {
    313 	switch (order)
    314 	{
    315 		case tcu::TextureFormat::R:		return tcu::BVec4(true,	false,	false,	false);
    316 		case tcu::TextureFormat::RG:	return tcu::BVec4(true,	true,	false,	false);
    317 		case tcu::TextureFormat::RGB:	return tcu::BVec4(true,	true,	true,	false);
    318 		case tcu::TextureFormat::RGBA:	return tcu::BVec4(true,	true,	true,	true);
    319 		case tcu::TextureFormat::sRGB:	return tcu::BVec4(true,	true,	true,	false);
    320 		case tcu::TextureFormat::sRGBA:	return tcu::BVec4(true,	true,	true,	true);
    321 		default:
    322 			DE_ASSERT(false);
    323 			return tcu::BVec4(false);
    324 	}
    325 }
    326 
    327 class BlitColorConversionCase : public FboTestCase
    328 {
    329 public:
    330 	BlitColorConversionCase (Context& context, const char* name, const char* desc, deUint32 srcFormat, deUint32 dstFormat, const IVec2& size)
    331 		: FboTestCase	(context, name, desc)
    332 		, m_srcFormat	(srcFormat)
    333 		, m_dstFormat	(dstFormat)
    334 		, m_size		(size)
    335 	{
    336 	}
    337 
    338 protected:
    339 	void preCheck (void)
    340 	{
    341 		checkFormatSupport(m_srcFormat);
    342 		checkFormatSupport(m_dstFormat);
    343 	}
    344 
    345 	void render (tcu::Surface& dst)
    346 	{
    347 		tcu::TextureFormat		srcFormat			= glu::mapGLInternalFormat(m_srcFormat);
    348 		tcu::TextureFormat		dstFormat			= glu::mapGLInternalFormat(m_dstFormat);
    349 		glu::DataType			srcOutputType		= getFragmentOutputType(srcFormat);
    350 		glu::DataType			dstOutputType		= getFragmentOutputType(dstFormat);
    351 
    352 		// Compute ranges \note Doesn't handle case where src or dest is not subset of the another!
    353 		tcu::TextureFormatInfo	srcFmtRangeInfo		= tcu::getTextureFormatInfo(srcFormat);
    354 		tcu::TextureFormatInfo	dstFmtRangeInfo		= tcu::getTextureFormatInfo(dstFormat);
    355 		tcu::BVec4				copyMask			= tcu::logicalAnd(getChannelMask(srcFormat.order), getChannelMask(dstFormat.order));
    356 		tcu::BVec4				srcIsGreater		= tcu::greaterThan(srcFmtRangeInfo.valueMax-srcFmtRangeInfo.valueMin, dstFmtRangeInfo.valueMax-dstFmtRangeInfo.valueMin);
    357 		tcu::TextureFormatInfo	srcRangeInfo		(tcu::select(dstFmtRangeInfo.valueMin,		srcFmtRangeInfo.valueMin,		tcu::logicalAnd(copyMask, srcIsGreater)),
    358 													 tcu::select(dstFmtRangeInfo.valueMax,		srcFmtRangeInfo.valueMax,		tcu::logicalAnd(copyMask, srcIsGreater)),
    359 													 tcu::select(dstFmtRangeInfo.lookupScale,	srcFmtRangeInfo.lookupScale,	tcu::logicalAnd(copyMask, srcIsGreater)),
    360 													 tcu::select(dstFmtRangeInfo.lookupBias,	srcFmtRangeInfo.lookupBias,		tcu::logicalAnd(copyMask, srcIsGreater)));
    361 		tcu::TextureFormatInfo	dstRangeInfo		(tcu::select(dstFmtRangeInfo.valueMin,		srcFmtRangeInfo.valueMin,		tcu::logicalOr(tcu::logicalNot(copyMask), srcIsGreater)),
    362 													 tcu::select(dstFmtRangeInfo.valueMax,		srcFmtRangeInfo.valueMax,		tcu::logicalOr(tcu::logicalNot(copyMask), srcIsGreater)),
    363 													 tcu::select(dstFmtRangeInfo.lookupScale,	srcFmtRangeInfo.lookupScale,	tcu::logicalOr(tcu::logicalNot(copyMask), srcIsGreater)),
    364 													 tcu::select(dstFmtRangeInfo.lookupBias,	srcFmtRangeInfo.lookupBias,		tcu::logicalOr(tcu::logicalNot(copyMask), srcIsGreater)));
    365 
    366 		// Shaders.
    367 		GradientShader			gradientToSrcShader	(srcOutputType);
    368 		GradientShader			gradientToDstShader	(dstOutputType);
    369 
    370 		deUint32				gradShaderSrcID		= getCurrentContext()->createProgram(&gradientToSrcShader);
    371 		deUint32				gradShaderDstID		= getCurrentContext()->createProgram(&gradientToDstShader);
    372 
    373 		deUint32				srcFbo, dstFbo;
    374 		deUint32				srcRbo, dstRbo;
    375 
    376 		// Create framebuffers.
    377 		for (int ndx = 0; ndx < 2; ndx++)
    378 		{
    379 			deUint32&	fbo		= ndx ? dstFbo : srcFbo;
    380 			deUint32&	rbo		= ndx ? dstRbo : srcRbo;
    381 			deUint32	format	= ndx ? m_dstFormat : m_srcFormat;
    382 
    383 			glGenFramebuffers(1, &fbo);
    384 			glGenRenderbuffers(1, &rbo);
    385 
    386 			glBindRenderbuffer(GL_RENDERBUFFER, rbo);
    387 			glRenderbufferStorage(GL_RENDERBUFFER, format, m_size.x(), m_size.y());
    388 
    389 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    390 			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
    391 			checkError();
    392 			checkFramebufferStatus(GL_FRAMEBUFFER);
    393 		}
    394 
    395 		glViewport(0, 0, m_size.x(), m_size.y());
    396 
    397 		// Render gradients.
    398 		for (int ndx = 0; ndx < 2; ndx++)
    399 		{
    400 			glBindFramebuffer(GL_FRAMEBUFFER, ndx ? dstFbo : srcFbo);
    401 
    402 			if (ndx)
    403 			{
    404 				gradientToDstShader.setGradient(*getCurrentContext(), gradShaderDstID, dstRangeInfo.valueMax, dstRangeInfo.valueMin);
    405 				sglr::drawQuad(*getCurrentContext(), gradShaderDstID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    406 			}
    407 			else
    408 			{
    409 				gradientToSrcShader.setGradient(*getCurrentContext(), gradShaderSrcID, srcRangeInfo.valueMin, dstRangeInfo.valueMax);
    410 				sglr::drawQuad(*getCurrentContext(), gradShaderSrcID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    411 			}
    412 		}
    413 
    414 		// Execute copy.
    415 		glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFbo);
    416 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFbo);
    417 		glBlitFramebuffer(0, 0, m_size.x(), m_size.y(), 0, 0, m_size.x(), m_size.y(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
    418 		checkError();
    419 
    420 		// Read results.
    421 		glBindFramebuffer(GL_READ_FRAMEBUFFER, dstFbo);
    422 		readPixels(dst, 0, 0, m_size.x(), m_size.y(), dstFormat, dstRangeInfo.lookupScale, dstRangeInfo.lookupBias);
    423 	}
    424 
    425 	bool compare (const tcu::Surface& reference, const tcu::Surface& result)
    426 	{
    427 		const tcu::TextureFormat	srcFormat	= glu::mapGLInternalFormat(m_srcFormat);
    428 		const tcu::TextureFormat	dstFormat	= glu::mapGLInternalFormat(m_dstFormat);
    429 		const bool					srcIsSRGB	= tcu::isSRGB(srcFormat);
    430 		const bool					dstIsSRGB	= tcu::isSRGB(dstFormat);
    431 
    432 		tcu::RGBA					threshold;
    433 
    434 		if (dstIsSRGB)
    435 		{
    436 			threshold = getToSRGBConversionThreshold(srcFormat, dstFormat);
    437 		}
    438 		else
    439 		{
    440 			const tcu::RGBA	srcMaxDiff	= getFormatThreshold(srcFormat) * (srcIsSRGB ? 2 : 1);
    441 			const tcu::RGBA	dstMaxDiff	= getFormatThreshold(dstFormat);
    442 
    443 			threshold = tcu::max(srcMaxDiff, dstMaxDiff);
    444 		}
    445 
    446 		m_testCtx.getLog() << tcu::TestLog::Message << "threshold = " << threshold << tcu::TestLog::EndMessage;
    447 		return tcu::pixelThresholdCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference, result, threshold, tcu::COMPARE_LOG_RESULT);
    448 	}
    449 
    450 private:
    451 	deUint32		m_srcFormat;
    452 	deUint32		m_dstFormat;
    453 	IVec2			m_size;
    454 };
    455 
    456 class BlitDepthStencilCase : public FboTestCase
    457 {
    458 public:
    459 	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)
    460 		: FboTestCase	(context, name, desc)
    461 		, m_format		(format)
    462 		, m_srcBuffers	(srcBuffers)
    463 		, m_srcSize		(srcSize)
    464 		, m_srcRect		(srcRect)
    465 		, m_dstBuffers	(dstBuffers)
    466 		, m_dstSize		(dstSize)
    467 		, m_dstRect		(dstRect)
    468 		, m_copyBuffers	(copyBuffers)
    469 	{
    470 	}
    471 
    472 protected:
    473 	void preCheck (void)
    474 	{
    475 		checkFormatSupport(m_format);
    476 	}
    477 
    478 	void render (tcu::Surface& dst)
    479 	{
    480 		const deUint32			colorFormat			= GL_RGBA8;
    481 
    482 		GradientShader			gradShader			(glu::TYPE_FLOAT_VEC4);
    483 		Texture2DShader			texShader			(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
    484 		FlatColorShader			flatShader			(glu::TYPE_FLOAT_VEC4);
    485 
    486 		deUint32				flatShaderID		= getCurrentContext()->createProgram(&flatShader);
    487 		deUint32				texShaderID			= getCurrentContext()->createProgram(&texShader);
    488 		deUint32				gradShaderID		= getCurrentContext()->createProgram(&gradShader);
    489 
    490 		deUint32				srcFbo				= 0;
    491 		deUint32				dstFbo				= 0;
    492 		deUint32				srcColorRbo			= 0;
    493 		deUint32				dstColorRbo			= 0;
    494 		deUint32				srcDepthStencilRbo	= 0;
    495 		deUint32				dstDepthStencilRbo	= 0;
    496 
    497 		// setup shaders
    498 		gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));
    499 		texShader.setUniforms(*getCurrentContext(), texShaderID);
    500 
    501 		// Create framebuffers.
    502 		for (int ndx = 0; ndx < 2; ndx++)
    503 		{
    504 			deUint32&		fbo				= ndx ? dstFbo : srcFbo;
    505 			deUint32&		colorRbo		= ndx ? dstColorRbo : srcColorRbo;
    506 			deUint32&		depthStencilRbo	= ndx ? dstDepthStencilRbo : srcDepthStencilRbo;
    507 			deUint32		bufs			= ndx ? m_dstBuffers : m_srcBuffers;
    508 			const IVec2&	size			= ndx ? m_dstSize : m_srcSize;
    509 
    510 			glGenFramebuffers(1, &fbo);
    511 			glGenRenderbuffers(1, &colorRbo);
    512 			glGenRenderbuffers(1, &depthStencilRbo);
    513 
    514 			glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
    515 			glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, size.x(), size.y());
    516 
    517 			glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo);
    518 			glRenderbufferStorage(GL_RENDERBUFFER, m_format, size.x(), size.y());
    519 
    520 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    521 			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
    522 
    523 			if (bufs & GL_DEPTH_BUFFER_BIT)
    524 				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
    525 			if (bufs & GL_STENCIL_BUFFER_BIT)
    526 				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
    527 
    528 			checkError();
    529 			checkFramebufferStatus(GL_FRAMEBUFFER);
    530 
    531 			// Clear depth to 1 and stencil to 0.
    532 			glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0);
    533 		}
    534 
    535 		// Fill source with gradient, depth = [-1..1], stencil = 7
    536 		glBindFramebuffer(GL_FRAMEBUFFER, srcFbo);
    537 		glViewport(0, 0, m_srcSize.x(), m_srcSize.y());
    538 		glEnable(GL_DEPTH_TEST);
    539 		glEnable(GL_STENCIL_TEST);
    540 		glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    541 		glStencilFunc(GL_ALWAYS, 7, 0xffu);
    542 
    543 		sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
    544 
    545 		// Fill destination with grid pattern, depth = 0 and stencil = 1
    546 		{
    547 			const deUint32		format		= GL_RGBA;
    548 			const deUint32		dataType	= GL_UNSIGNED_BYTE;
    549 			const int			texW		= m_srcSize.x();
    550 			const int			texH		= m_srcSize.y();
    551 			deUint32			gridTex		= 0;
    552 			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
    553 
    554 			tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f));
    555 
    556 			glGenTextures(1, &gridTex);
    557 			glBindTexture(GL_TEXTURE_2D, gridTex);
    558 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    559 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    560 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
    561 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
    562 			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
    563 
    564 			glBindFramebuffer(GL_FRAMEBUFFER, dstFbo);
    565 			glViewport(0, 0, m_dstSize.x(), m_dstSize.y());
    566 			glStencilFunc(GL_ALWAYS, 1, 0xffu);
    567 			sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    568 		}
    569 
    570 		// Perform copy.
    571 		glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFbo);
    572 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFbo);
    573 		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);
    574 
    575 		// Render blue color where depth < 0, decrement on depth failure.
    576 		glBindFramebuffer(GL_FRAMEBUFFER, dstFbo);
    577 		glViewport(0, 0, m_dstSize.x(), m_dstSize.y());
    578 		glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
    579 		glStencilFunc(GL_ALWAYS, 0, 0xffu);
    580 
    581 		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
    582 		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    583 
    584 		if (m_dstBuffers & GL_STENCIL_BUFFER_BIT)
    585 		{
    586 			// Render green color where stencil == 6.
    587 			glDisable(GL_DEPTH_TEST);
    588 			glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
    589 			glStencilFunc(GL_EQUAL, 6, 0xffu);
    590 
    591 			flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
    592 			sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    593 		}
    594 
    595 		readPixels(dst, 0, 0, m_dstSize.x(), m_dstSize.y(), glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f));
    596 	}
    597 
    598 private:
    599 	deUint32	m_format;
    600 	deUint32	m_srcBuffers;
    601 	IVec2		m_srcSize;
    602 	IVec4		m_srcRect;
    603 	deUint32	m_dstBuffers;
    604 	IVec2		m_dstSize;
    605 	IVec4		m_dstRect;
    606 	deUint32	m_copyBuffers;
    607 };
    608 
    609 class BlitDefaultFramebufferCase : public FboTestCase
    610 {
    611 public:
    612 	BlitDefaultFramebufferCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 filter)
    613 		: FboTestCase	(context, name, desc)
    614 		, m_format		(format)
    615 		, m_filter		(filter)
    616 	{
    617 	}
    618 
    619 protected:
    620 	void preCheck (void)
    621 	{
    622 		if (m_context.getRenderTarget().getNumSamples() > 0)
    623 			throw tcu::NotSupportedError("Not supported in MSAA config");
    624 
    625 		checkFormatSupport(m_format);
    626 	}
    627 
    628 	virtual void render (tcu::Surface& dst)
    629 	{
    630 		tcu::TextureFormat		colorFormat		= glu::mapGLInternalFormat(m_format);
    631 		glu::TransferFormat		transferFmt		= glu::getTransferFormat(colorFormat);
    632 		GradientShader			gradShader		(glu::TYPE_FLOAT_VEC4);
    633 		Texture2DShader			texShader		(DataTypes() << glu::getSampler2DType(colorFormat), glu::TYPE_FLOAT_VEC4);
    634 		deUint32				gradShaderID	= getCurrentContext()->createProgram(&gradShader);
    635 		deUint32				texShaderID		= getCurrentContext()->createProgram(&texShader);
    636 		deUint32				fbo				= 0;
    637 		deUint32				tex				= 0;
    638 		const int				texW			= 128;
    639 		const int				texH			= 128;
    640 
    641 		// Setup shaders
    642 		gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));
    643 		texShader.setUniforms(*getCurrentContext(), texShaderID);
    644 
    645 		// FBO
    646 		glGenFramebuffers(1, &fbo);
    647 		glGenTextures(1, &tex);
    648 
    649 		glBindTexture(GL_TEXTURE_2D, tex);
    650 		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    651 		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    652 		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	m_filter);
    653 		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	m_filter);
    654 		glTexImage2D(GL_TEXTURE_2D, 0, m_format, texW, texH, 0, transferFmt.format, transferFmt.dataType, DE_NULL);
    655 
    656 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    657 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
    658 		checkError();
    659 		checkFramebufferStatus(GL_FRAMEBUFFER);
    660 
    661 		// Render gradient to screen.
    662 		glBindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
    663 
    664 		sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    665 
    666 		// Blit gradient from screen to fbo.
    667 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
    668 		glBlitFramebuffer(0, 0, getWidth(), getHeight(), 0, 0, texW, texH, GL_COLOR_BUFFER_BIT, m_filter);
    669 
    670 		// Fill left half of viewport with quad that uses texture.
    671 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
    672 		glClearBufferfv(GL_COLOR, 0, Vec4(1.0f, 0.0f, 0.0f, 1.0f).getPtr());
    673 		sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
    674 
    675 		// Blit fbo to right half.
    676 		glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
    677 		glBlitFramebuffer(0, 0, texW, texH, getWidth()/2, 0, getWidth(), getHeight(), GL_COLOR_BUFFER_BIT, m_filter);
    678 
    679 		glBindFramebuffer(GL_READ_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
    680 		readPixels(dst, 0, 0, getWidth(), getHeight());
    681 	}
    682 
    683 	bool compare (const tcu::Surface& reference, const tcu::Surface& result)
    684 	{
    685 		const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_format), tcu::RGBA(12, 12, 12, 12)));
    686 
    687 		m_testCtx.getLog() << TestLog::Message << "Comparing images, threshold: " << threshold << TestLog::EndMessage;
    688 
    689 		return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
    690 	}
    691 
    692 protected:
    693 	const deUint32	m_format;
    694 	const deUint32	m_filter;
    695 };
    696 
    697 class DefaultFramebufferBlitCase : public BlitDefaultFramebufferCase
    698 {
    699 public:
    700 	enum BlitDirection
    701 	{
    702 		BLIT_DEFAULT_TO_TARGET,
    703 		BLIT_TO_DEFAULT_FROM_TARGET,
    704 
    705 		BLIT_LAST
    706 	};
    707 	enum BlitArea
    708 	{
    709 		AREA_SCALE,
    710 		AREA_OUT_OF_BOUNDS,
    711 
    712 		AREA_LAST
    713 	};
    714 
    715 	DefaultFramebufferBlitCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 filter, BlitDirection dir, BlitArea area)
    716 		: BlitDefaultFramebufferCase	(context, name, desc, format, filter)
    717 		, m_blitDir						(dir)
    718 		, m_blitArea					(area)
    719 		, m_srcRect						(-1, -1, -1, -1)
    720 		, m_dstRect						(-1, -1, -1, -1)
    721 		, m_interestingArea				(-1, -1, -1, -1)
    722 	{
    723 		DE_ASSERT(dir < BLIT_LAST);
    724 		DE_ASSERT(area < AREA_LAST);
    725 	}
    726 
    727 	void init (void)
    728 	{
    729 		// requirements
    730 		const int minViewportSize = 128;
    731 		if (m_context.getRenderTarget().getWidth() < minViewportSize || m_context.getRenderTarget().getHeight() < minViewportSize)
    732 			throw tcu::NotSupportedError("Viewport size " + de::toString(minViewportSize) + "x" + de::toString(minViewportSize) + " required");
    733 
    734 		// prevent viewport randoming
    735 		m_viewportWidth = m_context.getRenderTarget().getWidth();
    736 		m_viewportHeight = m_context.getRenderTarget().getHeight();
    737 
    738 		// set proper areas
    739 		if (m_blitArea == AREA_SCALE)
    740 		{
    741 			m_srcRect = IVec4( 10,  20,  65, 100);
    742 			m_dstRect = IVec4( 25,  30, 125,  94);
    743 			m_interestingArea = IVec4(0, 0, 128, 128);
    744 		}
    745 		else if (m_blitArea == AREA_OUT_OF_BOUNDS)
    746 		{
    747 			const tcu::IVec2 ubound = (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (tcu::IVec2(128, 128)) : (tcu::IVec2(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight()));
    748 
    749 			m_srcRect = IVec4(-10, -15, 100,  63);
    750 			m_dstRect = ubound.swizzle(0, 1, 0, 1) + IVec4(-75, -99, 8, 16);
    751 			m_interestingArea = IVec4(ubound.x() - 128, ubound.y() - 128, ubound.x(), ubound.y());
    752 		}
    753 		else
    754 			DE_ASSERT(false);
    755 	}
    756 
    757 	void render (tcu::Surface& dst)
    758 	{
    759 		const tcu::TextureFormat		colorFormat		= glu::mapGLInternalFormat(m_format);
    760 		const glu::TransferFormat		transferFmt		= glu::getTransferFormat(colorFormat);
    761 		const tcu::TextureChannelClass	targetClass		= (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (tcu::getTextureChannelClass(colorFormat.type)) : (tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT);
    762 		deUint32						fbo				= 0;
    763 		deUint32						fboTex			= 0;
    764 		const int						fboTexW			= 128;
    765 		const int						fboTexH			= 128;
    766 		const int						sourceWidth		= (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (getWidth()) : (fboTexW);
    767 		const int						sourceHeight	= (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (getHeight()) : (fboTexH);
    768 		const int						gridRenderWidth	= de::min(256, sourceWidth);
    769 		const int						gridRenderHeight= de::min(256, sourceHeight);
    770 
    771 		int								targetFbo		= -1;
    772 		int								sourceFbo		= -1;
    773 
    774 		// FBO
    775 		glGenFramebuffers(1, &fbo);
    776 		glGenTextures(1, &fboTex);
    777 
    778 		glBindTexture(GL_TEXTURE_2D, fboTex);
    779 		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    780 		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    781 		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	m_filter);
    782 		glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	m_filter);
    783 		glTexImage2D(GL_TEXTURE_2D, 0, m_format, fboTexW, fboTexH, 0, transferFmt.format, transferFmt.dataType, DE_NULL);
    784 
    785 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    786 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
    787 		checkError();
    788 		checkFramebufferStatus(GL_FRAMEBUFFER);
    789 
    790 		targetFbo = (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (fbo) : (m_context.getRenderContext().getDefaultFramebuffer());
    791 		sourceFbo = (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (m_context.getRenderContext().getDefaultFramebuffer()) : (fbo);
    792 
    793 		// Render grid to source framebuffer
    794 		{
    795 			Texture2DShader		texShader		(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
    796 			const deUint32		texShaderID		= getCurrentContext()->createProgram(&texShader);
    797 			const deUint32		internalFormat	= GL_RGBA8;
    798 			const deUint32		format			= GL_RGBA;
    799 			const deUint32		dataType		= GL_UNSIGNED_BYTE;
    800 			const int			gridTexW		= 128;
    801 			const int			gridTexH		= 128;
    802 			deUint32			gridTex			= 0;
    803 			tcu::TextureLevel	data			(glu::mapGLTransferFormat(format, dataType), gridTexW, gridTexH, 1);
    804 
    805 			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));
    806 
    807 			glGenTextures(1, &gridTex);
    808 			glBindTexture(GL_TEXTURE_2D, gridTex);
    809 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    810 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    811 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
    812 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
    813 			glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, gridTexW, gridTexH, 0, format, dataType, data.getAccess().getDataPtr());
    814 
    815 			glBindFramebuffer(GL_FRAMEBUFFER, sourceFbo);
    816 			glViewport(0, 0, gridRenderWidth, gridRenderHeight);
    817 			glClearBufferfv(GL_COLOR, 0, Vec4(1.0f, 0.0f, 0.0f, 1.0f).getPtr());
    818 
    819 			texShader.setUniforms(*getCurrentContext(), texShaderID);
    820 			sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    821 			glUseProgram(0);
    822 		}
    823 
    824 		// Blit source framebuffer to destination
    825 
    826 		glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFbo);
    827 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, targetFbo);
    828 		checkError();
    829 
    830 		if (targetClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || targetClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || targetClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
    831 			glClearBufferfv(GL_COLOR, 0, Vec4(1.0f, 1.0f, 0.0f, 1.0f).getPtr());
    832 		else if (targetClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
    833 			glClearBufferiv(GL_COLOR, 0, IVec4(0, 0, 0, 0).getPtr());
    834 		else if (targetClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
    835 			glClearBufferuiv(GL_COLOR, 0, UVec4(0, 0, 0, 0).getPtr());
    836 		else
    837 			DE_ASSERT(false);
    838 
    839 		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);
    840 		checkError();
    841 
    842 		// Read target
    843 
    844 		glBindFramebuffer(GL_FRAMEBUFFER, targetFbo);
    845 
    846 		if (m_blitDir == BLIT_TO_DEFAULT_FROM_TARGET)
    847 			readPixels(dst, m_interestingArea.x(), m_interestingArea.y(), m_interestingArea.z() - m_interestingArea.x(), m_interestingArea.w() - m_interestingArea.y());
    848 		else
    849 			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));
    850 
    851 		checkError();
    852 	}
    853 
    854 private:
    855 	const BlitDirection	m_blitDir;
    856 	const BlitArea		m_blitArea;
    857 	tcu::IVec4			m_srcRect;
    858 	tcu::IVec4			m_dstRect;
    859 	tcu::IVec4			m_interestingArea;
    860 };
    861 
    862 FramebufferBlitTests::FramebufferBlitTests (Context& context)
    863 	: TestCaseGroup(context, "blit", "Framebuffer blit tests")
    864 {
    865 }
    866 
    867 FramebufferBlitTests::~FramebufferBlitTests (void)
    868 {
    869 }
    870 
    871 void FramebufferBlitTests::init (void)
    872 {
    873 	static const deUint32 colorFormats[] =
    874 	{
    875 		// RGBA formats
    876 		GL_RGBA32I,
    877 		GL_RGBA32UI,
    878 		GL_RGBA16I,
    879 		GL_RGBA16UI,
    880 		GL_RGBA8,
    881 		GL_RGBA8I,
    882 		GL_RGBA8UI,
    883 		GL_SRGB8_ALPHA8,
    884 		GL_RGB10_A2,
    885 		GL_RGB10_A2UI,
    886 		GL_RGBA4,
    887 		GL_RGB5_A1,
    888 
    889 		// RGB formats
    890 		GL_RGB8,
    891 		GL_RGB565,
    892 
    893 		// RG formats
    894 		GL_RG32I,
    895 		GL_RG32UI,
    896 		GL_RG16I,
    897 		GL_RG16UI,
    898 		GL_RG8,
    899 		GL_RG8I,
    900 		GL_RG8UI,
    901 
    902 		// R formats
    903 		GL_R32I,
    904 		GL_R32UI,
    905 		GL_R16I,
    906 		GL_R16UI,
    907 		GL_R8,
    908 		GL_R8I,
    909 		GL_R8UI,
    910 
    911 		// GL_EXT_color_buffer_float
    912 		GL_RGBA32F,
    913 		GL_RGBA16F,
    914 		GL_R11F_G11F_B10F,
    915 		GL_RG32F,
    916 		GL_RG16F,
    917 		GL_R32F,
    918 		GL_R16F
    919 	};
    920 
    921 	static const deUint32 depthStencilFormats[] =
    922 	{
    923 		GL_DEPTH_COMPONENT32F,
    924 		GL_DEPTH_COMPONENT24,
    925 		GL_DEPTH_COMPONENT16,
    926 		GL_DEPTH32F_STENCIL8,
    927 		GL_DEPTH24_STENCIL8,
    928 		GL_STENCIL_INDEX8
    929 	};
    930 
    931 	// .rect
    932 	{
    933 		static const struct
    934 		{
    935 			const char*	name;
    936 			IVec4		srcRect;
    937 			IVec4		dstRect;
    938 		} copyRects[] =
    939 		{
    940 			{ "basic",						IVec4( 10,  20,  65, 100),		IVec4( 45,   5, 100,  85) },
    941 			{ "scale",						IVec4( 10,  20,  65, 100),		IVec4( 25,  30, 125,  94) },
    942 			{ "out_of_bounds",				IVec4(-10, -15, 100,  63),		IVec4( 50,  30, 136, 144) },
    943 		};
    944 
    945 		static const struct
    946 		{
    947 			const char*	name;
    948 			IVec4		srcRect;
    949 			IVec4		dstRect;
    950 		} filterConsistencyRects[] =
    951 		{
    952 			{ "mag",						IVec4( 20,  10,  74, 88),		IVec4( 10,  10,  91, 101) },
    953 			{ "min",						IVec4( 10,  20,  78, 100),		IVec4( 20,  20,  71,  80) },
    954 			{ "out_of_bounds_mag",			IVec4( 21,  10,  73, 82),		IVec4( 11,  43, 141, 151) },
    955 			{ "out_of_bounds_min",			IVec4( 11,  21,  77, 97),		IVec4( 80,  82, 135, 139) },
    956 		};
    957 
    958 		static const struct
    959 		{
    960 			const char* name;
    961 			IVec4		srcSwizzle;
    962 			IVec4		dstSwizzle;
    963 		} swizzles[] =
    964 		{
    965 			{ DE_NULL,				IVec4(0,1,2,3),	IVec4(0,1,2,3) },
    966 			{ "reverse_src_x",		IVec4(2,1,0,3), IVec4(0,1,2,3) },
    967 			{ "reverse_src_y",		IVec4(0,3,2,1), IVec4(0,1,2,3) },
    968 			{ "reverse_dst_x",		IVec4(0,1,2,3), IVec4(2,1,0,3) },
    969 			{ "reverse_dst_y",		IVec4(0,1,2,3), IVec4(0,3,2,1) },
    970 			{ "reverse_src_dst_x",	IVec4(2,1,0,3), IVec4(2,1,0,3) },
    971 			{ "reverse_src_dst_y",	IVec4(0,3,2,1), IVec4(0,3,2,1) }
    972 		};
    973 
    974 		const IVec2 srcSize(127, 119);
    975 		const IVec2 dstSize(132, 128);
    976 
    977 		// Blit rectangle tests.
    978 		tcu::TestCaseGroup* rectGroup = new tcu::TestCaseGroup(m_testCtx, "rect", "Blit rectangle tests");
    979 		addChild(rectGroup);
    980 		for (int rectNdx = 0; rectNdx < DE_LENGTH_OF_ARRAY(copyRects); rectNdx++)
    981 		{
    982 			for (int swzNdx = 0; swzNdx < DE_LENGTH_OF_ARRAY(swizzles); swzNdx++)
    983 			{
    984 				string		name	= string(copyRects[rectNdx].name) + (swizzles[swzNdx].name ? (string("_") + swizzles[swzNdx].name) : string());
    985 				IVec4		srcSwz	= swizzles[swzNdx].srcSwizzle;
    986 				IVec4		dstSwz	= swizzles[swzNdx].dstSwizzle;
    987 				IVec4		srcRect	= copyRects[rectNdx].srcRect.swizzle(srcSwz[0], srcSwz[1], srcSwz[2], srcSwz[3]);
    988 				IVec4		dstRect	= copyRects[rectNdx].dstRect.swizzle(dstSwz[0], dstSwz[1], dstSwz[2], dstSwz[3]);
    989 
    990 				rectGroup->addChild(new BlitRectCase(m_context, (name + "_nearest").c_str(),	"", GL_NEAREST,	srcSize, srcRect, dstSize, dstRect));
    991 				rectGroup->addChild(new BlitRectCase(m_context, (name + "_linear").c_str(),		"", GL_LINEAR,	srcSize, srcRect, dstSize, dstRect));
    992 			}
    993 		}
    994 
    995 		// Nearest filter tests
    996 		for (int rectNdx = 0; rectNdx < DE_LENGTH_OF_ARRAY(filterConsistencyRects); rectNdx++)
    997 		{
    998 			for (int swzNdx = 0; swzNdx < DE_LENGTH_OF_ARRAY(swizzles); swzNdx++)
    999 			{
   1000 				string		name	= string("nearest_consistency_") + filterConsistencyRects[rectNdx].name + (swizzles[swzNdx].name ? (string("_") + swizzles[swzNdx].name) : string());
   1001 				IVec4		srcSwz	= swizzles[swzNdx].srcSwizzle;
   1002 				IVec4		dstSwz	= swizzles[swzNdx].dstSwizzle;
   1003 				IVec4		srcRect	= filterConsistencyRects[rectNdx].srcRect.swizzle(srcSwz[0], srcSwz[1], srcSwz[2], srcSwz[3]);
   1004 				IVec4		dstRect	= filterConsistencyRects[rectNdx].dstRect.swizzle(dstSwz[0], dstSwz[1], dstSwz[2], dstSwz[3]);
   1005 
   1006 				rectGroup->addChild(new BlitNearestFilterConsistencyCase(m_context, name.c_str(), "Test consistency of the nearest filter", srcSize, srcRect, dstSize, dstRect));
   1007 			}
   1008 		}
   1009 	}
   1010 
   1011 	// .conversion
   1012 	{
   1013 		tcu::TestCaseGroup* conversionGroup = new tcu::TestCaseGroup(m_testCtx, "conversion", "Color conversion tests");
   1014 		addChild(conversionGroup);
   1015 
   1016 		for (int srcFmtNdx = 0; srcFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); srcFmtNdx++)
   1017 		{
   1018 			for (int dstFmtNdx = 0; dstFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); dstFmtNdx++)
   1019 			{
   1020 				deUint32					srcFormat	= colorFormats[srcFmtNdx];
   1021 				tcu::TextureFormat			srcTexFmt	= glu::mapGLInternalFormat(srcFormat);
   1022 				tcu::TextureChannelClass	srcType		= tcu::getTextureChannelClass(srcTexFmt.type);
   1023 				deUint32					dstFormat	= colorFormats[dstFmtNdx];
   1024 				tcu::TextureFormat			dstTexFmt	= glu::mapGLInternalFormat(dstFormat);
   1025 				tcu::TextureChannelClass	dstType		= tcu::getTextureChannelClass(dstTexFmt.type);
   1026 
   1027 				if (((srcType == tcu::TEXTURECHANNELCLASS_FLOATING_POINT || srcType == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) !=
   1028 					 (dstType == tcu::TEXTURECHANNELCLASS_FLOATING_POINT || dstType == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)) ||
   1029 					((srcType == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) != (dstType == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)) ||
   1030 					((srcType == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) != (dstType == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)))
   1031 					continue; // Conversion not supported.
   1032 
   1033 				string						name		= string(getFormatName(srcFormat)) + "_to_" + getFormatName(dstFormat);
   1034 
   1035 				conversionGroup->addChild(new BlitColorConversionCase(m_context, name.c_str(), "", srcFormat, dstFormat, IVec2(127, 113)));
   1036 			}
   1037 		}
   1038 	}
   1039 
   1040 	// .depth_stencil
   1041 	{
   1042 		tcu::TestCaseGroup* depthStencilGroup = new tcu::TestCaseGroup(m_testCtx, "depth_stencil", "Depth and stencil blits");
   1043 		addChild(depthStencilGroup);
   1044 
   1045 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
   1046 		{
   1047 			deUint32			format		= depthStencilFormats[fmtNdx];
   1048 			tcu::TextureFormat	texFmt		= glu::mapGLInternalFormat(format);
   1049 			string				fmtName		= getFormatName(format);
   1050 			bool				depth		= texFmt.order == tcu::TextureFormat::D || texFmt.order == tcu::TextureFormat::DS;
   1051 			bool				stencil		= texFmt.order == tcu::TextureFormat::S || texFmt.order == tcu::TextureFormat::DS;
   1052 			deUint32			buffers		= (depth ? GL_DEPTH_BUFFER_BIT : 0) | (stencil ? GL_STENCIL_BUFFER_BIT : 0);
   1053 
   1054 			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));
   1055 			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));
   1056 
   1057 			if (depth && stencil)
   1058 			{
   1059 				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));
   1060 				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));
   1061 			}
   1062 		}
   1063 	}
   1064 
   1065 	// .default_framebuffer
   1066 	{
   1067 		static const struct
   1068 		{
   1069 			const char*								name;
   1070 			DefaultFramebufferBlitCase::BlitArea	area;
   1071 		} areas[] =
   1072 		{
   1073 			{ "scale",						DefaultFramebufferBlitCase::AREA_SCALE			},
   1074 			{ "out_of_bounds",				DefaultFramebufferBlitCase::AREA_OUT_OF_BOUNDS	},
   1075 		};
   1076 
   1077 		tcu::TestCaseGroup* defaultFbGroup = new tcu::TestCaseGroup(m_testCtx, "default_framebuffer", "Blits with default framebuffer");
   1078 		addChild(defaultFbGroup);
   1079 
   1080 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
   1081 		{
   1082 			const deUint32					format		= colorFormats[fmtNdx];
   1083 			const tcu::TextureFormat		texFmt		= glu::mapGLInternalFormat(format);
   1084 			const tcu::TextureChannelClass	fmtClass	= tcu::getTextureChannelClass(texFmt.type);
   1085 			const deUint32					filter		= glu::isGLInternalColorFormatFilterable(format) ? GL_LINEAR : GL_NEAREST;
   1086 			const bool						filterable	= glu::isGLInternalColorFormatFilterable(format);
   1087 
   1088 			if (fmtClass != tcu::TEXTURECHANNELCLASS_FLOATING_POINT &&
   1089 				fmtClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT &&
   1090 				fmtClass != tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT)
   1091 				continue; // Conversion not supported.
   1092 
   1093 			defaultFbGroup->addChild(new BlitDefaultFramebufferCase(m_context, getFormatName(format), "", format, filter));
   1094 
   1095 			for (int areaNdx = 0; areaNdx < DE_LENGTH_OF_ARRAY(areas); areaNdx++)
   1096 			{
   1097 				const string	name				= string(areas[areaNdx].name);
   1098 				const bool		addLinear			= filterable;
   1099 				const bool		addNearest			= !addLinear || (areas[areaNdx].area != DefaultFramebufferBlitCase::AREA_OUT_OF_BOUNDS); // No need to check out-of-bounds with different filtering
   1100 
   1101 				if (addNearest)
   1102 				{
   1103 					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));
   1104 					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));
   1105 				}
   1106 
   1107 				if (addLinear)
   1108 				{
   1109 					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));
   1110 					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));
   1111 				}
   1112 			}
   1113 		}
   1114 	}
   1115 }
   1116 
   1117 } // Functional
   1118 } // gles3
   1119 } // deqp
   1120