Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 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 without attachments (GL_ARB_framebuffer_no_attachments) tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fFboNoAttachmentTests.hpp"
     25 
     26 #include "glwDefs.hpp"
     27 #include "glwEnums.hpp"
     28 #include "glwFunctions.hpp"
     29 
     30 #include "gluRenderContext.hpp"
     31 #include "gluDefs.hpp"
     32 #include "gluShaderProgram.hpp"
     33 
     34 #include "tcuTestContext.hpp"
     35 #include "tcuVectorType.hpp"
     36 #include "tcuVectorUtil.hpp"
     37 #include "tcuTestLog.hpp"
     38 #include "tcuCommandLine.hpp"
     39 #include "tcuResultCollector.hpp"
     40 
     41 #include "deMemory.h"
     42 #include "deRandom.hpp"
     43 #include "deString.h"
     44 #include "deStringUtil.hpp"
     45 
     46 #include <string>
     47 #include <vector>
     48 
     49 namespace deqp
     50 {
     51 namespace gles31
     52 {
     53 namespace Functional
     54 {
     55 namespace
     56 {
     57 
     58 using namespace glw;
     59 
     60 using tcu::IVec2;
     61 using tcu::TestLog;
     62 
     63 using std::stringstream;
     64 using std::string;
     65 using std::vector;
     66 
     67 bool checkFramebufferSize (TestLog& log, const glu::RenderContext& renderCtx, GLuint framebuffer, const IVec2& size)
     68 {
     69 	const glw::Functions&		gl				= renderCtx.getFunctions();
     70 
     71 	const char* const			vertexSource	= "#version 310 es\n"
     72 												  "in layout(location = 0) highp vec2 a_position;\n\n"
     73 												  "void main()\n"
     74 												  "{\n"
     75 												  "	gl_Position = vec4(a_position, 0.0, 1.0);\n"
     76 												  "}\n";
     77 
     78 	const char* const			fragmentSource	= "#version 310 es\n"
     79 												  "uniform layout(location = 0) highp ivec2 u_expectedSize;\n"
     80 												  "out layout(location = 0) mediump vec4 f_color;\n\n"
     81 												  "void main()\n"
     82 												  "{\n"
     83 												  "	if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;\n"
     84 												  "	f_color = vec4(1.0, 0.5, 0.25, 1.0);\n"
     85 												  "}\n";
     86 
     87 	const glu::ShaderProgram	program			(renderCtx, glu::makeVtxFragSources(vertexSource, fragmentSource));
     88 	GLuint						query			= 0;
     89 	GLuint						insidePassed	= 0;
     90 	GLuint						outsideXPassed	= 0;
     91 	GLuint						outsideYPassed	= 0;
     92 
     93 	if (!program.isOk())
     94 		log << program;
     95 
     96 	TCU_CHECK(program.isOk());
     97 
     98 	gl.useProgram(program.getProgram());
     99 	gl.enable(GL_DEPTH_TEST);
    100 	gl.depthFunc(GL_ALWAYS);
    101 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
    102 	gl.viewport(0, 0, size.x()*2, size.y()*2); // Oversized viewport so that it will not accidentally limit us to the correct size
    103 
    104 	log << TestLog::Message << "Using " << size.x()*2 << "x" << size.y()*2 << " viewport" << TestLog::EndMessage;
    105 	log << TestLog::Message << "Discarding fragments outside pixel of interest" << TestLog::EndMessage;
    106 	log << TestLog::Message << "Using occlusion query to check for rendered fragments" << TestLog::EndMessage;
    107 
    108 	TCU_CHECK(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
    109 
    110 	// Render
    111 	{
    112 		const float data[] =
    113 		{
    114 			 1.0f,  1.0f,
    115 			 1.0f, -1.0f,
    116 			-1.0f,  1.0f,
    117 			-1.0f,  1.0f,
    118 			 1.0f, -1.0f,
    119 			-1.0f, -1.0f,
    120 		};
    121 
    122 		GLuint vertexArray	= 0;
    123 		GLuint vertexBuffer	= 0;
    124 
    125 		gl.genQueries(1, &query);
    126 		gl.genVertexArrays(1, &vertexArray);
    127 		gl.bindVertexArray(vertexArray);
    128 
    129 		gl.genBuffers(1, &vertexBuffer);
    130 		gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    131 		gl.bufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
    132 
    133 		gl.enableVertexAttribArray(0);
    134 		gl.vertexAttribPointer(0, 2, GL_FLOAT, false, 0, DE_NULL);
    135 
    136 		gl.uniform2i(0, size.x()-1, size.y()-1);
    137 		gl.beginQuery(GL_ANY_SAMPLES_PASSED, query);
    138 		gl.drawArrays(GL_TRIANGLES, 0, 6);
    139 		gl.endQuery(GL_ANY_SAMPLES_PASSED);
    140 		gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &insidePassed);
    141 		log << TestLog::Message << "A fragment was not discarded at (" << size.x()-1 << ", " << size.y()-1 << "). "
    142 			<< "Occlusion query reports it was " << (insidePassed > 0 ? "rendered." : "not rendered") << TestLog::EndMessage;
    143 
    144 		gl.uniform2i(0, size.x(), size.y()-1);
    145 		gl.beginQuery(GL_ANY_SAMPLES_PASSED, query);
    146 		gl.drawArrays(GL_TRIANGLES, 0, 6);
    147 		gl.endQuery(GL_ANY_SAMPLES_PASSED);
    148 		gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &outsideXPassed);
    149 		log << TestLog::Message << "A fragment was not discarded at (" << size.x() << ", " << size.y()-1 << "). "
    150 			<< "Occlusion query reports it was " << (outsideXPassed > 0 ? "rendered." : "not rendered") << TestLog::EndMessage;
    151 
    152 		gl.uniform2i(0, size.x()-1, size.y());
    153 		gl.beginQuery(GL_ANY_SAMPLES_PASSED, query);
    154 		gl.drawArrays(GL_TRIANGLES, 0, 6);
    155 		gl.endQuery(GL_ANY_SAMPLES_PASSED);
    156 		gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &outsideYPassed);
    157 		log << TestLog::Message << "A fragment was not discarded at (" << size.x()-1 << ", " << size.y() << "). "
    158 			<< "Occlusion query reports it was " << (outsideYPassed > 0 ? "rendered." : "not rendered") << TestLog::EndMessage;
    159 
    160 		gl.disableVertexAttribArray(0);
    161 		gl.bindBuffer(GL_ARRAY_BUFFER, 0);
    162 		gl.bindVertexArray(0);
    163 		gl.deleteBuffers(1, &vertexBuffer);
    164 		gl.deleteVertexArrays(1, &vertexArray);
    165 	}
    166 
    167 	gl.deleteQueries(1, &query);
    168 
    169 	GLU_EXPECT_NO_ERROR(gl.getError(), "Query failed");
    170 
    171 	return insidePassed && !outsideXPassed && !outsideYPassed;
    172 }
    173 
    174 bool checkFramebufferRenderable (TestLog& log, const glu::RenderContext& renderCtx, GLuint framebuffer, const IVec2& size)
    175 {
    176 	const glw::Functions&		gl				= renderCtx.getFunctions();
    177 
    178 	const char* const			vertexSource	= "#version 310 es\n"
    179 												  "in layout(location = 0) highp vec2 a_position;\n\n"
    180 												  "void main()\n"
    181 												  "{\n"
    182 												  "	gl_Position = vec4(a_position, 0.0, 1.0);\n"
    183 												  "}\n";
    184 
    185 	const char* const			fragmentSource	= "#version 310 es\n"
    186 												  "out layout(location = 0) mediump vec4 f_color;\n\n"
    187 												  "void main()\n"
    188 												  "{\n"
    189 												  "	f_color = vec4(1.0, 0.5, 0.25, 1.0);\n"
    190 												  "}\n";
    191 
    192 	const glu::ShaderProgram	program			(renderCtx, glu::makeVtxFragSources(vertexSource, fragmentSource));
    193 	GLuint						query			= 0;
    194 
    195 	if (!program.isOk())
    196 		log << program;
    197 
    198 	TCU_CHECK(program.isOk());
    199 
    200 	gl.useProgram(program.getProgram());
    201 	gl.enable(GL_DEPTH_TEST);
    202 	gl.depthFunc(GL_ALWAYS);
    203 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
    204 	gl.viewport(0, 0, size.x(), size.y());
    205 
    206 	TCU_CHECK(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
    207 
    208 	log << TestLog::Message << "Rendering full framebuffer quad with color ouput, verifying output presence with occlusion query" << TestLog::EndMessage;
    209 
    210 	// Render
    211 	{
    212 		const float data[] =
    213 		{
    214 			 1.0f,  1.0f,
    215 			 1.0f, -1.0f,
    216 			-1.0f,  1.0f,
    217 			-1.0f,  1.0f,
    218 			 1.0f, -1.0f,
    219 			-1.0f, -1.0f,
    220 		};
    221 
    222 		GLuint vertexArray	= 0;
    223 		GLuint vertexBuffer	= 0;
    224 
    225 		gl.genQueries(1, &query);
    226 		gl.genVertexArrays(1, &vertexArray);
    227 		gl.bindVertexArray(vertexArray);
    228 
    229 		gl.genBuffers(1, &vertexBuffer);
    230 		gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    231 		gl.bufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
    232 
    233 		gl.enableVertexAttribArray(0);
    234 		gl.vertexAttribPointer(0, 2, GL_FLOAT, false, 0, DE_NULL);
    235 
    236 		gl.beginQuery(GL_ANY_SAMPLES_PASSED, query);
    237 		gl.drawArrays(GL_TRIANGLES, 0, 6);
    238 		gl.endQuery(GL_ANY_SAMPLES_PASSED);
    239 
    240 		gl.disableVertexAttribArray(0);
    241 		gl.bindBuffer(GL_ARRAY_BUFFER, 0);
    242 		gl.bindVertexArray(0);
    243 		gl.deleteBuffers(1, &vertexBuffer);
    244 		gl.deleteVertexArrays(1, &vertexArray);
    245 	}
    246 
    247 	// Read
    248 	{
    249 		GLuint passed = 0;
    250 
    251 		gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &passed);
    252 		gl.deleteQueries(1, &query);
    253 
    254 		GLU_EXPECT_NO_ERROR(gl.getError(), "Query failed");
    255 
    256 		if (passed)
    257 			log << TestLog::Message << "Query passed" << TestLog::EndMessage;
    258 		else
    259 			log << TestLog::Message << "Query did not pass" << TestLog::EndMessage;
    260 
    261 		return passed != 0;
    262 	}
    263 }
    264 
    265 class FramebufferCompletenessCase : public tcu::TestCase
    266 {
    267 public:
    268 								FramebufferCompletenessCase		(tcu::TestContext&			testCtx,
    269 																 const glu::RenderContext&	renderCtx,
    270 																 const char*				name,
    271 																 const char*				desc);
    272 	virtual						~FramebufferCompletenessCase	 (void) {}
    273 	virtual IterateResult		iterate							(void);
    274 
    275 private:
    276 	const glu::RenderContext&	m_renderCtx;
    277 	tcu::ResultCollector		m_results;
    278 };
    279 
    280 FramebufferCompletenessCase::FramebufferCompletenessCase (tcu::TestContext&			testCtx,
    281 														  const glu::RenderContext&	renderCtx,
    282 														  const char*				name,
    283 														  const char*				desc)
    284 	: TestCase		(testCtx, name, desc)
    285 	, m_renderCtx	(renderCtx)
    286 {
    287 }
    288 
    289 FramebufferCompletenessCase::IterateResult FramebufferCompletenessCase::iterate (void)
    290 {
    291 	const glw::Functions&	gl			= m_renderCtx.getFunctions();
    292 	GLuint					framebuffer	= 0;
    293 
    294 	gl.genFramebuffers(1, &framebuffer);
    295 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
    296 
    297 	m_results.check(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, "Framebuffer was incorrectly reported as complete when it had no width, height or attachments");
    298 
    299 	gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 16);
    300 	m_results.check(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, "Framebuffer was incorrectly reported as complete when it only had a width");
    301 
    302 	gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 16);
    303 	m_results.check(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Framebuffer not reported as complete when it had width and height set");
    304 
    305 	gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
    306 	m_results.check(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, "Framebuffer was incorrectly reported as complete when it only had a height");
    307 
    308 	gl.deleteFramebuffers(1, &framebuffer);
    309 
    310 	m_results.setTestContextResult(m_testCtx);
    311 	return STOP;
    312 }
    313 
    314 struct FboSpec
    315 {
    316 	int width;
    317 	int height;
    318 	int samples;
    319 
    320 	FboSpec(int width_, int height_, int samples_) : width(width_), height(height_), samples(samples_){}
    321 };
    322 
    323 class SizeCase : public tcu::TestCase
    324 {
    325 public:
    326 								SizeCase	(tcu::TestContext&			testCtx,
    327 											 const glu::RenderContext&	renderCtx,
    328 											 const char*				name,
    329 											 const char*				desc,
    330 											 const FboSpec&				spec);
    331 	virtual						~SizeCase	(void) {}
    332 
    333 	virtual IterateResult		iterate		(void);
    334 
    335 	enum
    336 	{
    337 		USE_MAXIMUM = -1
    338 	};
    339 private:
    340 	int							getWidth	(void) const;
    341 	int							getHeight	(void) const;
    342 	int							getSamples	(void) const;
    343 
    344 	const glu::RenderContext&	m_renderCtx;
    345 
    346 	const FboSpec				m_spec;
    347 };
    348 
    349 SizeCase::SizeCase (tcu::TestContext&			testCtx,
    350 					const glu::RenderContext&	renderCtx,
    351 					const char*					name,
    352 					const char*					desc,
    353 					const FboSpec&				spec)
    354 	: TestCase		(testCtx, name, desc)
    355 	, m_renderCtx	(renderCtx)
    356 	, m_spec		(spec)
    357 {
    358 }
    359 
    360 SizeCase::IterateResult SizeCase::iterate (void)
    361 {
    362 	const glw::Functions&	gl			= m_renderCtx.getFunctions();
    363 	TestLog&				log			= m_testCtx.getLog();
    364 	GLuint					framebuffer	= 0;
    365 	const int				width		= getWidth();
    366 	const int				height		= getHeight();
    367 	const int				samples		= getSamples();
    368 
    369 	gl.genFramebuffers(1, &framebuffer);
    370 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
    371 	gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, width);
    372 	gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, height);
    373 	gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, samples);
    374 
    375 	log << TestLog::Message << "Verifying " << width << "x" << height << " framebuffer with " << samples << "x multisampling" << TestLog::EndMessage;
    376 
    377 	if(checkFramebufferRenderable(log, m_renderCtx, framebuffer, IVec2(width, height)) && checkFramebufferSize(log, m_renderCtx, framebuffer, IVec2(width, height)))
    378 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    379 	else
    380 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Framebuffer did not behave as expected");
    381 
    382 	gl.deleteFramebuffers(1, &framebuffer);
    383 
    384 	return STOP;
    385 }
    386 
    387 int SizeCase::getWidth (void) const
    388 {
    389 	if (m_spec.width != USE_MAXIMUM)
    390 		return m_spec.width;
    391 	else
    392 	{
    393 		const glw::Functions&	gl		= m_renderCtx.getFunctions();
    394 		GLint					width	= 0;
    395 
    396 		gl.getIntegerv(GL_MAX_FRAMEBUFFER_WIDTH, &width);
    397 
    398 		return width;
    399 	}
    400 }
    401 
    402 int SizeCase::getHeight (void) const
    403 {
    404 	if (m_spec.height != USE_MAXIMUM)
    405 		return m_spec.height;
    406 	else
    407 	{
    408 		const glw::Functions&	gl		= m_renderCtx.getFunctions();
    409 		GLint					height	= 0;
    410 
    411 		gl.getIntegerv(GL_MAX_FRAMEBUFFER_HEIGHT, &height);
    412 
    413 		return height;
    414 	}
    415 }
    416 
    417 int SizeCase::getSamples (void) const
    418 {
    419 	if (m_spec.samples != USE_MAXIMUM)
    420 		return m_spec.samples;
    421 	else
    422 	{
    423 		const glw::Functions&	gl		= m_renderCtx.getFunctions();
    424 		GLint					samples	= 0;
    425 
    426 		gl.getIntegerv(GL_MAX_FRAMEBUFFER_SAMPLES, &samples);
    427 
    428 		return samples;
    429 	}
    430 }
    431 
    432 class AttachmentInteractionCase : public tcu::TestCase
    433 {
    434 public:
    435 								AttachmentInteractionCase	(tcu::TestContext&			testCtx,
    436 															 const glu::RenderContext&	renderCtx,
    437 															 const char*				name,
    438 															 const char*				desc,
    439 															 const FboSpec&				defaultSpec,
    440 															 const FboSpec&				attachmentSpec);
    441 	virtual						~AttachmentInteractionCase	(void) {}
    442 
    443 	virtual IterateResult		iterate						(void);
    444 
    445 private:
    446 	const glu::RenderContext&	m_renderCtx;
    447 	const FboSpec				m_defaultSpec;
    448 	const FboSpec				m_attachmentSpec;
    449 };
    450 
    451 AttachmentInteractionCase::AttachmentInteractionCase (tcu::TestContext&			testCtx,
    452 													  const glu::RenderContext&	renderCtx,
    453 													  const char*				name,
    454 													  const char*				desc,
    455 													  const FboSpec&			defaultSpec,
    456 													  const FboSpec&			attachmentSpec)
    457 	: TestCase			(testCtx, name, desc)
    458 	, m_renderCtx		(renderCtx)
    459 	, m_defaultSpec		(defaultSpec)
    460 	, m_attachmentSpec	(attachmentSpec)
    461 {
    462 }
    463 
    464 AttachmentInteractionCase::IterateResult AttachmentInteractionCase::iterate (void)
    465 {
    466 	const glw::Functions&	gl			= m_renderCtx.getFunctions();
    467 	TestLog&				log			= m_testCtx.getLog();
    468 	GLuint					framebuffer	= 0;
    469 	GLuint					renderbuffer= 0;
    470 
    471 	gl.genFramebuffers(1, &framebuffer);
    472 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
    473 	gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, m_defaultSpec.width);
    474 	gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, m_defaultSpec.height);
    475 	gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, m_defaultSpec.samples);
    476 
    477 	gl.genRenderbuffers(1, &renderbuffer);
    478 	gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
    479 	gl.renderbufferStorageMultisample(GL_RENDERBUFFER, m_attachmentSpec.samples, GL_RGBA8, m_attachmentSpec.width, m_attachmentSpec.height);
    480 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
    481 
    482 	log << TestLog::Message << "Verifying " << m_attachmentSpec.width << "x" << m_attachmentSpec.height << " framebuffer with " << m_attachmentSpec.samples << "x multisampling"
    483 		<< " and defaults set to " << m_defaultSpec.width << "x" << m_defaultSpec.height << " with " << m_defaultSpec.samples << "x multisampling" << TestLog::EndMessage;
    484 
    485 	if(checkFramebufferRenderable(log, m_renderCtx, framebuffer, IVec2(m_attachmentSpec.width, m_attachmentSpec.height))
    486 	   && checkFramebufferSize(log, m_renderCtx, framebuffer, IVec2(m_attachmentSpec.width, m_attachmentSpec.height)))
    487 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    488 	else
    489 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Framebuffer did not behave as expected");
    490 
    491 	gl.deleteRenderbuffers(1, &renderbuffer);
    492 	gl.deleteFramebuffers(1, &framebuffer);
    493 
    494 	return STOP;
    495 }
    496 
    497 } // Anonymous
    498 
    499 tcu::TestCaseGroup* createFboNoAttachmentTests(Context& context)
    500 {
    501 	const glu::RenderContext&	renderCtx	= context.getRenderContext();
    502 	tcu::TestContext&			testCtx		= context.getTestContext();
    503 
    504 	const int					maxWidth	= 2048; // MAX_FRAMEBUFFER_WIDTH in ES 3.1
    505 	const int					maxHeight	= 2048; // MAX_FRAMEBUFFER_HEIGHT in ES 3.1
    506 	const int					maxSamples	= 4;
    507 
    508 	tcu::TestCaseGroup* const	root		= new tcu::TestCaseGroup(testCtx, "no_attachments", "Framebuffer without attachments");
    509 
    510 	// Size
    511 	{
    512 		tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "size", "Basic functionality tests with varying default size");
    513 
    514 		root->addChild(group);
    515 
    516 		for (int width = 16; width <= maxWidth; width *= 4)
    517 		{
    518 			for (int height = 16; height <= maxHeight; height *= 4)
    519 			{
    520 				const FboSpec	spec (width, height, 0);
    521 				stringstream	name;
    522 
    523 				name << width << "x" << height;
    524 
    525 				group->addChild(new SizeCase(testCtx, renderCtx, name.str().c_str(), name.str().c_str(), spec));
    526 			}
    527 		}
    528 	}
    529 
    530 	// NPOT size
    531 	{
    532 		const FboSpec specs[] =
    533 		{
    534 			// Square
    535 			FboSpec(1,    1,    0),
    536 			FboSpec(3,    3,    0),
    537 			FboSpec(15,   15,   0),
    538 			FboSpec(17,   17,   0),
    539 			FboSpec(31,   31,   0),
    540 			FboSpec(33,   33,   0),
    541 			FboSpec(63,   63,   0),
    542 			FboSpec(65,   65,   0),
    543 			FboSpec(127,  127,  0),
    544 			FboSpec(129,  129,  0),
    545 			FboSpec(255,  255,  0),
    546 			FboSpec(257,  257,  0),
    547 			FboSpec(511,  511,  0),
    548 			FboSpec(513,  513,  0),
    549 			FboSpec(1023, 1023, 0),
    550 			FboSpec(1025, 1025, 0),
    551 			FboSpec(2047, 2047, 0),
    552 
    553 			// Non-square
    554 			FboSpec(15,   511,  0),
    555 			FboSpec(127,  15,   0),
    556 			FboSpec(129,  127,  0),
    557 			FboSpec(511,  127,  0),
    558 			FboSpec(2047, 1025, 0),
    559 		};
    560 		tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "npot_size", "Basic functionality with Non-power-of-two size");
    561 
    562 		root->addChild(group);
    563 
    564 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(specs); caseNdx++)
    565 		{
    566 			const FboSpec&	spec = specs[caseNdx];
    567 			stringstream	name;
    568 
    569 			name << spec.width << "x" << spec.height;
    570 
    571 			group->addChild(new SizeCase(testCtx, renderCtx, name.str().c_str(), name.str().c_str(), spec));
    572 		}
    573 	}
    574 
    575 	// Multisample
    576 	{
    577 		tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "multisample", "Basic functionality with multisampled fbo");
    578 
    579 		root->addChild(group);
    580 
    581 		for (int samples = 0; samples <= maxSamples; samples++)
    582 		{
    583 			const FboSpec	spec (128, 128, samples);
    584 			stringstream	name;
    585 
    586 			name << "samples" << samples;
    587 
    588 			group->addChild(new SizeCase(testCtx, renderCtx, name.str().c_str(), name.str().c_str(), spec));
    589 		}
    590 	}
    591 
    592 	// Randomized
    593 	{
    594 		tcu::TestCaseGroup* const	group	= new tcu::TestCaseGroup(testCtx, "random", "Randomized size & multisampling");
    595 		de::Random					rng		(0xF0E1E2D3 ^ testCtx.getCommandLine().getBaseSeed());
    596 
    597 		root->addChild(group);
    598 
    599 		for (int caseNdx = 0; caseNdx < 16; caseNdx++)
    600 		{
    601 			const int		width	= rng.getInt(1, maxWidth);
    602 			const int		height	= rng.getInt(1, maxHeight);
    603 			const int		samples = rng.getInt(0, maxSamples);
    604 			const FboSpec	spec	(width, height, samples);
    605 			const string	name	= de::toString(caseNdx);
    606 
    607 			group->addChild(new SizeCase(testCtx, renderCtx, name.c_str(), name.c_str(), spec));
    608 		}
    609 	}
    610 
    611 	// Normal fbo with defaults set
    612 	{
    613 		tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "interaction", "Interaction of default parameters with normal fbo");
    614 
    615 		root->addChild(group);
    616 
    617 		const FboSpec specs[][2] =
    618 		{
    619 			{ FboSpec(256,  256,  0), FboSpec(128,  128,  1) },
    620 			{ FboSpec(256,  256,  1), FboSpec(128,  128,  0) },
    621 			{ FboSpec(256,  256,  0), FboSpec(512,  512,  2) },
    622 			{ FboSpec(256,  256,  2), FboSpec(128,  512,  0) },
    623 			{ FboSpec(127,  127,  0), FboSpec(129,  129,  0) },
    624 			{ FboSpec(17,   512,  4), FboSpec(16,   16,   2) },
    625 			{ FboSpec(2048, 2048, 4), FboSpec(1,    1,    0) },
    626 			{ FboSpec(1,    1,    0), FboSpec(2048, 2048, 4) },
    627 		};
    628 
    629 		for (int specNdx = 0; specNdx < DE_LENGTH_OF_ARRAY(specs); specNdx++)
    630 		{
    631 			const FboSpec& baseSpec = specs[specNdx][0];
    632 			const FboSpec& altSpec	= specs[specNdx][1];
    633 			stringstream baseSpecName, altSpecName;
    634 
    635 			baseSpecName << baseSpec.width << "x" << baseSpec.height << "ms" << baseSpec.samples;
    636 			altSpecName << altSpec.width << "x" << altSpec.height << "ms" << altSpec.samples;
    637 
    638 			{
    639 				const string name = baseSpecName.str() + "_default_" + altSpecName.str();
    640 
    641 				group->addChild(new AttachmentInteractionCase(testCtx, renderCtx, name.c_str(), name.c_str(), altSpec, baseSpec));
    642 			}
    643 		}
    644 	}
    645 
    646 	// Maximums
    647 	{
    648 		tcu::TestCaseGroup* const	group	= new tcu::TestCaseGroup(testCtx, "maximums", "Maximum dimensions");
    649 
    650 		root->addChild(group);
    651 		group->addChild(new SizeCase(testCtx, renderCtx, "width",	"Maximum width",		  FboSpec(SizeCase::USE_MAXIMUM,	128,					0)));
    652 		group->addChild(new SizeCase(testCtx, renderCtx, "height",	"Maximum height",		  FboSpec(128,						SizeCase::USE_MAXIMUM,  0)));
    653 		group->addChild(new SizeCase(testCtx, renderCtx, "size",	"Maximum size",			  FboSpec(SizeCase::USE_MAXIMUM,	SizeCase::USE_MAXIMUM,  0)));
    654 		group->addChild(new SizeCase(testCtx, renderCtx, "samples", "Maximum samples",		  FboSpec(128,						128,					SizeCase::USE_MAXIMUM)));
    655 		group->addChild(new SizeCase(testCtx, renderCtx, "all",		"Maximum size & samples", FboSpec(SizeCase::USE_MAXIMUM,	SizeCase::USE_MAXIMUM,  SizeCase::USE_MAXIMUM)));
    656 	}
    657 
    658 	return root;
    659 }
    660 
    661 tcu::TestCaseGroup* createFboNoAttachmentCompletenessTests(Context& context)
    662 {
    663 	TestCaseGroup* const group = new TestCaseGroup(context, "completeness", "Completeness tests");
    664 
    665 	group->addChild(new FramebufferCompletenessCase(context.getTestContext(), context.getRenderContext(), "no_attachments", "No attachments completeness"));
    666 
    667 	return group;
    668 }
    669 
    670 } // Functional
    671 } // gles31
    672 } // deqp
    673