xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fFboNoAttachmentTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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::string;
64 using std::stringstream;
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,
103                 size.y() * 2); // Oversized viewport so that it will not accidentally limit us to the correct size
104 
105     log << TestLog::Message << "Using " << size.x() * 2 << "x" << size.y() * 2 << " viewport" << TestLog::EndMessage;
106     log << TestLog::Message << "Discarding fragments outside pixel of interest" << TestLog::EndMessage;
107     log << TestLog::Message << "Using occlusion query to check for rendered fragments" << TestLog::EndMessage;
108 
109     TCU_CHECK(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
110 
111     // Render
112     {
113         const float data[] = {
114             1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
115         };
116 
117         GLuint vertexArray  = 0;
118         GLuint vertexBuffer = 0;
119 
120         gl.genQueries(1, &query);
121         gl.genVertexArrays(1, &vertexArray);
122         gl.bindVertexArray(vertexArray);
123 
124         gl.genBuffers(1, &vertexBuffer);
125         gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
126         gl.bufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
127 
128         gl.enableVertexAttribArray(0);
129         gl.vertexAttribPointer(0, 2, GL_FLOAT, false, 0, DE_NULL);
130 
131         gl.uniform2i(0, size.x() - 1, size.y() - 1);
132         gl.beginQuery(GL_ANY_SAMPLES_PASSED, query);
133         gl.drawArrays(GL_TRIANGLES, 0, 6);
134         gl.endQuery(GL_ANY_SAMPLES_PASSED);
135         gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &insidePassed);
136         log << TestLog::Message << "A fragment was not discarded at (" << size.x() - 1 << ", " << size.y() - 1 << "). "
137             << "Occlusion query reports it was " << (insidePassed > 0 ? "rendered." : "not rendered")
138             << TestLog::EndMessage;
139 
140         gl.uniform2i(0, size.x(), size.y() - 1);
141         gl.beginQuery(GL_ANY_SAMPLES_PASSED, query);
142         gl.drawArrays(GL_TRIANGLES, 0, 6);
143         gl.endQuery(GL_ANY_SAMPLES_PASSED);
144         gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &outsideXPassed);
145         log << TestLog::Message << "A fragment was not discarded at (" << size.x() << ", " << size.y() - 1 << "). "
146             << "Occlusion query reports it was " << (outsideXPassed > 0 ? "rendered." : "not rendered")
147             << TestLog::EndMessage;
148 
149         gl.uniform2i(0, size.x() - 1, size.y());
150         gl.beginQuery(GL_ANY_SAMPLES_PASSED, query);
151         gl.drawArrays(GL_TRIANGLES, 0, 6);
152         gl.endQuery(GL_ANY_SAMPLES_PASSED);
153         gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &outsideYPassed);
154         log << TestLog::Message << "A fragment was not discarded at (" << size.x() - 1 << ", " << size.y() << "). "
155             << "Occlusion query reports it was " << (outsideYPassed > 0 ? "rendered." : "not rendered")
156             << TestLog::EndMessage;
157 
158         gl.disableVertexAttribArray(0);
159         gl.bindBuffer(GL_ARRAY_BUFFER, 0);
160         gl.bindVertexArray(0);
161         gl.deleteBuffers(1, &vertexBuffer);
162         gl.deleteVertexArrays(1, &vertexArray);
163     }
164 
165     gl.deleteQueries(1, &query);
166 
167     GLU_EXPECT_NO_ERROR(gl.getError(), "Query failed");
168 
169     return insidePassed && !outsideXPassed && !outsideYPassed;
170 }
171 
checkFramebufferRenderable(TestLog & log,const glu::RenderContext & renderCtx,GLuint framebuffer,const IVec2 & size)172 bool checkFramebufferRenderable(TestLog &log, const glu::RenderContext &renderCtx, GLuint framebuffer,
173                                 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
208         << "Rendering full framebuffer quad with color ouput, verifying output presence with occlusion query"
209         << TestLog::EndMessage;
210 
211     // Render
212     {
213         const float data[] = {
214             1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
215         };
216 
217         GLuint vertexArray  = 0;
218         GLuint vertexBuffer = 0;
219 
220         gl.genQueries(1, &query);
221         gl.genVertexArrays(1, &vertexArray);
222         gl.bindVertexArray(vertexArray);
223 
224         gl.genBuffers(1, &vertexBuffer);
225         gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
226         gl.bufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
227 
228         gl.enableVertexAttribArray(0);
229         gl.vertexAttribPointer(0, 2, GL_FLOAT, false, 0, DE_NULL);
230 
231         gl.beginQuery(GL_ANY_SAMPLES_PASSED, query);
232         gl.drawArrays(GL_TRIANGLES, 0, 6);
233         gl.endQuery(GL_ANY_SAMPLES_PASSED);
234 
235         gl.disableVertexAttribArray(0);
236         gl.bindBuffer(GL_ARRAY_BUFFER, 0);
237         gl.bindVertexArray(0);
238         gl.deleteBuffers(1, &vertexBuffer);
239         gl.deleteVertexArrays(1, &vertexArray);
240     }
241 
242     // Read
243     {
244         GLuint passed = 0;
245 
246         gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &passed);
247         gl.deleteQueries(1, &query);
248 
249         GLU_EXPECT_NO_ERROR(gl.getError(), "Query failed");
250 
251         if (passed)
252             log << TestLog::Message << "Query passed" << TestLog::EndMessage;
253         else
254             log << TestLog::Message << "Query did not pass" << TestLog::EndMessage;
255 
256         return passed != 0;
257     }
258 }
259 
260 class FramebufferCompletenessCase : public tcu::TestCase
261 {
262 public:
263     FramebufferCompletenessCase(tcu::TestContext &testCtx, const glu::RenderContext &renderCtx, const char *name,
264                                 const char *desc);
~FramebufferCompletenessCase(void)265     virtual ~FramebufferCompletenessCase(void)
266     {
267     }
268     virtual IterateResult iterate(void);
269 
270 private:
271     const glu::RenderContext &m_renderCtx;
272     tcu::ResultCollector m_results;
273 };
274 
FramebufferCompletenessCase(tcu::TestContext & testCtx,const glu::RenderContext & renderCtx,const char * name,const char * desc)275 FramebufferCompletenessCase::FramebufferCompletenessCase(tcu::TestContext &testCtx, const glu::RenderContext &renderCtx,
276                                                          const char *name, const char *desc)
277     : TestCase(testCtx, name, desc)
278     , m_renderCtx(renderCtx)
279 {
280 }
281 
iterate(void)282 FramebufferCompletenessCase::IterateResult FramebufferCompletenessCase::iterate(void)
283 {
284     const glw::Functions &gl = m_renderCtx.getFunctions();
285     GLuint framebuffer       = 0;
286 
287     gl.genFramebuffers(1, &framebuffer);
288     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
289 
290     m_results.check(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
291                     "Framebuffer was incorrectly reported as complete when it had no width, height or attachments");
292 
293     gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 16);
294     m_results.check(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
295                     "Framebuffer was incorrectly reported as complete when it only had a width");
296 
297     gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 16);
298     m_results.check(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE,
299                     "Framebuffer not reported as complete when it had width and height set");
300 
301     gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
302     m_results.check(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
303                     "Framebuffer was incorrectly reported as complete when it only had a height");
304 
305     gl.deleteFramebuffers(1, &framebuffer);
306 
307     m_results.setTestContextResult(m_testCtx);
308     return STOP;
309 }
310 
311 struct FboSpec
312 {
313     int width;
314     int height;
315     int samples;
316 
FboSpecdeqp::gles31::Functional::__anonec4a052b0111::FboSpec317     FboSpec(int width_, int height_, int samples_) : width(width_), height(height_), samples(samples_)
318     {
319     }
320 };
321 
322 class SizeCase : public tcu::TestCase
323 {
324 public:
325     SizeCase(tcu::TestContext &testCtx, const glu::RenderContext &renderCtx, const char *name, const char *desc,
326              const FboSpec &spec);
~SizeCase(void)327     virtual ~SizeCase(void)
328     {
329     }
330 
331     virtual IterateResult iterate(void);
332 
333     enum
334     {
335         USE_MAXIMUM = -1
336     };
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, const glu::RenderContext &renderCtx, const char *name, const char *desc,
349                    const FboSpec &spec)
350     : TestCase(testCtx, name, desc)
351     , m_renderCtx(renderCtx)
352     , m_spec(spec)
353 {
354 }
355 
iterate(void)356 SizeCase::IterateResult SizeCase::iterate(void)
357 {
358     const glw::Functions &gl = m_renderCtx.getFunctions();
359     TestLog &log             = m_testCtx.getLog();
360     GLuint framebuffer       = 0;
361     const int width          = getWidth();
362     const int height         = getHeight();
363     int samples              = getSamples();
364 
365     for (;;)
366     {
367         gl.genFramebuffers(1, &framebuffer);
368         gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
369         gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, width);
370         gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, height);
371         gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, samples);
372 
373         GLenum status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
374         if (status == GL_FRAMEBUFFER_COMPLETE)
375             break;
376         else
377         {
378             gl.deleteFramebuffers(1, &framebuffer);
379             framebuffer = 0;
380 
381             if (status == GL_FRAMEBUFFER_UNSUPPORTED)
382                 if (samples >= 2)
383                     samples /= 2;
384                 else
385                     break;
386             else
387             {
388                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected no-attachment framebuffer status");
389                 return STOP;
390             }
391         }
392     }
393     if (!framebuffer)
394     {
395         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL,
396                                 "Unable to find a supported no-attachment framebuffer width/height/samples");
397         return STOP;
398     }
399 
400     log << TestLog::Message << "Verifying " << width << "x" << height << " framebuffer with " << samples
401         << "x multisampling" << TestLog::EndMessage;
402 
403     if (checkFramebufferRenderable(log, m_renderCtx, framebuffer, IVec2(width, height)) &&
404         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, const glu::RenderContext &renderCtx, const char *name,
463                               const char *desc, const FboSpec &defaultSpec, const FboSpec &attachmentSpec);
~AttachmentInteractionCase(void)464     virtual ~AttachmentInteractionCase(void)
465     {
466     }
467 
468     virtual IterateResult iterate(void);
469 
470 private:
471     const glu::RenderContext &m_renderCtx;
472     const FboSpec m_defaultSpec;
473     const FboSpec m_attachmentSpec;
474 };
475 
AttachmentInteractionCase(tcu::TestContext & testCtx,const glu::RenderContext & renderCtx,const char * name,const char * desc,const FboSpec & defaultSpec,const FboSpec & attachmentSpec)476 AttachmentInteractionCase::AttachmentInteractionCase(tcu::TestContext &testCtx, const glu::RenderContext &renderCtx,
477                                                      const char *name, const char *desc, const FboSpec &defaultSpec,
478                                                      const FboSpec &attachmentSpec)
479     : TestCase(testCtx, name, desc)
480     , m_renderCtx(renderCtx)
481     , m_defaultSpec(defaultSpec)
482     , m_attachmentSpec(attachmentSpec)
483 {
484 }
485 
iterate(void)486 AttachmentInteractionCase::IterateResult AttachmentInteractionCase::iterate(void)
487 {
488     const glw::Functions &gl = m_renderCtx.getFunctions();
489     TestLog &log             = m_testCtx.getLog();
490     GLuint framebuffer       = 0;
491     GLuint renderbuffer      = 0;
492 
493     gl.genFramebuffers(1, &framebuffer);
494     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
495     gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, m_defaultSpec.width);
496     gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, m_defaultSpec.height);
497     gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, m_defaultSpec.samples);
498 
499     gl.genRenderbuffers(1, &renderbuffer);
500     gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
501     gl.renderbufferStorageMultisample(GL_RENDERBUFFER, m_attachmentSpec.samples, GL_RGBA8, m_attachmentSpec.width,
502                                       m_attachmentSpec.height);
503     gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
504 
505     log << TestLog::Message << "Verifying " << m_attachmentSpec.width << "x" << m_attachmentSpec.height
506         << " framebuffer with " << m_attachmentSpec.samples << "x multisampling"
507         << " and defaults set to " << m_defaultSpec.width << "x" << m_defaultSpec.height << " with "
508         << m_defaultSpec.samples << "x multisampling" << TestLog::EndMessage;
509 
510     if (checkFramebufferRenderable(log, m_renderCtx, framebuffer,
511                                    IVec2(m_attachmentSpec.width, m_attachmentSpec.height)) &&
512         checkFramebufferSize(log, m_renderCtx, framebuffer, IVec2(m_attachmentSpec.width, m_attachmentSpec.height)))
513         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
514     else
515         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Framebuffer did not behave as expected");
516 
517     gl.deleteRenderbuffers(1, &renderbuffer);
518     gl.deleteFramebuffers(1, &framebuffer);
519 
520     return STOP;
521 }
522 
523 } // namespace
524 
createFboNoAttachmentTests(Context & context)525 tcu::TestCaseGroup *createFboNoAttachmentTests(Context &context)
526 {
527     const glu::RenderContext &renderCtx = context.getRenderContext();
528     tcu::TestContext &testCtx           = context.getTestContext();
529 
530     const int maxWidth   = 2048; // MAX_FRAMEBUFFER_WIDTH in ES 3.1
531     const int maxHeight  = 2048; // MAX_FRAMEBUFFER_HEIGHT in ES 3.1
532     const int maxSamples = 4;
533 
534     tcu::TestCaseGroup *const root =
535         new tcu::TestCaseGroup(testCtx, "no_attachments", "Framebuffer without attachments");
536 
537     // Size
538     {
539         tcu::TestCaseGroup *const group =
540             new tcu::TestCaseGroup(testCtx, "size", "Basic functionality tests with varying default size");
541 
542         root->addChild(group);
543 
544         for (int width = 16; width <= maxWidth; width *= 4)
545         {
546             for (int height = 16; height <= maxHeight; height *= 4)
547             {
548                 const FboSpec spec(width, height, 0);
549                 stringstream name;
550 
551                 name << width << "x" << height;
552 
553                 group->addChild(new SizeCase(testCtx, renderCtx, name.str().c_str(), name.str().c_str(), spec));
554             }
555         }
556     }
557 
558     // NPOT size
559     {
560         const FboSpec specs[] = {
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 =
588             new tcu::TestCaseGroup(testCtx, "npot_size", "Basic functionality with Non-power-of-two size");
589 
590         root->addChild(group);
591 
592         for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(specs); caseNdx++)
593         {
594             const FboSpec &spec = specs[caseNdx];
595             stringstream name;
596 
597             name << spec.width << "x" << spec.height;
598 
599             group->addChild(new SizeCase(testCtx, renderCtx, name.str().c_str(), name.str().c_str(), spec));
600         }
601     }
602 
603     // Multisample
604     {
605         tcu::TestCaseGroup *const group =
606             new tcu::TestCaseGroup(testCtx, "multisample", "Basic functionality with multisampled fbo");
607 
608         root->addChild(group);
609 
610         for (int samples = 0; samples <= maxSamples; samples++)
611         {
612             const FboSpec spec(128, 128, samples);
613             stringstream name;
614 
615             name << "samples" << samples;
616 
617             group->addChild(new SizeCase(testCtx, renderCtx, name.str().c_str(), name.str().c_str(), spec));
618         }
619     }
620 
621     // Randomized
622     {
623         tcu::TestCaseGroup *const group = new tcu::TestCaseGroup(testCtx, "random", "Randomized size & multisampling");
624         de::Random rng(0xF0E1E2D3 ^ testCtx.getCommandLine().getBaseSeed());
625 
626         root->addChild(group);
627 
628         for (int caseNdx = 0; caseNdx < 16; caseNdx++)
629         {
630             const int width   = rng.getInt(1, maxWidth);
631             const int height  = rng.getInt(1, maxHeight);
632             const int samples = rng.getInt(0, maxSamples);
633             const FboSpec spec(width, height, samples);
634             const string name = de::toString(caseNdx);
635 
636             group->addChild(new SizeCase(testCtx, renderCtx, name.c_str(), name.c_str(), spec));
637         }
638     }
639 
640     // Normal fbo with defaults set
641     {
642         tcu::TestCaseGroup *const group =
643             new tcu::TestCaseGroup(testCtx, "interaction", "Interaction of default parameters with normal fbo");
644 
645         root->addChild(group);
646 
647         const FboSpec specs[][2] = {
648             {FboSpec(256, 256, 0), FboSpec(128, 128, 1)}, {FboSpec(256, 256, 1), FboSpec(128, 128, 0)},
649             {FboSpec(256, 256, 0), FboSpec(512, 512, 2)}, {FboSpec(256, 256, 2), FboSpec(128, 512, 0)},
650             {FboSpec(127, 127, 0), FboSpec(129, 129, 0)}, {FboSpec(17, 512, 4), FboSpec(16, 16, 2)},
651             {FboSpec(2048, 2048, 4), FboSpec(1, 1, 0)},   {FboSpec(1, 1, 0), FboSpec(2048, 2048, 4)},
652         };
653 
654         for (int specNdx = 0; specNdx < DE_LENGTH_OF_ARRAY(specs); specNdx++)
655         {
656             const FboSpec &baseSpec = specs[specNdx][0];
657             const FboSpec &altSpec  = specs[specNdx][1];
658             stringstream baseSpecName, altSpecName;
659 
660             baseSpecName << baseSpec.width << "x" << baseSpec.height << "ms" << baseSpec.samples;
661             altSpecName << altSpec.width << "x" << altSpec.height << "ms" << altSpec.samples;
662 
663             {
664                 const string name = baseSpecName.str() + "_default_" + altSpecName.str();
665 
666                 group->addChild(
667                     new AttachmentInteractionCase(testCtx, renderCtx, name.c_str(), name.c_str(), altSpec, baseSpec));
668             }
669         }
670     }
671 
672     // Maximums
673     {
674         tcu::TestCaseGroup *const group = new tcu::TestCaseGroup(testCtx, "maximums", "Maximum dimensions");
675 
676         root->addChild(group);
677         group->addChild(
678             new SizeCase(testCtx, renderCtx, "width", "Maximum width", FboSpec(SizeCase::USE_MAXIMUM, 128, 0)));
679         group->addChild(
680             new SizeCase(testCtx, renderCtx, "height", "Maximum height", FboSpec(128, SizeCase::USE_MAXIMUM, 0)));
681         group->addChild(new SizeCase(testCtx, renderCtx, "size", "Maximum size",
682                                      FboSpec(SizeCase::USE_MAXIMUM, SizeCase::USE_MAXIMUM, 0)));
683         group->addChild(
684             new SizeCase(testCtx, renderCtx, "samples", "Maximum samples", FboSpec(128, 128, SizeCase::USE_MAXIMUM)));
685         group->addChild(new SizeCase(testCtx, renderCtx, "all", "Maximum size & samples",
686                                      FboSpec(SizeCase::USE_MAXIMUM, SizeCase::USE_MAXIMUM, SizeCase::USE_MAXIMUM)));
687     }
688 
689     return root;
690 }
691 
createFboNoAttachmentCompletenessTests(Context & context)692 tcu::TestCaseGroup *createFboNoAttachmentCompletenessTests(Context &context)
693 {
694     TestCaseGroup *const group = new TestCaseGroup(context, "completeness", "Completeness tests");
695 
696     group->addChild(new FramebufferCompletenessCase(context.getTestContext(), context.getRenderContext(),
697                                                     "no_attachments", "No attachments completeness"));
698 
699     return group;
700 }
701 
702 } // namespace Functional
703 } // namespace gles31
704 } // namespace deqp
705