• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
FlatColorShader(void)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 
setColor(sglr::Context & gl,deUint32 program,const tcu::Vec4 & color)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 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const93 	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 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const99 	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:
SingleTex2DShader(void)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 
setUnit(sglr::Context & gl,deUint32 program,int unitNdx)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 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const146 	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 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const157 	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:
MixTexturesShader(void)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 
setUnits(sglr::Context & gl,deUint32 program,int unit0,int unit1)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 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const209 	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 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const220 	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:
FboConfig(void)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 
getFormatName(GLenum format)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 
getName(void) const284 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);
~FboIncompleteException(void)323 	virtual				~FboIncompleteException		(void) throw() {}
324 
getConfig(void) const325 	const FboConfig&	getConfig					(void) const { return m_config; }
getReason(void) const326 	GLenum				getReason					(void) const { return m_reason; }
327 
328 private:
329 	FboConfig			m_config;
330 	GLenum				m_reason;
331 };
332 
getFboIncompleteReasonName(GLenum reason)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 
FboIncompleteException(const FboConfig & config,GLenum reason,const char * file,int line)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 
getConfig(void) const359 	const FboConfig&	getConfig			(void) const { return m_config; }
getFramebuffer(void) const360 	deUint32			getFramebuffer		(void) const { return m_framebuffer; }
getColorbuffer(void) const361 	deUint32			getColorbuffer		(void) const { return m_colorbuffer; }
getDepthbuffer(void) const362 	deUint32			getDepthbuffer		(void) const { return m_depthbuffer; }
getStencilbuffer(void) const363 	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 
isExtensionSupported(sglr::Context & context,const char * name)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 
checkColorFormatSupport(sglr::Context & context,deUint32 sizedFormat)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 
Framebuffer(sglr::Context & context,const FboConfig & config,int width,int height,deUint32 fbo,deUint32 colorbuffer,deUint32 depthbuffer,deUint32 stencilbuffer)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 
~Framebuffer(void)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 
checkCompleteness(void)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 
createRbo(deUint32 & name,GLenum format,int width,int height)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 
destroyBuffer(deUint32 name,GLenum type)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 
createMetaballsTex2D(sglr::Context & context,deUint32 name,GLenum format,GLenum dataType,int width,int height)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 
createQuadsTex2D(sglr::Context & context,deUint32 name,GLenum format,GLenum dataType,int width,int height)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);
~FboRenderCase(void)539 	virtual						~FboRenderCase			(void) {}
540 
541 	virtual IterateResult		iterate					(void);
542 	virtual void				render					(sglr::Context& fboContext, Surface& dst) = DE_NULL;
543 
getConfig(void) const544 	const FboConfig&			getConfig				(void) const { return m_config; }
545 
isConfigSupported(const FboConfig & config)546 	static bool					isConfigSupported		(const FboConfig& config) { DE_UNREF(config); return true; }
547 
548 private:
549 	FboConfig					m_config;
550 };
551 
FboRenderCase(Context & context,const char * name,const char * description,const FboConfig & config)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 
iterate(void)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);
~ColorClearsTest(void)649 						~ColorClearsTest			(void) {}
650 
651 	void				render						(sglr::Context& context, Surface& dst);
652 };
653 
ColorClearsTest(Context & context,const FboConfig & config)654 ColorClearsTest::ColorClearsTest (Context& context, const FboConfig& config)
655 	: FboRenderCase(context, config.getName().c_str(), "Color buffer clears", config)
656 {
657 }
658 
render(sglr::Context & context,Surface & dst)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);
~IntersectingQuadsTest(void)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:
IntersectingQuadsNpotTest(Context & context,const FboConfig & config)740 	IntersectingQuadsNpotTest (Context& context, const FboConfig& config)
741 		: IntersectingQuadsTest(context, config, true)
742 	{
743 	}
744 };
745 
IntersectingQuadsTest(Context & context,const FboConfig & config,bool npot)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 
isConfigSupported(const FboConfig & config)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 
render(sglr::Context & ctx,Surface & dst)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);
~MixTest(void)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:
MixNpotTest(Context & context,const FboConfig & config)835 	MixNpotTest (Context& context, const FboConfig& config)
836 		: MixTest(context, config, true)
837 	{
838 	}
839 };
840 
MixTest(Context & context,const FboConfig & config,bool npot)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 
isConfigSupported(const FboConfig & config)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 
render(sglr::Context & context,Surface & dst)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);
~BlendTest(void)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:
BlendNpotTest(Context & context,const FboConfig & config)928 	BlendNpotTest (Context& context, const FboConfig& config)
929 		: BlendTest(context, config, true)
930 	{
931 	}
932 };
933 
BlendTest(Context & context,const FboConfig & config,bool npot)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 
isConfigSupported(const FboConfig & config)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 
render(sglr::Context & context,Surface & dst)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);
~StencilClearsTest(void)990 	virtual				~StencilClearsTest		(void) {};
991 
992 	void				render					(sglr::Context& context, Surface& dst);
993 
994 	static bool			isConfigSupported		(const FboConfig& config);
995 };
996 
StencilClearsTest(Context & context,const FboConfig & config)997 StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config)
998 	: FboRenderCase(context, config.getName().c_str(), "Stencil clears", config)
999 {
1000 }
1001 
render(sglr::Context & context,Surface & dst)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 
isConfigSupported(const FboConfig & config)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);
~StencilTest(void)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:
StencilNpotTest(Context & context,const FboConfig & config)1087 	StencilNpotTest (Context& context, const FboConfig& config)
1088 		: StencilTest(context, config, true)
1089 	{
1090 	}
1091 };
1092 
StencilTest(Context & context,const FboConfig & config,bool npot)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 
isConfigSupported(const FboConfig & config)1100 bool StencilTest::isConfigSupported (const FboConfig& config)
1101 {
1102 	return config.stencilbufferType != GL_NONE;
1103 }
1104 
render(sglr::Context & ctx,Surface & dst)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);
~SharedColorbufferTest(void)1176 	virtual				~SharedColorbufferTest			(void) {};
1177 
1178 	void				render							(sglr::Context& context, Surface& dst);
1179 };
1180 
SharedColorbufferTest(Context & context,const FboConfig & config)1181 SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config)
1182 	: FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer", config)
1183 {
1184 }
1185 
render(sglr::Context & context,Surface & dst)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);
~SharedColorbufferClearsTest(void)1302 	virtual			~SharedColorbufferClearsTest	(void) {}
1303 
1304 	static bool		isConfigSupported				(const FboConfig& config);
1305 	void			render							(sglr::Context& context, Surface& dst);
1306 };
1307 
SharedColorbufferClearsTest(Context & context,const FboConfig & config)1308 SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config)
1309 	: FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer clears", config)
1310 {
1311 }
1312 
isConfigSupported(const FboConfig & config)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 
render(sglr::Context & context,Surface & dst)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);
~SharedDepthbufferTest(void)1409 	virtual			~SharedDepthbufferTest		(void) {};
1410 
1411 	static bool		isConfigSupported			(const FboConfig& config);
1412 	void			render						(sglr::Context& context, Surface& dst);
1413 };
1414 
SharedDepthbufferTest(Context & context,const FboConfig & config)1415 SharedDepthbufferTest::SharedDepthbufferTest (Context& context, const FboConfig& config)
1416 	: FboRenderCase(context, config.getName().c_str(), "Shared depthbuffer", config)
1417 {
1418 }
1419 
isConfigSupported(const FboConfig & config)1420 bool SharedDepthbufferTest::isConfigSupported (const FboConfig& config)
1421 {
1422 	return config.depthbufferType == GL_RENDERBUFFER;
1423 }
1424 
render(sglr::Context & context,Surface & dst)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);
~TexSubImageAfterRenderTest(void)1523 	virtual			~TexSubImageAfterRenderTest		(void) {}
1524 
1525 	static bool		isConfigSupported				(const FboConfig& config);
1526 	void			render							(sglr::Context& context, Surface& dst);
1527 };
1528 
TexSubImageAfterRenderTest(Context & context,const FboConfig & config)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 
isConfigSupported(const FboConfig & config)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 
render(sglr::Context & context,Surface & dst)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);
~TexSubImageBetweenRenderTest(void)1589 	virtual			~TexSubImageBetweenRenderTest		(void) {}
1590 
1591 	static bool		isConfigSupported					(const FboConfig& config);
1592 	void			render								(sglr::Context& context, Surface& dst);
1593 };
1594 
TexSubImageBetweenRenderTest(Context & context,const FboConfig & config)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 
isConfigSupported(const FboConfig & config)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 
render(sglr::Context & context,Surface & dst)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);
~ResizeTest(void)1672 	virtual			~ResizeTest				(void) {}
1673 
1674 	void			render					(sglr::Context& context, Surface& dst);
1675 };
1676 
ResizeTest(Context & context,const FboConfig & config)1677 ResizeTest::ResizeTest (Context& context, const FboConfig& config)
1678 	: FboRenderCase(context, config.getName().c_str(), "Resize framebuffer", config)
1679 {
1680 }
1681 
render(sglr::Context & context,Surface & dst)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);
~RecreateBuffersTest(void)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:
RecreateBuffersNoRebindTest(Context & context,const FboConfig & config)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:
RecreateBuffersRebindTest(Context & context,const FboConfig & config)1826 	RecreateBuffersRebindTest (Context& context, const FboConfig& config)
1827 		: RecreateBuffersTest<Buffers>(context, config, true)
1828 	{
1829 	}
1830 };
1831 
1832 template <GLenum Buffers>
RecreateBuffersTest(Context & context,const FboConfig & config,bool rebind)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>
isConfigSupported(const FboConfig & config)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>
render(sglr::Context & ctx,Surface & dst)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:
makeConfig(deUint32 format)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:
RepeatedClearCase(Context & context,deUint32 format)1988 	RepeatedClearCase (Context& context, deUint32 format)
1989 		: FboRenderCase(context, makeConfig(format).getName().c_str(), "Repeated clears", makeConfig(format))
1990 	{
1991 	}
1992 
1993 protected:
render(sglr::Context & ctx,Surface & dst)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 
FboRenderTestGroup(Context & context)2060 FboRenderTestGroup::FboRenderTestGroup (Context& context)
2061 	: TestCaseGroup(context, "render", "Rendering Tests")
2062 {
2063 }
2064 
~FboRenderTestGroup(void)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>
addChildVariants(deqp::gles2::TestCaseGroup * group)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>
createChildGroup(deqp::gles2::TestCaseGroup * parent,const char * name,const char * description)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>
createRecreateBuffersGroup(deqp::gles2::TestCaseGroup * parent,const char * name,const char * description)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 
init(void)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