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