• 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 		// 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 
isExtensionSupported(sglr::Context & context,const char * name)193 static 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 
isAnyExtensionSupported(sglr::Context & context,const std::vector<std::string> & requiredExts)207 static 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 
223 template<typename T>
join(const std::vector<T> & list,const std::string & sep)224 static 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 
checkColorFormatSupport(sglr::Context & context,deUint32 sizedFormat)238 static 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 
Framebuffer(sglr::Context & context,const FboConfig & config,int width,int height,deUint32 fbo,deUint32 colorBufferName,deUint32 depthStencilBufferName)251 Framebuffer::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 
~Framebuffer(void)319 Framebuffer::~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 
checkCompleteness(void)326 void 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 
createTex2D(deUint32 name,GLenum format,int width,int height)335 deUint32 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 
createRbo(deUint32 name,GLenum format,int width,int height)356 deUint32 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 
destroyBuffer(deUint32 name,GLenum type)367 void 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 
createMetaballsTex2D(sglr::Context & context,deUint32 name,GLenum format,GLenum dataType,int width,int height)377 static 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 
createQuadsTex2D(sglr::Context & context,deUint32 name,GLenum format,GLenum dataType,int width,int height)389 static 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 
401 class FboRenderCase : public TestCase
402 {
403 public:
404 								FboRenderCase			(Context& context, const char* name, const char* description, const FboConfig& config);
~FboRenderCase(void)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 
412 protected:
413 	const FboConfig				m_config;
414 };
415 
FboRenderCase(Context & context,const char * name,const char * description,const FboConfig & config)416 FboRenderCase::FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config)
417 	: TestCase	(context, name, description)
418 	, m_config	(config)
419 {
420 }
421 
iterate(void)422 TestCase::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 
compare(const tcu::Surface & reference,const tcu::Surface & result)505 bool 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 
512 namespace FboCases
513 {
514 
515 class StencilClearsTest : public FboRenderCase
516 {
517 public:
518 						StencilClearsTest		(Context& context, const FboConfig& config);
~StencilClearsTest(void)519 	virtual				~StencilClearsTest		(void) {}
520 
521 	void				render					(sglr::Context& context, Surface& dst);
522 };
523 
StencilClearsTest(Context & context,const FboConfig & config)524 StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config)
525 	: FboRenderCase	(context, config.getName().c_str(), "Stencil clears", config)
526 {
527 }
528 
render(sglr::Context & context,Surface & dst)529 void 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 
606 class SharedColorbufferTest : public FboRenderCase
607 {
608 public:
609 						SharedColorbufferTest			(Context& context, const FboConfig& config);
~SharedColorbufferTest(void)610 	virtual				~SharedColorbufferTest			(void) {}
611 
612 	void				render							(sglr::Context& context, Surface& dst);
613 };
614 
SharedColorbufferTest(Context & context,const FboConfig & config)615 SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config)
616 	: FboRenderCase	(context, config.getName().c_str(), "Shared colorbuffer", config)
617 {
618 }
619 
render(sglr::Context & context,Surface & dst)620 void 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 
736 class SharedColorbufferClearsTest : public FboRenderCase
737 {
738 public:
739 					SharedColorbufferClearsTest		(Context& context, const FboConfig& config);
~SharedColorbufferClearsTest(void)740 	virtual			~SharedColorbufferClearsTest	(void) {}
741 
742 	void			render							(sglr::Context& context, Surface& dst);
743 };
744 
SharedColorbufferClearsTest(Context & context,const FboConfig & config)745 SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config)
746 	: FboRenderCase	(context, config.getName().c_str(), "Shared colorbuffer clears", config)
747 {
748 }
749 
render(sglr::Context & context,Surface & dst)750 void 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 
839 class SharedDepthStencilTest : public FboRenderCase
840 {
841 public:
842 					SharedDepthStencilTest		(Context& context, const FboConfig& config);
~SharedDepthStencilTest(void)843 	virtual			~SharedDepthStencilTest		(void) {}
844 
845 	static bool		isConfigSupported			(const FboConfig& config);
846 	void			render						(sglr::Context& context, Surface& dst);
847 };
848 
SharedDepthStencilTest(Context & context,const FboConfig & config)849 SharedDepthStencilTest::SharedDepthStencilTest (Context& context, const FboConfig& config)
850 	: FboRenderCase	(context, config.getName().c_str(), "Shared depth/stencilbuffer", config)
851 {
852 }
853 
isConfigSupported(const FboConfig & config)854 bool SharedDepthStencilTest::isConfigSupported (const FboConfig& config)
855 {
856 	return (config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0;
857 }
858 
render(sglr::Context & context,Surface & dst)859 void 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
971 class TexSubImageAfterRenderTest : public FboRenderCase
972 {
973 public:
974 					TexSubImageAfterRenderTest		(Context& context, const FboConfig& config);
975 	virtual			~TexSubImageAfterRenderTest		(void) {}
976 
977 	void			render							(sglr::Context& context, Surface& dst);
978 };
979 
980 TexSubImageAfterRenderTest::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 
985 void 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 
1026 class TexSubImageBetweenRenderTest : public FboRenderCase
1027 {
1028 public:
1029 					TexSubImageBetweenRenderTest		(Context& context, const FboConfig& config);
1030 	virtual			~TexSubImageBetweenRenderTest		(void) {}
1031 
1032 	void			render								(sglr::Context& context, Surface& dst);
1033 };
1034 
1035 TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config)
1036 	: FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config)
1037 {
1038 }
1039 
1040 void 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 
1097 class ResizeTest : public FboRenderCase
1098 {
1099 public:
1100 					ResizeTest				(Context& context, const FboConfig& config);
~ResizeTest(void)1101 	virtual			~ResizeTest				(void) {}
1102 
1103 	void			render					(sglr::Context& context, Surface& dst);
1104 };
1105 
ResizeTest(Context & context,const FboConfig & config)1106 ResizeTest::ResizeTest (Context& context, const FboConfig& config)
1107 	: FboRenderCase	(context, config.getName().c_str(), "Resize framebuffer", config)
1108 {
1109 }
1110 
render(sglr::Context & context,Surface & dst)1111 void 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 
1247 class RecreateBuffersTest : public FboRenderCase
1248 {
1249 public:
1250 					RecreateBuffersTest			(Context& context, const FboConfig& config, deUint32 buffers, bool rebind);
~RecreateBuffersTest(void)1251 	virtual			~RecreateBuffersTest		(void) {}
1252 
1253 	void			render						(sglr::Context& context, Surface& dst);
1254 
1255 private:
1256 	deUint32		m_buffers;
1257 	bool			m_rebind;
1258 };
1259 
RecreateBuffersTest(Context & context,const FboConfig & config,deUint32 buffers,bool rebind)1260 RecreateBuffersTest::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 
render(sglr::Context & ctx,Surface & dst)1267 void 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 
FboRenderTestGroup(Context & context)1450 FboRenderTestGroup::FboRenderTestGroup (Context& context)
1451 	: TestCaseGroup(context, "render", "Rendering Tests")
1452 {
1453 }
1454 
~FboRenderTestGroup(void)1455 FboRenderTestGroup::~FboRenderTestGroup (void)
1456 {
1457 }
1458 
init(void)1459 void 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