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