• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
44 using std::vector;
45 using std::string;
46 using tcu::TestLog;
47 using tcu::Vec2;
48 using tcu::Vec3;
49 using tcu::Vec4;
50 using tcu::IVec2;
51 using tcu::IVec3;
52 using tcu::IVec4;
53 using tcu::RGBA;
54 using tcu::Surface;
55 
56 namespace deqp
57 {
58 namespace gles3
59 {
60 namespace Functional
61 {
62 
63 using glw::GLenum;
64 using namespace FboTestUtil;
65 
66 class FboConfig
67 {
68 public:
FboConfig(deUint32 buffers_,deUint32 colorType_,deUint32 colorFormat_,deUint32 depthStencilType_,deUint32 depthStencilFormat_,int width_=0,int height_=0,int samples_=0)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 
FboConfig(void)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 
getTypeName(GLenum type)108 static 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 
getName(void) const119 std::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 
137 class Framebuffer
138 {
139 public:
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 
getConfig(void) const143 	const FboConfig&	getConfig				(void) const { return m_config;				}
getFramebuffer(void) const144 	deUint32			getFramebuffer			(void) const { return m_framebuffer;		}
getColorBuffer(void) const145 	deUint32			getColorBuffer			(void) const { return m_colorBuffer;		}
getDepthStencilBuffer(void) const146 	deUint32			getDepthStencilBuffer	(void) const { return m_depthStencilBuffer;	}
147 
148 	void				checkCompleteness		(void);
149 
150 private:
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 
getEnablingExtensions(deUint32 format)162 static 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 
isExtensionSupported(sglr::Context & context,const char * name)191 static 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 
isAnyExtensionSupported(sglr::Context & context,const std::vector<std::string> & requiredExts)205 static 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 
221 template<typename T>
join(const std::vector<T> & list,const std::string & sep)222 static 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 
checkColorFormatSupport(sglr::Context & context,deUint32 sizedFormat)236 static 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 
Framebuffer(sglr::Context & context,const FboConfig & config,int width,int height,deUint32 fbo,deUint32 colorBufferName,deUint32 depthStencilBufferName)249 Framebuffer::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 
~Framebuffer(void)317 Framebuffer::~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 
checkCompleteness(void)324 void 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 
createTex2D(deUint32 name,GLenum format,int width,int height)333 deUint32 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 
createRbo(deUint32 name,GLenum format,int width,int height)354 deUint32 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 
destroyBuffer(deUint32 name,GLenum type)365 void 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 
createMetaballsTex2D(sglr::Context & context,deUint32 name,GLenum format,GLenum dataType,int width,int height)375 static 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 
createQuadsTex2D(sglr::Context & context,deUint32 name,GLenum format,GLenum dataType,int width,int height)387 static 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 
399 class FboRenderCase : public TestCase
400 {
401 public:
402 								FboRenderCase			(Context& context, const char* name, const char* description, const FboConfig& config);
~FboRenderCase(void)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 
410 protected:
411 	const FboConfig				m_config;
412 };
413 
FboRenderCase(Context & context,const char * name,const char * description,const FboConfig & config)414 FboRenderCase::FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config)
415 	: TestCase	(context, name, description)
416 	, m_config	(config)
417 {
418 }
419 
iterate(void)420 TestCase::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 
compare(const tcu::Surface & reference,const tcu::Surface & result)503 bool 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 
510 namespace FboCases
511 {
512 
513 class StencilClearsTest : public FboRenderCase
514 {
515 public:
516 						StencilClearsTest		(Context& context, const FboConfig& config);
~StencilClearsTest(void)517 	virtual				~StencilClearsTest		(void) {};
518 
519 	void				render					(sglr::Context& context, Surface& dst);
520 };
521 
StencilClearsTest(Context & context,const FboConfig & config)522 StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config)
523 	: FboRenderCase	(context, config.getName().c_str(), "Stencil clears", config)
524 {
525 }
526 
render(sglr::Context & context,Surface & dst)527 void 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 
604 class SharedColorbufferTest : public FboRenderCase
605 {
606 public:
607 						SharedColorbufferTest			(Context& context, const FboConfig& config);
~SharedColorbufferTest(void)608 	virtual				~SharedColorbufferTest			(void) {};
609 
610 	void				render							(sglr::Context& context, Surface& dst);
611 };
612 
SharedColorbufferTest(Context & context,const FboConfig & config)613 SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config)
614 	: FboRenderCase	(context, config.getName().c_str(), "Shared colorbuffer", config)
615 {
616 }
617 
render(sglr::Context & context,Surface & dst)618 void 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 
734 class SharedColorbufferClearsTest : public FboRenderCase
735 {
736 public:
737 					SharedColorbufferClearsTest		(Context& context, const FboConfig& config);
~SharedColorbufferClearsTest(void)738 	virtual			~SharedColorbufferClearsTest	(void) {}
739 
740 	void			render							(sglr::Context& context, Surface& dst);
741 };
742 
SharedColorbufferClearsTest(Context & context,const FboConfig & config)743 SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config)
744 	: FboRenderCase	(context, config.getName().c_str(), "Shared colorbuffer clears", config)
745 {
746 }
747 
render(sglr::Context & context,Surface & dst)748 void 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 
837 class SharedDepthStencilTest : public FboRenderCase
838 {
839 public:
840 					SharedDepthStencilTest		(Context& context, const FboConfig& config);
~SharedDepthStencilTest(void)841 	virtual			~SharedDepthStencilTest		(void) {};
842 
843 	static bool		isConfigSupported			(const FboConfig& config);
844 	void			render						(sglr::Context& context, Surface& dst);
845 };
846 
SharedDepthStencilTest(Context & context,const FboConfig & config)847 SharedDepthStencilTest::SharedDepthStencilTest (Context& context, const FboConfig& config)
848 	: FboRenderCase	(context, config.getName().c_str(), "Shared depth/stencilbuffer", config)
849 {
850 }
851 
isConfigSupported(const FboConfig & config)852 bool SharedDepthStencilTest::isConfigSupported (const FboConfig& config)
853 {
854 	return (config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0;
855 }
856 
render(sglr::Context & context,Surface & dst)857 void 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
969 class TexSubImageAfterRenderTest : public FboRenderCase
970 {
971 public:
972 					TexSubImageAfterRenderTest		(Context& context, const FboConfig& config);
973 	virtual			~TexSubImageAfterRenderTest		(void) {}
974 
975 	void			render							(sglr::Context& context, Surface& dst);
976 };
977 
978 TexSubImageAfterRenderTest::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 
983 void 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 
1024 class TexSubImageBetweenRenderTest : public FboRenderCase
1025 {
1026 public:
1027 					TexSubImageBetweenRenderTest		(Context& context, const FboConfig& config);
1028 	virtual			~TexSubImageBetweenRenderTest		(void) {}
1029 
1030 	void			render								(sglr::Context& context, Surface& dst);
1031 };
1032 
1033 TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config)
1034 	: FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config)
1035 {
1036 }
1037 
1038 void 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 
1095 class ResizeTest : public FboRenderCase
1096 {
1097 public:
1098 					ResizeTest				(Context& context, const FboConfig& config);
~ResizeTest(void)1099 	virtual			~ResizeTest				(void) {}
1100 
1101 	void			render					(sglr::Context& context, Surface& dst);
1102 };
1103 
ResizeTest(Context & context,const FboConfig & config)1104 ResizeTest::ResizeTest (Context& context, const FboConfig& config)
1105 	: FboRenderCase	(context, config.getName().c_str(), "Resize framebuffer", config)
1106 {
1107 }
1108 
render(sglr::Context & context,Surface & dst)1109 void 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 
1245 class RecreateBuffersTest : public FboRenderCase
1246 {
1247 public:
1248 					RecreateBuffersTest			(Context& context, const FboConfig& config, deUint32 buffers, bool rebind);
~RecreateBuffersTest(void)1249 	virtual			~RecreateBuffersTest		(void) {}
1250 
1251 	void			render						(sglr::Context& context, Surface& dst);
1252 
1253 private:
1254 	deUint32		m_buffers;
1255 	bool			m_rebind;
1256 };
1257 
RecreateBuffersTest(Context & context,const FboConfig & config,deUint32 buffers,bool rebind)1258 RecreateBuffersTest::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 
render(sglr::Context & ctx,Surface & dst)1265 void 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 
FboRenderTestGroup(Context & context)1448 FboRenderTestGroup::FboRenderTestGroup (Context& context)
1449 	: TestCaseGroup(context, "render", "Rendering Tests")
1450 {
1451 }
1452 
~FboRenderTestGroup(void)1453 FboRenderTestGroup::~FboRenderTestGroup (void)
1454 {
1455 }
1456 
init(void)1457 void 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