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 Framebuffer Object Tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es3fFboRenderTest.hpp"
     25 #include "sglrContextUtil.hpp"
     26 #include "sglrGLContext.hpp"
     27 #include "sglrReferenceContext.hpp"
     28 #include "es3fFboTestUtil.hpp"
     29 #include "tcuSurface.hpp"
     30 #include "tcuImageCompare.hpp"
     31 #include "tcuTextureUtil.hpp"
     32 #include "tcuVectorUtil.hpp"
     33 #include "tcuRenderTarget.hpp"
     34 #include "gluPixelTransfer.hpp"
     35 #include "gluTextureUtil.hpp"
     36 #include "gluStrUtil.hpp"
     37 #include "deRandom.h"
     38 #include "deString.h"
     39 #include "glwDefs.hpp"
     40 #include "glwEnums.hpp"
     41 
     42 #include <sstream>
     43 
     44 using std::vector;
     45 using std::string;
     46 using tcu::TestLog;
     47 using tcu::Vec2;
     48 using tcu::Vec3;
     49 using tcu::Vec4;
     50 using tcu::IVec2;
     51 using tcu::IVec3;
     52 using tcu::IVec4;
     53 using tcu::RGBA;
     54 using tcu::Surface;
     55 
     56 namespace deqp
     57 {
     58 namespace gles3
     59 {
     60 namespace Functional
     61 {
     62 
     63 using glw::GLenum;
     64 using namespace FboTestUtil;
     65 
     66 class FboConfig
     67 {
     68 public:
     69 	FboConfig (deUint32 buffers_, deUint32 colorType_, deUint32 colorFormat_, deUint32 depthStencilType_, deUint32 depthStencilFormat_, int width_ = 0, int height_ = 0, int samples_ = 0)
     70 		: buffers				(buffers_)
     71 		, colorType				(colorType_)
     72 		, colorFormat			(colorFormat_)
     73 		, depthStencilType		(depthStencilType_)
     74 		, depthStencilFormat	(depthStencilFormat_)
     75 		, width					(width_)
     76 		, height				(height_)
     77 		, samples				(samples_)
     78 	{
     79 	}
     80 
     81 	FboConfig (void)
     82 		: buffers				(0)
     83 		, colorType				(GL_NONE)
     84 		, colorFormat			(GL_NONE)
     85 		, depthStencilType		(GL_NONE)
     86 		, depthStencilFormat	(GL_NONE)
     87 		, width					(0)
     88 		, height				(0)
     89 		, samples				(0)
     90 	{
     91 	}
     92 
     93 	std::string				getName			(void) const;
     94 
     95 	deUint32				buffers;		//!< Buffer bit mask (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|...)
     96 
     97 	GLenum					colorType;		//!< GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER
     98 	GLenum					colorFormat;	//!< Internal format for color buffer texture or renderbuffer
     99 
    100 	GLenum					depthStencilType;
    101 	GLenum					depthStencilFormat;
    102 
    103 	int						width;
    104 	int						height;
    105 	int						samples;
    106 };
    107 
    108 static const char* getTypeName (GLenum type)
    109 {
    110 	switch (type)
    111 	{
    112 		case GL_TEXTURE_2D:		return "tex2d";
    113 		case GL_RENDERBUFFER:	return "rbo";
    114 		default:
    115 			TCU_FAIL("Unknown type");
    116 	}
    117 }
    118 
    119 std::string FboConfig::getName (void) const
    120 {
    121 	std::ostringstream name;
    122 
    123 	DE_ASSERT(buffers & GL_COLOR_BUFFER_BIT);
    124 	name << getTypeName(colorType) << "_" << getFormatName(colorFormat);
    125 
    126 	if (buffers & GL_DEPTH_BUFFER_BIT)
    127 		name << "_depth";
    128 	if (buffers & GL_STENCIL_BUFFER_BIT)
    129 		name << "_stencil";
    130 
    131 	if (buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT))
    132 		name << "_" << getTypeName(depthStencilType) << "_" << getFormatName(depthStencilFormat);
    133 
    134 	return name.str();
    135 }
    136 
    137 class Framebuffer
    138 {
    139 public:
    140 						Framebuffer				(sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo = 0, deUint32 colorBuffer = 0, deUint32 depthStencilBuffer = 0);
    141 						~Framebuffer			(void);
    142 
    143 	const FboConfig&	getConfig				(void) const { return m_config;				}
    144 	deUint32			getFramebuffer			(void) const { return m_framebuffer;		}
    145 	deUint32			getColorBuffer			(void) const { return m_colorBuffer;		}
    146 	deUint32			getDepthStencilBuffer	(void) const { return m_depthStencilBuffer;	}
    147 
    148 	void				checkCompleteness		(void);
    149 
    150 private:
    151 	deUint32			createTex2D				(deUint32 name, GLenum format, int width, int height);
    152 	deUint32			createRbo				(deUint32 name, GLenum format, int width, int height);
    153 	void				destroyBuffer			(deUint32 name, GLenum type);
    154 
    155 	FboConfig			m_config;
    156 	sglr::Context&		m_context;
    157 	deUint32			m_framebuffer;
    158 	deUint32			m_colorBuffer;
    159 	deUint32			m_depthStencilBuffer;
    160 };
    161 
    162 static std::vector<std::string> getEnablingExtensions (deUint32 format)
    163 {
    164 	std::vector<std::string> out;
    165 
    166 	switch (format)
    167 	{
    168 		case GL_RGB16F:
    169 			out.push_back("GL_EXT_color_buffer_half_float");
    170 			break;
    171 
    172 		case GL_RGBA16F:
    173 		case GL_RG16F:
    174 		case GL_R16F:
    175 			out.push_back("GL_EXT_color_buffer_half_float");
    176 		// Fallthrough
    177 
    178 		case GL_RGBA32F:
    179 		case GL_RGB32F:
    180 		case GL_R11F_G11F_B10F:
    181 		case GL_RG32F:
    182 		case GL_R32F:
    183 			out.push_back("GL_EXT_color_buffer_float");
    184 			break;
    185 
    186 		default:
    187 			break;
    188 	}
    189 
    190 	return out;
    191 }
    192 
    193 static bool isExtensionSupported (sglr::Context& context, const char* name)
    194 {
    195 	std::istringstream extensions(context.getString(GL_EXTENSIONS));
    196 	std::string extension;
    197 
    198 	while (std::getline(extensions, extension, ' '))
    199 	{
    200 		if (extension == name)
    201 			return true;
    202 	}
    203 
    204 	return false;
    205 }
    206 
    207 static bool isAnyExtensionSupported (sglr::Context& context, const std::vector<std::string>& requiredExts)
    208 {
    209 	if (requiredExts.empty())
    210 		return true;
    211 
    212 	for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++)
    213 	{
    214 		const std::string& extension = *iter;
    215 
    216 		if (isExtensionSupported(context, extension.c_str()))
    217 			return true;
    218 	}
    219 
    220 	return false;
    221 }
    222 
    223 template<typename T>
    224 static std::string join (const std::vector<T>& list, const std::string& sep)
    225 {
    226 	std::ostringstream	out;
    227 
    228 	for (typename std::vector<T>::const_iterator iter = list.begin(); iter != list.end(); iter++)
    229 	{
    230 		if (iter != list.begin())
    231 			out << sep;
    232 		out << *iter;
    233 	}
    234 
    235 	return out.str();
    236 }
    237 
    238 static void checkColorFormatSupport (sglr::Context& context, deUint32 sizedFormat)
    239 {
    240 	const std::vector<std::string> requiredExts = getEnablingExtensions(sizedFormat);
    241 
    242 	if (!isAnyExtensionSupported(context, requiredExts))
    243 	{
    244 		std::string	errMsg	= "Format not supported, requires "
    245 							+ ((requiredExts.size() == 1) ? requiredExts[0] : " one of the following: " + join(requiredExts, ", "));
    246 
    247 		throw tcu::NotSupportedError(errMsg);
    248 	}
    249 }
    250 
    251 Framebuffer::Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo, deUint32 colorBufferName, deUint32 depthStencilBufferName)
    252 	: m_config				(config)
    253 	, m_context				(context)
    254 	, m_framebuffer			(fbo)
    255 	, m_colorBuffer			(0)
    256 	, m_depthStencilBuffer	(0)
    257 {
    258 	// Verify that color format is supported
    259 	checkColorFormatSupport(context, config.colorFormat);
    260 
    261 	if (m_framebuffer == 0)
    262 		context.genFramebuffers(1, &m_framebuffer);
    263 	context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
    264 
    265 	if (m_config.buffers & (GL_COLOR_BUFFER_BIT))
    266 	{
    267 		switch (m_config.colorType)
    268 		{
    269 			case GL_TEXTURE_2D:
    270 				m_colorBuffer = createTex2D(colorBufferName, m_config.colorFormat, width, height);
    271 				context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0);
    272 				break;
    273 
    274 			case GL_RENDERBUFFER:
    275 				m_colorBuffer = createRbo(colorBufferName, m_config.colorFormat, width, height);
    276 				context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorBuffer);
    277 				break;
    278 
    279 			default:
    280 				TCU_FAIL("Unsupported type");
    281 		}
    282 	}
    283 
    284 	if (m_config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT))
    285 	{
    286 		switch (m_config.depthStencilType)
    287 		{
    288 			case GL_TEXTURE_2D:		m_depthStencilBuffer = createTex2D(depthStencilBufferName, m_config.depthStencilFormat, width, height);		break;
    289 			case GL_RENDERBUFFER:	m_depthStencilBuffer = createRbo(depthStencilBufferName, m_config.depthStencilFormat, width, height);		break;
    290 			default:
    291 				TCU_FAIL("Unsupported type");
    292 		}
    293 	}
    294 
    295 	for (int ndx = 0; ndx < 2; ndx++)
    296 	{
    297 		deUint32	bit		= ndx ? GL_STENCIL_BUFFER_BIT : GL_DEPTH_BUFFER_BIT;
    298 		deUint32	point	= ndx ? GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
    299 
    300 		if ((m_config.buffers & bit) == 0)
    301 			continue; /* Not used. */
    302 
    303 		switch (m_config.depthStencilType)
    304 		{
    305 			case GL_TEXTURE_2D:		context.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, m_depthStencilBuffer, 0);	break;
    306 			case GL_RENDERBUFFER:	context.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, m_depthStencilBuffer);	break;
    307 			default:
    308 				DE_ASSERT(false);
    309 		}
    310 	}
    311 
    312 	GLenum err = m_context.getError();
    313 	if (err != GL_NO_ERROR)
    314 		throw glu::Error(err, glu::getErrorStr(err).toString().c_str(), "", __FILE__, __LINE__);
    315 
    316 	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
    317 }
    318 
    319 Framebuffer::~Framebuffer (void)
    320 {
    321 	m_context.deleteFramebuffers(1, &m_framebuffer);
    322 	destroyBuffer(m_colorBuffer, m_config.colorType);
    323 	destroyBuffer(m_depthStencilBuffer, m_config.depthStencilType);
    324 }
    325 
    326 void Framebuffer::checkCompleteness (void)
    327 {
    328 	m_context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
    329 	GLenum status = m_context.checkFramebufferStatus(GL_FRAMEBUFFER);
    330 	m_context.bindFramebuffer(GL_FRAMEBUFFER, 0);
    331 	if (status != GL_FRAMEBUFFER_COMPLETE)
    332 		throw FboIncompleteException(status, __FILE__, __LINE__);
    333 }
    334 
    335 deUint32 Framebuffer::createTex2D (deUint32 name, GLenum format, int width, int height)
    336 {
    337 	if (name == 0)
    338 		m_context.genTextures(1, &name);
    339 
    340 	m_context.bindTexture(GL_TEXTURE_2D, name);
    341 	m_context.texImage2D(GL_TEXTURE_2D, 0, format, width, height);
    342 
    343 	if (!deIsPowerOfTwo32(width) || !deIsPowerOfTwo32(height))
    344 	{
    345 		// Set wrap mode to clamp for NPOT FBOs
    346 		m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    347 		m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    348 	}
    349 
    350 	m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    351 	m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    352 
    353 	return name;
    354 }
    355 
    356 deUint32 Framebuffer::createRbo (deUint32 name, GLenum format, int width, int height)
    357 {
    358 	if (name == 0)
    359 		m_context.genRenderbuffers(1, &name);
    360 
    361 	m_context.bindRenderbuffer(GL_RENDERBUFFER, name);
    362 	m_context.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
    363 
    364 	return name;
    365 }
    366 
    367 void Framebuffer::destroyBuffer (deUint32 name, GLenum type)
    368 {
    369 	if (type == GL_TEXTURE_2D || type == GL_TEXTURE_CUBE_MAP)
    370 		m_context.deleteTextures(1, &name);
    371 	else if (type == GL_RENDERBUFFER)
    372 		m_context.deleteRenderbuffers(1, &name);
    373 	else
    374 		DE_ASSERT(type == GL_NONE);
    375 }
    376 
    377 static void createMetaballsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
    378 {
    379 	tcu::TextureFormat	texFormat	= glu::mapGLTransferFormat(format, dataType);
    380 	tcu::TextureLevel	level		(texFormat, width, height);
    381 
    382 	tcu::fillWithMetaballs(level.getAccess(), 5, name ^ width ^ height);
    383 
    384 	context.bindTexture(GL_TEXTURE_2D, name);
    385 	context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
    386 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    387 }
    388 
    389 static void createQuadsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
    390 {
    391 	tcu::TextureFormat	texFormat	= glu::mapGLTransferFormat(format, dataType);
    392 	tcu::TextureLevel	level		(texFormat, width, height);
    393 
    394 	tcu::fillWithRGBAQuads(level.getAccess());
    395 
    396 	context.bindTexture(GL_TEXTURE_2D, name);
    397 	context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
    398 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    399 }
    400 
    401 class FboRenderCase : public TestCase
    402 {
    403 public:
    404 								FboRenderCase			(Context& context, const char* name, const char* description, const FboConfig& config);
    405 	virtual						~FboRenderCase			(void) {}
    406 
    407 	virtual IterateResult		iterate					(void);
    408 	virtual void				render					(sglr::Context& fboContext, Surface& dst) = DE_NULL;
    409 
    410 	bool						compare					(const tcu::Surface& reference, const tcu::Surface& result);
    411 
    412 protected:
    413 	const FboConfig				m_config;
    414 };
    415 
    416 FboRenderCase::FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config)
    417 	: TestCase	(context, name, description)
    418 	, m_config	(config)
    419 {
    420 }
    421 
    422 TestCase::IterateResult FboRenderCase::iterate (void)
    423 {
    424 	tcu::Vec4					clearColor				= tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f);
    425 	glu::RenderContext&			renderCtx				= m_context.getRenderContext();
    426 	const tcu::RenderTarget&	renderTarget			= renderCtx.getRenderTarget();
    427 	tcu::TestLog&				log						= m_testCtx.getLog();
    428 	const char*					failReason				= DE_NULL;
    429 
    430 	// Position & size for context
    431 	deRandom rnd;
    432 	deRandom_init(&rnd, deStringHash(getName()));
    433 
    434 	int		width	= deMin32(renderTarget.getWidth(), 128);
    435 	int		height	= deMin32(renderTarget.getHeight(), 128);
    436 	int		xMax	= renderTarget.getWidth()-width+1;
    437 	int		yMax	= renderTarget.getHeight()-height+1;
    438 	int		x		= deRandom_getUint32(&rnd) % xMax;
    439 	int		y		= deRandom_getUint32(&rnd) % yMax;
    440 
    441 	tcu::Surface	gles3Frame	(width, height);
    442 	tcu::Surface	refFrame	(width, height);
    443 	GLenum			gles3Error;
    444 	GLenum			refError;
    445 
    446 	// Render using GLES3
    447 	try
    448 	{
    449 		sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
    450 
    451 		context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
    452 		context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    453 
    454 		render(context, gles3Frame); // Call actual render func
    455 		gles3Error = context.getError();
    456 	}
    457 	catch (const FboIncompleteException& e)
    458 	{
    459 		if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED)
    460 		{
    461 			// Mark test case as unsupported
    462 			log << e;
    463 			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
    464 			return STOP;
    465 		}
    466 		else
    467 			throw; // Propagate error
    468 	}
    469 
    470 	// Render reference image
    471 	{
    472 		sglr::ReferenceContextBuffers	buffers	(tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), renderTarget.getDepthBits(), renderTarget.getStencilBits(), width, height);
    473 		sglr::ReferenceContext			context	(sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
    474 
    475 		context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
    476 		context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    477 
    478 		render(context, refFrame);
    479 		refError = context.getError();
    480 	}
    481 
    482 	// Compare error codes
    483 	bool errorCodesOk = (gles3Error == refError);
    484 
    485 	if (!errorCodesOk)
    486 	{
    487 		log << tcu::TestLog::Message << "Error code mismatch: got " << glu::getErrorStr(gles3Error) << ", expected " << glu::getErrorStr(refError) << tcu::TestLog::EndMessage;
    488 		failReason = "Got unexpected error";
    489 	}
    490 
    491 	// Compare images
    492 	bool imagesOk = compare(refFrame, gles3Frame);
    493 
    494 	if (!imagesOk && !failReason)
    495 		failReason = "Image comparison failed";
    496 
    497 	// Store test result
    498 	bool isOk = errorCodesOk && imagesOk;
    499 	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
    500 							isOk ? "Pass"				: failReason);
    501 
    502 	return STOP;
    503 }
    504 
    505 bool FboRenderCase::compare (const tcu::Surface& reference, const tcu::Surface& result)
    506 {
    507 	const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_config.colorFormat), tcu::RGBA(12, 12, 12, 12)));
    508 
    509 	return tcu::bilinearCompare(m_testCtx.getLog(), "ComparisonResult", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
    510 }
    511 
    512 namespace FboCases
    513 {
    514 
    515 class StencilClearsTest : public FboRenderCase
    516 {
    517 public:
    518 						StencilClearsTest		(Context& context, const FboConfig& config);
    519 	virtual				~StencilClearsTest		(void) {};
    520 
    521 	void				render					(sglr::Context& context, Surface& dst);
    522 };
    523 
    524 StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config)
    525 	: FboRenderCase	(context, config.getName().c_str(), "Stencil clears", config)
    526 {
    527 }
    528 
    529 void StencilClearsTest::render (sglr::Context& context, Surface& dst)
    530 {
    531 	tcu::TextureFormat		colorFormat			= glu::mapGLInternalFormat(m_config.colorFormat);
    532 	glu::DataType			fboSamplerType		= glu::getSampler2DType(colorFormat);
    533 	glu::DataType			fboOutputType		= getFragmentOutputType(colorFormat);
    534 	tcu::TextureFormatInfo	fboRangeInfo		= tcu::getTextureFormatInfo(colorFormat);
    535 	Vec4					fboOutScale			= fboRangeInfo.valueMax - fboRangeInfo.valueMin;
    536 	Vec4					fboOutBias			= fboRangeInfo.valueMin;
    537 
    538 	Texture2DShader			texToFboShader		(DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
    539 	Texture2DShader			texFromFboShader	(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
    540 
    541 	deUint32				texToFboShaderID	= context.createProgram(&texToFboShader);
    542 	deUint32				texFromFboShaderID	= context.createProgram(&texFromFboShader);
    543 
    544 	deUint32				metaballsTex		= 1;
    545 	deUint32				quadsTex			= 2;
    546 	int						width				= 128;
    547 	int						height				= 128;
    548 
    549 	texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
    550 	texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
    551 
    552 	createQuadsTex2D(context, quadsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
    553 	createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
    554 
    555 	Framebuffer fbo(context, m_config, width, height);
    556 	fbo.checkCompleteness();
    557 
    558 	// Bind framebuffer and clear
    559 	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
    560 	context.viewport(0, 0, width, height);
    561 	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
    562 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    563 
    564 	// Do stencil clears
    565 	context.enable(GL_SCISSOR_TEST);
    566 	context.scissor(10, 16, 32, 120);
    567 	context.clearStencil(1);
    568 	context.clear(GL_STENCIL_BUFFER_BIT);
    569 	context.scissor(16, 32, 100, 64);
    570 	context.clearStencil(2);
    571 	context.clear(GL_STENCIL_BUFFER_BIT);
    572 	context.disable(GL_SCISSOR_TEST);
    573 
    574 	// Draw 2 textures with stecil tests
    575 	context.enable(GL_STENCIL_TEST);
    576 
    577 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
    578 	context.stencilFunc(GL_EQUAL, 1, 0xffu);
    579 
    580 	texToFboShader.setUniforms(context, texToFboShaderID);
    581 	sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
    582 
    583 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
    584 	context.stencilFunc(GL_EQUAL, 2, 0xffu);
    585 
    586 	texToFboShader.setUniforms(context, texToFboShaderID);
    587 	sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
    588 
    589 	context.disable(GL_STENCIL_TEST);
    590 
    591 	if (fbo.getConfig().colorType == GL_TEXTURE_2D)
    592 	{
    593 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
    594 		context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
    595 		context.viewport(0, 0, context.getWidth(), context.getHeight());
    596 
    597 		texFromFboShader.setUniforms(context, texFromFboShaderID);
    598 		sglr::drawQuad(context, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    599 
    600 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
    601 	}
    602 	else
    603 		readPixels(context, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
    604 }
    605 
    606 class SharedColorbufferTest : public FboRenderCase
    607 {
    608 public:
    609 						SharedColorbufferTest			(Context& context, const FboConfig& config);
    610 	virtual				~SharedColorbufferTest			(void) {};
    611 
    612 	void				render							(sglr::Context& context, Surface& dst);
    613 };
    614 
    615 SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config)
    616 	: FboRenderCase	(context, config.getName().c_str(), "Shared colorbuffer", config)
    617 {
    618 }
    619 
    620 void SharedColorbufferTest::render (sglr::Context& context, Surface& dst)
    621 {
    622 	Texture2DShader			texShader		(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
    623 	FlatColorShader			flatShader		(glu::TYPE_FLOAT_VEC4);
    624 	deUint32				texShaderID		= context.createProgram(&texShader);
    625 	deUint32				flatShaderID	= context.createProgram(&flatShader);
    626 
    627 	int						width			= 128;
    628 	int						height			= 128;
    629 	deUint32				quadsTex		= 1;
    630 	deUint32				metaballsTex	= 2;
    631 	bool					stencil			= (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
    632 
    633 	context.disable(GL_DITHER);
    634 
    635 	// Textures
    636 	createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
    637 	createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
    638 
    639 	context.viewport(0, 0, width, height);
    640 
    641 	// Fbo A
    642 	Framebuffer fboA(context, m_config, width, height);
    643 	fboA.checkCompleteness();
    644 
    645 	// Fbo B - don't create colorbuffer
    646 	FboConfig cfg = m_config;
    647 	cfg.buffers		&= ~GL_COLOR_BUFFER_BIT;
    648 	cfg.colorType	 = GL_NONE;
    649 	cfg.colorFormat	 = GL_NONE;
    650 	Framebuffer fboB(context, cfg, width, height);
    651 
    652 	// Attach color buffer from fbo A
    653 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
    654 	switch (m_config.colorType)
    655 	{
    656 		case GL_TEXTURE_2D:
    657 			context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboA.getColorBuffer(), 0);
    658 			break;
    659 
    660 		case GL_RENDERBUFFER:
    661 			context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboA.getColorBuffer());
    662 			break;
    663 
    664 		default:
    665 			DE_ASSERT(DE_FALSE);
    666 	}
    667 
    668 	// Clear depth and stencil in fbo B
    669 	context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    670 
    671 	// Render quads to fbo 1, with depth 0.0
    672 	context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
    673 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
    674 	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
    675 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    676 
    677 	if (stencil)
    678 	{
    679 		// Stencil to 1 in fbo A
    680 		context.clearStencil(1);
    681 		context.clear(GL_STENCIL_BUFFER_BIT);
    682 	}
    683 
    684 	texShader.setUniforms(context, texShaderID);
    685 
    686 	context.enable(GL_DEPTH_TEST);
    687 	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    688 	context.disable(GL_DEPTH_TEST);
    689 
    690 	// Blend metaballs to fbo 2
    691 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
    692 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
    693 	context.enable(GL_BLEND);
    694 	context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
    695 	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    696 
    697 	// Render small quad that is only visible if depth buffer is not shared with fbo A - or there is no depth bits
    698 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
    699 	context.enable(GL_DEPTH_TEST);
    700 	sglr::drawQuad(context, texShaderID, Vec3(0.5f, 0.5f, 0.5f), Vec3(1.0f, 1.0f, 0.5f));
    701 	context.disable(GL_DEPTH_TEST);
    702 
    703 	if (stencil)
    704 	{
    705 		flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
    706 
    707 		// Clear subset of stencil buffer to 1
    708 		context.enable(GL_SCISSOR_TEST);
    709 		context.scissor(10, 10, 12, 25);
    710 		context.clearStencil(1);
    711 		context.clear(GL_STENCIL_BUFFER_BIT);
    712 		context.disable(GL_SCISSOR_TEST);
    713 
    714 		// Render quad with stencil mask == 1
    715 		context.enable(GL_STENCIL_TEST);
    716 		context.stencilFunc(GL_EQUAL, 1, 0xffu);
    717 		sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    718 		context.disable(GL_STENCIL_TEST);
    719 	}
    720 
    721 	// Get results
    722 	if (fboA.getConfig().colorType == GL_TEXTURE_2D)
    723 	{
    724 		texShader.setUniforms(context, texShaderID);
    725 
    726 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
    727 		context.bindTexture(GL_TEXTURE_2D, fboA.getColorBuffer());
    728 		context.viewport(0, 0, context.getWidth(), context.getHeight());
    729 		sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    730 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
    731 	}
    732 	else
    733 		readPixels(context, dst, 0, 0, width, height, glu::mapGLInternalFormat(fboA.getConfig().colorFormat), Vec4(1.0f), Vec4(0.0f));
    734 }
    735 
    736 class SharedColorbufferClearsTest : public FboRenderCase
    737 {
    738 public:
    739 					SharedColorbufferClearsTest		(Context& context, const FboConfig& config);
    740 	virtual			~SharedColorbufferClearsTest	(void) {}
    741 
    742 	void			render							(sglr::Context& context, Surface& dst);
    743 };
    744 
    745 SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config)
    746 	: FboRenderCase	(context, config.getName().c_str(), "Shared colorbuffer clears", config)
    747 {
    748 }
    749 
    750 void SharedColorbufferClearsTest::render (sglr::Context& context, Surface& dst)
    751 {
    752 	tcu::TextureFormat		colorFormat		= glu::mapGLInternalFormat(m_config.colorFormat);
    753 	glu::DataType			fboSamplerType	= glu::getSampler2DType(colorFormat);
    754 	int						width			= 128;
    755 	int						height			= 128;
    756 	deUint32				colorbuffer		= 1;
    757 
    758 	// Check for format support.
    759 	checkColorFormatSupport(context, m_config.colorFormat);
    760 
    761 	// Single colorbuffer
    762 	if (m_config.colorType == GL_TEXTURE_2D)
    763 	{
    764 		context.bindTexture(GL_TEXTURE_2D, colorbuffer);
    765 		context.texImage2D(GL_TEXTURE_2D, 0, m_config.colorFormat, width, height);
    766 		context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    767 		context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    768 	}
    769 	else
    770 	{
    771 		DE_ASSERT(m_config.colorType == GL_RENDERBUFFER);
    772 		context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
    773 		context.renderbufferStorage(GL_RENDERBUFFER, m_config.colorFormat, width, height);
    774 	}
    775 
    776 	// Multiple framebuffers sharing the colorbuffer
    777 	for (int fbo = 1; fbo <= 3; fbo++)
    778 	{
    779 		context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
    780 
    781 		if (m_config.colorType == GL_TEXTURE_2D)
    782 			context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
    783 		else
    784 			context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
    785 	}
    786 
    787 	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
    788 
    789 	// Check completeness
    790 	{
    791 		GLenum status = context.checkFramebufferStatus(GL_FRAMEBUFFER);
    792 		if (status != GL_FRAMEBUFFER_COMPLETE)
    793 			throw FboIncompleteException(status, __FILE__, __LINE__);
    794 	}
    795 
    796 	// Render to them
    797 	context.viewport(0, 0, width, height);
    798 	context.clearColor(0.0f, 0.0f, 1.0f, 1.0f);
    799 	context.clear(GL_COLOR_BUFFER_BIT);
    800 
    801 	context.enable(GL_SCISSOR_TEST);
    802 
    803 	context.bindFramebuffer(GL_FRAMEBUFFER, 2);
    804 	context.clearColor(0.6f, 0.0f, 0.0f, 1.0f);
    805 	context.scissor(10, 10, 64, 64);
    806 	context.clear(GL_COLOR_BUFFER_BIT);
    807 	context.clearColor(0.0f, 0.6f, 0.0f, 1.0f);
    808 	context.scissor(60, 60, 40, 20);
    809 	context.clear(GL_COLOR_BUFFER_BIT);
    810 
    811 	context.bindFramebuffer(GL_FRAMEBUFFER, 3);
    812 	context.clearColor(0.0f, 0.0f, 0.6f, 1.0f);
    813 	context.scissor(20, 20, 100, 10);
    814 	context.clear(GL_COLOR_BUFFER_BIT);
    815 
    816 	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
    817 	context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
    818 	context.scissor(20, 20, 5, 100);
    819 	context.clear(GL_COLOR_BUFFER_BIT);
    820 
    821 	context.disable(GL_SCISSOR_TEST);
    822 
    823 	if (m_config.colorType == GL_TEXTURE_2D)
    824 	{
    825 		Texture2DShader shader(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
    826 		deUint32 shaderID = context.createProgram(&shader);
    827 
    828 		shader.setUniforms(context, shaderID);
    829 
    830 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
    831 		context.viewport(0, 0, context.getWidth(), context.getHeight());
    832 		sglr::drawQuad(context, shaderID, Vec3(-0.9f, -0.9f, 0.0f), Vec3(0.9f, 0.9f, 0.0f));
    833 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
    834 	}
    835 	else
    836 		readPixels(context, dst, 0, 0, width, height, colorFormat, Vec4(1.0f), Vec4(0.0f));
    837 }
    838 
    839 class SharedDepthStencilTest : public FboRenderCase
    840 {
    841 public:
    842 					SharedDepthStencilTest		(Context& context, const FboConfig& config);
    843 	virtual			~SharedDepthStencilTest		(void) {};
    844 
    845 	static bool		isConfigSupported			(const FboConfig& config);
    846 	void			render						(sglr::Context& context, Surface& dst);
    847 };
    848 
    849 SharedDepthStencilTest::SharedDepthStencilTest (Context& context, const FboConfig& config)
    850 	: FboRenderCase	(context, config.getName().c_str(), "Shared depth/stencilbuffer", config)
    851 {
    852 }
    853 
    854 bool SharedDepthStencilTest::isConfigSupported (const FboConfig& config)
    855 {
    856 	return (config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0;
    857 }
    858 
    859 void SharedDepthStencilTest::render (sglr::Context& context, Surface& dst)
    860 {
    861 	Texture2DShader	texShader		(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
    862 	FlatColorShader	flatShader		(glu::TYPE_FLOAT_VEC4);
    863 	deUint32		texShaderID		= context.createProgram(&texShader);
    864 	deUint32		flatShaderID	= context.createProgram(&flatShader);
    865 	int				width			= 128;
    866 	int				height			= 128;
    867 //	bool			depth			= (m_config.buffers & GL_DEPTH_BUFFER_BIT) != 0;
    868 	bool			stencil			= (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
    869 
    870 	// Textures
    871 	deUint32 metaballsTex	= 5;
    872 	deUint32 quadsTex		= 6;
    873 	createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
    874 	createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
    875 
    876 	context.viewport(0, 0, width, height);
    877 
    878 	// Fbo A
    879 	Framebuffer fboA(context, m_config, width, height);
    880 	fboA.checkCompleteness();
    881 
    882 	// Fbo B
    883 	FboConfig cfg = m_config;
    884 	cfg.buffers				&= ~(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    885 	cfg.depthStencilType	 = GL_NONE;
    886 	cfg.depthStencilFormat	 = GL_NONE;
    887 	Framebuffer fboB(context, cfg, width, height);
    888 
    889 	// Bind depth/stencil buffers from fbo A to fbo B
    890 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
    891 	for (int ndx = 0; ndx < 2; ndx++)
    892 	{
    893 		deUint32	bit		= ndx ? GL_STENCIL_BUFFER_BIT : GL_DEPTH_BUFFER_BIT;
    894 		deUint32	point	= ndx ? GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
    895 
    896 		if ((m_config.buffers & bit) == 0)
    897 			continue;
    898 
    899 		switch (m_config.depthStencilType)
    900 		{
    901 			case GL_TEXTURE_2D:		context.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, fboA.getDepthStencilBuffer(), 0);	break;
    902 			case GL_RENDERBUFFER:	context.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, fboA.getDepthStencilBuffer());	break;
    903 			default:
    904 				TCU_FAIL("Not implemented");
    905 		}
    906 	}
    907 
    908 	// Setup uniforms
    909 	texShader.setUniforms(context, texShaderID);
    910 
    911 	// Clear color to red and stencil to 1 in fbo B.
    912 	context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
    913 	context.clearStencil(1);
    914 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    915 
    916 	context.enable(GL_DEPTH_TEST);
    917 
    918 	// Render quad to fbo A
    919 	context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
    920 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
    921 	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    922 
    923 	if (stencil)
    924 	{
    925 		// Clear subset of stencil buffer to 0 in fbo A
    926 		context.enable(GL_SCISSOR_TEST);
    927 		context.scissor(10, 10, 12, 25);
    928 		context.clearStencil(0);
    929 		context.clear(GL_STENCIL_BUFFER_BIT);
    930 		context.disable(GL_SCISSOR_TEST);
    931 	}
    932 
    933 	// Render metaballs to fbo B
    934 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
    935 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
    936 	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
    937 
    938 	context.disable(GL_DEPTH_TEST);
    939 
    940 	if (stencil)
    941 	{
    942 		// Render quad with stencil mask == 0
    943 		context.enable(GL_STENCIL_TEST);
    944 		context.stencilFunc(GL_EQUAL, 0, 0xffu);
    945 		context.useProgram(flatShaderID);
    946 		flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
    947 		sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
    948 		context.disable(GL_STENCIL_TEST);
    949 	}
    950 
    951 	if (m_config.colorType == GL_TEXTURE_2D)
    952 	{
    953 		// Render both to screen
    954 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
    955 		context.viewport(0, 0, context.getWidth(), context.getHeight());
    956 		context.bindTexture(GL_TEXTURE_2D, fboA.getColorBuffer());
    957 		sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
    958 		context.bindTexture(GL_TEXTURE_2D, fboB.getColorBuffer());
    959 		sglr::drawQuad(context, texShaderID, Vec3(0.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    960 
    961 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
    962 	}
    963 	else
    964 	{
    965 		// Read results from fbo B
    966 		readPixels(context, dst, 0, 0, width, height, glu::mapGLInternalFormat(m_config.colorFormat), Vec4(1.0f), Vec4(0.0f));
    967 	}
    968 }
    969 
    970 #if 0
    971 class TexSubImageAfterRenderTest : public FboRenderCase
    972 {
    973 public:
    974 					TexSubImageAfterRenderTest		(Context& context, const FboConfig& config);
    975 	virtual			~TexSubImageAfterRenderTest		(void) {}
    976 
    977 	void			render							(sglr::Context& context, Surface& dst);
    978 };
    979 
    980 TexSubImageAfterRenderTest::TexSubImageAfterRenderTest (Context& context, const FboConfig& config)
    981 	: FboRenderCase(context, (string("after_render_") + config.getName()).c_str(), "TexSubImage after rendering to texture", config)
    982 {
    983 }
    984 
    985 void TexSubImageAfterRenderTest::render (sglr::Context& context, Surface& dst)
    986 {
    987 	using sglr::TexturedQuadOp;
    988 
    989 	bool isRGBA = true;
    990 
    991 	Surface fourQuads(Surface::PIXELFORMAT_RGB, 64, 64);
    992 	tcu::SurfaceUtil::fillWithFourQuads(fourQuads);
    993 
    994 	Surface metaballs(isRGBA ? Surface::PIXELFORMAT_RGBA : Surface::PIXELFORMAT_RGB, 64, 64);
    995 	tcu::SurfaceUtil::fillWithMetaballs(metaballs, 5, 3);
    996 
    997 	deUint32 fourQuadsTex = 1;
    998 	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
    999 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1000 	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, fourQuads);
   1001 
   1002 	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
   1003 
   1004 	deUint32 fboTex = 2;
   1005 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1006 	context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
   1007 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1008 	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
   1009 
   1010 	// Render to fbo
   1011 	context.viewport(0, 0, 128, 128);
   1012 	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
   1013 	context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
   1014 
   1015 	// Update texture using TexSubImage2D
   1016 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1017 	context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, metaballs);
   1018 
   1019 	// Draw to screen
   1020 	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1021 	context.viewport(0, 0, context.getWidth(), context.getHeight());
   1022 	context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
   1023 	context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1024 }
   1025 
   1026 class TexSubImageBetweenRenderTest : public FboRenderCase
   1027 {
   1028 public:
   1029 					TexSubImageBetweenRenderTest		(Context& context, const FboConfig& config);
   1030 	virtual			~TexSubImageBetweenRenderTest		(void) {}
   1031 
   1032 	void			render								(sglr::Context& context, Surface& dst);
   1033 };
   1034 
   1035 TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config)
   1036 	: FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config)
   1037 {
   1038 }
   1039 
   1040 void TexSubImageBetweenRenderTest::render (sglr::Context& context, Surface& dst)
   1041 {
   1042 	using sglr::TexturedQuadOp;
   1043 	using sglr::BlendTextureOp;
   1044 
   1045 	bool isRGBA = true;
   1046 
   1047 	Surface fourQuads(Surface::PIXELFORMAT_RGB, 64, 64);
   1048 	tcu::SurfaceUtil::fillWithFourQuads(fourQuads);
   1049 
   1050 	Surface metaballs(isRGBA ? Surface::PIXELFORMAT_RGBA : Surface::PIXELFORMAT_RGB, 64, 64);
   1051 	tcu::SurfaceUtil::fillWithMetaballs(metaballs, 5, 3);
   1052 
   1053 	Surface metaballs2(Surface::PIXELFORMAT_RGBA, 64, 64);
   1054 	tcu::SurfaceUtil::fillWithMetaballs(metaballs2, 5, 4);
   1055 
   1056 	deUint32 metaballsTex = 3;
   1057 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1058 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1059 	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, metaballs2);
   1060 
   1061 	deUint32 fourQuadsTex = 1;
   1062 	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
   1063 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1064 	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, fourQuads);
   1065 
   1066 	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
   1067 
   1068 	deUint32 fboTex = 2;
   1069 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1070 	context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
   1071 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1072 	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
   1073 
   1074 	// Render to fbo
   1075 	context.viewport(0, 0, 128, 128);
   1076 	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
   1077 	context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
   1078 
   1079 	// Update texture using TexSubImage2D
   1080 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1081 	context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, metaballs);
   1082 
   1083 	// Render again to fbo
   1084 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1085 	context.draw(BlendTextureOp(0));
   1086 
   1087 	// Draw to screen
   1088 	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1089 	context.viewport(0, 0, context.getWidth(), context.getHeight());
   1090 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1091 	context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
   1092 
   1093 	context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1094 }
   1095 #endif
   1096 
   1097 class ResizeTest : public FboRenderCase
   1098 {
   1099 public:
   1100 					ResizeTest				(Context& context, const FboConfig& config);
   1101 	virtual			~ResizeTest				(void) {}
   1102 
   1103 	void			render					(sglr::Context& context, Surface& dst);
   1104 };
   1105 
   1106 ResizeTest::ResizeTest (Context& context, const FboConfig& config)
   1107 	: FboRenderCase	(context, config.getName().c_str(), "Resize framebuffer", config)
   1108 {
   1109 }
   1110 
   1111 void ResizeTest::render (sglr::Context& context, Surface& dst)
   1112 {
   1113 	tcu::TextureFormat		colorFormat			= glu::mapGLInternalFormat(m_config.colorFormat);
   1114 	glu::DataType			fboSamplerType		= glu::getSampler2DType(colorFormat);
   1115 	glu::DataType			fboOutputType		= getFragmentOutputType(colorFormat);
   1116 	tcu::TextureFormatInfo	fboRangeInfo		= tcu::getTextureFormatInfo(colorFormat);
   1117 	Vec4					fboOutScale			= fboRangeInfo.valueMax - fboRangeInfo.valueMin;
   1118 	Vec4					fboOutBias			= fboRangeInfo.valueMin;
   1119 
   1120 	Texture2DShader			texToFboShader		(DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
   1121 	Texture2DShader			texFromFboShader	(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
   1122 	FlatColorShader			flatShader			(fboOutputType);
   1123 	deUint32				texToFboShaderID	= context.createProgram(&texToFboShader);
   1124 	deUint32				texFromFboShaderID	= context.createProgram(&texFromFboShader);
   1125 	deUint32				flatShaderID		= context.createProgram(&flatShader);
   1126 
   1127 	deUint32				quadsTex			= 1;
   1128 	deUint32				metaballsTex		= 2;
   1129 	bool					depth				= (m_config.buffers & GL_DEPTH_BUFFER_BIT)		!= 0;
   1130 	bool					stencil				= (m_config.buffers & GL_STENCIL_BUFFER_BIT)	!= 0;
   1131 	int						initialWidth		= 128;
   1132 	int						initialHeight		= 128;
   1133 	int						newWidth			= 64;
   1134 	int						newHeight			= 32;
   1135 
   1136 	texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
   1137 	texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
   1138 
   1139 	createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1140 	createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 32, 32);
   1141 
   1142 	Framebuffer fbo(context, m_config, initialWidth, initialHeight);
   1143 	fbo.checkCompleteness();
   1144 
   1145 	// Setup shaders
   1146 	texToFboShader.setUniforms	(context, texToFboShaderID);
   1147 	texFromFboShader.setUniforms(context, texFromFboShaderID);
   1148 	flatShader.setColor			(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f) * fboOutScale + fboOutBias);
   1149 
   1150 	// Render quads
   1151 	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1152 	context.viewport(0, 0, initialWidth, initialHeight);
   1153 	clearColorBuffer(context, colorFormat, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
   1154 	context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1155 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1156 	sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1157 
   1158 	if (fbo.getConfig().colorType == GL_TEXTURE_2D)
   1159 	{
   1160 		// Render fbo to screen
   1161 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1162 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1163 		context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
   1164 		sglr::drawQuad(context, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1165 
   1166 		// Restore binding
   1167 		context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1168 	}
   1169 
   1170 	// Resize buffers
   1171 	switch (fbo.getConfig().colorType)
   1172 	{
   1173 		case GL_TEXTURE_2D:
   1174 			context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
   1175 			context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorFormat, newWidth, newHeight);
   1176 			break;
   1177 
   1178 		case GL_RENDERBUFFER:
   1179 			context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getColorBuffer());
   1180 			context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorFormat, newWidth, newHeight);
   1181 			break;
   1182 
   1183 		default:
   1184 			DE_ASSERT(DE_FALSE);
   1185 	}
   1186 
   1187 	if (depth || stencil)
   1188 	{
   1189 		switch (fbo.getConfig().depthStencilType)
   1190 		{
   1191 			case GL_TEXTURE_2D:
   1192 				context.bindTexture(GL_TEXTURE_2D, fbo.getDepthStencilBuffer());
   1193 				context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().depthStencilFormat, newWidth, newHeight);
   1194 				break;
   1195 
   1196 			case GL_RENDERBUFFER:
   1197 				context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getDepthStencilBuffer());
   1198 				context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthStencilFormat, newWidth, newHeight);
   1199 				break;
   1200 
   1201 			default:
   1202 				DE_ASSERT(false);
   1203 		}
   1204 	}
   1205 
   1206 	// Render to resized fbo
   1207 	context.viewport(0, 0, newWidth, newHeight);
   1208 	clearColorBuffer(context, colorFormat, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
   1209 	context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1210 
   1211 	context.enable(GL_DEPTH_TEST);
   1212 
   1213 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1214 	sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
   1215 
   1216 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1217 	sglr::drawQuad(context, texToFboShaderID, Vec3(0.0f, 0.0f, -1.0f), Vec3(+1.0f, +1.0f, 1.0f));
   1218 
   1219 	context.disable(GL_DEPTH_TEST);
   1220 
   1221 	if (stencil)
   1222 	{
   1223 		context.enable(GL_SCISSOR_TEST);
   1224 		context.clearStencil(1);
   1225 		context.scissor(10, 10, 5, 15);
   1226 		context.clear(GL_STENCIL_BUFFER_BIT);
   1227 		context.disable(GL_SCISSOR_TEST);
   1228 
   1229 		context.enable(GL_STENCIL_TEST);
   1230 		context.stencilFunc(GL_EQUAL, 1, 0xffu);
   1231 		sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
   1232 		context.disable(GL_STENCIL_TEST);
   1233 	}
   1234 
   1235 	if (m_config.colorType == GL_TEXTURE_2D)
   1236 	{
   1237 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1238 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1239 		context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
   1240 		sglr::drawQuad(context, texFromFboShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(0.5f, 0.5f, 0.0f));
   1241 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1242 	}
   1243 	else
   1244 		readPixels(context, dst, 0, 0, newWidth, newHeight, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
   1245 }
   1246 
   1247 class RecreateBuffersTest : public FboRenderCase
   1248 {
   1249 public:
   1250 					RecreateBuffersTest			(Context& context, const FboConfig& config, deUint32 buffers, bool rebind);
   1251 	virtual			~RecreateBuffersTest		(void) {}
   1252 
   1253 	void			render						(sglr::Context& context, Surface& dst);
   1254 
   1255 private:
   1256 	deUint32		m_buffers;
   1257 	bool			m_rebind;
   1258 };
   1259 
   1260 RecreateBuffersTest::RecreateBuffersTest (Context& context, const FboConfig& config, deUint32 buffers, bool rebind)
   1261 	: FboRenderCase		(context, (string(config.getName()) + (rebind ? "" : "_no_rebind")).c_str(), "Recreate buffers", config)
   1262 	, m_buffers			(buffers)
   1263 	, m_rebind			(rebind)
   1264 {
   1265 }
   1266 
   1267 void RecreateBuffersTest::render (sglr::Context& ctx, Surface& dst)
   1268 {
   1269 	tcu::TextureFormat		colorFormat			= glu::mapGLInternalFormat(m_config.colorFormat);
   1270 	glu::DataType			fboSamplerType		= glu::getSampler2DType(colorFormat);
   1271 	glu::DataType			fboOutputType		= getFragmentOutputType(colorFormat);
   1272 	tcu::TextureFormatInfo	fboRangeInfo		= tcu::getTextureFormatInfo(colorFormat);
   1273 	Vec4					fboOutScale			= fboRangeInfo.valueMax - fboRangeInfo.valueMin;
   1274 	Vec4					fboOutBias			= fboRangeInfo.valueMin;
   1275 
   1276 	Texture2DShader			texToFboShader		(DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
   1277 	Texture2DShader			texFromFboShader	(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
   1278 	FlatColorShader			flatShader			(fboOutputType);
   1279 	deUint32				texToFboShaderID	= ctx.createProgram(&texToFboShader);
   1280 	deUint32				texFromFboShaderID	= ctx.createProgram(&texFromFboShader);
   1281 	deUint32				flatShaderID		= ctx.createProgram(&flatShader);
   1282 
   1283 	int						width				= 128;
   1284 	int						height				= 128;
   1285 	deUint32				metaballsTex		= 1;
   1286 	deUint32				quadsTex			= 2;
   1287 	bool					stencil				= (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
   1288 
   1289 	createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1290 	createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1291 
   1292 	Framebuffer fbo(ctx, m_config, width, height);
   1293 	fbo.checkCompleteness();
   1294 
   1295 	// Setup shaders
   1296 	texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
   1297 	texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
   1298 	texToFboShader.setUniforms	(ctx, texToFboShaderID);
   1299 	texFromFboShader.setUniforms(ctx, texFromFboShaderID);
   1300 	flatShader.setColor			(ctx, flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f) * fboOutScale + fboOutBias);
   1301 
   1302 	// Draw scene
   1303 	ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1304 	ctx.viewport(0, 0, width, height);
   1305 	clearColorBuffer(ctx, colorFormat, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
   1306 	ctx.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1307 
   1308 	ctx.enable(GL_DEPTH_TEST);
   1309 
   1310 	ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
   1311 	sglr::drawQuad(ctx, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1312 
   1313 	ctx.disable(GL_DEPTH_TEST);
   1314 
   1315 	if (stencil)
   1316 	{
   1317 		ctx.enable(GL_SCISSOR_TEST);
   1318 		ctx.scissor(width/4, height/4, width/2, height/2);
   1319 		ctx.clearStencil(1);
   1320 		ctx.clear(GL_STENCIL_BUFFER_BIT);
   1321 		ctx.disable(GL_SCISSOR_TEST);
   1322 	}
   1323 
   1324 	// Recreate buffers
   1325 	if (!m_rebind)
   1326 		ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1327 
   1328 	DE_ASSERT((m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) == 0 ||
   1329 			  (m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) == (m_config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)));
   1330 
   1331 	// Recreate.
   1332 	for (int ndx = 0; ndx < 2; ndx++)
   1333 	{
   1334 		deUint32	bit		= ndx == 0 ? GL_COLOR_BUFFER_BIT
   1335 									   : (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1336 		deUint32	type	= ndx == 0 ? fbo.getConfig().colorType
   1337 									   : fbo.getConfig().depthStencilType;
   1338 		deUint32	format	= ndx == 0 ? fbo.getConfig().colorFormat
   1339 									   : fbo.getConfig().depthStencilFormat;
   1340 		deUint32	buf		= ndx == 0 ? fbo.getColorBuffer()
   1341 									   : fbo.getDepthStencilBuffer();
   1342 
   1343 		if ((m_buffers & bit) == 0)
   1344 			continue;
   1345 
   1346 		switch (type)
   1347 		{
   1348 			case GL_TEXTURE_2D:
   1349 				ctx.deleteTextures(1, &buf);
   1350 				ctx.bindTexture(GL_TEXTURE_2D, buf);
   1351 				ctx.texImage2D(GL_TEXTURE_2D, 0, format, width, height);
   1352 				ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   1353 				ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   1354 				break;
   1355 
   1356 			case GL_RENDERBUFFER:
   1357 				ctx.deleteRenderbuffers(1, &buf);
   1358 				ctx.bindRenderbuffer(GL_RENDERBUFFER, buf);
   1359 				ctx.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
   1360 				break;
   1361 
   1362 			default:
   1363 				DE_ASSERT(false);
   1364 		}
   1365 	}
   1366 
   1367 	// Rebind.
   1368 	if (m_rebind)
   1369 	{
   1370 		for (int ndx = 0; ndx < 3; ndx++)
   1371 		{
   1372 			deUint32	bit		= ndx == 0 ? GL_COLOR_BUFFER_BIT	:
   1373 								  ndx == 1 ? GL_DEPTH_BUFFER_BIT	:
   1374 								  ndx == 2 ? GL_STENCIL_BUFFER_BIT	: 0;
   1375 			deUint32	point	= ndx == 0 ? GL_COLOR_ATTACHMENT0	:
   1376 								  ndx == 1 ? GL_DEPTH_ATTACHMENT	:
   1377 								  ndx == 2 ? GL_STENCIL_ATTACHMENT	: 0;
   1378 			deUint32	type	= ndx == 0 ? fbo.getConfig().colorType
   1379 										   : fbo.getConfig().depthStencilType;
   1380 			deUint32	buf		= ndx == 0 ? fbo.getColorBuffer()
   1381 										   : fbo.getDepthStencilBuffer();
   1382 
   1383 			if ((m_buffers & bit) == 0)
   1384 				continue;
   1385 
   1386 			switch (type)
   1387 			{
   1388 				case GL_TEXTURE_2D:
   1389 					ctx.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, buf, 0);
   1390 					break;
   1391 
   1392 				case GL_RENDERBUFFER:
   1393 					ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, buf);
   1394 					break;
   1395 
   1396 				default:
   1397 					DE_ASSERT(false);
   1398 			}
   1399 		}
   1400 	}
   1401 
   1402 	if (!m_rebind)
   1403 		ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1404 
   1405 	ctx.clearStencil(0);
   1406 	ctx.clear(m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); // \note Clear only buffers that were re-created
   1407 	if (m_buffers & GL_COLOR_BUFFER_BIT)
   1408 	{
   1409 		// Clearing of integer buffers is undefined so do clearing by rendering flat color.
   1410 		sglr::drawQuad(ctx, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1411 	}
   1412 
   1413 	ctx.enable(GL_DEPTH_TEST);
   1414 
   1415 	if (stencil)
   1416 	{
   1417 		// \note Stencil test enabled only if we have stencil buffer
   1418 		ctx.enable(GL_STENCIL_TEST);
   1419 		ctx.stencilFunc(GL_EQUAL, 0, 0xffu);
   1420 	}
   1421 	ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1422 	sglr::drawQuad(ctx, texToFboShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
   1423 	if (stencil)
   1424 		ctx.disable(GL_STENCIL_TEST);
   1425 
   1426 	ctx.disable(GL_DEPTH_TEST);
   1427 
   1428 	if (fbo.getConfig().colorType == GL_TEXTURE_2D)
   1429 	{
   1430 		// Unbind fbo
   1431 		ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1432 
   1433 		// Draw to screen
   1434 		ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
   1435 		ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
   1436 		sglr::drawQuad(ctx, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1437 
   1438 		// Read from screen
   1439 		ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
   1440 	}
   1441 	else
   1442 	{
   1443 		// Read from fbo
   1444 		readPixels(ctx, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
   1445 	}
   1446 }
   1447 
   1448 } // FboCases
   1449 
   1450 FboRenderTestGroup::FboRenderTestGroup (Context& context)
   1451 	: TestCaseGroup(context, "render", "Rendering Tests")
   1452 {
   1453 }
   1454 
   1455 FboRenderTestGroup::~FboRenderTestGroup (void)
   1456 {
   1457 }
   1458 
   1459 void FboRenderTestGroup::init (void)
   1460 {
   1461 	static const deUint32 objectTypes[] =
   1462 	{
   1463 		GL_TEXTURE_2D,
   1464 		GL_RENDERBUFFER
   1465 	};
   1466 
   1467 	enum FormatType
   1468 	{
   1469 		FORMATTYPE_FLOAT = 0,
   1470 		FORMATTYPE_FIXED,
   1471 		FORMATTYPE_INT,
   1472 		FORMATTYPE_UINT,
   1473 
   1474 		FORMATTYPE_LAST
   1475 	};
   1476 
   1477 	// Required by specification.
   1478 	static const struct
   1479 	{
   1480 		deUint32	format;
   1481 		FormatType	type;
   1482 	} colorFormats[] =
   1483 	{
   1484 		{ GL_RGBA32F,			FORMATTYPE_FLOAT	},
   1485 		{ GL_RGBA32I,			FORMATTYPE_INT		},
   1486 		{ GL_RGBA32UI,			FORMATTYPE_UINT		},
   1487 		{ GL_RGBA16F,			FORMATTYPE_FLOAT	},
   1488 		{ GL_RGBA16I,			FORMATTYPE_INT		},
   1489 		{ GL_RGBA16UI,			FORMATTYPE_UINT		},
   1490 		{ GL_RGB16F,			FORMATTYPE_FLOAT	},
   1491 		{ GL_RGBA8,				FORMATTYPE_FIXED	},
   1492 		{ GL_RGBA8I,			FORMATTYPE_INT		},
   1493 		{ GL_RGBA8UI,			FORMATTYPE_UINT		},
   1494 		{ GL_SRGB8_ALPHA8,		FORMATTYPE_FIXED	},
   1495 		{ GL_RGB10_A2,			FORMATTYPE_FIXED	},
   1496 		{ GL_RGB10_A2UI,		FORMATTYPE_UINT		},
   1497 		{ GL_RGBA4,				FORMATTYPE_FIXED	},
   1498 		{ GL_RGB5_A1,			FORMATTYPE_FIXED	},
   1499 		{ GL_RGB8,				FORMATTYPE_FIXED	},
   1500 		{ GL_RGB565,			FORMATTYPE_FIXED	},
   1501 		{ GL_R11F_G11F_B10F,	FORMATTYPE_FLOAT	},
   1502 		{ GL_RG32F,				FORMATTYPE_FLOAT	},
   1503 		{ GL_RG32I,				FORMATTYPE_INT		},
   1504 		{ GL_RG32UI,			FORMATTYPE_UINT		},
   1505 		{ GL_RG16F,				FORMATTYPE_FLOAT	},
   1506 		{ GL_RG16I,				FORMATTYPE_INT		},
   1507 		{ GL_RG16UI,			FORMATTYPE_UINT		},
   1508 		{ GL_RG8,				FORMATTYPE_FLOAT	},
   1509 		{ GL_RG8I,				FORMATTYPE_INT		},
   1510 		{ GL_RG8UI,				FORMATTYPE_UINT		},
   1511 		{ GL_R32F,				FORMATTYPE_FLOAT	},
   1512 		{ GL_R32I,				FORMATTYPE_INT		},
   1513 		{ GL_R32UI,				FORMATTYPE_UINT		},
   1514 		{ GL_R16F,				FORMATTYPE_FLOAT	},
   1515 		{ GL_R16I,				FORMATTYPE_INT		},
   1516 		{ GL_R16UI,				FORMATTYPE_UINT		},
   1517 		{ GL_R8,				FORMATTYPE_FLOAT	},
   1518 		{ GL_R8I,				FORMATTYPE_INT		},
   1519 		{ GL_R8UI,				FORMATTYPE_UINT		}
   1520 	};
   1521 
   1522 	static const struct
   1523 	{
   1524 		deUint32	format;
   1525 		bool		depth;
   1526 		bool		stencil;
   1527 	} depthStencilFormats[] =
   1528 	{
   1529 		{ GL_DEPTH_COMPONENT32F,	true,	false	},
   1530 		{ GL_DEPTH_COMPONENT24,		true,	false	},
   1531 		{ GL_DEPTH_COMPONENT16,		true,	false	},
   1532 		{ GL_DEPTH32F_STENCIL8,		true,	true	},
   1533 		{ GL_DEPTH24_STENCIL8,		true,	true	},
   1534 		{ GL_STENCIL_INDEX8,		false,	true	}
   1535 	};
   1536 
   1537 	using namespace FboCases;
   1538 
   1539 	// .stencil_clear
   1540 	tcu::TestCaseGroup* stencilClearGroup = new tcu::TestCaseGroup(m_testCtx, "stencil_clear", "Stencil buffer clears");
   1541 	addChild(stencilClearGroup);
   1542 	for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
   1543 	{
   1544 		deUint32	colorType	= GL_TEXTURE_2D;
   1545 		deUint32	stencilType	= GL_RENDERBUFFER;
   1546 		deUint32	colorFmt	= GL_RGBA8;
   1547 
   1548 		if (!depthStencilFormats[fmtNdx].stencil)
   1549 			continue;
   1550 
   1551 		FboConfig config(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, colorType, colorFmt, stencilType, depthStencilFormats[fmtNdx].format);
   1552 		stencilClearGroup->addChild(new StencilClearsTest(m_context, config));
   1553 	}
   1554 
   1555 	// .shared_colorbuffer_clear
   1556 	tcu::TestCaseGroup* sharedColorbufferClearGroup = new tcu::TestCaseGroup(m_testCtx, "shared_colorbuffer_clear", "Shader colorbuffer clears");
   1557 	addChild(sharedColorbufferClearGroup);
   1558 	for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
   1559 	{
   1560 		// Clearing of integer buffers is undefined.
   1561 		if (colorFormats[colorFmtNdx].type == FORMATTYPE_INT || colorFormats[colorFmtNdx].type == FORMATTYPE_UINT)
   1562 			continue;
   1563 
   1564 		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
   1565 		{
   1566 			FboConfig config(GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, GL_NONE, GL_NONE);
   1567 			sharedColorbufferClearGroup->addChild(new SharedColorbufferClearsTest(m_context, config));
   1568 		}
   1569 	}
   1570 
   1571 	// .shared_colorbuffer
   1572 	tcu::TestCaseGroup* sharedColorbufferGroup = new tcu::TestCaseGroup(m_testCtx, "shared_colorbuffer", "Shared colorbuffer tests");
   1573 	addChild(sharedColorbufferGroup);
   1574 	for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
   1575 	{
   1576 		deUint32	depthStencilType	= GL_RENDERBUFFER;
   1577 		deUint32	depthStencilFormat	= GL_DEPTH24_STENCIL8;
   1578 
   1579 		// Blending with integer buffers and fp32 targets is not supported.
   1580 		if (colorFormats[colorFmtNdx].type == FORMATTYPE_INT	||
   1581 			colorFormats[colorFmtNdx].type == FORMATTYPE_UINT	||
   1582 			colorFormats[colorFmtNdx].format == GL_RGBA32F		||
   1583 			colorFormats[colorFmtNdx].format == GL_RGB32F		||
   1584 			colorFormats[colorFmtNdx].format == GL_RG32F		||
   1585 			colorFormats[colorFmtNdx].format == GL_R32F)
   1586 			continue;
   1587 
   1588 		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
   1589 		{
   1590 			FboConfig colorOnlyConfig			(GL_COLOR_BUFFER_BIT,											objectTypes[typeNdx], colorFormats[colorFmtNdx].format, GL_NONE, GL_NONE);
   1591 			FboConfig colorDepthConfig			(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT,						objectTypes[typeNdx], colorFormats[colorFmtNdx].format, depthStencilType, depthStencilFormat);
   1592 			FboConfig colorDepthStencilConfig	(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT,	objectTypes[typeNdx], colorFormats[colorFmtNdx].format, depthStencilType, depthStencilFormat);
   1593 
   1594 			sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorOnlyConfig));
   1595 			sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorDepthConfig));
   1596 			sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorDepthStencilConfig));
   1597 		}
   1598 	}
   1599 
   1600 	// .shared_depth_stencil
   1601 	tcu::TestCaseGroup* sharedDepthStencilGroup = new tcu::TestCaseGroup(m_testCtx, "shared_depth_stencil", "Shared depth and stencil buffers");
   1602 	addChild(sharedDepthStencilGroup);
   1603 	for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
   1604 	{
   1605 		deUint32	colorType		= GL_TEXTURE_2D;
   1606 		deUint32	colorFmt		= GL_RGBA8;
   1607 		bool		depth			= depthStencilFormats[fmtNdx].depth;
   1608 		bool		stencil			= depthStencilFormats[fmtNdx].stencil;
   1609 
   1610 		if (!depth)
   1611 			continue; // Not verified.
   1612 
   1613 		// Depth and stencil: both rbo and textures
   1614 		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
   1615 		{
   1616 			FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format);
   1617 			sharedDepthStencilGroup->addChild(new SharedDepthStencilTest(m_context, config));
   1618 		}
   1619 	}
   1620 
   1621 	// .resize
   1622 	tcu::TestCaseGroup* resizeGroup = new tcu::TestCaseGroup(m_testCtx, "resize", "FBO resize tests");
   1623 	addChild(resizeGroup);
   1624 	for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
   1625 	{
   1626 		deUint32 colorFormat = colorFormats[colorFmtNdx].format;
   1627 
   1628 		// Color-only.
   1629 		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
   1630 		{
   1631 			FboConfig config(GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormat, GL_NONE, GL_NONE);
   1632 			resizeGroup->addChild(new ResizeTest(m_context, config));
   1633 		}
   1634 
   1635 		// For selected color formats tests depth & stencil variants.
   1636 		if (colorFormat == GL_RGBA8 || colorFormat == GL_RGBA16F)
   1637 		{
   1638 			for (int depthStencilFmtNdx = 0; depthStencilFmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); depthStencilFmtNdx++)
   1639 			{
   1640 				deUint32	colorType		= GL_TEXTURE_2D;
   1641 				bool		depth			= depthStencilFormats[depthStencilFmtNdx].depth;
   1642 				bool		stencil			= depthStencilFormats[depthStencilFmtNdx].stencil;
   1643 
   1644 				// Depth and stencil: both rbo and textures
   1645 				for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
   1646 				{
   1647 					if (!depth && objectTypes[typeNdx] != GL_RENDERBUFFER)
   1648 						continue; // Not supported.
   1649 
   1650 					FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0),
   1651 									 colorType, colorFormat,
   1652 									 objectTypes[typeNdx], depthStencilFormats[depthStencilFmtNdx].format);
   1653 					resizeGroup->addChild(new ResizeTest(m_context, config));
   1654 				}
   1655 			}
   1656 		}
   1657 	}
   1658 
   1659 	// .recreate_color
   1660 	tcu::TestCaseGroup* recreateColorGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_color", "Recreate colorbuffer tests");
   1661 	addChild(recreateColorGroup);
   1662 	for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
   1663 	{
   1664 		deUint32	colorFormat			= colorFormats[colorFmtNdx].format;
   1665 		deUint32	depthStencilFormat	= GL_DEPTH24_STENCIL8;
   1666 		deUint32	depthStencilType	= GL_RENDERBUFFER;
   1667 
   1668 		// Color-only.
   1669 		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
   1670 		{
   1671 			FboConfig config(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, objectTypes[typeNdx], colorFormat, depthStencilType, depthStencilFormat);
   1672 			recreateColorGroup->addChild(new RecreateBuffersTest(m_context, config, GL_COLOR_BUFFER_BIT, true /* rebind */));
   1673 		}
   1674 	}
   1675 
   1676 	// .recreate_depth_stencil
   1677 	tcu::TestCaseGroup* recreateDepthStencilGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_depth_stencil", "Recreate depth and stencil buffers");
   1678 	addChild(recreateDepthStencilGroup);
   1679 	for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
   1680 	{
   1681 		deUint32	colorType		= GL_TEXTURE_2D;
   1682 		deUint32	colorFmt		= GL_RGBA8;
   1683 		bool		depth			= depthStencilFormats[fmtNdx].depth;
   1684 		bool		stencil			= depthStencilFormats[fmtNdx].stencil;
   1685 
   1686 		// Depth and stencil: both rbo and textures
   1687 		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
   1688 		{
   1689 			if (!depth && objectTypes[typeNdx] != GL_RENDERBUFFER)
   1690 				continue;
   1691 
   1692 			FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format);
   1693 			recreateDepthStencilGroup->addChild(new RecreateBuffersTest(m_context, config, (depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), true /* rebind */));
   1694 		}
   1695 	}
   1696 }
   1697 
   1698 } // Functional
   1699 } // gles3
   1700 } // deqp
   1701