xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/glcFramebufferCompleteness.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2021 Google Inc.
6  * Copyright (c) 2021 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file glcFramebuffercompleteness.cpp
22  * \brief Tests for OpenGL ES frame buffer completeness
23  *//*--------------------------------------------------------------------*/
24 #include "glcFramebufferCompleteness.hpp"
25 #include "deInt32.h"
26 #include "gluDefs.hpp"
27 #include "gluContextInfo.hpp"
28 #include "glwEnums.hpp"
29 #include "glwFunctions.hpp"
30 #include "tcuStringTemplate.hpp"
31 
32 #include <algorithm>
33 #include <functional>
34 #include <map>
35 #include <memory>
36 #include <sstream>
37 #include <string>
38 #include <vector>
39 
40 namespace glcts
41 {
42 namespace
43 {
44 
45 using namespace glw;
46 using namespace std;
47 
48 struct TestContext
49 {
50     const glu::RenderContext &renderContext;
51     const glw::Functions &gl;
52     vector<GLuint> &fboIds;
53     vector<GLuint> &texIds;
54     vector<GLuint> &rboIds;
55 
56     void texParameteri(GLuint texId, GLenum target, GLenum pname, GLint parameter);
57     void bindTexture(GLenum target, GLuint texId);
58     void texImage2D(GLenum target, GLuint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border,
59                     GLenum format, GLenum type, const void *data);
60     void texImage2D(GLuint texId, GLenum target, GLuint level, GLint internalFormat, GLsizei width, GLsizei height,
61                     GLint border, GLenum format, GLenum type, const void *data);
62     void texImage3D(GLuint texId, GLenum target, GLuint level, GLint internalFormat, GLsizei width, GLsizei height,
63                     GLsizei depth, GLint border, GLenum format, GLenum type, const void *data);
64     void renderbufferStorage(GLuint rboId, GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
65     void renderbufferStorageMultisample(GLuint rboId, GLenum target, GLsizei samples, GLenum internalFormat,
66                                         GLsizei width, GLsizei height);
67     void bindFramebuffer(GLenum target, GLuint fboId);
68     void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texId, GLint level);
69     void framebufferTextureLayer(GLenum target, GLenum attachment, GLuint texId, GLint level, GLint layer);
70     void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint rboId);
71 };
72 
texParameteri(GLuint texId,GLenum target,GLenum pname,GLint parameter)73 void TestContext::texParameteri(GLuint texId, GLenum target, GLenum pname, GLint parameter)
74 {
75     bindTexture(target, texId);
76     gl.texParameteri(target, pname, parameter);
77     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
78     bindTexture(target, 0);
79 }
80 
bindTexture(GLenum target,GLuint texId)81 void TestContext::bindTexture(GLenum target, GLuint texId)
82 {
83     gl.bindTexture(target, texId);
84     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed");
85 }
86 
texImage2D(GLenum target,GLuint level,GLint internalFormat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const void * data)87 void TestContext::texImage2D(GLenum target, GLuint level, GLint internalFormat, GLsizei width, GLsizei height,
88                              GLint border, GLenum format, GLenum type, const void *data)
89 {
90     gl.texImage2D(target, level, internalFormat, width, height, border, format, type, data);
91     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() failed");
92 }
93 
texImage2D(GLuint texId,GLenum target,GLuint level,GLint internalFormat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const void * data)94 void TestContext::texImage2D(GLuint texId, GLenum target, GLuint level, GLint internalFormat, GLsizei width,
95                              GLsizei height, GLint border, GLenum format, GLenum type, const void *data)
96 {
97     bindTexture(target, texId);
98     texImage2D(target, level, internalFormat, width, height, border, format, type, data);
99     bindTexture(target, 0);
100 }
101 
texImage3D(GLuint texId,GLenum target,GLuint level,GLint internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const void * data)102 void TestContext::texImage3D(GLuint texId, GLenum target, GLuint level, GLint internalFormat, GLsizei width,
103                              GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *data)
104 {
105     bindTexture(target, texId);
106     gl.texImage3D(target, level, internalFormat, width, height, depth, border, format, type, data);
107     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage3D() failed");
108     bindTexture(target, 0);
109 }
110 
renderbufferStorage(GLuint rboId,GLenum target,GLenum internalFormat,GLsizei width,GLsizei height)111 void TestContext::renderbufferStorage(GLuint rboId, GLenum target, GLenum internalFormat, GLsizei width, GLsizei height)
112 {
113     gl.bindRenderbuffer(GL_RENDERBUFFER, rboId);
114     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed");
115     gl.renderbufferStorage(target, internalFormat, width, height);
116     GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage() failed");
117     gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
118     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed");
119 }
120 
renderbufferStorageMultisample(GLuint rboId,GLenum target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height)121 void TestContext::renderbufferStorageMultisample(GLuint rboId, GLenum target, GLsizei samples, GLenum internalFormat,
122                                                  GLsizei width, GLsizei height)
123 {
124     gl.bindRenderbuffer(GL_RENDERBUFFER, rboId);
125     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed");
126     gl.renderbufferStorageMultisample(target, samples, internalFormat, width, height);
127     GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorageMultisample() failed");
128     gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
129     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed");
130 }
131 
bindFramebuffer(GLenum target,GLuint fboId)132 void TestContext::bindFramebuffer(GLenum target, GLuint fboId)
133 {
134     gl.bindFramebuffer(target, fboId);
135     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() failed");
136 }
137 
framebufferTexture2D(GLenum target,GLenum attachment,GLenum textarget,GLuint texId,GLint level)138 void TestContext::framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texId, GLint level)
139 {
140     gl.framebufferTexture2D(target, attachment, textarget, texId, level);
141     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed");
142 }
143 
framebufferTextureLayer(GLenum target,GLenum attachment,GLuint texId,GLint level,GLint layer)144 void TestContext::framebufferTextureLayer(GLenum target, GLenum attachment, GLuint texId, GLint level, GLint layer)
145 {
146     gl.framebufferTextureLayer(target, attachment, texId, level, layer);
147     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTextureLayer() failed");
148 }
149 
framebufferRenderbuffer(GLenum target,GLenum attachment,GLenum renderbuffertarget,GLuint rboId)150 void TestContext::framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint rboId)
151 {
152     gl.framebufferRenderbuffer(target, attachment, renderbuffertarget, rboId);
153     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer() failed");
154 }
155 
156 typedef function<GLenum(const glu::ContextInfo &contextInfo)> ExpectedStatusFn;
157 typedef function<void(TestContext &context)> TestFn;
158 
expectedStatusConstant(GLenum expectedStatus)159 ExpectedStatusFn expectedStatusConstant(GLenum expectedStatus)
160 {
161     return [expectedStatus](const glu::ContextInfo &) { return expectedStatus; };
162 }
163 
expectedStatusWithExtension(const string & extension,GLenum statusIfSupported,GLenum statusIfNotSupported)164 ExpectedStatusFn expectedStatusWithExtension(const string &extension, GLenum statusIfSupported,
165                                              GLenum statusIfNotSupported)
166 {
167     return [extension, statusIfSupported, statusIfNotSupported](const glu::ContextInfo &contextInfo)
168     {
169         if (contextInfo.isExtensionSupported(extension.c_str()))
170             return statusIfSupported;
171         else
172             return statusIfNotSupported;
173     };
174 }
175 
176 struct TestStep
177 {
178     TestFn testFn;
179     ExpectedStatusFn expectedFbStatus;
180 };
181 
182 typedef function<void(vector<TestStep> &, TestContext &context)> StepsGeneratorFn;
183 
184 struct ExtensionEntry
185 {
186     string name;
187     bool supportedStatus;
188 };
189 
190 struct TestParams
191 {
192     string name;
193     string description;
194     glu::ApiType apiType;
195     size_t numFboIds;
196     size_t numTexIds;
197     size_t numRboIds;
198     vector<TestStep> initialSteps;
199     StepsGeneratorFn stepsGenerator;
200 };
201 
202 const GLuint TEXTURE_WIDTH  = 16;
203 const GLuint TEXTURE_HEIGHT = 16;
204 const GLuint TEXTURE_DEPTH  = 16;
205 
206 static const GLenum cubemapTextureTargets[] = {GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
207                                                GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
208                                                GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Z};
209 
210 const glu::ApiType apiES30 = glu::ApiType::es(3, 0);
211 const glu::ApiType apiES31 = glu::ApiType::es(3, 1);
212 const glu::ApiType apiES32 = glu::ApiType::es(3, 2);
213 
isDifferentRboSampleCountsSupported(TestContext & testContext,GLint & maxSamples)214 bool isDifferentRboSampleCountsSupported(TestContext &testContext, GLint &maxSamples)
215 {
216     const auto &gl = testContext.gl;
217     gl.getIntegerv(GL_MAX_SAMPLES, &maxSamples);
218     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed");
219 
220     if (maxSamples < 4)
221         TCU_FAIL("GL_MAX_SAMPLES needs to be >= 4");
222 
223     testContext.renderbufferStorageMultisample(testContext.rboIds[0], GL_RENDERBUFFER, 1, GL_RGBA8, TEXTURE_WIDTH,
224                                                TEXTURE_HEIGHT);
225     gl.bindRenderbuffer(GL_RENDERBUFFER, testContext.rboIds[0]);
226     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed");
227 
228     GLint minSamplesRbo;
229     gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &minSamplesRbo);
230     GLU_EXPECT_NO_ERROR(gl.getError(), "getRenderbufferParameteriv() failed");
231     gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
232     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed");
233 
234     return minSamplesRbo < maxSamples;
235 }
236 
isDifferentTextureSampleCountsSupported(TestContext & testContext,GLint & maxSamples)237 bool isDifferentTextureSampleCountsSupported(TestContext &testContext, GLint &maxSamples)
238 {
239     if (glu::contextSupports(testContext.renderContext.getType(), apiES31))
240     {
241         const auto &gl = testContext.gl;
242         GLint maxColorSamples;
243         gl.getIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorSamples);
244         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed");
245 
246         GLint maxDepthSamples;
247         gl.getIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthSamples);
248         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed");
249 
250         maxSamples = min(maxColorSamples, maxDepthSamples);
251 
252         GLuint tempTexId;
253         gl.genTextures(1, &tempTexId);
254         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
255 
256         testContext.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, tempTexId);
257         gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_TRUE);
258         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() failed");
259 
260         GLint minSamplesTex;
261         gl.getTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &minSamplesTex);
262         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv() failed");
263 
264         testContext.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
265         gl.deleteTextures(1, &tempTexId);
266         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() failed");
267 
268         return minSamplesTex < maxSamples;
269     }
270     return false;
271 }
272 
273 /* Tests are defined as ordered series of steps that each expect a specific current framebuffer status
274    after being executed. A new TestContext instance (parameter) is created for each test but all steps
275    within a test use the same context. No code in addition to the framebuffer status check is executed
276    between steps. */
277 const TestParams tests[] = {
278     {
279         "incomplete_missing_attachment", // string                    name
280         "No attachments",                // string                    description
281         apiES30,                         // glu::ApiType                apiType
282         1,                               // size_t                    numFboIds
283         0,                               // size_t                    numTexIds
284         0,                               // size_t                    numRboIds
285         {                                // vector<TestStep>            initialSteps
__anon6da9912e0402() 286          {[](TestContext &context) { context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]); },
287           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)}},
288         DE_NULL, // StepsGeneratorFn            stepsGenerator
289     },
290     {
291         "incomplete_image_zero_width", // string                    name
292         "Zero width attachment image", // string                    description
293         apiES30,                       // glu::ApiType                apiType
294         1,                             // size_t                    numFboIds
295         1,                             // size_t                    numTexIds
296         0,                             // size_t                    numRboIds
297         {                              // vector<TestStep>            initialSteps
__anon6da9912e0502() 298          {[](TestContext &context) { context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]); },
299           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
300          {[](TestContext &context)
__anon6da9912e0602() 301           {
302               context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 0, TEXTURE_HEIGHT, 0,
303                                  GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, DE_NULL);
304               context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, context.texIds[0], 0);
305           },
306           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)}},
307         DE_NULL, // StepsGeneratorFn            stepsGenerator
308     },
309     {
310         "incomplete_image_zero_height", // string                    name
311         "Zero height attachment image", // string                    description
312         apiES30,                        // glu::ApiType                apiType
313         1,                              // size_t                    numFboIds
314         1,                              // size_t                    numTexIds
315         0,                              // size_t                    numRboIds
316         {                               // vector<TestStep>            initialSteps
__anon6da9912e0702() 317          {[](TestContext &context) { context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]); },
318           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
319          {[](TestContext &context)
__anon6da9912e0802() 320           {
321               context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 0, TEXTURE_WIDTH, 0,
322                                  GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, DE_NULL);
323               context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, context.texIds[0], 0);
324           },
325           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)}},
326         DE_NULL, // StepsGeneratorFn            stepsGenerator
327     },
328     {
329         "incomplete_texture_3d_layer_oob", // string                    name
330         "3D texture layer out of bounds",  // string                    description
331         apiES30,                           // glu::ApiType                apiType
332         1,                                 // size_t                    numFboIds
333         1,                                 // size_t                    numTexIds
334         0,                                 // size_t                    numRboIds
335         {                                  // vector<TestStep>            initialSteps
__anon6da9912e0902() 336          {[](TestContext &context) { context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]); },
337           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
338          {[](TestContext &context)
__anon6da9912e0a02() 339           {
340               context.texImage3D(context.texIds[0], GL_TEXTURE_3D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT,
341                                  TEXTURE_DEPTH, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
342               context.framebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, context.texIds[0], 0,
343                                               TEXTURE_DEPTH + 1);
344           },
345           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)}},
346         DE_NULL, // StepsGeneratorFn            stepsGenerator
347     },
348     {
349         "incomplete_texture_2d_layer_oob", // string                    name
350         "2D texture layer out of bounds",  // string                    description
351         apiES30,                           // glu::ApiType                apiType
352         1,                                 // size_t                    numFboIds
353         1,                                 // size_t                    numTexIds
354         0,                                 // size_t                    numRboIds
355         {                                  // vector<TestStep>            initialSteps
__anon6da9912e0b02() 356          {[](TestContext &context) { context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]); },
357           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
358          {[](TestContext &context)
__anon6da9912e0c02() 359           {
360               context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
361                                  GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
362               context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 1);
363           },
364           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)}},
365         DE_NULL, // StepsGeneratorFn            stepsGenerator
366     },
367     {
368         "incomplete_texture_2d_mm_layer_oob",       // string                    name
369         "2D mipmapped texture layer out of bounds", // string                    description
370         apiES30,                                    // glu::ApiType                apiType
371         1,                                          // size_t                    numFboIds
372         1,                                          // size_t                    numTexIds
373         0,                                          // size_t                    numRboIds
374         {
375             // vector<TestStep>            initialSteps
376             {[](TestContext &context)
__anon6da9912e0d02() 377              {
378                  context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
379                                        GL_LINEAR_MIPMAP_LINEAR);
380                  context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
381                  context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 1, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
382                                     GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
383                  context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
384              },
385              expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
__anon6da9912e0e02() 386             {[](TestContext &context) {
387                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0],
388                                               0);
389              },
390              expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)},
__anon6da9912e0f02() 391             {[](TestContext &context) {
392                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0],
393                                               1);
394              },
395              expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)},
396             {[](TestContext &context)
__anon6da9912e1002() 397              {
398                  const uint32_t maxMipmapLevel = deLog2Floor32(de::max(TEXTURE_WIDTH, TEXTURE_HEIGHT));
399                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0],
400                                               maxMipmapLevel + 2);
401              },
402              expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)},
403         },
404         DE_NULL, // StepsGeneratorFn            stepsGenerator
405     },
406     {
407         "mutable_nbl_texture_expect_mipmap_complete", // string                    name
408         "Mutable non base level texture as framebuffer attachment must be mipmap complete", // string                    description
409         apiES30, // glu::ApiType                apiType
410         1,       // size_t                    numFboIds
411         1,       // size_t                    numTexIds
412         0,       // size_t                    numRboIds
413         {        // vector<TestStep>            initialSteps
414          {[](TestContext &context)
__anon6da9912e1102() 415           {
416               DE_ASSERT(TEXTURE_WIDTH >= 8 && TEXTURE_HEIGHT >= 8);
417 
418               context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
419                                  GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
420               context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 1, GL_RGBA8, TEXTURE_WIDTH >> 1, TEXTURE_HEIGHT >> 1,
421                                  0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
422               context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 3, GL_RGBA8, TEXTURE_WIDTH >> 3, TEXTURE_HEIGHT >> 3,
423                                  0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
424               context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);
425               context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
426               context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
427           },
428           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
429          {[](TestContext &context)
__anon6da9912e1202() 430           { context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 1); },
431           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)},
432          {[](TestContext &context)
__anon6da9912e1302() 433           {
434               context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 2, GL_RGBA8, TEXTURE_WIDTH >> 2, TEXTURE_HEIGHT >> 2,
435                                  0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
436           },
437           expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)}},
438         DE_NULL, // StepsGeneratorFn            stepsGenerator
439     },
440     {
441         "mutable_nbl_texture_expect_cube_complete", // string                    name
442         "Mutable non base level texture as framebuffer attachment must be cube complete", // string                    description
443         apiES30, // glu::ApiType                apiType
444         1,       // size_t                    numFboIds
445         1,       // size_t                    numTexIds
446         0,       // size_t                    numRboIds
447         {        // vector<TestStep>            initialSteps
__anon6da9912e1402() 448          {[](TestContext &context) { context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]); },
449           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
450          {[](TestContext &context)
__anon6da9912e1502() 451           {
452               context.texParameteri(context.texIds[0], GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 1);
453               context.texParameteri(context.texIds[0], GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,
454                                     GL_LINEAR_MIPMAP_LINEAR);
455 
456               context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]);
457               for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(cubemapTextureTargets); ++i)
458               {
459                   if (i % 2)
460                       continue;
461                   context.texImage2D(cubemapTextureTargets[i], 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA,
462                                      GL_UNSIGNED_BYTE, DE_NULL);
463                   context.texImage2D(cubemapTextureTargets[i], 1, GL_RGBA8, TEXTURE_WIDTH >> 1, TEXTURE_HEIGHT >> 1, 0,
464                                      GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
465               }
466               context.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
467 
468               context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubemapTextureTargets[0],
469                                            context.texIds[0], 1);
470           },
471           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)},
472          {[](TestContext &context)
__anon6da9912e1602() 473           {
474               context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]);
475               for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(cubemapTextureTargets); ++i)
476               {
477                   if (i % 2 == 0)
478                       continue;
479                   context.texImage2D(cubemapTextureTargets[i], 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA,
480                                      GL_UNSIGNED_BYTE, DE_NULL);
481                   context.texImage2D(cubemapTextureTargets[i], 1, GL_RGBA8, TEXTURE_WIDTH >> 1, TEXTURE_HEIGHT >> 1, 0,
482                                      GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
483               }
484               context.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
485           },
486           expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)}},
487         DE_NULL, // StepsGeneratorFn            stepsGenerator
488     },
489     {
490         "expect_renderable_internal_format",                                     // string                    name
491         "Color/Depth/Stencil attachment texture must have a color/depth/stencil" // string                    description
492         " renderable internal format",
493         apiES30, // glu::ApiType                apiType
494         1,       // size_t                    numFboIds
495         3,       // size_t                    numTexIds
496         0,       // size_t                    numRboIds
497         {        // vector<TestStep>            initialSteps
498          {[](TestContext &context)
__anon6da9912e1702() 499           {
500               context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
501                                  GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
502               context.texImage2D(context.texIds[1], GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, TEXTURE_WIDTH,
503                                  TEXTURE_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, DE_NULL);
504               context.texImage2D(context.texIds[2], GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, TEXTURE_WIDTH,
505                                  TEXTURE_HEIGHT, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, DE_NULL);
506               context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
507           },
508           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
509          {[](TestContext &context)
__anon6da9912e1802() 510           { context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, context.texIds[0], 0); },
511           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)},
512          {[](TestContext &context)
__anon6da9912e1902() 513           { context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, context.texIds[1], 0); },
514           expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)},
__anon6da9912e1a02() 515          {[](TestContext &context) {
516               context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
517                                            context.texIds[0], 0);
518           },
519           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)},
__anon6da9912e1b02() 520          {[](TestContext &context) {
521               context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
522                                            context.texIds[2], 0);
523           },
524           expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)}},
525         [](vector<TestStep> &steps, TestContext &testContext) // StepsGeneratorFn            stepsGenerator
__anon6da9912e1c02() 526         {
527             GLint maxColorAttachmentsCount;
528             testContext.gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachmentsCount);
529             GLU_EXPECT_NO_ERROR(testContext.gl.getError(), "glGetInteger() failed");
530 
531             steps.reserve(steps.size() + 2 * maxColorAttachmentsCount);
532             for (GLint i = 0; i < maxColorAttachmentsCount; ++i)
533             {
534                 steps.push_back({[i](TestContext &context) {
535                                      context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
536                                                                   GL_TEXTURE_2D, context.texIds[1], 0);
537                                  },
538                                  expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)});
539                 steps.push_back({[i](TestContext &context) {
540                                      context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
541                                                                   GL_TEXTURE_2D, context.texIds[0], 0);
542                                  },
543                                  expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)});
544             }
545         },
546     },
547     {
548         "all_rbos_expect_same_numsamples",                                   // string                    name
549         "Same value of FRAMEBUFFER_SAMPLES for all attached render buffers", // string                    description
550         apiES30,                                                             // glu::ApiType                apiType
551         1,                                                                   // size_t                    numFboIds
552         0,                                                                   // size_t                    numTexIds
553         2,                                                                   // size_t                    numRboIds
554         {},                                                                  // vector<TestStep>            initialSteps
555         [](vector<TestStep> &steps, TestContext &testContext) // StepsGeneratorFn            stepsGenerator
__anon6da9912e1f02() 556         {
557             GLint maxSamples;
558             if (!isDifferentRboSampleCountsSupported(testContext, maxSamples))
559                 return;
560 
561             steps.push_back({[](TestContext &context) { context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]); },
562                              expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)});
563             steps.push_back({[](TestContext &context)
564                              {
565                                  context.renderbufferStorage(context.rboIds[0], GL_RENDERBUFFER, GL_RGBA8,
566                                                              TEXTURE_WIDTH, TEXTURE_HEIGHT);
567                                  context.renderbufferStorage(context.rboIds[1], GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
568                                                              TEXTURE_WIDTH, TEXTURE_HEIGHT);
569 
570                                  context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
571                                                                  context.rboIds[0]);
572                                  context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
573                                                                  GL_RENDERBUFFER, context.rboIds[1]);
574                              },
575                              expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)});
576             steps.push_back({[maxSamples](TestContext &context)
577                              {
578                                  context.renderbufferStorageMultisample(context.rboIds[0], GL_RENDERBUFFER, maxSamples,
579                                                                         GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
580                                  context.renderbufferStorageMultisample(context.rboIds[1], GL_RENDERBUFFER, 1,
581                                                                         GL_DEPTH24_STENCIL8, TEXTURE_WIDTH,
582                                                                         TEXTURE_HEIGHT);
583                              },
584                              expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)});
585         },
586     },
587     {
588         "rbo_and_texture_expect_zero_numsamples",                             // string                    name
589         "When using mixed renderbuffer and texture attachments, the value of" // string                    description
590         " FRAMEBUFFER_SAMPLES needs to be zero for all attached renderbuffers",
591         apiES30, // glu::ApiType                apiType
592         1,       // size_t                    numFboIds
593         2,       // size_t                    numTexIds
594         2,       // size_t    u                numRboIds
595         {        // vector<TestStep>            initialSteps
__anon6da9912e2302() 596          {[](TestContext &context) { context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]); },
597           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
598          {[](TestContext &context)
__anon6da9912e2402() 599           {
600               context.renderbufferStorage(context.rboIds[0], GL_RENDERBUFFER, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
601               context.texImage2D(context.texIds[1], GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, TEXTURE_WIDTH,
602                                  TEXTURE_HEIGHT, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, DE_NULL);
603 
604               context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, context.rboIds[0]);
605               context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
606                                            context.texIds[1], 0);
607           },
608           expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)},
609          {[](TestContext &context)
__anon6da9912e2502() 610           {
611               context.renderbufferStorage(context.rboIds[1], GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, TEXTURE_WIDTH,
612                                           TEXTURE_HEIGHT);
613               context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
614                                  GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
615 
616               context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 0);
617               context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
618                                               context.rboIds[1]);
619           },
620           expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)},
621          {[](TestContext &context)
__anon6da9912e2602() 622           {
623               context.renderbufferStorageMultisample(context.rboIds[1], GL_RENDERBUFFER, 2, GL_DEPTH24_STENCIL8,
624                                                      TEXTURE_WIDTH, TEXTURE_HEIGHT);
625           },
626           expectedStatusWithExtension("GL_NV_framebuffer_mixed_samples", GL_FRAMEBUFFER_COMPLETE,
627                                       GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)},
628          {[](TestContext &context)
__anon6da9912e2702() 629           {
630               context.renderbufferStorageMultisample(context.rboIds[0], GL_RENDERBUFFER, 3, GL_RGBA8, TEXTURE_WIDTH,
631                                                      TEXTURE_HEIGHT);
632 
633               context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, context.rboIds[0]);
634               context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
635                                            context.texIds[1], 0);
636           },
637           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)},
638          {[](TestContext &context)
__anon6da9912e2802() 639           {
640               context.renderbufferStorageMultisample(context.rboIds[0], GL_RENDERBUFFER, 0, GL_RGBA8, TEXTURE_WIDTH,
641                                                      TEXTURE_HEIGHT);
642           },
643           expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)}},
644         DE_NULL, // StepsGeneratorFn            stepsGenerator
645     },
646     {
647         "expect_equal_numsamples",                                     // string                    name
648         "The value of samples for each attached target must be equal", // string                    description
649         apiES31,                                                       // glu::ApiType                apiType
650         1,                                                             // size_t                    numFboIds
651         4,                                                             // size_t                    numTexIds
652         2,                                                             // size_t                    numRboIds
653         {},                                                            // vector<TestStep>            initialSteps
654         [](vector<TestStep> &steps, TestContext &testContext)          // StepsGeneratorFn            stepsGenerator
__anon6da9912e2902() 655         {
656             GLint maxRboSamples, maxTextureSamples;
657             if (!isDifferentRboSampleCountsSupported(testContext, maxRboSamples) ||
658                 !isDifferentTextureSampleCountsSupported(testContext, maxTextureSamples))
659                 return;
660 
661             steps.push_back(
662                 {[maxRboSamples, maxTextureSamples](TestContext &context)
663                  {
664                      // Set up textures and renderbuffers for all following steps, complete = (tex0, rbo1) or (tex1, rbo0) */
665                      context.renderbufferStorageMultisample(context.rboIds[0], GL_RENDERBUFFER, maxRboSamples, GL_RGBA8,
666                                                             TEXTURE_WIDTH, TEXTURE_HEIGHT);
667                      context.renderbufferStorageMultisample(context.rboIds[1], GL_RENDERBUFFER, 1, GL_DEPTH24_STENCIL8,
668                                                             TEXTURE_WIDTH, TEXTURE_HEIGHT);
669 
670                      const auto &gl = context.gl;
671                      context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, context.texIds[0]);
672                      gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT,
673                                                 GL_TRUE);
674                      GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() failed");
675 
676                      context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, context.texIds[1]);
677                      gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_DEPTH24_STENCIL8, TEXTURE_WIDTH,
678                                                 TEXTURE_HEIGHT, GL_TRUE);
679                      GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() failed");
680 
681                      context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, context.texIds[2]);
682                      gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxTextureSamples, GL_RGBA8, TEXTURE_WIDTH,
683                                                 TEXTURE_HEIGHT, GL_TRUE);
684                      GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() failed");
685 
686                      context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, context.texIds[3]);
687                      gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxTextureSamples, GL_DEPTH24_STENCIL8,
688                                                 TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_TRUE);
689                      GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() failed");
690 
691                      context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
692 
693                      // Framebuffer binding for rest of this test
694                      context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
695                  },
696                  expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)});
697             steps.push_back({[](TestContext &context)
698                              {
699                                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
700                                                               GL_TEXTURE_2D_MULTISAMPLE, context.texIds[0], 0);
701                                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
702                                                               GL_TEXTURE_2D_MULTISAMPLE, context.texIds[1], 0);
703                              },
704                              expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)});
705             steps.push_back({[](TestContext &context)
706                              {
707                                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
708                                                               GL_TEXTURE_2D_MULTISAMPLE, context.texIds[3], 0);
709                              },
710                              expectedStatusWithExtension("GL_NV_framebuffer_mixed_samples", GL_FRAMEBUFFER_COMPLETE,
711                                                          GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)});
712             steps.push_back({[](TestContext &context) {
713                                  context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
714                                                                  GL_RENDERBUFFER, context.rboIds[1]);
715                              },
716                              expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)});
717             steps.push_back({[](TestContext &context) {
718                                  context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
719                                                                  context.rboIds[0]);
720                              },
721                              expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)});
722             steps.push_back({[](TestContext &context)
723                              {
724                                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
725                                                               GL_TEXTURE_2D_MULTISAMPLE, context.texIds[2], 0);
726                                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
727                                                               GL_TEXTURE_2D_MULTISAMPLE, context.texIds[3], 0);
728                              },
729                              expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)});
730             steps.push_back({[](TestContext &context)
731                              {
732                                  const auto &gl = context.gl;
733                                  gl.deleteTextures(1, &context.texIds[0]);
734                                  GLU_EXPECT_NO_ERROR(context.gl.getError(), "glDeleteTextures() failed");
735                                  gl.genTextures(1, &context.texIds[0]);
736                                  GLU_EXPECT_NO_ERROR(context.gl.getError(), "glGenTextures() failed");
737                                  context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, context.texIds[0]);
738                                  gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, TEXTURE_WIDTH,
739                                                             TEXTURE_HEIGHT, GL_FALSE);
740                                  GLU_EXPECT_NO_ERROR(context.gl.getError(), "glTexStorage2DMultisample() failed");
741                                  context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
742                                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
743                                                               GL_TEXTURE_2D_MULTISAMPLE, context.texIds[0], 0);
744                                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
745                                                               GL_TEXTURE_2D_MULTISAMPLE, context.texIds[1], 0);
746                              },
747                              expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)});
748         }, // StepsGeneratorFn            stepsGenerator
749     },
750     {
751         "status_tracking",                                                         // string                    name
752         "Modifying framebuffer attached objects correctly updates the fbo status", // string                    description
753         apiES30, // glu::ApiType                apiType
754         3,       // size_t                    numFboIds
755         2,       // size_t                    numTexIds
756         1,       // size_t                    numRboIds
757         {        // vector<TestStep>            initialSteps
758          {       // Initial status -> missing_attachment
__anon6da9912e3102() 759           [](TestContext &context) { context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]); },
760           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
761          {// Allocate and attach texture -> complete
762           [](TestContext &context)
__anon6da9912e3202() 763           {
764               context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
765                                  GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
766               context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 0);
767           },
768           expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)},
769          {// Detach texture from fbo -> missing_attachment
770           [](TestContext &context)
__anon6da9912e3302() 771           { context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); },
772           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
773          {// Allocate and attach renderbuffer -> complete
774           [](TestContext &context)
__anon6da9912e3402() 775           {
776               context.renderbufferStorage(context.rboIds[0], GL_RENDERBUFFER, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
777               context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, context.rboIds[0]);
778           },
779           expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)},
780          {// Detach renderbuffer -> incomplete
781           [](TestContext &context)
__anon6da9912e3502() 782           { context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); },
783           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
784          {// Switch to incomplete fb -> missing_attachment
__anon6da9912e3602() 785           [](TestContext &context) { context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[1]); },
786           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
787          {// Attach texture to fbo -> complete
788           [](TestContext &context)
__anon6da9912e3702() 789           { context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 0); },
790           expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)},
791          {// Change image format of attached texture -> incomplete_attachment
792           [](TestContext &context)
__anon6da9912e3802() 793           {
794               context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, TEXTURE_WIDTH,
795                                  TEXTURE_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, DE_NULL);
796           },
797           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)},
798          {// Change image format (tex storage) -> complete
799           [](TestContext &context)
__anon6da9912e3902() 800           {
801               context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
802               context.gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
803               GLU_EXPECT_NO_ERROR(context.gl.getError(), "glTexStorage2D() failed");
804               context.bindTexture(GL_TEXTURE_2D, 0);
805           },
806           expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)},
807          {// Delete image -> missing_attachment
808           [](TestContext &context)
__anon6da9912e3a02() 809           {
810               context.gl.deleteTextures(1, &context.texIds[0]);
811               GLU_EXPECT_NO_ERROR(context.gl.getError(), "glDeleteTextures() failed");
812               context.texIds.erase(context.texIds.begin());
813           },
814           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)},
815          {// Recreate image in wrong format, attach to color attachment -> incomplete_attachment
816           [](TestContext &context)
__anon6da9912e3b02() 817           {
818               const auto &gl = context.gl;
819               GLuint texId;
820               gl.genTextures(1, &texId);
821               GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
822               context.texIds.push_back(texId);
823 
824               context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
825               context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, TEXTURE_WIDTH,
826                                  TEXTURE_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, DE_NULL);
827               context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 0);
828           },
829           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)},
830          {// Format to rgba8 using copyTexImage2D from compatible fbo -> framebuffer_complete
831           [](TestContext &context)
__anon6da9912e3c02() 832           {
833               context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[2]);
834               context.texImage2D(context.texIds[1], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
835                                  GL_RGBA, GL_UNSIGNED_BYTE, 0);
836               context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[1], 0);
837 
838               context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
839               const auto &gl = context.gl;
840               gl.copyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0);
841               GLU_EXPECT_NO_ERROR(gl.getError(), "glCopyTexImage2D() failed");
842 
843               context.bindTexture(GL_TEXTURE_2D, 0);
844               context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
845           },
846           expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)},
847          {// Change currently attached texture's format to compressed tex image -> incomplete_attachment (non color renderable)
848           [](TestContext &context)
__anon6da9912e3d02() 849           {
850               DE_ASSERT(TEXTURE_WIDTH == 16 && TEXTURE_HEIGHT == 16);
851               static const glw::GLubyte textureDataETC2[] = // 16x16 all black RGBA8 texture in ETC2 format
852                   {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
853                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
854                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
855                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
856                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
857                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
858                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
859                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
860                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
861                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
862                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
863                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
864                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
865                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
866                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
867                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00};
868               const auto &gl = context.gl;
869               context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
870 
871               gl.compressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA8_ETC2_EAC, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
872                                       DE_LENGTH_OF_ARRAY(textureDataETC2), textureDataETC2);
873               GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed");
874 
875               context.bindTexture(GL_TEXTURE_2D, 0);
876           },
877           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)},
878          {// Re-attach rbo0 -> complete
__anon6da9912e3e02() 879           [](TestContext &context) {
880               context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, context.rboIds[0]);
881           },
882           expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)},
883          {// Rbo storage to non renderable format -> incomplete_attachment
884           [](TestContext &context)
__anon6da9912e3f02() 885           {
886               context.renderbufferStorage(context.rboIds[0], GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, TEXTURE_WIDTH,
887                                           TEXTURE_HEIGHT);
888           },
889           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)},
890          {// Delete rbo -> missing_attachment
891           [](TestContext &context)
__anon6da9912e4002() 892           {
893               context.gl.deleteRenderbuffers(1, &context.rboIds[0]);
894               GLU_EXPECT_NO_ERROR(context.gl.getError(), "glDeleteRenderbuffers() failed");
895               context.rboIds.erase(context.rboIds.begin());
896           },
897           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)}},
898         DE_NULL, // StepsGeneratorFn            stepsGenerator
899     },
900     {"mutable_texture_missing_attachment_level", // string                    name
901      "Attaching a mutable texture with undefined image for attachment level"
902      " should be invalid",                      // string                    description
903      apiES30,                                   // glu::ApiType                apiType
904      1,                                         // size_t                    numFboIds
905      1,                                         // size_t                    numTexIds
906      0,                                         // size_t                    numRboIds
907      {},                                        // vector<TestStep>            initialSteps
908      [](vector<TestStep> &steps, TestContext &) // StepsGeneratorFn            stepsGenerator
__anon6da9912e4102() 909      {
910          DE_ASSERT(TEXTURE_WIDTH >= 16 && TEXTURE_HEIGHT >= 16);
911          steps.push_back({[](TestContext &context) { context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]); },
912                           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)});
913          steps.push_back({
914              [](TestContext &context)
915              {
916                  context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
917                                        GL_LINEAR_MIPMAP_LINEAR);
918                  context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
919                                     GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
920                  context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 1, GL_RGBA8, TEXTURE_WIDTH >> 1,
921                                     TEXTURE_HEIGHT >> 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
922                  context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 3, GL_RGBA8, TEXTURE_WIDTH >> 3,
923                                     TEXTURE_HEIGHT >> 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
924 
925                  context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
926 
927                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0],
928                                               2);
929              },
930              expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
931          });
932      }},
933     {"immutable_texture_any_level_as_attachment",                    // string                    name
934      "Any level of immutable texture as attachment should be valid", // string                    description
935      apiES30,                                                        // glu::ApiType                apiType
936      1,                                                              // size_t                    numFboIds
937      1,                                                              // size_t                    numTexIds
938      0,                                                              // size_t                    numRboIds
939      {},                                                             // vector<TestStep>            initialSteps
940      [](vector<TestStep> &steps, TestContext &)                      // StepsGeneratorFn            stepsGenerator
__anon6da9912e4402() 941      {
942          DE_ASSERT(TEXTURE_WIDTH >= 8 && TEXTURE_HEIGHT >= 8);
943          steps.push_back({[](TestContext &context) { context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]); },
944                           expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)});
945          steps.push_back({
946              [](TestContext &context)
947              {
948                  context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
949                                        GL_LINEAR_MIPMAP_LINEAR);
950                  context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
951                  const auto &gl = context.gl;
952                  gl.texStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
953                  GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() failed");
954                  context.bindTexture(GL_TEXTURE_2D, 0);
955 
956                  context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
957 
958                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0],
959                                               2);
960              },
961              expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE),
962          });
963          steps.push_back({
964              [](TestContext &context) {
965                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0],
966                                               1);
967              },
968              expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE),
969          });
970          steps.push_back({
971              [](TestContext &context) {
972                  context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0],
973                                               0);
974              },
975              expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE),
976          });
977      }},
978     {
979         "cube_map_layered_attachment_valid_size_and_format", // string                    name
980         "Cube map attachment with images of same size, same format and square should be valid", // string                    description
981         apiES32, // glu::ApiType                apiType
982         1,       // size_t                    numFboIds
983         1,       // size_t                    numTexIds
984         0,       // size_t                    numRboIds
985         {        // vector<TestStep>            initialSteps
986          {
987              [](TestContext &context)
__anon6da9912e4902() 988              {
989                  context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]);
990                  for (const auto target : cubemapTextureTargets)
991                      context.texImage2D(target, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA,
992                                         GL_UNSIGNED_BYTE, 0);
993                  context.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
994 
995                  context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
996                  context.gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, context.texIds[0], 0);
997                  GLU_EXPECT_NO_ERROR(context.gl.getError(), "glFramebufferTexture() failed");
998              },
999              expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE),
1000          }},
1001         DE_NULL, // StepsGeneratorFn            stepsGenerator
1002     },
1003     {
1004         "cube_map_layered_attachment_different_formats", // string                    name
1005         "Cube map attachment with images of the same size, square but different formats"
1006         " should be incomplete", // string                    description
1007         apiES32,                 // glu::ApiType                apiType
1008         1,                       // size_t                    numFboIds
1009         1,                       // size_t                    numTexIds
1010         0,                       // size_t                    numRboIds
1011         {                        // vector<TestStep>            initialSteps
1012          {
1013              [](TestContext &context)
__anon6da9912e4a02() 1014              {
1015                  context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]);
1016                  for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(cubemapTextureTargets); ++i)
1017                      context.texImage2D(cubemapTextureTargets[i], 0, (i % 2) ? GL_RGBA8 : GL_RGB8, TEXTURE_WIDTH,
1018                                         TEXTURE_HEIGHT, 0, (i % 2) ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, 0);
1019                  context.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
1020 
1021                  context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
1022                  context.gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, context.texIds[0], 0);
1023                  GLU_EXPECT_NO_ERROR(context.gl.getError(), "glFramebufferTexture() failed");
1024              },
1025              expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
1026          },
1027          {
1028              [](TestContext &context)
__anon6da9912e4b02() 1029              {
1030                  context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]);
1031                  for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(cubemapTextureTargets); ++i)
1032                      context.texImage2D(cubemapTextureTargets[i], 0, (i % 2) ? GL_RGBA8 : GL_SRGB8_ALPHA8,
1033                                         TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1034                  context.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
1035 
1036                  context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
1037                  context.gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, context.texIds[0], 0);
1038                  GLU_EXPECT_NO_ERROR(context.gl.getError(), "glFramebufferTexture() failed");
1039              },
1040              expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
1041          }},
1042         DE_NULL, // StepsGeneratorFn            stepsGenerator
1043     },
1044     {
1045         "cube_map_layered_attachment_different_sizes", // string                    name
1046         "Cube map with images of different sizes, same format and all square should"
1047         " be incomplete", // string                    description
1048         apiES32,          // glu::ApiType                apiType
1049         1,                // size_t                    numFboIds
1050         1,                // size_t                    numTexIds
1051         0,                // size_t                    numRboIds
1052         {
1053             // vector<TestStep>            initialSteps
1054             {
1055                 [](TestContext &context)
__anon6da9912e4c02() 1056                 {
1057                     context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]);
1058                     for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(cubemapTextureTargets); ++i)
1059                         context.texImage2D(
1060                             cubemapTextureTargets[i], 0, GL_RGBA8, (i % 2) ? TEXTURE_WIDTH : TEXTURE_WIDTH / 2,
1061                             (i % 2) ? TEXTURE_HEIGHT : TEXTURE_HEIGHT / 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1062                     context.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
1063 
1064                     context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
1065                     context.gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, context.texIds[0], 0);
1066                     GLU_EXPECT_NO_ERROR(context.gl.getError(), "glFramebufferTexture() failed");
1067                 },
1068                 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
1069             },
1070         },
1071         DE_NULL, // StepsGeneratorFn            stepsGenerator
1072     }};
1073 
1074 class FramebufferCompletenessTestCase : public deqp::TestCase
1075 {
1076 public:
1077     FramebufferCompletenessTestCase(deqp::Context &context, const TestParams &params);
1078     virtual ~FramebufferCompletenessTestCase();
1079 
1080     virtual void init(void);
1081     virtual void deinit(void);
1082     TestNode::IterateResult iterate(void);
1083 
1084 private:
1085     bool verifyFramebufferStatus(const glw::Functions &gl, const ExpectedStatusFn expectedStatusFn,
1086                                  const size_t stepIndex);
1087 
1088     const TestParams m_params;
1089     vector<GLuint> m_fboIds;
1090     vector<GLuint> m_texIds;
1091     vector<GLuint> m_rboIds;
1092 };
1093 
FramebufferCompletenessTestCase(deqp::Context & context,const TestParams & params)1094 FramebufferCompletenessTestCase::FramebufferCompletenessTestCase(deqp::Context &context, const TestParams &params)
1095     : deqp::TestCase(context, params.name.c_str(), params.description.c_str())
1096     , m_params(params)
1097 {
1098 }
1099 
~FramebufferCompletenessTestCase()1100 FramebufferCompletenessTestCase::~FramebufferCompletenessTestCase()
1101 {
1102 }
1103 
init(void)1104 void FramebufferCompletenessTestCase::init(void)
1105 {
1106     const auto &renderContext = m_context.getRenderContext();
1107     const auto &gl            = renderContext.getFunctions();
1108 
1109     if (m_params.numFboIds > 0)
1110     {
1111         m_fboIds.resize(m_params.numFboIds);
1112         gl.genFramebuffers((glw::GLsizei)m_params.numFboIds, m_fboIds.data());
1113         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed");
1114     }
1115     if (m_params.numTexIds > 0)
1116     {
1117         m_texIds.resize(m_params.numTexIds);
1118         gl.genTextures((glw::GLsizei)m_params.numTexIds, m_texIds.data());
1119         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
1120     }
1121     if (m_params.numRboIds > 0)
1122     {
1123         m_rboIds.resize(m_params.numRboIds);
1124         gl.genRenderbuffers((glw::GLsizei)m_params.numRboIds, m_rboIds.data());
1125         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers() failed");
1126     }
1127 }
1128 
deinit(void)1129 void FramebufferCompletenessTestCase::deinit(void)
1130 {
1131     const auto &renderContext = m_context.getRenderContext();
1132     const auto &gl            = renderContext.getFunctions();
1133 
1134     if (!m_rboIds.empty())
1135     {
1136         gl.deleteRenderbuffers((glw::GLsizei)m_params.numRboIds, m_rboIds.data());
1137         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteRenderbuffers() failed");
1138         m_rboIds.clear();
1139     }
1140     if (!m_texIds.empty())
1141     {
1142         gl.deleteTextures((glw::GLsizei)m_params.numTexIds, m_texIds.data());
1143         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() failed");
1144         m_texIds.clear();
1145     }
1146     if (!m_fboIds.empty())
1147     {
1148         gl.deleteFramebuffers((glw::GLsizei)m_params.numFboIds, m_fboIds.data());
1149         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebufers() failed");
1150         m_fboIds.clear();
1151     }
1152 }
1153 
iterate(void)1154 tcu::TestNode::IterateResult FramebufferCompletenessTestCase::iterate(void)
1155 {
1156     const auto &renderContext = m_context.getRenderContext();
1157     const auto &gl            = renderContext.getFunctions();
1158     TestContext context       = {
1159         renderContext, // const glu::RenderContext&    renderContext
1160         gl,            // const glw::Functions&        gl
1161         m_fboIds,      // vector<GLuint>&                fboIds
1162         m_texIds,      // vector<GLuint>&                texIds
1163         m_rboIds       // vector<GLuint>&                rboIds
1164     };
1165     auto steps = vector<TestStep>(m_params.initialSteps);
1166     if (m_params.stepsGenerator != DE_NULL)
1167         m_params.stepsGenerator(steps, context);
1168 
1169     if (steps.empty())
1170     {
1171         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1172         return STOP;
1173     }
1174 
1175     size_t stepIndex = 0;
1176     for (const auto &step : steps)
1177     {
1178         step.testFn(context);
1179 
1180         if (!verifyFramebufferStatus(gl, step.expectedFbStatus, stepIndex++))
1181             return STOP;
1182     }
1183     return STOP;
1184 }
1185 
verifyFramebufferStatus(const glw::Functions & gl,const ExpectedStatusFn expectedStatusFn,const size_t stepIndex)1186 bool FramebufferCompletenessTestCase::verifyFramebufferStatus(const glw::Functions &gl,
1187                                                               const ExpectedStatusFn expectedStatusFn,
1188                                                               const size_t stepIndex)
1189 {
1190     static const map<GLenum, string> statusNames = {
1191         {GL_FRAMEBUFFER_COMPLETE, "GL_FRAMEBUFFER_COMPLETE"},
1192         {GL_FRAMEBUFFER_UNDEFINED, "GL_FRAMEBUFFER_UNDEFINED"},
1193         {GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"},
1194         {GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT, "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"},
1195         {GL_FRAMEBUFFER_UNSUPPORTED, "GL_FRAMEBUFFER_UNSUPPORTED"},
1196         {GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"},
1197         {GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS, "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"}};
1198     const auto expectedStatus = expectedStatusFn(m_context.getContextInfo());
1199     const auto fboStatus      = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
1200     GLU_EXPECT_NO_ERROR(gl.getError(), "glCheckFramebufferStatus() failed");
1201     if (fboStatus != expectedStatus)
1202     {
1203         ostringstream msg;
1204         const auto &fboStatusName      = statusNames.find(fboStatus);
1205         const auto &expectedStatusName = statusNames.find(expectedStatus);
1206         msg << "Frame buffer status ("
1207             << ((fboStatusName != statusNames.end()) ? fboStatusName->second : std::to_string(fboStatus))
1208             << ") does not match the expected status ("
1209             << ((expectedStatusName != statusNames.end()) ? expectedStatusName->second : std::to_string(expectedStatus))
1210             << ") after step " << stepIndex;
1211         TCU_FAIL(msg.str().c_str());
1212         return false;
1213     }
1214     m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1215     return true;
1216 }
1217 
1218 } // namespace
1219 
FramebufferCompletenessTests(deqp::Context & context)1220 FramebufferCompletenessTests::FramebufferCompletenessTests(deqp::Context &context)
1221     : deqp::TestCaseGroup(context, "framebuffer_completeness", "Tests for frame buffer completeness")
1222 {
1223 }
1224 
init(void)1225 void FramebufferCompletenessTests::init(void)
1226 {
1227     const auto &renderContext = m_context.getRenderContext();
1228     for (const auto &test : tests)
1229     {
1230         if (!glu::contextSupports(renderContext.getType(), test.apiType))
1231             continue;
1232 
1233         addChild(new FramebufferCompletenessTestCase(m_context, test));
1234     }
1235 }
1236 
1237 } // namespace glcts
1238