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