Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 2.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  * Notes:
     24  *   + Like in API tests, tcu::sgl2s::Context class is used.
     25  *   + ReferenceContext is used to generate reference images.
     26  *   + API calls can be logged \todo [pyry] Implement.
     27  *//*--------------------------------------------------------------------*/
     28 
     29 #include "es2fFboRenderTest.hpp"
     30 #include "sglrContextUtil.hpp"
     31 #include "sglrGLContext.hpp"
     32 #include "sglrReferenceContext.hpp"
     33 #include "tcuSurface.hpp"
     34 #include "tcuTextureUtil.hpp"
     35 #include "tcuImageCompare.hpp"
     36 #include "tcuRenderTarget.hpp"
     37 #include "gluPixelTransfer.hpp"
     38 #include "gluTextureUtil.hpp"
     39 #include "gluStrUtil.hpp"
     40 #include "deRandom.hpp"
     41 #include "deString.h"
     42 
     43 #include "glwFunctions.hpp"
     44 #include "glwEnums.hpp"
     45 
     46 using std::vector;
     47 using std::string;
     48 using tcu::Vec2;
     49 using tcu::Vec3;
     50 using tcu::Vec4;
     51 using tcu::RGBA;
     52 using tcu::Surface;
     53 using namespace glw; // GL types
     54 
     55 namespace deqp
     56 {
     57 namespace gles2
     58 {
     59 namespace Functional
     60 {
     61 
     62 // Shaders.
     63 
     64 class FlatColorShader : public sglr::ShaderProgram
     65 {
     66 public:
     67 	FlatColorShader (void)
     68 		: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
     69 								<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
     70 								<< sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
     71 								<< sglr::pdec::Uniform("u_color", glu::TYPE_FLOAT_VEC4)
     72 								<< sglr::pdec::VertexSource(
     73 										"attribute highp vec4 a_position;\n"
     74 										"void main (void)\n"
     75 										"{\n"
     76 										"	gl_Position = a_position;\n"
     77 										"}\n")
     78 								<< sglr::pdec::FragmentSource(
     79 										"uniform mediump vec4 u_color;\n"
     80 										"void main (void)\n"
     81 										"{\n"
     82 										"	gl_FragColor = u_color;\n"
     83 										"}\n"))
     84 	{
     85 	}
     86 
     87 	void setColor (sglr::Context& gl, deUint32 program, const tcu::Vec4& color)
     88 	{
     89 		gl.useProgram(program);
     90 		gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, color.getPtr());
     91 	}
     92 
     93 	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
     94 	{
     95 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
     96 			packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
     97 	}
     98 
     99 	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
    100 	{
    101 		const tcu::Vec4 color(m_uniforms[0].value.f4);
    102 
    103 		DE_UNREF(packets);
    104 
    105 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
    106 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
    107 			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
    108 	}
    109 };
    110 
    111 class SingleTex2DShader : public sglr::ShaderProgram
    112 {
    113 public:
    114 	SingleTex2DShader (void)
    115 		: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
    116 								<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
    117 								<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
    118 								<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
    119 								<< sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
    120 								<< sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_2D)
    121 								<< sglr::pdec::VertexSource(
    122 										"attribute highp vec4 a_position;\n"
    123 										"attribute mediump vec2 a_coord;\n"
    124 										"varying mediump vec2 v_coord;\n"
    125 										"void main (void)\n"
    126 										"{\n"
    127 										"	gl_Position = a_position;\n"
    128 										"	v_coord = a_coord;\n"
    129 										"}\n")
    130 								<< sglr::pdec::FragmentSource(
    131 										"uniform sampler2D u_sampler0;\n"
    132 										"varying mediump vec2 v_coord;\n"
    133 										"void main (void)\n"
    134 										"{\n"
    135 										"	gl_FragColor = texture2D(u_sampler0, v_coord);\n"
    136 										"}\n"))
    137 	{
    138 	}
    139 
    140 	void setUnit (sglr::Context& gl, deUint32 program, int unitNdx)
    141 	{
    142 		gl.useProgram(program);
    143 		gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), unitNdx);
    144 	}
    145 
    146 	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
    147 	{
    148 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
    149 		{
    150 			rr::VertexPacket& packet = *packets[packetNdx];
    151 
    152 			packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
    153 			packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
    154 		}
    155 	}
    156 
    157 	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
    158 	{
    159 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
    160 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
    161 		{
    162 			const tcu::Vec4 v_coord = rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx);
    163 			const float		lod		= 0.0f;
    164 
    165 			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, this->m_uniforms[0].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod));
    166 		}
    167 	}
    168 
    169 };
    170 
    171 class MixTexturesShader : public sglr::ShaderProgram
    172 {
    173 public:
    174 	MixTexturesShader (void)
    175 		: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
    176 								<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
    177 								<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
    178 								<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
    179 								<< sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
    180 								<< sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_2D)
    181 								<< sglr::pdec::Uniform("u_sampler1", glu::TYPE_SAMPLER_2D)
    182 								<< sglr::pdec::VertexSource(
    183 										"attribute highp vec4 a_position;\n"
    184 										"attribute mediump vec2 a_coord;\n"
    185 										"varying mediump vec2 v_coord;\n"
    186 										"void main (void)\n"
    187 										"{\n"
    188 										"	gl_Position = a_position;\n"
    189 										"	v_coord = a_coord;\n"
    190 										"}\n")
    191 								<< sglr::pdec::FragmentSource(
    192 										"uniform sampler2D u_sampler0;\n"
    193 										"uniform sampler2D u_sampler1;\n"
    194 										"varying mediump vec2 v_coord;\n"
    195 										"void main (void)\n"
    196 										"{\n"
    197 										"	gl_FragColor = texture2D(u_sampler0, v_coord)*0.5 + texture2D(u_sampler1, v_coord)*0.5;\n"
    198 										"}\n"))
    199 	{
    200 	}
    201 
    202 	void setUnits (sglr::Context& gl, deUint32 program, int unit0, int unit1)
    203 	{
    204 		gl.useProgram(program);
    205 		gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), unit0);
    206 		gl.uniform1i(gl.getUniformLocation(program, "u_sampler1"), unit1);
    207 	}
    208 
    209 	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
    210 	{
    211 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
    212 		{
    213 			rr::VertexPacket& packet = *packets[packetNdx];
    214 
    215 			packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
    216 			packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
    217 		}
    218 	}
    219 
    220 	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
    221 	{
    222 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
    223 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
    224 		{
    225 			const tcu::Vec4 v_coord = rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx);
    226 			const float		lod		= 0.0f;
    227 
    228 			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0,   this->m_uniforms[0].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod) * 0.5f
    229 			                                                        + this->m_uniforms[1].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod) * 0.5f);
    230 		}
    231 	}
    232 };
    233 
    234 // Framebuffer config.
    235 
    236 class FboConfig
    237 {
    238 public:
    239 	FboConfig (void)
    240 		: colorbufferType		(GL_NONE)
    241 		, colorbufferFormat		(GL_NONE)
    242 		, depthbufferType		(GL_NONE)
    243 		, depthbufferFormat		(GL_NONE)
    244 		, stencilbufferType		(GL_NONE)
    245 		, stencilbufferFormat	(GL_NONE)
    246 	{
    247 	}
    248 
    249 	std::string				getName			(void) const;
    250 
    251 	GLenum					colorbufferType;		//!< GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER
    252 	GLenum					colorbufferFormat;		//!< Internal format for color buffer texture or renderbuffer
    253 
    254 	GLenum					depthbufferType;		//!< GL_RENDERBUFFER
    255 	GLenum					depthbufferFormat;
    256 
    257 	GLenum					stencilbufferType;		//!< GL_RENDERBUFFER
    258 	GLenum					stencilbufferFormat;
    259 
    260 private:
    261 	static const char*		getFormatName	(GLenum format);
    262 };
    263 
    264 const char* FboConfig::getFormatName (GLenum format)
    265 {
    266 	switch (format)
    267 	{
    268 		case GL_RGB:				return "rgb";
    269 		case GL_RGBA:				return "rgba";
    270 		case GL_ALPHA:				return "alpha";
    271 		case GL_LUMINANCE:			return "luminance";
    272 		case GL_LUMINANCE_ALPHA:	return "luminance_alpha";
    273 		case GL_RGB565:				return "rgb565";
    274 		case GL_RGB5_A1:			return "rgb5_a1";
    275 		case GL_RGBA4:				return "rgba4";
    276 		case GL_RGBA16F:			return "rgba16f";
    277 		case GL_RGB16F:				return "rgb16f";
    278 		case GL_DEPTH_COMPONENT16:	return "depth_component16";
    279 		case GL_STENCIL_INDEX8:		return "stencil_index8";
    280 		default:					DE_ASSERT(false); return DE_NULL;
    281 	}
    282 }
    283 
    284 std::string FboConfig::getName (void) const
    285 {
    286 	std::string name = "";
    287 
    288 	if (colorbufferType != GL_NONE)
    289 	{
    290 		switch (colorbufferType)
    291 		{
    292 			case GL_TEXTURE_2D:			name += "tex2d_";	break;
    293 			case GL_TEXTURE_CUBE_MAP:	name += "texcube_";	break;
    294 			case GL_RENDERBUFFER:		name += "rbo_";		break;
    295 			default:					DE_ASSERT(false);	break;
    296 		}
    297 		name += getFormatName(colorbufferFormat);
    298 	}
    299 
    300 	if (depthbufferType != GL_NONE)
    301 	{
    302 		DE_ASSERT(depthbufferType == GL_RENDERBUFFER);
    303 		if (name.length() > 0)
    304 			name += "_";
    305 		name += getFormatName(depthbufferFormat);
    306 	}
    307 
    308 	if (stencilbufferType != GL_NONE)
    309 	{
    310 		DE_ASSERT(stencilbufferType == GL_RENDERBUFFER);
    311 		if (name.length() > 0)
    312 			name += "_";
    313 		name += getFormatName(stencilbufferFormat);
    314 	}
    315 
    316 	return name;
    317 }
    318 
    319 class FboIncompleteException : public tcu::TestError
    320 {
    321 public:
    322 						FboIncompleteException		(const FboConfig& config, GLenum reason, const char* file, int line);
    323 	virtual				~FboIncompleteException		(void) throw() {}
    324 
    325 	const FboConfig&	getConfig					(void) const { return m_config; }
    326 	GLenum				getReason					(void) const { return m_reason; }
    327 
    328 private:
    329 	FboConfig			m_config;
    330 	GLenum				m_reason;
    331 };
    332 
    333 static const char* getFboIncompleteReasonName (GLenum reason)
    334 {
    335 	switch (reason)
    336 	{
    337 		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:			return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
    338 		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:	return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
    339 		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:			return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
    340 		case GL_FRAMEBUFFER_UNSUPPORTED:					return "GL_FRAMEBUFFER_UNSUPPORTED";
    341 		case GL_FRAMEBUFFER_COMPLETE:						return "GL_FRAMEBUFFER_COMPLETE";
    342 		default:											return "UNKNOWN";
    343 	}
    344 }
    345 
    346 FboIncompleteException::FboIncompleteException (const FboConfig& config, GLenum reason, const char* file, int line)
    347 	: TestError("Framebuffer is not complete", getFboIncompleteReasonName(reason), file, line)
    348 	, m_config(config)
    349 	, m_reason(reason)
    350 {
    351 }
    352 
    353 class Framebuffer
    354 {
    355 public:
    356 						Framebuffer			(sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo = 0, deUint32 colorbuffer = 0, deUint32 depthbuffer = 0, deUint32 stencilbuffer = 0);
    357 						~Framebuffer		(void);
    358 
    359 	const FboConfig&	getConfig			(void) const { return m_config; }
    360 	deUint32			getFramebuffer		(void) const { return m_framebuffer; }
    361 	deUint32			getColorbuffer		(void) const { return m_colorbuffer; }
    362 	deUint32			getDepthbuffer		(void) const { return m_depthbuffer; }
    363 	deUint32			getStencilbuffer	(void) const { return m_stencilbuffer; }
    364 
    365 	void				checkCompleteness	(void);
    366 
    367 private:
    368 	void				createRbo			(deUint32& name, GLenum format, int width, int height);
    369 	void				destroyBuffer		(deUint32 name, GLenum type);
    370 
    371 	FboConfig			m_config;
    372 	sglr::Context&		m_context;
    373 	deUint32			m_framebuffer;
    374 	deUint32			m_colorbuffer;
    375 	deUint32			m_depthbuffer;
    376 	deUint32			m_stencilbuffer;
    377 };
    378 
    379 static bool isExtensionSupported (sglr::Context& context, const char* name)
    380 {
    381 	std::istringstream extensions(context.getString(GL_EXTENSIONS));
    382 	std::string extension;
    383 
    384 	while (std::getline(extensions, extension, ' '))
    385 	{
    386 		if (extension == name)
    387 			return true;
    388 	}
    389 
    390 	return false;
    391 }
    392 
    393 static void checkColorFormatSupport (sglr::Context& context, deUint32 sizedFormat)
    394 {
    395 	switch (sizedFormat)
    396 	{
    397 		case GL_RGBA16F:
    398 		case GL_RGB16F:
    399 		case GL_RG16F:
    400 		case GL_R16F:
    401 			if (!isExtensionSupported(context, "GL_EXT_color_buffer_half_float"))
    402 				throw tcu::NotSupportedError("GL_EXT_color_buffer_half_float is not supported");
    403 
    404 		default:
    405 			break;
    406 	}
    407 }
    408 
    409 Framebuffer::Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo, deUint32 colorbuffer, deUint32 depthbuffer, deUint32 stencilbuffer)
    410 	: m_config			(config)
    411 	, m_context			(context)
    412 	, m_framebuffer		(fbo)
    413 	, m_colorbuffer		(colorbuffer)
    414 	, m_depthbuffer		(depthbuffer)
    415 	, m_stencilbuffer	(stencilbuffer)
    416 {
    417 	// Verify that color format is supported
    418 	checkColorFormatSupport(context, config.colorbufferFormat);
    419 
    420 	if (m_framebuffer == 0)
    421 		context.genFramebuffers(1, &m_framebuffer);
    422 	context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
    423 
    424 	switch (m_config.colorbufferType)
    425 	{
    426 		case GL_TEXTURE_2D:
    427 			if (m_colorbuffer == 0)
    428 				context.genTextures(1, &m_colorbuffer);
    429 			context.bindTexture(GL_TEXTURE_2D, m_colorbuffer);
    430 			context.texImage2D(GL_TEXTURE_2D, 0, m_config.colorbufferFormat, width, height);
    431 			context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    432 
    433 			if (!deIsPowerOfTwo32(width) || !deIsPowerOfTwo32(height))
    434 			{
    435 				// Set wrap mode to clamp for NPOT FBOs
    436 				context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    437 				context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    438 			}
    439 
    440 			context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorbuffer, 0);
    441 			break;
    442 
    443 		case GL_TEXTURE_CUBE_MAP:
    444 			DE_FATAL("TODO");
    445 			break;
    446 
    447 		case GL_RENDERBUFFER:
    448 			createRbo(m_colorbuffer, m_config.colorbufferFormat, width, height);
    449 			context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorbuffer);
    450 			break;
    451 
    452 		default:
    453 			DE_ASSERT(m_config.colorbufferType == GL_NONE);
    454 			break;
    455 	}
    456 
    457 	if (m_config.depthbufferType == GL_RENDERBUFFER)
    458 	{
    459 		createRbo(m_depthbuffer, m_config.depthbufferFormat, width, height);
    460 		context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer);
    461 	}
    462 	else
    463 		DE_ASSERT(m_config.depthbufferType == GL_NONE);
    464 
    465 	if (m_config.stencilbufferType == GL_RENDERBUFFER)
    466 	{
    467 		createRbo(m_stencilbuffer, m_config.stencilbufferFormat, width, height);
    468 		context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilbuffer);
    469 	}
    470 	else
    471 		DE_ASSERT(m_config.stencilbufferType == GL_NONE);
    472 
    473 	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
    474 }
    475 
    476 Framebuffer::~Framebuffer (void)
    477 {
    478 	m_context.deleteFramebuffers(1, &m_framebuffer);
    479 	destroyBuffer(m_colorbuffer, m_config.colorbufferType);
    480 	destroyBuffer(m_depthbuffer, m_config.depthbufferType);
    481 	destroyBuffer(m_stencilbuffer, m_config.stencilbufferType);
    482 }
    483 
    484 void Framebuffer::checkCompleteness (void)
    485 {
    486 	m_context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
    487 	GLenum status = m_context.checkFramebufferStatus(GL_FRAMEBUFFER);
    488 	m_context.bindFramebuffer(GL_FRAMEBUFFER, 0);
    489 	if (status != GL_FRAMEBUFFER_COMPLETE)
    490 		throw FboIncompleteException(m_config, status, __FILE__, __LINE__);
    491 }
    492 
    493 void Framebuffer::createRbo (deUint32& name, GLenum format, int width, int height)
    494 {
    495 	if (name == 0)
    496 		m_context.genRenderbuffers(1, &name);
    497 	m_context.bindRenderbuffer(GL_RENDERBUFFER, name);
    498 	m_context.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
    499 }
    500 
    501 void Framebuffer::destroyBuffer (deUint32 name, GLenum type)
    502 {
    503 	if (type == GL_TEXTURE_2D || type == GL_TEXTURE_CUBE_MAP)
    504 		m_context.deleteTextures(1, &name);
    505 	else if (type == GL_RENDERBUFFER)
    506 		m_context.deleteRenderbuffers(1, &name);
    507 	else
    508 		DE_ASSERT(type == GL_NONE);
    509 }
    510 
    511 static void createMetaballsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
    512 {
    513 	tcu::TextureFormat	texFormat	= glu::mapGLTransferFormat(format, dataType);
    514 	tcu::TextureLevel	level		(texFormat, width, height);
    515 
    516 	tcu::fillWithMetaballs(level.getAccess(), 5, name ^ width ^ height);
    517 
    518 	context.bindTexture(GL_TEXTURE_2D, name);
    519 	context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
    520 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    521 }
    522 
    523 static void createQuadsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
    524 {
    525 	tcu::TextureFormat	texFormat	= glu::mapGLTransferFormat(format, dataType);
    526 	tcu::TextureLevel	level		(texFormat, width, height);
    527 
    528 	tcu::fillWithRGBAQuads(level.getAccess());
    529 
    530 	context.bindTexture(GL_TEXTURE_2D, name);
    531 	context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
    532 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    533 }
    534 
    535 class FboRenderCase : public TestCase
    536 {
    537 public:
    538 								FboRenderCase			(Context& context, const char* name, const char* description, const FboConfig& config);
    539 	virtual						~FboRenderCase			(void) {}
    540 
    541 	virtual IterateResult		iterate					(void);
    542 	virtual void				render					(sglr::Context& fboContext, Surface& dst) = DE_NULL;
    543 
    544 	const FboConfig&			getConfig				(void) const { return m_config; }
    545 
    546 	static bool					isConfigSupported		(const FboConfig& config) { DE_UNREF(config); return true; }
    547 
    548 private:
    549 	FboConfig					m_config;
    550 };
    551 
    552 FboRenderCase::FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config)
    553 	: TestCase(context, name, description)
    554 	, m_config(config)
    555 {
    556 }
    557 
    558 TestCase::IterateResult FboRenderCase::iterate (void)
    559 {
    560 	Vec4						clearColor				(0.125f, 0.25f, 0.5f, 1.0f);
    561 	glu::RenderContext&			renderCtx				= m_context.getRenderContext();
    562 	const tcu::RenderTarget&	renderTarget			= m_context.getRenderTarget();
    563 	tcu::TestLog&				log						= m_testCtx.getLog();
    564 	const char*					failReason				= DE_NULL;
    565 
    566 	// Position & size for context
    567 	deRandom rnd;
    568 	deRandom_init(&rnd, deStringHash(getName()));
    569 
    570 	int		width	= deMin32(renderTarget.getWidth(), 128);
    571 	int		height	= deMin32(renderTarget.getHeight(), 128);
    572 	int		xMax	= renderTarget.getWidth()-width+1;
    573 	int		yMax	= renderTarget.getHeight()-height+1;
    574 	int		x		= deRandom_getUint32(&rnd) % xMax;
    575 	int		y		= deRandom_getUint32(&rnd) % yMax;
    576 
    577 	tcu::Surface	gles2Frame	(width, height);
    578 	tcu::Surface	refFrame	(width, height);
    579 	GLenum			gles2Error;
    580 	GLenum			refError;
    581 
    582 	// Render using GLES2
    583 	try
    584 	{
    585 		sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
    586 
    587 		context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
    588 		context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    589 
    590 		render(context, gles2Frame); // Call actual render func
    591 		gles2Error = context.getError();
    592 	}
    593 	catch (const FboIncompleteException& e)
    594 	{
    595 		if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED)
    596 		{
    597 			// Mark test case as unsupported
    598 			log << e;
    599 			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
    600 			return STOP;
    601 		}
    602 		else
    603 			throw; // Propagate error
    604 	}
    605 
    606 	// Render reference image
    607 	{
    608 		sglr::ReferenceContextBuffers	buffers	(tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), renderTarget.getDepthBits(), renderTarget.getStencilBits(), width, height);
    609 		sglr::ReferenceContext			context	(sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
    610 
    611 		context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
    612 		context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    613 
    614 		render(context, refFrame);
    615 		refError = context.getError();
    616 	}
    617 
    618 	// Compare error codes
    619 	bool errorCodesOk = (gles2Error == refError);
    620 
    621 	if (!errorCodesOk)
    622 	{
    623 		log << tcu::TestLog::Message << "Error code mismatch: got " << glu::getErrorStr(gles2Error) << ", expected " << glu::getErrorStr(refError) << tcu::TestLog::EndMessage;
    624 		failReason = "Got unexpected error";
    625 	}
    626 
    627 	// Compare images
    628 	const float		threshold	= 0.03f;
    629 	bool			imagesOk	= tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, gles2Frame, threshold, tcu::COMPARE_LOG_RESULT);
    630 
    631 	if (!imagesOk && !failReason)
    632 		failReason = "Image comparison failed";
    633 
    634 	// Store test result
    635 	bool isOk = errorCodesOk && imagesOk;
    636 	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
    637 							isOk ? "Pass"				: failReason);
    638 
    639 	return STOP;
    640 }
    641 
    642 namespace FboCases
    643 {
    644 
    645 class ColorClearsTest : public FboRenderCase
    646 {
    647 public:
    648 						ColorClearsTest				(Context& context, const FboConfig& config);
    649 						~ColorClearsTest			(void) {}
    650 
    651 	void				render						(sglr::Context& context, Surface& dst);
    652 };
    653 
    654 ColorClearsTest::ColorClearsTest (Context& context, const FboConfig& config)
    655 	: FboRenderCase(context, config.getName().c_str(), "Color buffer clears", config)
    656 {
    657 }
    658 
    659 void ColorClearsTest::render (sglr::Context& context, Surface& dst)
    660 {
    661 	int			width	= 128;
    662 	int			height	= 128;
    663 	deRandom	rnd;
    664 
    665 	deRandom_init(&rnd, 0);
    666 
    667 	// Create framebuffer
    668 	Framebuffer fbo(context, getConfig(), width, height);
    669 	fbo.checkCompleteness();
    670 
    671 	// Clear fbo
    672 	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
    673 	context.viewport(0, 0, width, height);
    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 	// Enable scissor test.
    678 	context.enable(GL_SCISSOR_TEST);
    679 
    680 	// Do 10 random color clears
    681 	for (int i = 0; i < 15; i++)
    682 	{
    683 		int		cX		= (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % width;
    684 		int		cY		= (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % height;
    685 		int		cWidth	= (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % (width-cX);
    686 		int		cHeight	= (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % (height-cY);
    687 		Vec4	color	= RGBA(deRandom_getUint32(&rnd)).toVec();
    688 
    689 		context.scissor(cX, cY, cWidth, cHeight);
    690 		context.clearColor(color.x(), color.y(), color.z(), color.w());
    691 		context.clear(GL_COLOR_BUFFER_BIT);
    692 	}
    693 
    694 	// Disable scissor.
    695 	context.disable(GL_SCISSOR_TEST);
    696 
    697 	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
    698 	{
    699 		// Unbind fbo
    700 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
    701 
    702 		// Draw to screen
    703 		SingleTex2DShader	shader;
    704 		deUint32			shaderID = context.createProgram(&shader);
    705 
    706 		shader.setUnit(context, shaderID, 0);
    707 
    708 		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
    709 		context.viewport(0, 0, context.getWidth(), context.getHeight());
    710 		sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    711 
    712 		// Read from screen
    713 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
    714 	}
    715 	else
    716 	{
    717 		// clear alpha channel for GL_RGB5_A1 format because test
    718 		// thresholds for the alpha channel do not account for dithering
    719 		if(getConfig().colorbufferFormat == GL_RGB5_A1)
    720 		{
    721 			context.colorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
    722 			context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
    723 			context.clear(GL_COLOR_BUFFER_BIT);
    724 			context.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    725 		}
    726 
    727 		// Read from fbo
    728 		context.readPixels(dst, 0, 0, width, height);
    729 	}
    730 }
    731 
    732 class IntersectingQuadsTest : public FboRenderCase
    733 {
    734 public:
    735 					IntersectingQuadsTest			(Context& context, const FboConfig& config, bool npot = false);
    736 	virtual			~IntersectingQuadsTest			(void) {}
    737 
    738 	virtual void	render							(sglr::Context& context, Surface& dst);
    739 
    740 	static bool		isConfigSupported				(const FboConfig& config);
    741 
    742 private:
    743 	int				m_fboWidth;
    744 	int				m_fboHeight;
    745 };
    746 
    747 class IntersectingQuadsNpotTest : public IntersectingQuadsTest
    748 {
    749 public:
    750 	IntersectingQuadsNpotTest (Context& context, const FboConfig& config)
    751 		: IntersectingQuadsTest(context, config, true)
    752 	{
    753 	}
    754 };
    755 
    756 IntersectingQuadsTest::IntersectingQuadsTest (Context& context, const FboConfig& config, bool npot)
    757 	: FboRenderCase	(context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Intersecting textured quads", config)
    758 	, m_fboWidth	(npot ? 127 : 128)
    759 	, m_fboHeight	(npot ?  95 : 128)
    760 {
    761 }
    762 
    763 bool IntersectingQuadsTest::isConfigSupported (const FboConfig& config)
    764 {
    765 	// \note Disabled for stencil configurations since doesn't exercise stencil buffer
    766 	return config.depthbufferType	!= GL_NONE &&
    767 		   config.stencilbufferType	== GL_NONE;
    768 }
    769 
    770 void IntersectingQuadsTest::render (sglr::Context& ctx, Surface& dst)
    771 {
    772 	SingleTex2DShader	texShader;
    773 	deUint32			texShaderID = ctx.createProgram(&texShader);
    774 
    775 	deUint32 metaballsTex	= 1;
    776 	deUint32 quadsTex		= 2;
    777 
    778 	createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
    779 	createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
    780 
    781 	int width	= m_fboWidth;
    782 	int height	= m_fboHeight;
    783 	Framebuffer fbo(ctx, getConfig(), width, height);
    784 	fbo.checkCompleteness();
    785 
    786 	// Setup shaders
    787 	texShader.setUnit(ctx, texShaderID, 0);
    788 
    789 	// Draw scene
    790 	ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
    791 	ctx.viewport(0, 0, width, height);
    792 	ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
    793 	ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    794 
    795 	ctx.enable(GL_DEPTH_TEST);
    796 
    797 	ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
    798 	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
    799 
    800 	ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
    801 	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
    802 
    803 	ctx.disable(GL_DEPTH_TEST);
    804 
    805 	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
    806 	{
    807 		// Unbind fbo
    808 		ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
    809 
    810 		// Draw to screen
    811 		ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
    812 		ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
    813 		sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    814 
    815 		// Read from screen
    816 		ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
    817 	}
    818 	else
    819 	{
    820 		// Read from fbo
    821 		ctx.readPixels(dst, 0, 0, width, height);
    822 	}
    823 }
    824 
    825 class MixTest : public FboRenderCase
    826 {
    827 public:
    828 						MixTest				(Context& context, const FboConfig& config, bool npot = false);
    829 	virtual				~MixTest			(void) {}
    830 
    831 	void				render				(sglr::Context& context, Surface& dst);
    832 
    833 	static bool			isConfigSupported	(const FboConfig& config);
    834 
    835 private:
    836 	int					m_fboAWidth;
    837 	int					m_fboAHeight;
    838 	int					m_fboBWidth;
    839 	int					m_fboBHeight;
    840 };
    841 
    842 class MixNpotTest : public MixTest
    843 {
    844 public:
    845 	MixNpotTest (Context& context, const FboConfig& config)
    846 		: MixTest(context, config, true)
    847 	{
    848 	}
    849 };
    850 
    851 MixTest::MixTest (Context& context, const FboConfig& config, bool npot)
    852 	: FboRenderCase	(context, (string(npot ? "mix_npot_" : "mix_") + config.getName()).c_str(), "Use two fbos as sources in draw operation", config)
    853 	, m_fboAWidth	(npot ? 127 : 128)
    854 	, m_fboAHeight	(npot ?  95 : 128)
    855 	, m_fboBWidth	(npot ?  55 :  64)
    856 	, m_fboBHeight	(npot ?  63 :  64)
    857 {
    858 }
    859 
    860 bool MixTest::isConfigSupported (const FboConfig& config)
    861 {
    862 	// \note Disabled for stencil configurations since doesn't exercise stencil buffer
    863 	return config.colorbufferType	== GL_TEXTURE_2D &&
    864 		   config.stencilbufferType	== GL_NONE;
    865 }
    866 
    867 void MixTest::render (sglr::Context& context, Surface& dst)
    868 {
    869 	SingleTex2DShader	singleTexShader;
    870 	MixTexturesShader	mixShader;
    871 
    872 	deUint32			singleTexShaderID	= context.createProgram(&singleTexShader);
    873 	deUint32			mixShaderID			= context.createProgram(&mixShader);
    874 
    875 	// Texture with metaballs
    876 	deUint32 metaballsTex = 1;
    877 	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
    878 	createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
    879 
    880 	// Setup shaders
    881 	singleTexShader.setUnit(context, singleTexShaderID, 0);
    882 	mixShader.setUnits(context, mixShaderID, 0, 1);
    883 
    884 	// Fbo, quad with metaballs texture
    885 	Framebuffer fboA(context, getConfig(), m_fboAWidth, m_fboAHeight);
    886 	fboA.checkCompleteness();
    887 	context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
    888 	context.viewport(0, 0, m_fboAWidth, m_fboAHeight);
    889 	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
    890 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    891 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
    892 	sglr::drawQuad(context, singleTexShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    893 
    894 	// Fbo, color clears
    895 	Framebuffer fboB(context, getConfig(), m_fboBWidth, m_fboBHeight);
    896 	fboB.checkCompleteness();
    897 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
    898 	context.viewport(0, 0, m_fboBWidth, m_fboBHeight);
    899 	context.enable(GL_SCISSOR_TEST);
    900 	context.scissor(0, 0, 32, 64);
    901 	context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
    902 	context.clear(GL_COLOR_BUFFER_BIT);
    903 	context.scissor(32, 0, 32, 64);
    904 	context.clearColor(0.0f, 1.0f, 0.0f, 1.0f);
    905 	context.clear(GL_COLOR_BUFFER_BIT);
    906 	context.disable(GL_SCISSOR_TEST);
    907 
    908 	// Final mix op
    909 	context.activeTexture(GL_TEXTURE0);
    910 	context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
    911 	context.activeTexture(GL_TEXTURE1);
    912 	context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer());
    913 	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
    914 	context.viewport(0, 0, context.getWidth(), context.getHeight());
    915 	sglr::drawQuad(context, mixShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    916 
    917 	context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
    918 }
    919 
    920 class BlendTest : public FboRenderCase
    921 {
    922 public:
    923 						BlendTest			(Context& context, const FboConfig& config, bool npot = false);
    924 	virtual				~BlendTest			(void) {}
    925 
    926 	void				render				(sglr::Context& context, Surface& dst);
    927 
    928 	static bool			isConfigSupported	(const FboConfig& config);
    929 
    930 private:
    931 	int					m_fboWidth;
    932 	int					m_fboHeight;
    933 };
    934 
    935 class BlendNpotTest : public BlendTest
    936 {
    937 public:
    938 	BlendNpotTest (Context& context, const FboConfig& config)
    939 		: BlendTest(context, config, true)
    940 	{
    941 	}
    942 };
    943 
    944 BlendTest::BlendTest (Context& context, const FboConfig& config, bool npot)
    945 	: FboRenderCase	(context, (string(npot ? "blend_npot_" : "blend_") + config.getName()).c_str(), "Blend to fbo", config)
    946 	, m_fboWidth	(npot ? 111 : 128)
    947 	, m_fboHeight	(npot ? 122 : 128)
    948 {
    949 }
    950 
    951 bool BlendTest::isConfigSupported (const FboConfig& config)
    952 {
    953 	// \note Disabled for stencil configurations since doesn't exercise stencil buffer
    954 	return config.stencilbufferType	== GL_NONE;
    955 }
    956 
    957 void BlendTest::render (sglr::Context& context, Surface& dst)
    958 {
    959 	SingleTex2DShader	shader;
    960 	deUint32			shaderID		= context.createProgram(&shader);
    961 	int					width			= m_fboWidth;
    962 	int					height			= m_fboHeight;
    963 	deUint32			metaballsTex	= 1;
    964 
    965 	createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
    966 
    967 	Framebuffer fbo(context, getConfig(), width, height);
    968 	fbo.checkCompleteness();
    969 
    970 	shader.setUnit(context, shaderID, 0);
    971 
    972 	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
    973 	context.viewport(0, 0, width, height);
    974 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
    975 	context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
    976 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    977 
    978 	context.enable(GL_BLEND);
    979 	context.blendEquation(GL_FUNC_ADD);
    980 	context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
    981 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    982 	context.disable(GL_BLEND);
    983 
    984 	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
    985 	{
    986 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
    987 		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
    988 		context.viewport(0, 0, context.getWidth(), context.getHeight());
    989 		sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    990 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
    991 	}
    992 	else
    993 		context.readPixels(dst, 0, 0, width, height);
    994 }
    995 
    996 class StencilClearsTest : public FboRenderCase
    997 {
    998 public:
    999 						StencilClearsTest		(Context& context, const FboConfig& config);
   1000 	virtual				~StencilClearsTest		(void) {};
   1001 
   1002 	void				render					(sglr::Context& context, Surface& dst);
   1003 
   1004 	static bool			isConfigSupported		(const FboConfig& config);
   1005 };
   1006 
   1007 StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config)
   1008 	: FboRenderCase(context, config.getName().c_str(), "Stencil clears", config)
   1009 {
   1010 }
   1011 
   1012 void StencilClearsTest::render (sglr::Context& context, Surface& dst)
   1013 {
   1014 	SingleTex2DShader	shader;
   1015 	deUint32			shaderID		= context.createProgram(&shader);
   1016 	int					width			= 128;
   1017 	int					height			= 128;
   1018 	deUint32			quadsTex		= 1;
   1019 	deUint32			metaballsTex	= 2;
   1020 
   1021 	createQuadsTex2D(context, quadsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
   1022 	createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
   1023 
   1024 	Framebuffer fbo(context, getConfig(), width, height);
   1025 	fbo.checkCompleteness();
   1026 
   1027 	// Bind framebuffer and clear
   1028 	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1029 	context.viewport(0, 0, width, height);
   1030 	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
   1031 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1032 
   1033 	// Do stencil clears
   1034 	context.enable(GL_SCISSOR_TEST);
   1035 	context.scissor(10, 16, 32, 120);
   1036 	context.clearStencil(1);
   1037 	context.clear(GL_STENCIL_BUFFER_BIT);
   1038 	context.scissor(16, 32, 100, 64);
   1039 	context.clearStencil(2);
   1040 	context.clear(GL_STENCIL_BUFFER_BIT);
   1041 	context.disable(GL_SCISSOR_TEST);
   1042 
   1043 	// Draw 2 textures with stecil tests
   1044 	context.activeTexture(GL_TEXTURE0);
   1045 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1046 	context.activeTexture(GL_TEXTURE1);
   1047 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1048 
   1049 	context.enable(GL_STENCIL_TEST);
   1050 	context.stencilFunc(GL_EQUAL, 1, 0xffffffffu);
   1051 	shader.setUnit(context, shaderID, 0);
   1052 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1053 
   1054 	context.stencilFunc(GL_EQUAL, 2, 0xffffffffu);
   1055 	shader.setUnit(context, shaderID, 1);
   1056 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1057 
   1058 	context.disable(GL_STENCIL_TEST);
   1059 
   1060 	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
   1061 	{
   1062 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1063 		context.activeTexture(GL_TEXTURE0);
   1064 		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
   1065 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1066 		shader.setUnit(context, shaderID, 0);
   1067 		sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1068 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1069 	}
   1070 	else
   1071 	{
   1072 		// clear alpha channel for GL_RGB5_A1 format because test
   1073 		// thresholds for the alpha channel do not account for dithering
   1074 		if(getConfig().colorbufferFormat == GL_RGB5_A1)
   1075 		{
   1076 			context.colorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
   1077 			context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
   1078 			context.clear(GL_COLOR_BUFFER_BIT);
   1079 			context.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
   1080 		}
   1081 
   1082 		context.readPixels(dst, 0, 0, width, height);
   1083 	}
   1084 }
   1085 
   1086 bool StencilClearsTest::isConfigSupported (const FboConfig& config)
   1087 {
   1088 	return config.stencilbufferType != GL_NONE;
   1089 }
   1090 
   1091 class StencilTest : public FboRenderCase
   1092 {
   1093 public:
   1094 						StencilTest				(Context& context, const FboConfig& config, bool npot = false);
   1095 	virtual				~StencilTest			(void) {};
   1096 
   1097 	void				render					(sglr::Context& context, Surface& dst);
   1098 
   1099 	static bool			isConfigSupported		(const FboConfig& config);
   1100 
   1101 private:
   1102 	int					m_fboWidth;
   1103 	int					m_fboHeight;
   1104 };
   1105 
   1106 class StencilNpotTest : public StencilTest
   1107 {
   1108 public:
   1109 	StencilNpotTest (Context& context, const FboConfig& config)
   1110 		: StencilTest(context, config, true)
   1111 	{
   1112 	}
   1113 };
   1114 
   1115 StencilTest::StencilTest (Context& context, const FboConfig& config, bool npot)
   1116 	: FboRenderCase	(context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Stencil ops", config)
   1117 	, m_fboWidth	(npot ?  99 : 128)
   1118 	, m_fboHeight	(npot ? 110 : 128)
   1119 {
   1120 }
   1121 
   1122 bool StencilTest::isConfigSupported (const FboConfig& config)
   1123 {
   1124 	return config.stencilbufferType != GL_NONE;
   1125 }
   1126 
   1127 void StencilTest::render (sglr::Context& ctx, Surface& dst)
   1128 {
   1129 	FlatColorShader		colorShader;
   1130 	SingleTex2DShader	texShader;
   1131 	deUint32			colorShaderID	= ctx.createProgram(&colorShader);
   1132 	deUint32			texShaderID		= ctx.createProgram(&texShader);
   1133 	int					width			= m_fboWidth;
   1134 	int					height			= m_fboHeight;
   1135 	int					texWidth		= 64;
   1136 	int					texHeight		= 64;
   1137 	deUint32			quadsTex		= 1;
   1138 	deUint32			metaballsTex	= 2;
   1139 	bool				depth			= getConfig().depthbufferType != GL_NONE;
   1140 
   1141 	createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
   1142 	createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
   1143 
   1144 	Framebuffer fbo(ctx, getConfig(), width, height);
   1145 	fbo.checkCompleteness();
   1146 
   1147 	// Bind framebuffer and clear
   1148 	ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1149 	ctx.viewport(0, 0, width, height);
   1150 	ctx.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
   1151 	ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1152 
   1153 	// Render intersecting quads - increment stencil on depth pass
   1154 	ctx.enable(GL_DEPTH_TEST);
   1155 	ctx.enable(GL_STENCIL_TEST);
   1156 	ctx.stencilFunc(GL_ALWAYS, 0, 0xffu);
   1157 	ctx.stencilOp(GL_KEEP, GL_KEEP, GL_INCR);
   1158 
   1159 	colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
   1160 	sglr::drawQuad(ctx, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
   1161 
   1162 	ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
   1163 	texShader.setUnit(ctx, texShaderID, 0);
   1164 	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f));
   1165 
   1166 	// Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure
   1167 	ctx.disable(GL_DEPTH_TEST);
   1168 	ctx.stencilFunc(GL_EQUAL, depth ? 2 : 1, 0xffu);
   1169 	ctx.stencilOp(GL_DECR, GL_KEEP, GL_KEEP);
   1170 	colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
   1171 	sglr::drawQuad(ctx, colorShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f));
   1172 
   1173 	// Draw metaballs with stencil test where stencil > 1 or 2 depending on depth buffer
   1174 	ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1175 	ctx.stencilFunc(GL_GREATER, depth ? 1 : 2, 0xffu);
   1176 	ctx.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
   1177 	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
   1178 
   1179 	ctx.disable(GL_STENCIL_TEST);
   1180 
   1181 	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
   1182 	{
   1183 		ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1184 		ctx.activeTexture(GL_TEXTURE0);
   1185 		ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
   1186 		ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
   1187 		sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1188 		ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
   1189 	}
   1190 	else
   1191 		ctx.readPixels(dst, 0, 0, width, height);
   1192 }
   1193 
   1194 class SharedColorbufferTest : public FboRenderCase
   1195 {
   1196 public:
   1197 						SharedColorbufferTest			(Context& context, const FboConfig& config);
   1198 	virtual				~SharedColorbufferTest			(void) {};
   1199 
   1200 	void				render							(sglr::Context& context, Surface& dst);
   1201 };
   1202 
   1203 SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config)
   1204 	: FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer", config)
   1205 {
   1206 }
   1207 
   1208 void SharedColorbufferTest::render (sglr::Context& context, Surface& dst)
   1209 {
   1210 	SingleTex2DShader	shader;
   1211 	deUint32			shaderID		= context.createProgram(&shader);
   1212 	int					width			= 128;
   1213 	int					height			= 128;
   1214 //	bool				depth			= getConfig().depthbufferFormat		!= GL_NONE;
   1215 	bool				stencil			= getConfig().stencilbufferFormat	!= GL_NONE;
   1216 
   1217 	// Textures
   1218 	deUint32	quadsTex		= 1;
   1219 	deUint32	metaballsTex	= 2;
   1220 	createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1221 	createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
   1222 
   1223 	context.viewport(0, 0, width, height);
   1224 
   1225 	shader.setUnit(context, shaderID, 0);
   1226 
   1227 	// Fbo A
   1228 	Framebuffer fboA(context, getConfig(), width, height);
   1229 	fboA.checkCompleteness();
   1230 
   1231 	// Fbo B - don't create colorbuffer
   1232 	FboConfig cfg = getConfig();
   1233 	cfg.colorbufferType		= GL_NONE;
   1234 	cfg.colorbufferFormat	= GL_NONE;
   1235 	Framebuffer fboB(context, cfg, width, height);
   1236 
   1237 	// Attach color buffer from fbo A
   1238 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
   1239 	switch (getConfig().colorbufferType)
   1240 	{
   1241 		case GL_TEXTURE_2D:
   1242 			context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboA.getColorbuffer(), 0);
   1243 			break;
   1244 
   1245 		case GL_RENDERBUFFER:
   1246 			context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboA.getColorbuffer());
   1247 			break;
   1248 
   1249 		default:
   1250 			DE_ASSERT(false);
   1251 	}
   1252 
   1253 	// Clear depth and stencil in fbo B
   1254 	context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1255 
   1256 	// Render quads to fbo 1, with depth 0.0
   1257 	context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
   1258 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1259 	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
   1260 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1261 
   1262 	if (stencil)
   1263 	{
   1264 		// Stencil to 1 in fbo A
   1265 		context.clearStencil(1);
   1266 		context.clear(GL_STENCIL_BUFFER_BIT);
   1267 	}
   1268 
   1269 	context.enable(GL_DEPTH_TEST);
   1270 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1271 	context.disable(GL_DEPTH_TEST);
   1272 
   1273 	// Blend metaballs to fbo 2
   1274 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
   1275 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1276 	context.enable(GL_BLEND);
   1277 	context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
   1278 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1279 
   1280 	// Render small quad that is only visible if depth buffer is not shared with fbo A - or there is no depth bits
   1281 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1282 	context.enable(GL_DEPTH_TEST);
   1283 	sglr::drawQuad(context, shaderID, Vec3(0.5f, 0.5f, 0.5f), Vec3(1.0f, 1.0f, 0.5f));
   1284 	context.disable(GL_DEPTH_TEST);
   1285 
   1286 	if (stencil)
   1287 	{
   1288 		FlatColorShader flatShader;
   1289 		deUint32		flatShaderID = context.createProgram(&flatShader);
   1290 
   1291 		flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
   1292 
   1293 		// Clear subset of stencil buffer to 1
   1294 		context.enable(GL_SCISSOR_TEST);
   1295 		context.scissor(10, 10, 12, 25);
   1296 		context.clearStencil(1);
   1297 		context.clear(GL_STENCIL_BUFFER_BIT);
   1298 		context.disable(GL_SCISSOR_TEST);
   1299 
   1300 		// Render quad with stencil mask == 1
   1301 		context.enable(GL_STENCIL_TEST);
   1302 		context.stencilFunc(GL_EQUAL, 1, 0xffu);
   1303 		sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1304 		context.disable(GL_STENCIL_TEST);
   1305 	}
   1306 
   1307 	// Get results
   1308 	if (fboA.getConfig().colorbufferType == GL_TEXTURE_2D)
   1309 	{
   1310 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1311 		context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
   1312 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1313 		sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1314 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1315 	}
   1316 	else
   1317 		context.readPixels(dst, 0, 0, width, height);
   1318 }
   1319 
   1320 class SharedColorbufferClearsTest : public FboRenderCase
   1321 {
   1322 public:
   1323 					SharedColorbufferClearsTest		(Context& context, const FboConfig& config);
   1324 	virtual			~SharedColorbufferClearsTest	(void) {}
   1325 
   1326 	static bool		isConfigSupported				(const FboConfig& config);
   1327 	void			render							(sglr::Context& context, Surface& dst);
   1328 };
   1329 
   1330 SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config)
   1331 	: FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer clears", config)
   1332 {
   1333 }
   1334 
   1335 bool SharedColorbufferClearsTest::isConfigSupported (const FboConfig& config)
   1336 {
   1337 	return config.colorbufferType	!= GL_NONE &&
   1338 		   config.depthbufferType	== GL_NONE &&
   1339 		   config.stencilbufferType	== GL_NONE;
   1340 }
   1341 
   1342 void SharedColorbufferClearsTest::render (sglr::Context& context, Surface& dst)
   1343 {
   1344 	int			width			= 128;
   1345 	int			height			= 128;
   1346 	deUint32	colorbuffer		= 1;
   1347 
   1348 	checkColorFormatSupport(context, getConfig().colorbufferFormat);
   1349 
   1350 	// Single colorbuffer
   1351 	if (getConfig().colorbufferType == GL_TEXTURE_2D)
   1352 	{
   1353 		context.bindTexture(GL_TEXTURE_2D, colorbuffer);
   1354 		context.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, width, height);
   1355 		context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1356 	}
   1357 	else
   1358 	{
   1359 		DE_ASSERT(getConfig().colorbufferType == GL_RENDERBUFFER);
   1360 		context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
   1361 		context.renderbufferStorage(GL_RENDERBUFFER, getConfig().colorbufferFormat, width, height);
   1362 	}
   1363 
   1364 	// Multiple framebuffers sharing the colorbuffer
   1365 	for (int fbo = 1; fbo <= 3; fbo++)
   1366 	{
   1367 		context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
   1368 
   1369 		if (getConfig().colorbufferType == GL_TEXTURE_2D)
   1370 			context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
   1371 		else
   1372 			context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
   1373 	}
   1374 
   1375 	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
   1376 
   1377 	// Check completeness
   1378 	{
   1379 		GLenum status = context.checkFramebufferStatus(GL_FRAMEBUFFER);
   1380 		if (status != GL_FRAMEBUFFER_COMPLETE)
   1381 			throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
   1382 	}
   1383 
   1384 	// Render to them
   1385 	context.viewport(0, 0, width, height);
   1386 	context.clearColor(0.0f, 0.0f, 1.0f, 1.0f);
   1387 	context.clear(GL_COLOR_BUFFER_BIT);
   1388 
   1389 	context.enable(GL_SCISSOR_TEST);
   1390 
   1391 	context.bindFramebuffer(GL_FRAMEBUFFER, 2);
   1392 	context.clearColor(0.6f, 0.0f, 0.0f, 1.0f);
   1393 	context.scissor(10, 10, 64, 64);
   1394 	context.clear(GL_COLOR_BUFFER_BIT);
   1395 	context.clearColor(0.0f, 0.6f, 0.0f, 1.0f);
   1396 	context.scissor(60, 60, 40, 20);
   1397 	context.clear(GL_COLOR_BUFFER_BIT);
   1398 
   1399 	context.bindFramebuffer(GL_FRAMEBUFFER, 3);
   1400 	context.clearColor(0.0f, 0.0f, 0.6f, 1.0f);
   1401 	context.scissor(20, 20, 100, 10);
   1402 	context.clear(GL_COLOR_BUFFER_BIT);
   1403 
   1404 	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
   1405 	context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
   1406 	context.scissor(20, 20, 5, 100);
   1407 	context.clear(GL_COLOR_BUFFER_BIT);
   1408 
   1409 	context.disable(GL_SCISSOR_TEST);
   1410 
   1411 	if (getConfig().colorbufferType == GL_TEXTURE_2D)
   1412 	{
   1413 		SingleTex2DShader	shader;
   1414 		deUint32			shaderID = context.createProgram(&shader);
   1415 
   1416 		shader.setUnit(context, shaderID, 0);
   1417 
   1418 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1419 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1420 		sglr::drawQuad(context, shaderID, Vec3(-0.9f, -0.9f, 0.0f), Vec3(0.9f, 0.9f, 0.0f));
   1421 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1422 	}
   1423 	else
   1424 		context.readPixels(dst, 0, 0, width, height);
   1425 }
   1426 
   1427 class SharedDepthbufferTest : public FboRenderCase
   1428 {
   1429 public:
   1430 					SharedDepthbufferTest		(Context& context, const FboConfig& config);
   1431 	virtual			~SharedDepthbufferTest		(void) {};
   1432 
   1433 	static bool		isConfigSupported			(const FboConfig& config);
   1434 	void			render						(sglr::Context& context, Surface& dst);
   1435 };
   1436 
   1437 SharedDepthbufferTest::SharedDepthbufferTest (Context& context, const FboConfig& config)
   1438 	: FboRenderCase(context, config.getName().c_str(), "Shared depthbuffer", config)
   1439 {
   1440 }
   1441 
   1442 bool SharedDepthbufferTest::isConfigSupported (const FboConfig& config)
   1443 {
   1444 	return config.depthbufferType == GL_RENDERBUFFER;
   1445 }
   1446 
   1447 void SharedDepthbufferTest::render (sglr::Context& context, Surface& dst)
   1448 {
   1449 	SingleTex2DShader	texShader;
   1450 	FlatColorShader		colorShader;
   1451 	deUint32			texShaderID		= context.createProgram(&texShader);
   1452 	deUint32			colorShaderID	= context.createProgram(&colorShader);
   1453 	int					width			= 128;
   1454 	int					height			= 128;
   1455 	bool				stencil			= getConfig().stencilbufferType != GL_NONE;
   1456 
   1457 	// Setup shaders
   1458 	texShader.setUnit(context, texShaderID, 0);
   1459 	colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
   1460 
   1461 	// Textures
   1462 	deUint32 metaballsTex	= 5;
   1463 	deUint32 quadsTex		= 6;
   1464 	createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1465 	createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1466 
   1467 	context.viewport(0, 0, width, height);
   1468 
   1469 	// Fbo A
   1470 	Framebuffer fboA(context, getConfig(), width, height);
   1471 	fboA.checkCompleteness();
   1472 
   1473 	// Fbo B
   1474 	FboConfig cfg = getConfig();
   1475 	cfg.depthbufferType		= GL_NONE;
   1476 	cfg.depthbufferFormat	= GL_NONE;
   1477 	Framebuffer fboB(context, cfg, width, height);
   1478 
   1479 	// Bind depth buffer from fbo A to fbo B
   1480 	DE_ASSERT(fboA.getConfig().depthbufferType == GL_RENDERBUFFER);
   1481 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
   1482 	context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboA.getDepthbuffer());
   1483 
   1484 	// Clear fbo B color to red and stencil to 1
   1485 	context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
   1486 	context.clearStencil(1);
   1487 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1488 
   1489 	// Enable depth test.
   1490 	context.enable(GL_DEPTH_TEST);
   1491 
   1492 	// Render quad to fbo A
   1493 	context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
   1494 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1495 	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
   1496 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1497 	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1498 
   1499 	// Render metaballs to fbo B
   1500 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
   1501 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1502 	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
   1503 
   1504 	context.disable(GL_DEPTH_TEST);
   1505 
   1506 	if (stencil)
   1507 	{
   1508 		// Clear subset of stencil buffer to 0
   1509 		context.enable(GL_SCISSOR_TEST);
   1510 		context.scissor(10, 10, 12, 25);
   1511 		context.clearStencil(0);
   1512 		context.clear(GL_STENCIL_BUFFER_BIT);
   1513 		context.disable(GL_SCISSOR_TEST);
   1514 
   1515 		// Render quad with stencil mask == 0
   1516 		context.enable(GL_STENCIL_TEST);
   1517 		context.stencilFunc(GL_EQUAL, 0, 0xffu);
   1518 		sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1519 		context.disable(GL_STENCIL_TEST);
   1520 	}
   1521 
   1522 	if (getConfig().colorbufferType == GL_TEXTURE_2D)
   1523 	{
   1524 		// Render both to screen
   1525 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1526 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1527 		context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
   1528 		sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
   1529 		context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer());
   1530 		sglr::drawQuad(context, texShaderID, Vec3(0.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1531 
   1532 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1533 	}
   1534 	else
   1535 	{
   1536 		// Read results from fbo B
   1537 		context.readPixels(dst, 0, 0, width, height);
   1538 	}
   1539 }
   1540 
   1541 class TexSubImageAfterRenderTest : public FboRenderCase
   1542 {
   1543 public:
   1544 					TexSubImageAfterRenderTest		(Context& context, const FboConfig& config);
   1545 	virtual			~TexSubImageAfterRenderTest		(void) {}
   1546 
   1547 	static bool		isConfigSupported				(const FboConfig& config);
   1548 	void			render							(sglr::Context& context, Surface& dst);
   1549 };
   1550 
   1551 TexSubImageAfterRenderTest::TexSubImageAfterRenderTest (Context& context, const FboConfig& config)
   1552 	: FboRenderCase(context, (string("after_render_") + config.getName()).c_str(), "TexSubImage after rendering to texture", config)
   1553 {
   1554 }
   1555 
   1556 bool TexSubImageAfterRenderTest::isConfigSupported (const FboConfig& config)
   1557 {
   1558 	return config.colorbufferType == GL_TEXTURE_2D &&
   1559 		   (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) &&
   1560 		   config.depthbufferType == GL_NONE &&
   1561 		   config.stencilbufferType == GL_NONE;
   1562 }
   1563 
   1564 void TexSubImageAfterRenderTest::render (sglr::Context& context, Surface& dst)
   1565 {
   1566 	SingleTex2DShader	shader;
   1567 	deUint32			shaderID	= context.createProgram(&shader);
   1568 	bool				isRGBA		= getConfig().colorbufferFormat == GL_RGBA;
   1569 
   1570 	tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
   1571 	tcu::fillWithRGBAQuads(fourQuads.getAccess());
   1572 
   1573 	tcu::TextureLevel metaballs(tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
   1574 	tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3);
   1575 
   1576 	shader.setUnit(context, shaderID, 0);
   1577 
   1578 	deUint32 fourQuadsTex = 1;
   1579 	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
   1580 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1581 	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, fourQuads.getAccess().getDataPtr());
   1582 
   1583 	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
   1584 
   1585 	deUint32 fboTex = 2;
   1586 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1587 	context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
   1588 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1589 	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
   1590 
   1591 	// Render to fbo
   1592 	context.viewport(0, 0, 128, 128);
   1593 	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
   1594 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1595 
   1596 	// Update texture using TexSubImage2D
   1597 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1598 	context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, metaballs.getAccess().getDataPtr());
   1599 
   1600 	// Draw to screen
   1601 	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1602 	context.viewport(0, 0, context.getWidth(), context.getHeight());
   1603 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1604 	context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1605 }
   1606 
   1607 class TexSubImageBetweenRenderTest : public FboRenderCase
   1608 {
   1609 public:
   1610 					TexSubImageBetweenRenderTest		(Context& context, const FboConfig& config);
   1611 	virtual			~TexSubImageBetweenRenderTest		(void) {}
   1612 
   1613 	static bool		isConfigSupported					(const FboConfig& config);
   1614 	void			render								(sglr::Context& context, Surface& dst);
   1615 };
   1616 
   1617 TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config)
   1618 	: FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config)
   1619 {
   1620 }
   1621 
   1622 bool TexSubImageBetweenRenderTest::isConfigSupported (const FboConfig& config)
   1623 {
   1624 	return config.colorbufferType == GL_TEXTURE_2D &&
   1625 		   (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) &&
   1626 		   config.depthbufferType == GL_NONE &&
   1627 		   config.stencilbufferType == GL_NONE;
   1628 }
   1629 
   1630 void TexSubImageBetweenRenderTest::render (sglr::Context& context, Surface& dst)
   1631 {
   1632 	SingleTex2DShader	shader;
   1633 	deUint32			shaderID	= context.createProgram(&shader);
   1634 	bool				isRGBA		= getConfig().colorbufferFormat == GL_RGBA;
   1635 
   1636 	tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
   1637 	tcu::fillWithRGBAQuads(fourQuads.getAccess());
   1638 
   1639 	tcu::TextureLevel metaballs(tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
   1640 	tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3);
   1641 
   1642 	tcu::TextureLevel metaballs2(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 64, 64);
   1643 	tcu::fillWithMetaballs(metaballs2.getAccess(), 5, 4);
   1644 
   1645 	deUint32 metaballsTex = 3;
   1646 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1647 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1648 	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, metaballs2.getAccess().getDataPtr());
   1649 
   1650 	deUint32 fourQuadsTex = 1;
   1651 	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
   1652 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1653 	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, fourQuads.getAccess().getDataPtr());
   1654 
   1655 	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
   1656 
   1657 	deUint32 fboTex = 2;
   1658 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1659 	context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
   1660 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1661 	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
   1662 
   1663 	shader.setUnit(context, shaderID, 0);
   1664 
   1665 	// Render to fbo
   1666 	context.viewport(0, 0, 128, 128);
   1667 	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
   1668 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1669 
   1670 	// Update texture using TexSubImage2D
   1671 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1672 	context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, metaballs.getAccess().getDataPtr());
   1673 
   1674 	// Render again to fbo
   1675 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1676 	context.enable(GL_BLEND);
   1677 	context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
   1678 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1679 	context.disable(GL_BLEND);
   1680 
   1681 	// Draw to screen
   1682 	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1683 	context.viewport(0, 0, context.getWidth(), context.getHeight());
   1684 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1685 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1686 
   1687 	context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1688 }
   1689 
   1690 class ResizeTest : public FboRenderCase
   1691 {
   1692 public:
   1693 					ResizeTest				(Context& context, const FboConfig& config);
   1694 	virtual			~ResizeTest				(void) {}
   1695 
   1696 	void			render					(sglr::Context& context, Surface& dst);
   1697 };
   1698 
   1699 ResizeTest::ResizeTest (Context& context, const FboConfig& config)
   1700 	: FboRenderCase(context, config.getName().c_str(), "Resize framebuffer", config)
   1701 {
   1702 }
   1703 
   1704 void ResizeTest::render (sglr::Context& context, Surface& dst)
   1705 {
   1706 	SingleTex2DShader	texShader;
   1707 	FlatColorShader		colorShader;
   1708 	deUint32			texShaderID		= context.createProgram(&texShader);
   1709 	deUint32			colorShaderID	= context.createProgram(&colorShader);
   1710 	deUint32			quadsTex		= 1;
   1711 	deUint32			metaballsTex	= 2;
   1712 	bool				depth			= getConfig().depthbufferType	 != GL_NONE;
   1713 	bool				stencil			= getConfig().stencilbufferType	 != GL_NONE;
   1714 
   1715 	createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1716 	createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 32, 32);
   1717 
   1718 	Framebuffer fbo(context, getConfig(), 128, 128);
   1719 	fbo.checkCompleteness();
   1720 
   1721 	// Setup shaders
   1722 	texShader.setUnit(context, texShaderID, 0);
   1723 	colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
   1724 
   1725 	// Render quads
   1726 	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1727 	context.viewport(0, 0, 128, 128);
   1728 	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
   1729 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1730 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1731 	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1732 
   1733 	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
   1734 	{
   1735 		// Render fbo to screen
   1736 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1737 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1738 		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
   1739 		sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1740 
   1741 		// Restore binding
   1742 		context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1743 	}
   1744 
   1745 	int newWidth	= 64;
   1746 	int newHeight	= 32;
   1747 
   1748 	// Resize buffers
   1749 	switch (fbo.getConfig().colorbufferType)
   1750 	{
   1751 		case GL_TEXTURE_2D:
   1752 			context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
   1753 			context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
   1754 			break;
   1755 
   1756 		case GL_RENDERBUFFER:
   1757 			context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getColorbuffer());
   1758 			context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
   1759 			break;
   1760 
   1761 		default:
   1762 			DE_ASSERT(false);
   1763 	}
   1764 
   1765 	if (depth)
   1766 	{
   1767 		DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER);
   1768 		context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getDepthbuffer());
   1769 		context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, newWidth, newHeight);
   1770 	}
   1771 
   1772 	if (stencil)
   1773 	{
   1774 		DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER);
   1775 		context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getStencilbuffer());
   1776 		context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, newWidth, newHeight);
   1777 	}
   1778 
   1779 	// Render to resized fbo
   1780 	context.viewport(0, 0, newWidth, newHeight);
   1781 	context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
   1782 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1783 
   1784 	context.enable(GL_DEPTH_TEST);
   1785 
   1786 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1787 	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
   1788 
   1789 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1790 	sglr::drawQuad(context, texShaderID, Vec3(0.0f, 0.0f, -1.0f), Vec3(+1.0f, +1.0f, 1.0f));
   1791 
   1792 	context.disable(GL_DEPTH_TEST);
   1793 
   1794 	if (stencil)
   1795 	{
   1796 		context.enable(GL_SCISSOR_TEST);
   1797 		context.scissor(10, 10, 5, 15);
   1798 		context.clearStencil(1);
   1799 		context.clear(GL_STENCIL_BUFFER_BIT);
   1800 		context.disable(GL_SCISSOR_TEST);
   1801 
   1802 		context.enable(GL_STENCIL_TEST);
   1803 		context.stencilFunc(GL_EQUAL, 1, 0xffu);
   1804 		sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
   1805 		context.disable(GL_STENCIL_TEST);
   1806 	}
   1807 
   1808 	if (getConfig().colorbufferType == GL_TEXTURE_2D)
   1809 	{
   1810 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1811 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1812 		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
   1813 		sglr::drawQuad(context, texShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(0.5f, 0.5f, 0.0f));
   1814 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1815 	}
   1816 	else
   1817 		context.readPixels(dst, 0, 0, newWidth, newHeight);
   1818 }
   1819 
   1820 template <GLenum Buffers>
   1821 class RecreateBuffersTest : public FboRenderCase
   1822 {
   1823 public:
   1824 					RecreateBuffersTest			(Context& context, const FboConfig& config, bool rebind);
   1825 	virtual			~RecreateBuffersTest		(void) {}
   1826 
   1827 	static bool		isConfigSupported			(const FboConfig& config);
   1828 	void			render						(sglr::Context& context, Surface& dst);
   1829 
   1830 private:
   1831 	bool			m_rebind;
   1832 };
   1833 
   1834 template <GLenum Buffers>
   1835 class RecreateBuffersNoRebindTest : public RecreateBuffersTest<Buffers>
   1836 {
   1837 public:
   1838 	RecreateBuffersNoRebindTest (Context& context, const FboConfig& config)
   1839 		: RecreateBuffersTest<Buffers>(context, config, false)
   1840 	{
   1841 	}
   1842 };
   1843 
   1844 template <GLenum Buffers>
   1845 class RecreateBuffersRebindTest : public RecreateBuffersTest<Buffers>
   1846 {
   1847 public:
   1848 	RecreateBuffersRebindTest (Context& context, const FboConfig& config)
   1849 		: RecreateBuffersTest<Buffers>(context, config, true)
   1850 	{
   1851 	}
   1852 };
   1853 
   1854 template <GLenum Buffers>
   1855 RecreateBuffersTest<Buffers>::RecreateBuffersTest (Context& context, const FboConfig& config, bool rebind)
   1856 	: FboRenderCase		(context, (string(rebind ? "rebind_" : "no_rebind_") + config.getName()).c_str(), "Recreate buffers", config)
   1857 	, m_rebind			(rebind)
   1858 {
   1859 }
   1860 
   1861 template <GLenum Buffers>
   1862 bool RecreateBuffersTest<Buffers>::isConfigSupported (const FboConfig& config)
   1863 {
   1864 	if ((Buffers & GL_COLOR_BUFFER_BIT) && config.colorbufferType == GL_NONE)
   1865 		return false;
   1866 	if ((Buffers & GL_DEPTH_BUFFER_BIT) && config.depthbufferType == GL_NONE)
   1867 		return false;
   1868 	if ((Buffers & GL_STENCIL_BUFFER_BIT) && config.stencilbufferType == GL_NONE)
   1869 		return false;
   1870 	return true;
   1871 }
   1872 
   1873 template <GLenum Buffers>
   1874 void RecreateBuffersTest<Buffers>::render (sglr::Context& ctx, Surface& dst)
   1875 {
   1876 	SingleTex2DShader	texShader;
   1877 	deUint32			texShaderID		= ctx.createProgram(&texShader);
   1878 	int					width			= 128;
   1879 	int					height			= 128;
   1880 	deUint32			metaballsTex	= 1;
   1881 	deUint32			quadsTex		= 2;
   1882 	bool				stencil			= getConfig().stencilbufferType != GL_NONE;
   1883 
   1884 	createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1885 	createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1886 
   1887 	Framebuffer fbo(ctx, getConfig(), width, height);
   1888 	fbo.checkCompleteness();
   1889 
   1890 	// Setup shader
   1891 	texShader.setUnit(ctx, texShaderID, 0);
   1892 
   1893 	// Draw scene
   1894 	ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1895 	ctx.viewport(0, 0, width, height);
   1896 	ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
   1897 	ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1898 
   1899 	ctx.enable(GL_DEPTH_TEST);
   1900 
   1901 	ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
   1902 	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1903 
   1904 	if (stencil)
   1905 	{
   1906 		ctx.enable(GL_SCISSOR_TEST);
   1907 		ctx.scissor(width/4, height/4, width/2, height/2);
   1908 		ctx.clearStencil(1);
   1909 		ctx.clear(GL_STENCIL_BUFFER_BIT);
   1910 		ctx.disable(GL_SCISSOR_TEST);
   1911 	}
   1912 
   1913 	// Recreate buffers
   1914 	if (!m_rebind)
   1915 		ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1916 
   1917 	if (Buffers & GL_COLOR_BUFFER_BIT)
   1918 	{
   1919 		deUint32 colorbuf = fbo.getColorbuffer();
   1920 		switch (fbo.getConfig().colorbufferType)
   1921 		{
   1922 			case GL_TEXTURE_2D:
   1923 				ctx.deleteTextures(1, &colorbuf);
   1924 				ctx.bindTexture(GL_TEXTURE_2D, colorbuf);
   1925 				ctx.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, width, height);
   1926 				ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1927 
   1928 				if (m_rebind)
   1929 					ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuf, 0);
   1930 				break;
   1931 
   1932 			case GL_RENDERBUFFER:
   1933 				ctx.deleteRenderbuffers(1, &colorbuf);
   1934 				ctx.bindRenderbuffer(GL_RENDERBUFFER, colorbuf);
   1935 				ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, width, height);
   1936 
   1937 				if (m_rebind)
   1938 					ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuf);
   1939 				break;
   1940 
   1941 			default:
   1942 				DE_ASSERT(false);
   1943 		}
   1944 	}
   1945 
   1946 	if (Buffers & GL_DEPTH_BUFFER_BIT)
   1947 	{
   1948 		deUint32 depthbuf = fbo.getDepthbuffer();
   1949 		DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER);
   1950 
   1951 		ctx.deleteRenderbuffers(1, &depthbuf);
   1952 		ctx.bindRenderbuffer(GL_RENDERBUFFER, depthbuf);
   1953 		ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, width, height);
   1954 
   1955 		if (m_rebind)
   1956 			ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuf);
   1957 	}
   1958 
   1959 	if (Buffers & GL_STENCIL_BUFFER_BIT)
   1960 	{
   1961 		deUint32 stencilbuf = fbo.getStencilbuffer();
   1962 		DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER);
   1963 
   1964 		ctx.deleteRenderbuffers(1, &stencilbuf);
   1965 		ctx.bindRenderbuffer(GL_RENDERBUFFER, stencilbuf);
   1966 		ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, width, height);
   1967 
   1968 		if (m_rebind)
   1969 			ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilbuf);
   1970 	}
   1971 
   1972 	if (!m_rebind)
   1973 		ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1974 
   1975 	ctx.clearColor(0.0f, 0.0f, 1.0f, 0.0f);
   1976 	ctx.clearStencil(0);
   1977 	ctx.clear(Buffers); // \note Clear only buffers that were re-created
   1978 
   1979 	if (stencil)
   1980 	{
   1981 		// \note Stencil test enabled only if we have stencil buffer
   1982 		ctx.enable(GL_STENCIL_TEST);
   1983 		ctx.stencilFunc(GL_EQUAL, 0, 0xffu);
   1984 	}
   1985 	ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1986 	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
   1987 	if (stencil)
   1988 		ctx.disable(GL_STENCIL_TEST);
   1989 
   1990 	ctx.disable(GL_DEPTH_TEST);
   1991 
   1992 	// Read from fbo
   1993 	ctx.readPixels(dst, 0, 0, width, height);
   1994 }
   1995 
   1996 class RepeatedClearCase : public FboRenderCase
   1997 {
   1998 private:
   1999 	static FboConfig makeConfig (deUint32 format)
   2000 	{
   2001 		FboConfig cfg;
   2002 		cfg.colorbufferType		= GL_TEXTURE_2D;
   2003 		cfg.colorbufferFormat	= format;
   2004 		cfg.depthbufferType		= GL_NONE;
   2005 		cfg.stencilbufferType	= GL_NONE;
   2006 		return cfg;
   2007 	}
   2008 
   2009 public:
   2010 	RepeatedClearCase (Context& context, deUint32 format)
   2011 		: FboRenderCase(context, makeConfig(format).getName().c_str(), "Repeated clears", makeConfig(format))
   2012 	{
   2013 	}
   2014 
   2015 protected:
   2016 	void render (sglr::Context& ctx, Surface& dst)
   2017 	{
   2018 		const int						numRowsCols		= 4;
   2019 		const int						cellSize		= 16;
   2020 		const int						fboSizes[]		= { cellSize, cellSize*numRowsCols };
   2021 
   2022 		SingleTex2DShader				fboBlitShader;
   2023 		const deUint32					fboBlitShaderID	= ctx.createProgram(&fboBlitShader);
   2024 
   2025 		de::Random						rnd				(18169662);
   2026 		deUint32						fbos[]			= { 0, 0 };
   2027 		deUint32						textures[]		= { 0, 0 };
   2028 
   2029 		ctx.genFramebuffers(2, &fbos[0]);
   2030 		ctx.genTextures(2, &textures[0]);
   2031 
   2032 		for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
   2033 		{
   2034 			ctx.bindTexture(GL_TEXTURE_2D, textures[fboNdx]);
   2035 			ctx.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, fboSizes[fboNdx], fboSizes[fboNdx], 0,
   2036 						   getConfig().colorbufferFormat, GL_UNSIGNED_BYTE, DE_NULL);
   2037 			ctx.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
   2038 			ctx.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
   2039 			ctx.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
   2040 			ctx.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
   2041 
   2042 			ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
   2043 			ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
   2044 
   2045 			{
   2046 				const GLenum status = ctx.checkFramebufferStatus(GL_FRAMEBUFFER);
   2047 				if (status != GL_FRAMEBUFFER_COMPLETE)
   2048 					throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
   2049 			}
   2050 		}
   2051 
   2052 		// larger fbo bound -- clear to transparent black
   2053 		ctx.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
   2054 		ctx.clear(GL_COLOR_BUFFER_BIT);
   2055 
   2056 		fboBlitShader.setUnit(ctx, fboBlitShaderID, 0);
   2057 		ctx.bindTexture(GL_TEXTURE_2D, textures[0]);
   2058 
   2059 		for (int cellY = 0; cellY < numRowsCols; cellY++)
   2060 		for (int cellX = 0; cellX < numRowsCols; cellX++)
   2061 		{
   2062 			const float	r	= rnd.getFloat();
   2063 			const float	g	= rnd.getFloat();
   2064 			const float	b	= rnd.getFloat();
   2065 			const float	a	= rnd.getFloat();
   2066 
   2067 			ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
   2068 			ctx.clearColor(r, g, b, a);
   2069 			ctx.clear(GL_COLOR_BUFFER_BIT);
   2070 
   2071 			ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
   2072 			ctx.viewport(cellX*cellSize, cellY*cellSize, cellSize, cellSize);
   2073 			sglr::drawQuad(ctx, fboBlitShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   2074 		}
   2075 
   2076 		ctx.readPixels(dst, 0, 0, fboSizes[1], fboSizes[1]);
   2077 	}
   2078 };
   2079 
   2080 } // FboCases
   2081 
   2082 FboRenderTestGroup::FboRenderTestGroup (Context& context)
   2083 	: TestCaseGroup(context, "render", "Rendering Tests")
   2084 {
   2085 }
   2086 
   2087 FboRenderTestGroup::~FboRenderTestGroup (void)
   2088 {
   2089 }
   2090 
   2091 namespace
   2092 {
   2093 
   2094 struct TypeFormatPair
   2095 {
   2096 	GLenum		type;
   2097 	GLenum		format;
   2098 };
   2099 
   2100 template <typename CaseType>
   2101 void addChildVariants (deqp::gles2::TestCaseGroup* group)
   2102 {
   2103 	TypeFormatPair colorbufferConfigs[] =
   2104 	{
   2105 //		{ GL_TEXTURE_2D,	GL_ALPHA },
   2106 //		{ GL_TEXTURE_2D,	GL_LUMINANCE },
   2107 //		{ GL_TEXTURE_2D,	GL_LUMINANCE_ALPHA },
   2108 		{ GL_TEXTURE_2D,	GL_RGB },
   2109 		{ GL_TEXTURE_2D,	GL_RGBA },
   2110 		{ GL_RENDERBUFFER,	GL_RGB565 },
   2111 		{ GL_RENDERBUFFER,	GL_RGB5_A1 },
   2112 		{ GL_RENDERBUFFER,	GL_RGBA4 },
   2113 //		{ GL_RENDERBUFFER,	GL_RGBA16F },
   2114 //		{ GL_RENDERBUFFER,	GL_RGB16F }
   2115 	};
   2116 	TypeFormatPair depthbufferConfigs[] =
   2117 	{
   2118 		{ GL_NONE,			GL_NONE },
   2119 		{ GL_RENDERBUFFER,	GL_DEPTH_COMPONENT16 }
   2120 	};
   2121 	TypeFormatPair stencilbufferConfigs[] =
   2122 	{
   2123 		{ GL_NONE,			GL_NONE },
   2124 		{ GL_RENDERBUFFER,	GL_STENCIL_INDEX8 }
   2125 	};
   2126 
   2127 	for (int colorbufferNdx = 0; colorbufferNdx < DE_LENGTH_OF_ARRAY(colorbufferConfigs); colorbufferNdx++)
   2128 	for (int depthbufferNdx = 0; depthbufferNdx < DE_LENGTH_OF_ARRAY(depthbufferConfigs); depthbufferNdx++)
   2129 	for (int stencilbufferNdx = 0; stencilbufferNdx < DE_LENGTH_OF_ARRAY(stencilbufferConfigs); stencilbufferNdx++)
   2130 	{
   2131 		FboConfig config;
   2132 		config.colorbufferType		= colorbufferConfigs[colorbufferNdx].type;
   2133 		config.colorbufferFormat	= colorbufferConfigs[colorbufferNdx].format;
   2134 		config.depthbufferType		= depthbufferConfigs[depthbufferNdx].type;
   2135 		config.depthbufferFormat	= depthbufferConfigs[depthbufferNdx].format;
   2136 		config.stencilbufferType	= stencilbufferConfigs[stencilbufferNdx].type;
   2137 		config.stencilbufferFormat	= stencilbufferConfigs[stencilbufferNdx].format;
   2138 
   2139 		if (CaseType::isConfigSupported(config))
   2140 			group->addChild(new CaseType(group->getContext(), config));
   2141 	}
   2142 }
   2143 
   2144 template <typename CaseType>
   2145 void createChildGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description)
   2146 {
   2147 	deqp::gles2::TestCaseGroup* tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description);
   2148 	parent->addChild(tmpGroup);
   2149 	addChildVariants<CaseType>(tmpGroup);
   2150 }
   2151 
   2152 template <GLbitfield Buffers>
   2153 void createRecreateBuffersGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description)
   2154 {
   2155 	deqp::gles2::TestCaseGroup* tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description);
   2156 	parent->addChild(tmpGroup);
   2157 	addChildVariants<FboCases::RecreateBuffersRebindTest<Buffers> >		(tmpGroup);
   2158 	addChildVariants<FboCases::RecreateBuffersNoRebindTest<Buffers> >	(tmpGroup);
   2159 }
   2160 
   2161 } // anonymous
   2162 
   2163 void FboRenderTestGroup::init (void)
   2164 {
   2165 	createChildGroup<FboCases::ColorClearsTest>					(this, "color_clear",		"Color buffer clears");
   2166 	createChildGroup<FboCases::StencilClearsTest>				(this, "stencil_clear",		"Stencil buffer clears");
   2167 
   2168 	deqp::gles2::TestCaseGroup* colorGroup = new deqp::gles2::TestCaseGroup(m_context, "color", "Color buffer tests");
   2169 	addChild(colorGroup);
   2170 	addChildVariants<FboCases::MixTest>			(colorGroup);
   2171 	addChildVariants<FboCases::MixNpotTest>		(colorGroup);
   2172 	addChildVariants<FboCases::BlendTest>		(colorGroup);
   2173 	addChildVariants<FboCases::BlendNpotTest>	(colorGroup);
   2174 
   2175 	deqp::gles2::TestCaseGroup* depthGroup = new deqp::gles2::TestCaseGroup(m_context, "depth", "Depth bufer tests");
   2176 	addChild(depthGroup);
   2177 	addChildVariants<FboCases::IntersectingQuadsTest>		(depthGroup);
   2178 	addChildVariants<FboCases::IntersectingQuadsNpotTest>	(depthGroup);
   2179 
   2180 	deqp::gles2::TestCaseGroup* stencilGroup = new deqp::gles2::TestCaseGroup(m_context, "stencil", "Stencil buffer tests");
   2181 	addChild(stencilGroup);
   2182 	addChildVariants<FboCases::StencilTest>		(stencilGroup);
   2183 	addChildVariants<FboCases::StencilNpotTest>	(stencilGroup);
   2184 
   2185 	createChildGroup<FboCases::SharedColorbufferClearsTest>		(this, "shared_colorbuffer_clear",	"Shared colorbuffer clears");
   2186 	createChildGroup<FboCases::SharedColorbufferTest>			(this, "shared_colorbuffer",		"Shared colorbuffer tests");
   2187 	createChildGroup<FboCases::SharedDepthbufferTest>			(this, "shared_depthbuffer",		"Shared depthbuffer tests");
   2188 	createChildGroup<FboCases::ResizeTest>						(this, "resize",					"FBO resize tests");
   2189 
   2190 	createRecreateBuffersGroup<GL_COLOR_BUFFER_BIT>				(this, "recreate_colorbuffer",		"Recreate colorbuffer tests");
   2191 	createRecreateBuffersGroup<GL_DEPTH_BUFFER_BIT>				(this, "recreate_depthbuffer",		"Recreate depthbuffer tests");
   2192 	createRecreateBuffersGroup<GL_STENCIL_BUFFER_BIT>			(this, "recreate_stencilbuffer",	"Recreate stencilbuffer tests");
   2193 
   2194 	deqp::gles2::TestCaseGroup* texSubImageGroup = new deqp::gles2::TestCaseGroup(m_context, "texsubimage", "TexSubImage interop with FBO colorbuffer texture");
   2195 	addChild(texSubImageGroup);
   2196 	addChildVariants<FboCases::TexSubImageAfterRenderTest>		(texSubImageGroup);
   2197 	addChildVariants<FboCases::TexSubImageBetweenRenderTest>	(texSubImageGroup);
   2198 
   2199 	{
   2200 		tcu::TestCaseGroup* const repeatedClearGroup = new tcu::TestCaseGroup(m_testCtx, "repeated_clear", "Repeated FBO clears");
   2201 		addChild(repeatedClearGroup);
   2202 
   2203 		repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGB));
   2204 		repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGBA));
   2205 	}
   2206 }
   2207 
   2208 } // Functional
   2209 } // gles2
   2210 } // deqp
   2211