• 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 #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 
checkFramebufferSize(TestLog & log,const glu::RenderContext & renderCtx,GLuint framebuffer,const IVec2 & size)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 
checkFramebufferRenderable(TestLog & log,const glu::RenderContext & renderCtx,GLuint framebuffer,const IVec2 & size)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);
~FramebufferCompletenessCase(void)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 
FramebufferCompletenessCase(tcu::TestContext & testCtx,const glu::RenderContext & renderCtx,const char * name,const char * desc)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 
iterate(void)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 
FboSpecdeqp::gles31::Functional::__anon63c430160111::FboSpec320 	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);
~SizeCase(void)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 
SizeCase(tcu::TestContext & testCtx,const glu::RenderContext & renderCtx,const char * name,const char * desc,const FboSpec & spec)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 
iterate(void)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 	int						samples		= getSamples();
368 
369 	for (;;) {
370 		gl.genFramebuffers(1, &framebuffer);
371 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
372 		gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, width);
373 		gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, height);
374 		gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, samples);
375 
376 		GLenum status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
377 		if (status == GL_FRAMEBUFFER_COMPLETE)
378 			break;
379 		else
380 		{
381 			gl.deleteFramebuffers(1, &framebuffer);
382 			framebuffer = 0;
383 
384 			if (status == GL_FRAMEBUFFER_UNSUPPORTED)
385 				if (samples >= 2)
386 					samples /= 2;
387 				else
388 					break;
389 			else
390 			{
391 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected no-attachment framebuffer status");
392 				return STOP;
393 			}
394 		}
395 	}
396 	if (!framebuffer)
397 	{
398 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unable to find a supported no-attachment framebuffer width/height/samples");
399 		return STOP;
400 	}
401 
402 	log << TestLog::Message << "Verifying " << width << "x" << height << " framebuffer with " << samples << "x multisampling" << TestLog::EndMessage;
403 
404 	if(checkFramebufferRenderable(log, m_renderCtx, framebuffer, IVec2(width, height)) && checkFramebufferSize(log, m_renderCtx, framebuffer, IVec2(width, height)))
405 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
406 	else
407 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Framebuffer did not behave as expected");
408 
409 	gl.deleteFramebuffers(1, &framebuffer);
410 
411 	return STOP;
412 }
413 
getWidth(void) const414 int SizeCase::getWidth (void) const
415 {
416 	if (m_spec.width != USE_MAXIMUM)
417 		return m_spec.width;
418 	else
419 	{
420 		const glw::Functions&	gl		= m_renderCtx.getFunctions();
421 		GLint					width	= 0;
422 
423 		gl.getIntegerv(GL_MAX_FRAMEBUFFER_WIDTH, &width);
424 
425 		return width;
426 	}
427 }
428 
getHeight(void) const429 int SizeCase::getHeight (void) const
430 {
431 	if (m_spec.height != USE_MAXIMUM)
432 		return m_spec.height;
433 	else
434 	{
435 		const glw::Functions&	gl		= m_renderCtx.getFunctions();
436 		GLint					height	= 0;
437 
438 		gl.getIntegerv(GL_MAX_FRAMEBUFFER_HEIGHT, &height);
439 
440 		return height;
441 	}
442 }
443 
getSamples(void) const444 int SizeCase::getSamples (void) const
445 {
446 	if (m_spec.samples != USE_MAXIMUM)
447 		return m_spec.samples;
448 	else
449 	{
450 		const glw::Functions&	gl		= m_renderCtx.getFunctions();
451 		GLint					samples	= 0;
452 
453 		gl.getIntegerv(GL_MAX_FRAMEBUFFER_SAMPLES, &samples);
454 
455 		return samples;
456 	}
457 }
458 
459 class AttachmentInteractionCase : public tcu::TestCase
460 {
461 public:
462 								AttachmentInteractionCase	(tcu::TestContext&			testCtx,
463 															 const glu::RenderContext&	renderCtx,
464 															 const char*				name,
465 															 const char*				desc,
466 															 const FboSpec&				defaultSpec,
467 															 const FboSpec&				attachmentSpec);
~AttachmentInteractionCase(void)468 	virtual						~AttachmentInteractionCase	(void) {}
469 
470 	virtual IterateResult		iterate						(void);
471 
472 private:
473 	const glu::RenderContext&	m_renderCtx;
474 	const FboSpec				m_defaultSpec;
475 	const FboSpec				m_attachmentSpec;
476 };
477 
AttachmentInteractionCase(tcu::TestContext & testCtx,const glu::RenderContext & renderCtx,const char * name,const char * desc,const FboSpec & defaultSpec,const FboSpec & attachmentSpec)478 AttachmentInteractionCase::AttachmentInteractionCase (tcu::TestContext&			testCtx,
479 													  const glu::RenderContext&	renderCtx,
480 													  const char*				name,
481 													  const char*				desc,
482 													  const FboSpec&			defaultSpec,
483 													  const FboSpec&			attachmentSpec)
484 	: TestCase			(testCtx, name, desc)
485 	, m_renderCtx		(renderCtx)
486 	, m_defaultSpec		(defaultSpec)
487 	, m_attachmentSpec	(attachmentSpec)
488 {
489 }
490 
iterate(void)491 AttachmentInteractionCase::IterateResult AttachmentInteractionCase::iterate (void)
492 {
493 	const glw::Functions&	gl			= m_renderCtx.getFunctions();
494 	TestLog&				log			= m_testCtx.getLog();
495 	GLuint					framebuffer	= 0;
496 	GLuint					renderbuffer= 0;
497 
498 	gl.genFramebuffers(1, &framebuffer);
499 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
500 	gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, m_defaultSpec.width);
501 	gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, m_defaultSpec.height);
502 	gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, m_defaultSpec.samples);
503 
504 	gl.genRenderbuffers(1, &renderbuffer);
505 	gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
506 	gl.renderbufferStorageMultisample(GL_RENDERBUFFER, m_attachmentSpec.samples, GL_RGBA8, m_attachmentSpec.width, m_attachmentSpec.height);
507 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
508 
509 	log << TestLog::Message << "Verifying " << m_attachmentSpec.width << "x" << m_attachmentSpec.height << " framebuffer with " << m_attachmentSpec.samples << "x multisampling"
510 		<< " and defaults set to " << m_defaultSpec.width << "x" << m_defaultSpec.height << " with " << m_defaultSpec.samples << "x multisampling" << TestLog::EndMessage;
511 
512 	if(checkFramebufferRenderable(log, m_renderCtx, framebuffer, IVec2(m_attachmentSpec.width, m_attachmentSpec.height))
513 	   && checkFramebufferSize(log, m_renderCtx, framebuffer, IVec2(m_attachmentSpec.width, m_attachmentSpec.height)))
514 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
515 	else
516 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Framebuffer did not behave as expected");
517 
518 	gl.deleteRenderbuffers(1, &renderbuffer);
519 	gl.deleteFramebuffers(1, &framebuffer);
520 
521 	return STOP;
522 }
523 
524 } // Anonymous
525 
createFboNoAttachmentTests(Context & context)526 tcu::TestCaseGroup* createFboNoAttachmentTests(Context& context)
527 {
528 	const glu::RenderContext&	renderCtx	= context.getRenderContext();
529 	tcu::TestContext&			testCtx		= context.getTestContext();
530 
531 	const int					maxWidth	= 2048; // MAX_FRAMEBUFFER_WIDTH in ES 3.1
532 	const int					maxHeight	= 2048; // MAX_FRAMEBUFFER_HEIGHT in ES 3.1
533 	const int					maxSamples	= 4;
534 
535 	tcu::TestCaseGroup* const	root		= new tcu::TestCaseGroup(testCtx, "no_attachments", "Framebuffer without attachments");
536 
537 	// Size
538 	{
539 		tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "size", "Basic functionality tests with varying default size");
540 
541 		root->addChild(group);
542 
543 		for (int width = 16; width <= maxWidth; width *= 4)
544 		{
545 			for (int height = 16; height <= maxHeight; height *= 4)
546 			{
547 				const FboSpec	spec (width, height, 0);
548 				stringstream	name;
549 
550 				name << width << "x" << height;
551 
552 				group->addChild(new SizeCase(testCtx, renderCtx, name.str().c_str(), name.str().c_str(), spec));
553 			}
554 		}
555 	}
556 
557 	// NPOT size
558 	{
559 		const FboSpec specs[] =
560 		{
561 			// Square
562 			FboSpec(1,    1,    0),
563 			FboSpec(3,    3,    0),
564 			FboSpec(15,   15,   0),
565 			FboSpec(17,   17,   0),
566 			FboSpec(31,   31,   0),
567 			FboSpec(33,   33,   0),
568 			FboSpec(63,   63,   0),
569 			FboSpec(65,   65,   0),
570 			FboSpec(127,  127,  0),
571 			FboSpec(129,  129,  0),
572 			FboSpec(255,  255,  0),
573 			FboSpec(257,  257,  0),
574 			FboSpec(511,  511,  0),
575 			FboSpec(513,  513,  0),
576 			FboSpec(1023, 1023, 0),
577 			FboSpec(1025, 1025, 0),
578 			FboSpec(2047, 2047, 0),
579 
580 			// Non-square
581 			FboSpec(15,   511,  0),
582 			FboSpec(127,  15,   0),
583 			FboSpec(129,  127,  0),
584 			FboSpec(511,  127,  0),
585 			FboSpec(2047, 1025, 0),
586 		};
587 		tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "npot_size", "Basic functionality with Non-power-of-two size");
588 
589 		root->addChild(group);
590 
591 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(specs); caseNdx++)
592 		{
593 			const FboSpec&	spec = specs[caseNdx];
594 			stringstream	name;
595 
596 			name << spec.width << "x" << spec.height;
597 
598 			group->addChild(new SizeCase(testCtx, renderCtx, name.str().c_str(), name.str().c_str(), spec));
599 		}
600 	}
601 
602 	// Multisample
603 	{
604 		tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "multisample", "Basic functionality with multisampled fbo");
605 
606 		root->addChild(group);
607 
608 		for (int samples = 0; samples <= maxSamples; samples++)
609 		{
610 			const FboSpec	spec (128, 128, samples);
611 			stringstream	name;
612 
613 			name << "samples" << samples;
614 
615 			group->addChild(new SizeCase(testCtx, renderCtx, name.str().c_str(), name.str().c_str(), spec));
616 		}
617 	}
618 
619 	// Randomized
620 	{
621 		tcu::TestCaseGroup* const	group	= new tcu::TestCaseGroup(testCtx, "random", "Randomized size & multisampling");
622 		de::Random					rng		(0xF0E1E2D3 ^ testCtx.getCommandLine().getBaseSeed());
623 
624 		root->addChild(group);
625 
626 		for (int caseNdx = 0; caseNdx < 16; caseNdx++)
627 		{
628 			const int		width	= rng.getInt(1, maxWidth);
629 			const int		height	= rng.getInt(1, maxHeight);
630 			const int		samples = rng.getInt(0, maxSamples);
631 			const FboSpec	spec	(width, height, samples);
632 			const string	name	= de::toString(caseNdx);
633 
634 			group->addChild(new SizeCase(testCtx, renderCtx, name.c_str(), name.c_str(), spec));
635 		}
636 	}
637 
638 	// Normal fbo with defaults set
639 	{
640 		tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "interaction", "Interaction of default parameters with normal fbo");
641 
642 		root->addChild(group);
643 
644 		const FboSpec specs[][2] =
645 		{
646 			{ FboSpec(256,  256,  0), FboSpec(128,  128,  1) },
647 			{ FboSpec(256,  256,  1), FboSpec(128,  128,  0) },
648 			{ FboSpec(256,  256,  0), FboSpec(512,  512,  2) },
649 			{ FboSpec(256,  256,  2), FboSpec(128,  512,  0) },
650 			{ FboSpec(127,  127,  0), FboSpec(129,  129,  0) },
651 			{ FboSpec(17,   512,  4), FboSpec(16,   16,   2) },
652 			{ FboSpec(2048, 2048, 4), FboSpec(1,    1,    0) },
653 			{ FboSpec(1,    1,    0), FboSpec(2048, 2048, 4) },
654 		};
655 
656 		for (int specNdx = 0; specNdx < DE_LENGTH_OF_ARRAY(specs); specNdx++)
657 		{
658 			const FboSpec& baseSpec = specs[specNdx][0];
659 			const FboSpec& altSpec	= specs[specNdx][1];
660 			stringstream baseSpecName, altSpecName;
661 
662 			baseSpecName << baseSpec.width << "x" << baseSpec.height << "ms" << baseSpec.samples;
663 			altSpecName << altSpec.width << "x" << altSpec.height << "ms" << altSpec.samples;
664 
665 			{
666 				const string name = baseSpecName.str() + "_default_" + altSpecName.str();
667 
668 				group->addChild(new AttachmentInteractionCase(testCtx, renderCtx, name.c_str(), name.c_str(), altSpec, baseSpec));
669 			}
670 		}
671 	}
672 
673 	// Maximums
674 	{
675 		tcu::TestCaseGroup* const	group	= new tcu::TestCaseGroup(testCtx, "maximums", "Maximum dimensions");
676 
677 		root->addChild(group);
678 		group->addChild(new SizeCase(testCtx, renderCtx, "width",	"Maximum width",		  FboSpec(SizeCase::USE_MAXIMUM,	128,					0)));
679 		group->addChild(new SizeCase(testCtx, renderCtx, "height",	"Maximum height",		  FboSpec(128,						SizeCase::USE_MAXIMUM,  0)));
680 		group->addChild(new SizeCase(testCtx, renderCtx, "size",	"Maximum size",			  FboSpec(SizeCase::USE_MAXIMUM,	SizeCase::USE_MAXIMUM,  0)));
681 		group->addChild(new SizeCase(testCtx, renderCtx, "samples", "Maximum samples",		  FboSpec(128,						128,					SizeCase::USE_MAXIMUM)));
682 		group->addChild(new SizeCase(testCtx, renderCtx, "all",		"Maximum size & samples", FboSpec(SizeCase::USE_MAXIMUM,	SizeCase::USE_MAXIMUM,  SizeCase::USE_MAXIMUM)));
683 	}
684 
685 	return root;
686 }
687 
createFboNoAttachmentCompletenessTests(Context & context)688 tcu::TestCaseGroup* createFboNoAttachmentCompletenessTests(Context& context)
689 {
690 	TestCaseGroup* const group = new TestCaseGroup(context, "completeness", "Completeness tests");
691 
692 	group->addChild(new FramebufferCompletenessCase(context.getTestContext(), context.getRenderContext(), "no_attachments", "No attachments completeness"));
693 
694 	return group;
695 }
696 
697 } // Functional
698 } // gles31
699 } // deqp
700