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 		// Read from fbo
    718 		context.readPixels(dst, 0, 0, width, height);
    719 	}
    720 }
    721 
    722 class IntersectingQuadsTest : public FboRenderCase
    723 {
    724 public:
    725 					IntersectingQuadsTest			(Context& context, const FboConfig& config, bool npot = false);
    726 	virtual			~IntersectingQuadsTest			(void) {}
    727 
    728 	virtual void	render							(sglr::Context& context, Surface& dst);
    729 
    730 	static bool		isConfigSupported				(const FboConfig& config);
    731 
    732 private:
    733 	int				m_fboWidth;
    734 	int				m_fboHeight;
    735 };
    736 
    737 class IntersectingQuadsNpotTest : public IntersectingQuadsTest
    738 {
    739 public:
    740 	IntersectingQuadsNpotTest (Context& context, const FboConfig& config)
    741 		: IntersectingQuadsTest(context, config, true)
    742 	{
    743 	}
    744 };
    745 
    746 IntersectingQuadsTest::IntersectingQuadsTest (Context& context, const FboConfig& config, bool npot)
    747 	: FboRenderCase	(context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Intersecting textured quads", config)
    748 	, m_fboWidth	(npot ? 127 : 128)
    749 	, m_fboHeight	(npot ?  95 : 128)
    750 {
    751 }
    752 
    753 bool IntersectingQuadsTest::isConfigSupported (const FboConfig& config)
    754 {
    755 	// \note Disabled for stencil configurations since doesn't exercise stencil buffer
    756 	return config.depthbufferType	!= GL_NONE &&
    757 		   config.stencilbufferType	== GL_NONE;
    758 }
    759 
    760 void IntersectingQuadsTest::render (sglr::Context& ctx, Surface& dst)
    761 {
    762 	SingleTex2DShader	texShader;
    763 	deUint32			texShaderID = ctx.createProgram(&texShader);
    764 
    765 	deUint32 metaballsTex	= 1;
    766 	deUint32 quadsTex		= 2;
    767 
    768 	createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
    769 	createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
    770 
    771 	int width	= m_fboWidth;
    772 	int height	= m_fboHeight;
    773 	Framebuffer fbo(ctx, getConfig(), width, height);
    774 	fbo.checkCompleteness();
    775 
    776 	// Setup shaders
    777 	texShader.setUnit(ctx, texShaderID, 0);
    778 
    779 	// Draw scene
    780 	ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
    781 	ctx.viewport(0, 0, width, height);
    782 	ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
    783 	ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    784 
    785 	ctx.enable(GL_DEPTH_TEST);
    786 
    787 	ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
    788 	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
    789 
    790 	ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
    791 	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
    792 
    793 	ctx.disable(GL_DEPTH_TEST);
    794 
    795 	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
    796 	{
    797 		// Unbind fbo
    798 		ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
    799 
    800 		// Draw to screen
    801 		ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
    802 		ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
    803 		sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    804 
    805 		// Read from screen
    806 		ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
    807 	}
    808 	else
    809 	{
    810 		// Read from fbo
    811 		ctx.readPixels(dst, 0, 0, width, height);
    812 	}
    813 }
    814 
    815 class MixTest : public FboRenderCase
    816 {
    817 public:
    818 						MixTest				(Context& context, const FboConfig& config, bool npot = false);
    819 	virtual				~MixTest			(void) {}
    820 
    821 	void				render				(sglr::Context& context, Surface& dst);
    822 
    823 	static bool			isConfigSupported	(const FboConfig& config);
    824 
    825 private:
    826 	int					m_fboAWidth;
    827 	int					m_fboAHeight;
    828 	int					m_fboBWidth;
    829 	int					m_fboBHeight;
    830 };
    831 
    832 class MixNpotTest : public MixTest
    833 {
    834 public:
    835 	MixNpotTest (Context& context, const FboConfig& config)
    836 		: MixTest(context, config, true)
    837 	{
    838 	}
    839 };
    840 
    841 MixTest::MixTest (Context& context, const FboConfig& config, bool npot)
    842 	: FboRenderCase	(context, (string(npot ? "mix_npot_" : "mix_") + config.getName()).c_str(), "Use two fbos as sources in draw operation", config)
    843 	, m_fboAWidth	(npot ? 127 : 128)
    844 	, m_fboAHeight	(npot ?  95 : 128)
    845 	, m_fboBWidth	(npot ?  55 :  64)
    846 	, m_fboBHeight	(npot ?  63 :  64)
    847 {
    848 }
    849 
    850 bool MixTest::isConfigSupported (const FboConfig& config)
    851 {
    852 	// \note Disabled for stencil configurations since doesn't exercise stencil buffer
    853 	return config.colorbufferType	== GL_TEXTURE_2D &&
    854 		   config.stencilbufferType	== GL_NONE;
    855 }
    856 
    857 void MixTest::render (sglr::Context& context, Surface& dst)
    858 {
    859 	SingleTex2DShader	singleTexShader;
    860 	MixTexturesShader	mixShader;
    861 
    862 	deUint32			singleTexShaderID	= context.createProgram(&singleTexShader);
    863 	deUint32			mixShaderID			= context.createProgram(&mixShader);
    864 
    865 	// Texture with metaballs
    866 	deUint32 metaballsTex = 1;
    867 	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
    868 	createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
    869 
    870 	// Setup shaders
    871 	singleTexShader.setUnit(context, singleTexShaderID, 0);
    872 	mixShader.setUnits(context, mixShaderID, 0, 1);
    873 
    874 	// Fbo, quad with metaballs texture
    875 	Framebuffer fboA(context, getConfig(), m_fboAWidth, m_fboAHeight);
    876 	fboA.checkCompleteness();
    877 	context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
    878 	context.viewport(0, 0, m_fboAWidth, m_fboAHeight);
    879 	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
    880 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    881 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
    882 	sglr::drawQuad(context, singleTexShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    883 
    884 	// Fbo, color clears
    885 	Framebuffer fboB(context, getConfig(), m_fboBWidth, m_fboBHeight);
    886 	fboB.checkCompleteness();
    887 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
    888 	context.viewport(0, 0, m_fboBWidth, m_fboBHeight);
    889 	context.enable(GL_SCISSOR_TEST);
    890 	context.scissor(0, 0, 32, 64);
    891 	context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
    892 	context.clear(GL_COLOR_BUFFER_BIT);
    893 	context.scissor(32, 0, 32, 64);
    894 	context.clearColor(0.0f, 1.0f, 0.0f, 1.0f);
    895 	context.clear(GL_COLOR_BUFFER_BIT);
    896 	context.disable(GL_SCISSOR_TEST);
    897 
    898 	// Final mix op
    899 	context.activeTexture(GL_TEXTURE0);
    900 	context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
    901 	context.activeTexture(GL_TEXTURE1);
    902 	context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer());
    903 	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
    904 	context.viewport(0, 0, context.getWidth(), context.getHeight());
    905 	sglr::drawQuad(context, mixShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    906 
    907 	context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
    908 }
    909 
    910 class BlendTest : public FboRenderCase
    911 {
    912 public:
    913 						BlendTest			(Context& context, const FboConfig& config, bool npot = false);
    914 	virtual				~BlendTest			(void) {}
    915 
    916 	void				render				(sglr::Context& context, Surface& dst);
    917 
    918 	static bool			isConfigSupported	(const FboConfig& config);
    919 
    920 private:
    921 	int					m_fboWidth;
    922 	int					m_fboHeight;
    923 };
    924 
    925 class BlendNpotTest : public BlendTest
    926 {
    927 public:
    928 	BlendNpotTest (Context& context, const FboConfig& config)
    929 		: BlendTest(context, config, true)
    930 	{
    931 	}
    932 };
    933 
    934 BlendTest::BlendTest (Context& context, const FboConfig& config, bool npot)
    935 	: FboRenderCase	(context, (string(npot ? "blend_npot_" : "blend_") + config.getName()).c_str(), "Blend to fbo", config)
    936 	, m_fboWidth	(npot ? 111 : 128)
    937 	, m_fboHeight	(npot ? 122 : 128)
    938 {
    939 }
    940 
    941 bool BlendTest::isConfigSupported (const FboConfig& config)
    942 {
    943 	// \note Disabled for stencil configurations since doesn't exercise stencil buffer
    944 	return config.stencilbufferType	== GL_NONE;
    945 }
    946 
    947 void BlendTest::render (sglr::Context& context, Surface& dst)
    948 {
    949 	SingleTex2DShader	shader;
    950 	deUint32			shaderID		= context.createProgram(&shader);
    951 	int					width			= m_fboWidth;
    952 	int					height			= m_fboHeight;
    953 	deUint32			metaballsTex	= 1;
    954 
    955 	createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
    956 
    957 	Framebuffer fbo(context, getConfig(), width, height);
    958 	fbo.checkCompleteness();
    959 
    960 	shader.setUnit(context, shaderID, 0);
    961 
    962 	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
    963 	context.viewport(0, 0, width, height);
    964 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
    965 	context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
    966 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    967 
    968 	context.enable(GL_BLEND);
    969 	context.blendEquation(GL_FUNC_ADD);
    970 	context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
    971 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    972 	context.disable(GL_BLEND);
    973 
    974 	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
    975 	{
    976 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
    977 		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
    978 		context.viewport(0, 0, context.getWidth(), context.getHeight());
    979 		sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    980 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
    981 	}
    982 	else
    983 		context.readPixels(dst, 0, 0, width, height);
    984 }
    985 
    986 class StencilClearsTest : public FboRenderCase
    987 {
    988 public:
    989 						StencilClearsTest		(Context& context, const FboConfig& config);
    990 	virtual				~StencilClearsTest		(void) {};
    991 
    992 	void				render					(sglr::Context& context, Surface& dst);
    993 
    994 	static bool			isConfigSupported		(const FboConfig& config);
    995 };
    996 
    997 StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config)
    998 	: FboRenderCase(context, config.getName().c_str(), "Stencil clears", config)
    999 {
   1000 }
   1001 
   1002 void StencilClearsTest::render (sglr::Context& context, Surface& dst)
   1003 {
   1004 	SingleTex2DShader	shader;
   1005 	deUint32			shaderID		= context.createProgram(&shader);
   1006 	int					width			= 128;
   1007 	int					height			= 128;
   1008 	deUint32			quadsTex		= 1;
   1009 	deUint32			metaballsTex	= 2;
   1010 
   1011 	createQuadsTex2D(context, quadsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
   1012 	createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
   1013 
   1014 	Framebuffer fbo(context, getConfig(), width, height);
   1015 	fbo.checkCompleteness();
   1016 
   1017 	// Bind framebuffer and clear
   1018 	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1019 	context.viewport(0, 0, width, height);
   1020 	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
   1021 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1022 
   1023 	// Do stencil clears
   1024 	context.enable(GL_SCISSOR_TEST);
   1025 	context.scissor(10, 16, 32, 120);
   1026 	context.clearStencil(1);
   1027 	context.clear(GL_STENCIL_BUFFER_BIT);
   1028 	context.scissor(16, 32, 100, 64);
   1029 	context.clearStencil(2);
   1030 	context.clear(GL_STENCIL_BUFFER_BIT);
   1031 	context.disable(GL_SCISSOR_TEST);
   1032 
   1033 	// Draw 2 textures with stecil tests
   1034 	context.activeTexture(GL_TEXTURE0);
   1035 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1036 	context.activeTexture(GL_TEXTURE1);
   1037 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1038 
   1039 	context.enable(GL_STENCIL_TEST);
   1040 	context.stencilFunc(GL_EQUAL, 1, 0xffffffffu);
   1041 	shader.setUnit(context, shaderID, 0);
   1042 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1043 
   1044 	context.stencilFunc(GL_EQUAL, 2, 0xffffffffu);
   1045 	shader.setUnit(context, shaderID, 1);
   1046 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1047 
   1048 	context.disable(GL_STENCIL_TEST);
   1049 
   1050 	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
   1051 	{
   1052 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1053 		context.activeTexture(GL_TEXTURE0);
   1054 		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
   1055 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1056 		shader.setUnit(context, shaderID, 0);
   1057 		sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1058 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1059 	}
   1060 	else
   1061 		context.readPixels(dst, 0, 0, width, height);
   1062 }
   1063 
   1064 bool StencilClearsTest::isConfigSupported (const FboConfig& config)
   1065 {
   1066 	return config.stencilbufferType != GL_NONE;
   1067 }
   1068 
   1069 class StencilTest : public FboRenderCase
   1070 {
   1071 public:
   1072 						StencilTest				(Context& context, const FboConfig& config, bool npot = false);
   1073 	virtual				~StencilTest			(void) {};
   1074 
   1075 	void				render					(sglr::Context& context, Surface& dst);
   1076 
   1077 	static bool			isConfigSupported		(const FboConfig& config);
   1078 
   1079 private:
   1080 	int					m_fboWidth;
   1081 	int					m_fboHeight;
   1082 };
   1083 
   1084 class StencilNpotTest : public StencilTest
   1085 {
   1086 public:
   1087 	StencilNpotTest (Context& context, const FboConfig& config)
   1088 		: StencilTest(context, config, true)
   1089 	{
   1090 	}
   1091 };
   1092 
   1093 StencilTest::StencilTest (Context& context, const FboConfig& config, bool npot)
   1094 	: FboRenderCase	(context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Stencil ops", config)
   1095 	, m_fboWidth	(npot ?  99 : 128)
   1096 	, m_fboHeight	(npot ? 110 : 128)
   1097 {
   1098 }
   1099 
   1100 bool StencilTest::isConfigSupported (const FboConfig& config)
   1101 {
   1102 	return config.stencilbufferType != GL_NONE;
   1103 }
   1104 
   1105 void StencilTest::render (sglr::Context& ctx, Surface& dst)
   1106 {
   1107 	FlatColorShader		colorShader;
   1108 	SingleTex2DShader	texShader;
   1109 	deUint32			colorShaderID	= ctx.createProgram(&colorShader);
   1110 	deUint32			texShaderID		= ctx.createProgram(&texShader);
   1111 	int					width			= m_fboWidth;
   1112 	int					height			= m_fboHeight;
   1113 	int					texWidth		= 64;
   1114 	int					texHeight		= 64;
   1115 	deUint32			quadsTex		= 1;
   1116 	deUint32			metaballsTex	= 2;
   1117 	bool				depth			= getConfig().depthbufferType != GL_NONE;
   1118 
   1119 	createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
   1120 	createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
   1121 
   1122 	Framebuffer fbo(ctx, getConfig(), width, height);
   1123 	fbo.checkCompleteness();
   1124 
   1125 	// Bind framebuffer and clear
   1126 	ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1127 	ctx.viewport(0, 0, width, height);
   1128 	ctx.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
   1129 	ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1130 
   1131 	// Render intersecting quads - increment stencil on depth pass
   1132 	ctx.enable(GL_DEPTH_TEST);
   1133 	ctx.enable(GL_STENCIL_TEST);
   1134 	ctx.stencilFunc(GL_ALWAYS, 0, 0xffu);
   1135 	ctx.stencilOp(GL_KEEP, GL_KEEP, GL_INCR);
   1136 
   1137 	colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
   1138 	sglr::drawQuad(ctx, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
   1139 
   1140 	ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
   1141 	texShader.setUnit(ctx, texShaderID, 0);
   1142 	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f));
   1143 
   1144 	// Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure
   1145 	ctx.disable(GL_DEPTH_TEST);
   1146 	ctx.stencilFunc(GL_EQUAL, depth ? 2 : 1, 0xffu);
   1147 	ctx.stencilOp(GL_DECR, GL_KEEP, GL_KEEP);
   1148 	colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
   1149 	sglr::drawQuad(ctx, colorShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f));
   1150 
   1151 	// Draw metaballs with stencil test where stencil > 1 or 2 depending on depth buffer
   1152 	ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1153 	ctx.stencilFunc(GL_GREATER, depth ? 1 : 2, 0xffu);
   1154 	ctx.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
   1155 	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
   1156 
   1157 	ctx.disable(GL_STENCIL_TEST);
   1158 
   1159 	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
   1160 	{
   1161 		ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1162 		ctx.activeTexture(GL_TEXTURE0);
   1163 		ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
   1164 		ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
   1165 		sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1166 		ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
   1167 	}
   1168 	else
   1169 		ctx.readPixels(dst, 0, 0, width, height);
   1170 }
   1171 
   1172 class SharedColorbufferTest : public FboRenderCase
   1173 {
   1174 public:
   1175 						SharedColorbufferTest			(Context& context, const FboConfig& config);
   1176 	virtual				~SharedColorbufferTest			(void) {};
   1177 
   1178 	void				render							(sglr::Context& context, Surface& dst);
   1179 };
   1180 
   1181 SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config)
   1182 	: FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer", config)
   1183 {
   1184 }
   1185 
   1186 void SharedColorbufferTest::render (sglr::Context& context, Surface& dst)
   1187 {
   1188 	SingleTex2DShader	shader;
   1189 	deUint32			shaderID		= context.createProgram(&shader);
   1190 	int					width			= 128;
   1191 	int					height			= 128;
   1192 //	bool				depth			= getConfig().depthbufferFormat		!= GL_NONE;
   1193 	bool				stencil			= getConfig().stencilbufferFormat	!= GL_NONE;
   1194 
   1195 	// Textures
   1196 	deUint32	quadsTex		= 1;
   1197 	deUint32	metaballsTex	= 2;
   1198 	createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1199 	createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
   1200 
   1201 	context.viewport(0, 0, width, height);
   1202 
   1203 	shader.setUnit(context, shaderID, 0);
   1204 
   1205 	// Fbo A
   1206 	Framebuffer fboA(context, getConfig(), width, height);
   1207 	fboA.checkCompleteness();
   1208 
   1209 	// Fbo B - don't create colorbuffer
   1210 	FboConfig cfg = getConfig();
   1211 	cfg.colorbufferType		= GL_NONE;
   1212 	cfg.colorbufferFormat	= GL_NONE;
   1213 	Framebuffer fboB(context, cfg, width, height);
   1214 
   1215 	// Attach color buffer from fbo A
   1216 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
   1217 	switch (getConfig().colorbufferType)
   1218 	{
   1219 		case GL_TEXTURE_2D:
   1220 			context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboA.getColorbuffer(), 0);
   1221 			break;
   1222 
   1223 		case GL_RENDERBUFFER:
   1224 			context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboA.getColorbuffer());
   1225 			break;
   1226 
   1227 		default:
   1228 			DE_ASSERT(false);
   1229 	}
   1230 
   1231 	// Clear depth and stencil in fbo B
   1232 	context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1233 
   1234 	// Render quads to fbo 1, with depth 0.0
   1235 	context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
   1236 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1237 	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
   1238 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1239 
   1240 	if (stencil)
   1241 	{
   1242 		// Stencil to 1 in fbo A
   1243 		context.clearStencil(1);
   1244 		context.clear(GL_STENCIL_BUFFER_BIT);
   1245 	}
   1246 
   1247 	context.enable(GL_DEPTH_TEST);
   1248 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1249 	context.disable(GL_DEPTH_TEST);
   1250 
   1251 	// Blend metaballs to fbo 2
   1252 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
   1253 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1254 	context.enable(GL_BLEND);
   1255 	context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
   1256 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1257 
   1258 	// Render small quad that is only visible if depth buffer is not shared with fbo A - or there is no depth bits
   1259 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1260 	context.enable(GL_DEPTH_TEST);
   1261 	sglr::drawQuad(context, shaderID, Vec3(0.5f, 0.5f, 0.5f), Vec3(1.0f, 1.0f, 0.5f));
   1262 	context.disable(GL_DEPTH_TEST);
   1263 
   1264 	if (stencil)
   1265 	{
   1266 		FlatColorShader flatShader;
   1267 		deUint32		flatShaderID = context.createProgram(&flatShader);
   1268 
   1269 		flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
   1270 
   1271 		// Clear subset of stencil buffer to 1
   1272 		context.enable(GL_SCISSOR_TEST);
   1273 		context.scissor(10, 10, 12, 25);
   1274 		context.clearStencil(1);
   1275 		context.clear(GL_STENCIL_BUFFER_BIT);
   1276 		context.disable(GL_SCISSOR_TEST);
   1277 
   1278 		// Render quad with stencil mask == 1
   1279 		context.enable(GL_STENCIL_TEST);
   1280 		context.stencilFunc(GL_EQUAL, 1, 0xffu);
   1281 		sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1282 		context.disable(GL_STENCIL_TEST);
   1283 	}
   1284 
   1285 	// Get results
   1286 	if (fboA.getConfig().colorbufferType == GL_TEXTURE_2D)
   1287 	{
   1288 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1289 		context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
   1290 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1291 		sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1292 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1293 	}
   1294 	else
   1295 		context.readPixels(dst, 0, 0, width, height);
   1296 }
   1297 
   1298 class SharedColorbufferClearsTest : public FboRenderCase
   1299 {
   1300 public:
   1301 					SharedColorbufferClearsTest		(Context& context, const FboConfig& config);
   1302 	virtual			~SharedColorbufferClearsTest	(void) {}
   1303 
   1304 	static bool		isConfigSupported				(const FboConfig& config);
   1305 	void			render							(sglr::Context& context, Surface& dst);
   1306 };
   1307 
   1308 SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config)
   1309 	: FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer clears", config)
   1310 {
   1311 }
   1312 
   1313 bool SharedColorbufferClearsTest::isConfigSupported (const FboConfig& config)
   1314 {
   1315 	return config.colorbufferType	!= GL_NONE &&
   1316 		   config.depthbufferType	== GL_NONE &&
   1317 		   config.stencilbufferType	== GL_NONE;
   1318 }
   1319 
   1320 void SharedColorbufferClearsTest::render (sglr::Context& context, Surface& dst)
   1321 {
   1322 	int			width			= 128;
   1323 	int			height			= 128;
   1324 	deUint32	colorbuffer		= 1;
   1325 
   1326 	checkColorFormatSupport(context, getConfig().colorbufferFormat);
   1327 
   1328 	// Single colorbuffer
   1329 	if (getConfig().colorbufferType == GL_TEXTURE_2D)
   1330 	{
   1331 		context.bindTexture(GL_TEXTURE_2D, colorbuffer);
   1332 		context.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, width, height);
   1333 		context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1334 	}
   1335 	else
   1336 	{
   1337 		DE_ASSERT(getConfig().colorbufferType == GL_RENDERBUFFER);
   1338 		context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
   1339 		context.renderbufferStorage(GL_RENDERBUFFER, getConfig().colorbufferFormat, width, height);
   1340 	}
   1341 
   1342 	// Multiple framebuffers sharing the colorbuffer
   1343 	for (int fbo = 1; fbo <= 3; fbo++)
   1344 	{
   1345 		context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
   1346 
   1347 		if (getConfig().colorbufferType == GL_TEXTURE_2D)
   1348 			context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
   1349 		else
   1350 			context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
   1351 	}
   1352 
   1353 	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
   1354 
   1355 	// Check completeness
   1356 	{
   1357 		GLenum status = context.checkFramebufferStatus(GL_FRAMEBUFFER);
   1358 		if (status != GL_FRAMEBUFFER_COMPLETE)
   1359 			throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
   1360 	}
   1361 
   1362 	// Render to them
   1363 	context.viewport(0, 0, width, height);
   1364 	context.clearColor(0.0f, 0.0f, 1.0f, 1.0f);
   1365 	context.clear(GL_COLOR_BUFFER_BIT);
   1366 
   1367 	context.enable(GL_SCISSOR_TEST);
   1368 
   1369 	context.bindFramebuffer(GL_FRAMEBUFFER, 2);
   1370 	context.clearColor(0.6f, 0.0f, 0.0f, 1.0f);
   1371 	context.scissor(10, 10, 64, 64);
   1372 	context.clear(GL_COLOR_BUFFER_BIT);
   1373 	context.clearColor(0.0f, 0.6f, 0.0f, 1.0f);
   1374 	context.scissor(60, 60, 40, 20);
   1375 	context.clear(GL_COLOR_BUFFER_BIT);
   1376 
   1377 	context.bindFramebuffer(GL_FRAMEBUFFER, 3);
   1378 	context.clearColor(0.0f, 0.0f, 0.6f, 1.0f);
   1379 	context.scissor(20, 20, 100, 10);
   1380 	context.clear(GL_COLOR_BUFFER_BIT);
   1381 
   1382 	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
   1383 	context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
   1384 	context.scissor(20, 20, 5, 100);
   1385 	context.clear(GL_COLOR_BUFFER_BIT);
   1386 
   1387 	context.disable(GL_SCISSOR_TEST);
   1388 
   1389 	if (getConfig().colorbufferType == GL_TEXTURE_2D)
   1390 	{
   1391 		SingleTex2DShader	shader;
   1392 		deUint32			shaderID = context.createProgram(&shader);
   1393 
   1394 		shader.setUnit(context, shaderID, 0);
   1395 
   1396 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1397 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1398 		sglr::drawQuad(context, shaderID, Vec3(-0.9f, -0.9f, 0.0f), Vec3(0.9f, 0.9f, 0.0f));
   1399 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1400 	}
   1401 	else
   1402 		context.readPixels(dst, 0, 0, width, height);
   1403 }
   1404 
   1405 class SharedDepthbufferTest : public FboRenderCase
   1406 {
   1407 public:
   1408 					SharedDepthbufferTest		(Context& context, const FboConfig& config);
   1409 	virtual			~SharedDepthbufferTest		(void) {};
   1410 
   1411 	static bool		isConfigSupported			(const FboConfig& config);
   1412 	void			render						(sglr::Context& context, Surface& dst);
   1413 };
   1414 
   1415 SharedDepthbufferTest::SharedDepthbufferTest (Context& context, const FboConfig& config)
   1416 	: FboRenderCase(context, config.getName().c_str(), "Shared depthbuffer", config)
   1417 {
   1418 }
   1419 
   1420 bool SharedDepthbufferTest::isConfigSupported (const FboConfig& config)
   1421 {
   1422 	return config.depthbufferType == GL_RENDERBUFFER;
   1423 }
   1424 
   1425 void SharedDepthbufferTest::render (sglr::Context& context, Surface& dst)
   1426 {
   1427 	SingleTex2DShader	texShader;
   1428 	FlatColorShader		colorShader;
   1429 	deUint32			texShaderID		= context.createProgram(&texShader);
   1430 	deUint32			colorShaderID	= context.createProgram(&colorShader);
   1431 	int					width			= 128;
   1432 	int					height			= 128;
   1433 	bool				stencil			= getConfig().stencilbufferType != GL_NONE;
   1434 
   1435 	// Setup shaders
   1436 	texShader.setUnit(context, texShaderID, 0);
   1437 	colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
   1438 
   1439 	// Textures
   1440 	deUint32 metaballsTex	= 5;
   1441 	deUint32 quadsTex		= 6;
   1442 	createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1443 	createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1444 
   1445 	context.viewport(0, 0, width, height);
   1446 
   1447 	// Fbo A
   1448 	Framebuffer fboA(context, getConfig(), width, height);
   1449 	fboA.checkCompleteness();
   1450 
   1451 	// Fbo B
   1452 	FboConfig cfg = getConfig();
   1453 	cfg.depthbufferType		= GL_NONE;
   1454 	cfg.depthbufferFormat	= GL_NONE;
   1455 	Framebuffer fboB(context, cfg, width, height);
   1456 
   1457 	// Bind depth buffer from fbo A to fbo B
   1458 	DE_ASSERT(fboA.getConfig().depthbufferType == GL_RENDERBUFFER);
   1459 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
   1460 	context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboA.getDepthbuffer());
   1461 
   1462 	// Clear fbo B color to red and stencil to 1
   1463 	context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
   1464 	context.clearStencil(1);
   1465 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1466 
   1467 	// Enable depth test.
   1468 	context.enable(GL_DEPTH_TEST);
   1469 
   1470 	// Render quad to fbo A
   1471 	context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
   1472 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1473 	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
   1474 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1475 	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1476 
   1477 	// Render metaballs to fbo B
   1478 	context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
   1479 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1480 	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
   1481 
   1482 	context.disable(GL_DEPTH_TEST);
   1483 
   1484 	if (stencil)
   1485 	{
   1486 		// Clear subset of stencil buffer to 0
   1487 		context.enable(GL_SCISSOR_TEST);
   1488 		context.scissor(10, 10, 12, 25);
   1489 		context.clearStencil(0);
   1490 		context.clear(GL_STENCIL_BUFFER_BIT);
   1491 		context.disable(GL_SCISSOR_TEST);
   1492 
   1493 		// Render quad with stencil mask == 0
   1494 		context.enable(GL_STENCIL_TEST);
   1495 		context.stencilFunc(GL_EQUAL, 0, 0xffu);
   1496 		sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1497 		context.disable(GL_STENCIL_TEST);
   1498 	}
   1499 
   1500 	if (getConfig().colorbufferType == GL_TEXTURE_2D)
   1501 	{
   1502 		// Render both to screen
   1503 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1504 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1505 		context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
   1506 		sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
   1507 		context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer());
   1508 		sglr::drawQuad(context, texShaderID, Vec3(0.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1509 
   1510 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1511 	}
   1512 	else
   1513 	{
   1514 		// Read results from fbo B
   1515 		context.readPixels(dst, 0, 0, width, height);
   1516 	}
   1517 }
   1518 
   1519 class TexSubImageAfterRenderTest : public FboRenderCase
   1520 {
   1521 public:
   1522 					TexSubImageAfterRenderTest		(Context& context, const FboConfig& config);
   1523 	virtual			~TexSubImageAfterRenderTest		(void) {}
   1524 
   1525 	static bool		isConfigSupported				(const FboConfig& config);
   1526 	void			render							(sglr::Context& context, Surface& dst);
   1527 };
   1528 
   1529 TexSubImageAfterRenderTest::TexSubImageAfterRenderTest (Context& context, const FboConfig& config)
   1530 	: FboRenderCase(context, (string("after_render_") + config.getName()).c_str(), "TexSubImage after rendering to texture", config)
   1531 {
   1532 }
   1533 
   1534 bool TexSubImageAfterRenderTest::isConfigSupported (const FboConfig& config)
   1535 {
   1536 	return config.colorbufferType == GL_TEXTURE_2D &&
   1537 		   (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) &&
   1538 		   config.depthbufferType == GL_NONE &&
   1539 		   config.stencilbufferType == GL_NONE;
   1540 }
   1541 
   1542 void TexSubImageAfterRenderTest::render (sglr::Context& context, Surface& dst)
   1543 {
   1544 	SingleTex2DShader	shader;
   1545 	deUint32			shaderID	= context.createProgram(&shader);
   1546 	bool				isRGBA		= getConfig().colorbufferFormat == GL_RGBA;
   1547 
   1548 	tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
   1549 	tcu::fillWithRGBAQuads(fourQuads.getAccess());
   1550 
   1551 	tcu::TextureLevel metaballs(tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
   1552 	tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3);
   1553 
   1554 	shader.setUnit(context, shaderID, 0);
   1555 
   1556 	deUint32 fourQuadsTex = 1;
   1557 	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
   1558 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1559 	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, fourQuads.getAccess().getDataPtr());
   1560 
   1561 	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
   1562 
   1563 	deUint32 fboTex = 2;
   1564 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1565 	context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
   1566 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1567 	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
   1568 
   1569 	// Render to fbo
   1570 	context.viewport(0, 0, 128, 128);
   1571 	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
   1572 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1573 
   1574 	// Update texture using TexSubImage2D
   1575 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1576 	context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, metaballs.getAccess().getDataPtr());
   1577 
   1578 	// Draw to screen
   1579 	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1580 	context.viewport(0, 0, context.getWidth(), context.getHeight());
   1581 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1582 	context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1583 }
   1584 
   1585 class TexSubImageBetweenRenderTest : public FboRenderCase
   1586 {
   1587 public:
   1588 					TexSubImageBetweenRenderTest		(Context& context, const FboConfig& config);
   1589 	virtual			~TexSubImageBetweenRenderTest		(void) {}
   1590 
   1591 	static bool		isConfigSupported					(const FboConfig& config);
   1592 	void			render								(sglr::Context& context, Surface& dst);
   1593 };
   1594 
   1595 TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config)
   1596 	: FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config)
   1597 {
   1598 }
   1599 
   1600 bool TexSubImageBetweenRenderTest::isConfigSupported (const FboConfig& config)
   1601 {
   1602 	return config.colorbufferType == GL_TEXTURE_2D &&
   1603 		   (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) &&
   1604 		   config.depthbufferType == GL_NONE &&
   1605 		   config.stencilbufferType == GL_NONE;
   1606 }
   1607 
   1608 void TexSubImageBetweenRenderTest::render (sglr::Context& context, Surface& dst)
   1609 {
   1610 	SingleTex2DShader	shader;
   1611 	deUint32			shaderID	= context.createProgram(&shader);
   1612 	bool				isRGBA		= getConfig().colorbufferFormat == GL_RGBA;
   1613 
   1614 	tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
   1615 	tcu::fillWithRGBAQuads(fourQuads.getAccess());
   1616 
   1617 	tcu::TextureLevel metaballs(tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
   1618 	tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3);
   1619 
   1620 	tcu::TextureLevel metaballs2(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 64, 64);
   1621 	tcu::fillWithMetaballs(metaballs2.getAccess(), 5, 4);
   1622 
   1623 	deUint32 metaballsTex = 3;
   1624 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1625 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1626 	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, metaballs2.getAccess().getDataPtr());
   1627 
   1628 	deUint32 fourQuadsTex = 1;
   1629 	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
   1630 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1631 	context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, fourQuads.getAccess().getDataPtr());
   1632 
   1633 	context.bindFramebuffer(GL_FRAMEBUFFER, 1);
   1634 
   1635 	deUint32 fboTex = 2;
   1636 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1637 	context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
   1638 	context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1639 	context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
   1640 
   1641 	shader.setUnit(context, shaderID, 0);
   1642 
   1643 	// Render to fbo
   1644 	context.viewport(0, 0, 128, 128);
   1645 	context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
   1646 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1647 
   1648 	// Update texture using TexSubImage2D
   1649 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1650 	context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, metaballs.getAccess().getDataPtr());
   1651 
   1652 	// Render again to fbo
   1653 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1654 	context.enable(GL_BLEND);
   1655 	context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
   1656 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1657 	context.disable(GL_BLEND);
   1658 
   1659 	// Draw to screen
   1660 	context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1661 	context.viewport(0, 0, context.getWidth(), context.getHeight());
   1662 	context.bindTexture(GL_TEXTURE_2D, fboTex);
   1663 	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1664 
   1665 	context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1666 }
   1667 
   1668 class ResizeTest : public FboRenderCase
   1669 {
   1670 public:
   1671 					ResizeTest				(Context& context, const FboConfig& config);
   1672 	virtual			~ResizeTest				(void) {}
   1673 
   1674 	void			render					(sglr::Context& context, Surface& dst);
   1675 };
   1676 
   1677 ResizeTest::ResizeTest (Context& context, const FboConfig& config)
   1678 	: FboRenderCase(context, config.getName().c_str(), "Resize framebuffer", config)
   1679 {
   1680 }
   1681 
   1682 void ResizeTest::render (sglr::Context& context, Surface& dst)
   1683 {
   1684 	SingleTex2DShader	texShader;
   1685 	FlatColorShader		colorShader;
   1686 	deUint32			texShaderID		= context.createProgram(&texShader);
   1687 	deUint32			colorShaderID	= context.createProgram(&colorShader);
   1688 	deUint32			quadsTex		= 1;
   1689 	deUint32			metaballsTex	= 2;
   1690 	bool				depth			= getConfig().depthbufferType	 != GL_NONE;
   1691 	bool				stencil			= getConfig().stencilbufferType	 != GL_NONE;
   1692 
   1693 	createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1694 	createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 32, 32);
   1695 
   1696 	Framebuffer fbo(context, getConfig(), 128, 128);
   1697 	fbo.checkCompleteness();
   1698 
   1699 	// Setup shaders
   1700 	texShader.setUnit(context, texShaderID, 0);
   1701 	colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
   1702 
   1703 	// Render quads
   1704 	context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1705 	context.viewport(0, 0, 128, 128);
   1706 	context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
   1707 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1708 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1709 	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1710 
   1711 	if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
   1712 	{
   1713 		// Render fbo to screen
   1714 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1715 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1716 		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
   1717 		sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1718 
   1719 		// Restore binding
   1720 		context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1721 	}
   1722 
   1723 	int newWidth	= 64;
   1724 	int newHeight	= 32;
   1725 
   1726 	// Resize buffers
   1727 	switch (fbo.getConfig().colorbufferType)
   1728 	{
   1729 		case GL_TEXTURE_2D:
   1730 			context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
   1731 			context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
   1732 			break;
   1733 
   1734 		case GL_RENDERBUFFER:
   1735 			context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getColorbuffer());
   1736 			context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
   1737 			break;
   1738 
   1739 		default:
   1740 			DE_ASSERT(false);
   1741 	}
   1742 
   1743 	if (depth)
   1744 	{
   1745 		DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER);
   1746 		context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getDepthbuffer());
   1747 		context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, newWidth, newHeight);
   1748 	}
   1749 
   1750 	if (stencil)
   1751 	{
   1752 		DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER);
   1753 		context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getStencilbuffer());
   1754 		context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, newWidth, newHeight);
   1755 	}
   1756 
   1757 	// Render to resized fbo
   1758 	context.viewport(0, 0, newWidth, newHeight);
   1759 	context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
   1760 	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1761 
   1762 	context.enable(GL_DEPTH_TEST);
   1763 
   1764 	context.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1765 	sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
   1766 
   1767 	context.bindTexture(GL_TEXTURE_2D, quadsTex);
   1768 	sglr::drawQuad(context, texShaderID, Vec3(0.0f, 0.0f, -1.0f), Vec3(+1.0f, +1.0f, 1.0f));
   1769 
   1770 	context.disable(GL_DEPTH_TEST);
   1771 
   1772 	if (stencil)
   1773 	{
   1774 		context.enable(GL_SCISSOR_TEST);
   1775 		context.scissor(10, 10, 5, 15);
   1776 		context.clearStencil(1);
   1777 		context.clear(GL_STENCIL_BUFFER_BIT);
   1778 		context.disable(GL_SCISSOR_TEST);
   1779 
   1780 		context.enable(GL_STENCIL_TEST);
   1781 		context.stencilFunc(GL_EQUAL, 1, 0xffu);
   1782 		sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
   1783 		context.disable(GL_STENCIL_TEST);
   1784 	}
   1785 
   1786 	if (getConfig().colorbufferType == GL_TEXTURE_2D)
   1787 	{
   1788 		context.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1789 		context.viewport(0, 0, context.getWidth(), context.getHeight());
   1790 		context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
   1791 		sglr::drawQuad(context, texShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(0.5f, 0.5f, 0.0f));
   1792 		context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
   1793 	}
   1794 	else
   1795 		context.readPixels(dst, 0, 0, newWidth, newHeight);
   1796 }
   1797 
   1798 template <GLenum Buffers>
   1799 class RecreateBuffersTest : public FboRenderCase
   1800 {
   1801 public:
   1802 					RecreateBuffersTest			(Context& context, const FboConfig& config, bool rebind);
   1803 	virtual			~RecreateBuffersTest		(void) {}
   1804 
   1805 	static bool		isConfigSupported			(const FboConfig& config);
   1806 	void			render						(sglr::Context& context, Surface& dst);
   1807 
   1808 private:
   1809 	bool			m_rebind;
   1810 };
   1811 
   1812 template <GLenum Buffers>
   1813 class RecreateBuffersNoRebindTest : public RecreateBuffersTest<Buffers>
   1814 {
   1815 public:
   1816 	RecreateBuffersNoRebindTest (Context& context, const FboConfig& config)
   1817 		: RecreateBuffersTest<Buffers>(context, config, false)
   1818 	{
   1819 	}
   1820 };
   1821 
   1822 template <GLenum Buffers>
   1823 class RecreateBuffersRebindTest : public RecreateBuffersTest<Buffers>
   1824 {
   1825 public:
   1826 	RecreateBuffersRebindTest (Context& context, const FboConfig& config)
   1827 		: RecreateBuffersTest<Buffers>(context, config, true)
   1828 	{
   1829 	}
   1830 };
   1831 
   1832 template <GLenum Buffers>
   1833 RecreateBuffersTest<Buffers>::RecreateBuffersTest (Context& context, const FboConfig& config, bool rebind)
   1834 	: FboRenderCase		(context, (string(rebind ? "rebind_" : "no_rebind_") + config.getName()).c_str(), "Recreate buffers", config)
   1835 	, m_rebind			(rebind)
   1836 {
   1837 }
   1838 
   1839 template <GLenum Buffers>
   1840 bool RecreateBuffersTest<Buffers>::isConfigSupported (const FboConfig& config)
   1841 {
   1842 	if ((Buffers & GL_COLOR_BUFFER_BIT) && config.colorbufferType == GL_NONE)
   1843 		return false;
   1844 	if ((Buffers & GL_DEPTH_BUFFER_BIT) && config.depthbufferType == GL_NONE)
   1845 		return false;
   1846 	if ((Buffers & GL_STENCIL_BUFFER_BIT) && config.stencilbufferType == GL_NONE)
   1847 		return false;
   1848 	return true;
   1849 }
   1850 
   1851 template <GLenum Buffers>
   1852 void RecreateBuffersTest<Buffers>::render (sglr::Context& ctx, Surface& dst)
   1853 {
   1854 	SingleTex2DShader	texShader;
   1855 	deUint32			texShaderID		= ctx.createProgram(&texShader);
   1856 	int					width			= 128;
   1857 	int					height			= 128;
   1858 	deUint32			metaballsTex	= 1;
   1859 	deUint32			quadsTex		= 2;
   1860 	bool				stencil			= getConfig().stencilbufferType != GL_NONE;
   1861 
   1862 	createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1863 	createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
   1864 
   1865 	Framebuffer fbo(ctx, getConfig(), width, height);
   1866 	fbo.checkCompleteness();
   1867 
   1868 	// Setup shader
   1869 	texShader.setUnit(ctx, texShaderID, 0);
   1870 
   1871 	// Draw scene
   1872 	ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1873 	ctx.viewport(0, 0, width, height);
   1874 	ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
   1875 	ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
   1876 
   1877 	ctx.enable(GL_DEPTH_TEST);
   1878 
   1879 	ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
   1880 	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   1881 
   1882 	if (stencil)
   1883 	{
   1884 		ctx.enable(GL_SCISSOR_TEST);
   1885 		ctx.scissor(width/4, height/4, width/2, height/2);
   1886 		ctx.clearStencil(1);
   1887 		ctx.clear(GL_STENCIL_BUFFER_BIT);
   1888 		ctx.disable(GL_SCISSOR_TEST);
   1889 	}
   1890 
   1891 	// Recreate buffers
   1892 	if (!m_rebind)
   1893 		ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1894 
   1895 	if (Buffers & GL_COLOR_BUFFER_BIT)
   1896 	{
   1897 		deUint32 colorbuf = fbo.getColorbuffer();
   1898 		switch (fbo.getConfig().colorbufferType)
   1899 		{
   1900 			case GL_TEXTURE_2D:
   1901 				ctx.deleteTextures(1, &colorbuf);
   1902 				ctx.bindTexture(GL_TEXTURE_2D, colorbuf);
   1903 				ctx.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, width, height);
   1904 				ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1905 
   1906 				if (m_rebind)
   1907 					ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuf, 0);
   1908 				break;
   1909 
   1910 			case GL_RENDERBUFFER:
   1911 				ctx.deleteRenderbuffers(1, &colorbuf);
   1912 				ctx.bindRenderbuffer(GL_RENDERBUFFER, colorbuf);
   1913 				ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, width, height);
   1914 
   1915 				if (m_rebind)
   1916 					ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuf);
   1917 				break;
   1918 
   1919 			default:
   1920 				DE_ASSERT(false);
   1921 		}
   1922 	}
   1923 
   1924 	if (Buffers & GL_DEPTH_BUFFER_BIT)
   1925 	{
   1926 		deUint32 depthbuf = fbo.getDepthbuffer();
   1927 		DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER);
   1928 
   1929 		ctx.deleteRenderbuffers(1, &depthbuf);
   1930 		ctx.bindRenderbuffer(GL_RENDERBUFFER, depthbuf);
   1931 		ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, width, height);
   1932 
   1933 		if (m_rebind)
   1934 			ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuf);
   1935 	}
   1936 
   1937 	if (Buffers & GL_STENCIL_BUFFER_BIT)
   1938 	{
   1939 		deUint32 stencilbuf = fbo.getStencilbuffer();
   1940 		DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER);
   1941 
   1942 		ctx.deleteRenderbuffers(1, &stencilbuf);
   1943 		ctx.bindRenderbuffer(GL_RENDERBUFFER, stencilbuf);
   1944 		ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, width, height);
   1945 
   1946 		if (m_rebind)
   1947 			ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilbuf);
   1948 	}
   1949 
   1950 	if (!m_rebind)
   1951 		ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
   1952 
   1953 	ctx.clearColor(0.0f, 0.0f, 1.0f, 0.0f);
   1954 	ctx.clearStencil(0);
   1955 	ctx.clear(Buffers); // \note Clear only buffers that were re-created
   1956 
   1957 	if (stencil)
   1958 	{
   1959 		// \note Stencil test enabled only if we have stencil buffer
   1960 		ctx.enable(GL_STENCIL_TEST);
   1961 		ctx.stencilFunc(GL_EQUAL, 0, 0xffu);
   1962 	}
   1963 	ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
   1964 	sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
   1965 	if (stencil)
   1966 		ctx.disable(GL_STENCIL_TEST);
   1967 
   1968 	ctx.disable(GL_DEPTH_TEST);
   1969 
   1970 	// Read from fbo
   1971 	ctx.readPixels(dst, 0, 0, width, height);
   1972 }
   1973 
   1974 class RepeatedClearCase : public FboRenderCase
   1975 {
   1976 private:
   1977 	static FboConfig makeConfig (deUint32 format)
   1978 	{
   1979 		FboConfig cfg;
   1980 		cfg.colorbufferType		= GL_TEXTURE_2D;
   1981 		cfg.colorbufferFormat	= format;
   1982 		cfg.depthbufferType		= GL_NONE;
   1983 		cfg.stencilbufferType	= GL_NONE;
   1984 		return cfg;
   1985 	}
   1986 
   1987 public:
   1988 	RepeatedClearCase (Context& context, deUint32 format)
   1989 		: FboRenderCase(context, makeConfig(format).getName().c_str(), "Repeated clears", makeConfig(format))
   1990 	{
   1991 	}
   1992 
   1993 protected:
   1994 	void render (sglr::Context& ctx, Surface& dst)
   1995 	{
   1996 		const int						numRowsCols		= 4;
   1997 		const int						cellSize		= 16;
   1998 		const int						fboSizes[]		= { cellSize, cellSize*numRowsCols };
   1999 
   2000 		SingleTex2DShader				fboBlitShader;
   2001 		const deUint32					fboBlitShaderID	= ctx.createProgram(&fboBlitShader);
   2002 
   2003 		de::Random						rnd				(18169662);
   2004 		deUint32						fbos[]			= { 0, 0 };
   2005 		deUint32						textures[]		= { 0, 0 };
   2006 
   2007 		ctx.genFramebuffers(2, &fbos[0]);
   2008 		ctx.genTextures(2, &textures[0]);
   2009 
   2010 		for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
   2011 		{
   2012 			ctx.bindTexture(GL_TEXTURE_2D, textures[fboNdx]);
   2013 			ctx.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, fboSizes[fboNdx], fboSizes[fboNdx], 0,
   2014 						   getConfig().colorbufferFormat, GL_UNSIGNED_BYTE, DE_NULL);
   2015 			ctx.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
   2016 			ctx.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
   2017 			ctx.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
   2018 			ctx.texParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
   2019 
   2020 			ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
   2021 			ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
   2022 
   2023 			{
   2024 				const GLenum status = ctx.checkFramebufferStatus(GL_FRAMEBUFFER);
   2025 				if (status != GL_FRAMEBUFFER_COMPLETE)
   2026 					throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
   2027 			}
   2028 		}
   2029 
   2030 		// larger fbo bound -- clear to transparent black
   2031 		ctx.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
   2032 		ctx.clear(GL_COLOR_BUFFER_BIT);
   2033 
   2034 		fboBlitShader.setUnit(ctx, fboBlitShaderID, 0);
   2035 		ctx.bindTexture(GL_TEXTURE_2D, textures[0]);
   2036 
   2037 		for (int cellY = 0; cellY < numRowsCols; cellY++)
   2038 		for (int cellX = 0; cellX < numRowsCols; cellX++)
   2039 		{
   2040 			const float	r	= rnd.getFloat();
   2041 			const float	g	= rnd.getFloat();
   2042 			const float	b	= rnd.getFloat();
   2043 			const float	a	= rnd.getFloat();
   2044 
   2045 			ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
   2046 			ctx.clearColor(r, g, b, a);
   2047 			ctx.clear(GL_COLOR_BUFFER_BIT);
   2048 
   2049 			ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
   2050 			ctx.viewport(cellX*cellSize, cellY*cellSize, cellSize, cellSize);
   2051 			sglr::drawQuad(ctx, fboBlitShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
   2052 		}
   2053 
   2054 		ctx.readPixels(dst, 0, 0, fboSizes[1], fboSizes[1]);
   2055 	}
   2056 };
   2057 
   2058 } // FboCases
   2059 
   2060 FboRenderTestGroup::FboRenderTestGroup (Context& context)
   2061 	: TestCaseGroup(context, "render", "Rendering Tests")
   2062 {
   2063 }
   2064 
   2065 FboRenderTestGroup::~FboRenderTestGroup (void)
   2066 {
   2067 }
   2068 
   2069 namespace
   2070 {
   2071 
   2072 struct TypeFormatPair
   2073 {
   2074 	GLenum		type;
   2075 	GLenum		format;
   2076 };
   2077 
   2078 template <typename CaseType>
   2079 void addChildVariants (deqp::gles2::TestCaseGroup* group)
   2080 {
   2081 	TypeFormatPair colorbufferConfigs[] =
   2082 	{
   2083 //		{ GL_TEXTURE_2D,	GL_ALPHA },
   2084 //		{ GL_TEXTURE_2D,	GL_LUMINANCE },
   2085 //		{ GL_TEXTURE_2D,	GL_LUMINANCE_ALPHA },
   2086 		{ GL_TEXTURE_2D,	GL_RGB },
   2087 		{ GL_TEXTURE_2D,	GL_RGBA },
   2088 		{ GL_RENDERBUFFER,	GL_RGB565 },
   2089 		{ GL_RENDERBUFFER,	GL_RGB5_A1 },
   2090 		{ GL_RENDERBUFFER,	GL_RGBA4 },
   2091 //		{ GL_RENDERBUFFER,	GL_RGBA16F },
   2092 //		{ GL_RENDERBUFFER,	GL_RGB16F }
   2093 	};
   2094 	TypeFormatPair depthbufferConfigs[] =
   2095 	{
   2096 		{ GL_NONE,			GL_NONE },
   2097 		{ GL_RENDERBUFFER,	GL_DEPTH_COMPONENT16 }
   2098 	};
   2099 	TypeFormatPair stencilbufferConfigs[] =
   2100 	{
   2101 		{ GL_NONE,			GL_NONE },
   2102 		{ GL_RENDERBUFFER,	GL_STENCIL_INDEX8 }
   2103 	};
   2104 
   2105 	for (int colorbufferNdx = 0; colorbufferNdx < DE_LENGTH_OF_ARRAY(colorbufferConfigs); colorbufferNdx++)
   2106 	for (int depthbufferNdx = 0; depthbufferNdx < DE_LENGTH_OF_ARRAY(depthbufferConfigs); depthbufferNdx++)
   2107 	for (int stencilbufferNdx = 0; stencilbufferNdx < DE_LENGTH_OF_ARRAY(stencilbufferConfigs); stencilbufferNdx++)
   2108 	{
   2109 		FboConfig config;
   2110 		config.colorbufferType		= colorbufferConfigs[colorbufferNdx].type;
   2111 		config.colorbufferFormat	= colorbufferConfigs[colorbufferNdx].format;
   2112 		config.depthbufferType		= depthbufferConfigs[depthbufferNdx].type;
   2113 		config.depthbufferFormat	= depthbufferConfigs[depthbufferNdx].format;
   2114 		config.stencilbufferType	= stencilbufferConfigs[stencilbufferNdx].type;
   2115 		config.stencilbufferFormat	= stencilbufferConfigs[stencilbufferNdx].format;
   2116 
   2117 		if (CaseType::isConfigSupported(config))
   2118 			group->addChild(new CaseType(group->getContext(), config));
   2119 	}
   2120 }
   2121 
   2122 template <typename CaseType>
   2123 void createChildGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description)
   2124 {
   2125 	deqp::gles2::TestCaseGroup* tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description);
   2126 	parent->addChild(tmpGroup);
   2127 	addChildVariants<CaseType>(tmpGroup);
   2128 }
   2129 
   2130 template <GLbitfield Buffers>
   2131 void createRecreateBuffersGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description)
   2132 {
   2133 	deqp::gles2::TestCaseGroup* tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description);
   2134 	parent->addChild(tmpGroup);
   2135 	addChildVariants<FboCases::RecreateBuffersRebindTest<Buffers> >		(tmpGroup);
   2136 	addChildVariants<FboCases::RecreateBuffersNoRebindTest<Buffers> >	(tmpGroup);
   2137 }
   2138 
   2139 } // anonymous
   2140 
   2141 void FboRenderTestGroup::init (void)
   2142 {
   2143 	createChildGroup<FboCases::ColorClearsTest>					(this, "color_clear",		"Color buffer clears");
   2144 	createChildGroup<FboCases::StencilClearsTest>				(this, "stencil_clear",		"Stencil buffer clears");
   2145 
   2146 	deqp::gles2::TestCaseGroup* colorGroup = new deqp::gles2::TestCaseGroup(m_context, "color", "Color buffer tests");
   2147 	addChild(colorGroup);
   2148 	addChildVariants<FboCases::MixTest>			(colorGroup);
   2149 	addChildVariants<FboCases::MixNpotTest>		(colorGroup);
   2150 	addChildVariants<FboCases::BlendTest>		(colorGroup);
   2151 	addChildVariants<FboCases::BlendNpotTest>	(colorGroup);
   2152 
   2153 	deqp::gles2::TestCaseGroup* depthGroup = new deqp::gles2::TestCaseGroup(m_context, "depth", "Depth bufer tests");
   2154 	addChild(depthGroup);
   2155 	addChildVariants<FboCases::IntersectingQuadsTest>		(depthGroup);
   2156 	addChildVariants<FboCases::IntersectingQuadsNpotTest>	(depthGroup);
   2157 
   2158 	deqp::gles2::TestCaseGroup* stencilGroup = new deqp::gles2::TestCaseGroup(m_context, "stencil", "Stencil buffer tests");
   2159 	addChild(stencilGroup);
   2160 	addChildVariants<FboCases::StencilTest>		(stencilGroup);
   2161 	addChildVariants<FboCases::StencilNpotTest>	(stencilGroup);
   2162 
   2163 	createChildGroup<FboCases::SharedColorbufferClearsTest>		(this, "shared_colorbuffer_clear",	"Shared colorbuffer clears");
   2164 	createChildGroup<FboCases::SharedColorbufferTest>			(this, "shared_colorbuffer",		"Shared colorbuffer tests");
   2165 	createChildGroup<FboCases::SharedDepthbufferTest>			(this, "shared_depthbuffer",		"Shared depthbuffer tests");
   2166 	createChildGroup<FboCases::ResizeTest>						(this, "resize",					"FBO resize tests");
   2167 
   2168 	createRecreateBuffersGroup<GL_COLOR_BUFFER_BIT>				(this, "recreate_colorbuffer",		"Recreate colorbuffer tests");
   2169 	createRecreateBuffersGroup<GL_DEPTH_BUFFER_BIT>				(this, "recreate_depthbuffer",		"Recreate depthbuffer tests");
   2170 	createRecreateBuffersGroup<GL_STENCIL_BUFFER_BIT>			(this, "recreate_stencilbuffer",	"Recreate stencilbuffer tests");
   2171 
   2172 	deqp::gles2::TestCaseGroup* texSubImageGroup = new deqp::gles2::TestCaseGroup(m_context, "texsubimage", "TexSubImage interop with FBO colorbuffer texture");
   2173 	addChild(texSubImageGroup);
   2174 	addChildVariants<FboCases::TexSubImageAfterRenderTest>		(texSubImageGroup);
   2175 	addChildVariants<FboCases::TexSubImageBetweenRenderTest>	(texSubImageGroup);
   2176 
   2177 	{
   2178 		tcu::TestCaseGroup* const repeatedClearGroup = new tcu::TestCaseGroup(m_testCtx, "repeated_clear", "Repeated FBO clears");
   2179 		addChild(repeatedClearGroup);
   2180 
   2181 		repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGB));
   2182 		repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGBA));
   2183 	}
   2184 }
   2185 
   2186 } // Functional
   2187 } // gles2
   2188 } // deqp
   2189