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