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, GLenum statusIfNotSupported)
165 {
166 return [extension, statusIfSupported, statusIfNotSupported](const glu::ContextInfo &contextInfo)
167 {
168 if (contextInfo.isExtensionSupported(extension.c_str()))
169 return statusIfSupported;
170 else
171 return statusIfNotSupported;
172 };
173 }
174
175 struct TestStep
176 {
177 TestFn testFn;
178 ExpectedStatusFn expectedFbStatus;
179 };
180
181 typedef function<void(vector<TestStep>&, TestContext& context)> StepsGeneratorFn;
182
183 struct ExtensionEntry
184 {
185 string name;
186 bool supportedStatus;
187 };
188
189 struct TestParams
190 {
191 string name;
192 string description;
193 glu::ApiType apiType;
194 size_t numFboIds;
195 size_t numTexIds;
196 size_t numRboIds;
197 vector<TestStep> initialSteps;
198 StepsGeneratorFn stepsGenerator;
199 };
200
201 const GLuint TEXTURE_WIDTH = 16;
202 const GLuint TEXTURE_HEIGHT = 16;
203 const GLuint TEXTURE_DEPTH = 16;
204
205 static const GLenum cubemapTextureTargets[] =
206 {
207 GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
208 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
209 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Z
210 };
211
212 const glu::ApiType apiES30 = glu::ApiType::es(3, 0);
213 const glu::ApiType apiES31 = glu::ApiType::es(3, 1);
214 const glu::ApiType apiES32 = glu::ApiType::es(3, 2);
215
isDifferentRboSampleCountsSupported(TestContext & testContext,GLint & maxSamples)216 bool isDifferentRboSampleCountsSupported(TestContext& testContext, GLint& maxSamples)
217 {
218 const auto& gl = testContext.gl;
219 gl.getIntegerv(GL_MAX_SAMPLES, &maxSamples);
220 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed");
221
222 if (maxSamples < 4)
223 TCU_FAIL("GL_MAX_SAMPLES needs to be >= 4");
224
225 testContext.renderbufferStorageMultisample(testContext.rboIds[0], GL_RENDERBUFFER, 1, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
226 gl.bindRenderbuffer(GL_RENDERBUFFER, testContext.rboIds[0]);
227 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed");
228
229 GLint minSamplesRbo;
230 gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &minSamplesRbo);
231 GLU_EXPECT_NO_ERROR(gl.getError(), "getRenderbufferParameteriv() failed");
232 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
233 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed");
234
235 return minSamplesRbo < maxSamples;
236 }
237
isDifferentTextureSampleCountsSupported(TestContext & testContext,GLint & maxSamples)238 bool isDifferentTextureSampleCountsSupported(TestContext& testContext, GLint& maxSamples)
239 {
240 if (glu::contextSupports(testContext.renderContext.getType(), apiES31))
241 {
242 const auto& gl = testContext.gl;
243 GLint maxColorSamples;
244 gl.getIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxColorSamples);
245 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed");
246
247 GLint maxDepthSamples;
248 gl.getIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &maxDepthSamples);
249 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed");
250
251 maxSamples = min(maxColorSamples, maxDepthSamples);
252
253 GLuint tempTexId;
254 gl.genTextures(1, &tempTexId);
255 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
256
257 testContext.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, tempTexId);
258 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_TRUE);
259 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() failed");
260
261 GLint minSamplesTex;
262 gl.getTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &minSamplesTex);
263 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexLevelParameteriv() failed");
264
265 testContext.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
266 gl.deleteTextures(1, &tempTexId);
267 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() failed");
268
269 return minSamplesTex < maxSamples;
270 }
271 return false;
272 }
273
274 /* Tests are defined as ordered series of steps that each expect a specific current framebuffer status
275 after being executed. A new TestContext instance (parameter) is created for each test but all steps
276 within a test use the same context. No code in addition to the framebuffer status check is executed
277 between steps. */
278 const TestParams tests[] =
279 {
280 {
281 "incomplete_missing_attachment", // string name
282 "No attachments", // string description
283 apiES30, // glu::ApiType apiType
284 1, // size_t numFboIds
285 0, // size_t numTexIds
286 0, // size_t numRboIds
287 { // vector<TestStep> initialSteps
288 {
__anon57613fd90402() 289 [](TestContext& context) {
290 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
291 },
292 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
293 }
294 },
295 DE_NULL, // StepsGeneratorFn stepsGenerator
296 },
297 {
298 "incomplete_image_zero_width", // string name
299 "Zero width attachment image", // string description
300 apiES30, // glu::ApiType apiType
301 1, // size_t numFboIds
302 1, // size_t numTexIds
303 0, // size_t numRboIds
304 { // vector<TestStep> initialSteps
305 {
306 [](TestContext& context)
__anon57613fd90502() 307 {
308 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
309 },
310 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
311 },
312 {
313 [](TestContext& context)
__anon57613fd90602() 314 {
315 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 0, TEXTURE_HEIGHT, 0,
316 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, DE_NULL);
317 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, context.texIds[0], 0);
318 },
319 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
320 }
321 },
322 DE_NULL, // StepsGeneratorFn stepsGenerator
323 },
324 {
325 "incomplete_image_zero_height", // string name
326 "Zero height attachment image", // string description
327 apiES30, // glu::ApiType apiType
328 1, // size_t numFboIds
329 1, // size_t numTexIds
330 0, // size_t numRboIds
331 { // vector<TestStep> initialSteps
332 {
333 [](TestContext& context)
__anon57613fd90702() 334 {
335 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
336 },
337 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
338 },
339 {
340 [](TestContext& context)
__anon57613fd90802() 341 {
342 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 0, TEXTURE_WIDTH, 0,
343 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, DE_NULL);
344 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, context.texIds[0], 0);
345 },
346 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
347 }
348 },
349 DE_NULL, // StepsGeneratorFn stepsGenerator
350 },
351 {
352 "incomplete_texture_3d_layer_oob", // string name
353 "3D texture layer out of bounds", // string description
354 apiES30, // glu::ApiType apiType
355 1, // size_t numFboIds
356 1, // size_t numTexIds
357 0, // size_t numRboIds
358 { // vector<TestStep> initialSteps
359 {
360 [](TestContext& context)
__anon57613fd90902() 361 {
362 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
363 },
364 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
365 },
366 {
367 [](TestContext& context)
__anon57613fd90a02() 368 {
369 context.texImage3D(context.texIds[0], GL_TEXTURE_3D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT,
370 TEXTURE_DEPTH, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
371 context.framebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, context.texIds[0], 0,
372 TEXTURE_DEPTH + 1);
373 },
374 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
375 }
376 },
377 DE_NULL, // StepsGeneratorFn stepsGenerator
378 },
379 {
380 "incomplete_texture_2d_layer_oob", // string name
381 "2D texture layer out of bounds", // string description
382 apiES30, // glu::ApiType apiType
383 1, // size_t numFboIds
384 1, // size_t numTexIds
385 0, // size_t numRboIds
386 { // vector<TestStep> initialSteps
387 {
388 [](TestContext& context)
__anon57613fd90b02() 389 {
390 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
391 },
392 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
393 },
394 {
395 [](TestContext& context)
__anon57613fd90c02() 396 {
397 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
398 GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
399 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 1);
400 },
401 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
402 }
403 },
404 DE_NULL, // StepsGeneratorFn stepsGenerator
405 },
406 {
407 "incomplete_texture_2d_mm_layer_oob", // string name
408 "2D mipmapped texture layer out of bounds", // 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 {
415 [](TestContext& context)
__anon57613fd90d02() 416 {
417 context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
418 GL_LINEAR_MIPMAP_LINEAR);
419 context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
420 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 1, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
421 GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
422 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
423 },
424 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
425 },
426 {
427 [](TestContext& context)
__anon57613fd90e02() 428 {
429 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 0);
430 },
431 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
432 },
433 {
434 [](TestContext& context)
__anon57613fd90f02() 435 {
436 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 1);
437 },
438 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
439 },
440 {
441 [](TestContext& context)
__anon57613fd91002() 442 {
443 const deUint32 maxMipmapLevel = deLog2Floor32(de::max(TEXTURE_WIDTH, TEXTURE_HEIGHT));
444 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0],
445 maxMipmapLevel + 2);
446 },
447 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
448 },
449 },
450 DE_NULL, // StepsGeneratorFn stepsGenerator
451 },
452 {
453 "mutable_nbl_texture_expect_mipmap_complete", // string name
454 "Mutable non base level texture as framebuffer attachment must be mipmap complete", // string description
455 apiES30, // glu::ApiType apiType
456 1, // size_t numFboIds
457 1, // size_t numTexIds
458 0, // size_t numRboIds
459 { // vector<TestStep> initialSteps
460 {
461 [](TestContext& context)
__anon57613fd91102() 462 {
463 DE_ASSERT(TEXTURE_WIDTH >= 8 && TEXTURE_HEIGHT >= 8);
464
465 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
466 GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
467 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 1, GL_RGBA8, TEXTURE_WIDTH >> 1,
468 TEXTURE_HEIGHT >> 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
469 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 3, GL_RGBA8, TEXTURE_WIDTH >> 3,
470 TEXTURE_HEIGHT >> 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
471 context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);
472 context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
473 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
474 },
475 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
476 },
477 {
478 [](TestContext& context)
__anon57613fd91202() 479 {
480 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 1);
481 },
482 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
483 },
484 {
485 [](TestContext& context)
__anon57613fd91302() 486 {
487 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 2, GL_RGBA8, TEXTURE_WIDTH >> 2,
488 TEXTURE_HEIGHT >> 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
489 },
490 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
491 }
492 },
493 DE_NULL, // StepsGeneratorFn stepsGenerator
494 },
495 {
496 "mutable_nbl_texture_expect_cube_complete", // string name
497 "Mutable non base level texture as framebuffer attachment must be cube complete", // string description
498 apiES30, // glu::ApiType apiType
499 1, // size_t numFboIds
500 1, // size_t numTexIds
501 0, // size_t numRboIds
502 { // vector<TestStep> initialSteps
503 {
504 [](TestContext& context)
__anon57613fd91402() 505 {
506 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
507 },
508 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
509 },
510 {
511 [](TestContext& context)
__anon57613fd91502() 512 {
513 context.texParameteri(context.texIds[0], GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 1);
514 context.texParameteri(context.texIds[0], GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
515
516 context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]);
517 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(cubemapTextureTargets); ++i)
518 {
519 if (i % 2)
520 continue;
521 context.texImage2D(cubemapTextureTargets[i], 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA,
522 GL_UNSIGNED_BYTE, DE_NULL);
523 context.texImage2D(cubemapTextureTargets[i], 1, GL_RGBA8, TEXTURE_WIDTH >> 1, TEXTURE_HEIGHT >> 1, 0, GL_RGBA,
524 GL_UNSIGNED_BYTE, DE_NULL);
525 }
526 context.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
527
528 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubemapTextureTargets[0],
529 context.texIds[0], 1);
530 },
531 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
532 },
533 {
534 [](TestContext& context)
__anon57613fd91602() 535 {
536 context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]);
537 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(cubemapTextureTargets); ++i)
538 {
539 if (i % 2 == 0)
540 continue;
541 context.texImage2D(cubemapTextureTargets[i], 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA,
542 GL_UNSIGNED_BYTE, DE_NULL);
543 context.texImage2D(cubemapTextureTargets[i], 1, GL_RGBA8, TEXTURE_WIDTH >> 1, TEXTURE_HEIGHT >> 1, 0, GL_RGBA,
544 GL_UNSIGNED_BYTE, DE_NULL);
545 }
546 context.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
547 },
548 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
549 }
550 },
551 DE_NULL, // StepsGeneratorFn stepsGenerator
552 },
553 {
554 "expect_renderable_internal_format", // string name
555 "Color/Depth/Stencil attachment texture must have a color/depth/stencil" // string description
556 " renderable internal format",
557 apiES30, // glu::ApiType apiType
558 1, // size_t numFboIds
559 3, // size_t numTexIds
560 0, // size_t numRboIds
561 { // vector<TestStep> initialSteps
562 {
563 [](TestContext& context)
__anon57613fd91702() 564 {
565 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
566 GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
567 context.texImage2D(context.texIds[1], GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, TEXTURE_WIDTH,
568 TEXTURE_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, DE_NULL);
569 context.texImage2D(context.texIds[2], GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, TEXTURE_WIDTH, TEXTURE_HEIGHT,
570 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, DE_NULL);
571 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
572 },
573 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
574 },
575 {
576 [](TestContext& context)
__anon57613fd91802() 577 {
578 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, context.texIds[0], 0);
579 },
580 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
581 },
582 {
583 [](TestContext& context)
__anon57613fd91902() 584 {
585 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, context.texIds[1], 0);
586 },
587 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
588 },
589 {
590 [](TestContext& context)
__anon57613fd91a02() 591 {
592 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, context.texIds[0], 0);
593 },
594 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
595 },
596 {
597 [](TestContext& context)
__anon57613fd91b02() 598 {
599 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, context.texIds[2], 0);
600 },
601 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
602 }
603 },
604 [](vector<TestStep>& steps, TestContext& testContext) // StepsGeneratorFn stepsGenerator
__anon57613fd91c02() 605 {
606 GLint maxColorAttachmentsCount;
607 testContext.gl.getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachmentsCount);
608 GLU_EXPECT_NO_ERROR(testContext.gl.getError(), "glGetInteger() failed");
609
610 steps.reserve(steps.size() + 2 * maxColorAttachmentsCount);
611 for (GLint i = 0; i < maxColorAttachmentsCount; ++i)
612 {
613 steps.push_back(
614 {
615 [i](TestContext& context)
616 {
617 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
618 context.texIds[1], 0);
619 },
620 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
621 });
622 steps.push_back(
623 {
624 [i](TestContext& context)
625 {
626 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
627 context.texIds[0], 0);
628 },
629 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
630 });
631 }
632 },
633 },
634 {
635 "all_rbos_expect_same_numsamples", // string name
636 "Same value of FRAMEBUFFER_SAMPLES for all attached render buffers", // string description
637 apiES30, // glu::ApiType apiType
638 1, // size_t numFboIds
639 0, // size_t numTexIds
640 2, // size_t numRboIds
641 {}, // vector<TestStep> initialSteps
642 [](vector<TestStep>& steps, TestContext& testContext) // StepsGeneratorFn stepsGenerator
__anon57613fd91f02() 643 {
644 GLint maxSamples;
645 if (!isDifferentRboSampleCountsSupported(testContext, maxSamples))
646 return;
647
648 steps.push_back(
649 {
650 [](TestContext& context)
651 {
652 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
653 },
654 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
655 });
656 steps.push_back(
657 {
658 [](TestContext& context)
659 {
660 context.renderbufferStorage(context.rboIds[0], GL_RENDERBUFFER, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
661 context.renderbufferStorage(context.rboIds[1], GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, TEXTURE_WIDTH,
662 TEXTURE_HEIGHT);
663
664 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
665 context.rboIds[0]);
666 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
667 context.rboIds[1]);
668 },
669 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
670 });
671 steps.push_back(
672 {
673 [maxSamples](TestContext& context)
674 {
675 context.renderbufferStorageMultisample(context.rboIds[0], GL_RENDERBUFFER, maxSamples, GL_RGBA8, TEXTURE_WIDTH,
676 TEXTURE_HEIGHT);
677 context.renderbufferStorageMultisample(context.rboIds[1], GL_RENDERBUFFER, 1, GL_DEPTH24_STENCIL8,
678 TEXTURE_WIDTH, TEXTURE_HEIGHT);
679 },
680 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
681 });
682 },
683 },
684 {
685 "rbo_and_texture_expect_zero_numsamples", // string name
686 "When using mixed renderbuffer and texture attachments, the value of" // string description
687 " FRAMEBUFFER_SAMPLES needs to be zero for all attached renderbuffers",
688 apiES30, // glu::ApiType apiType
689 1, // size_t numFboIds
690 2, // size_t numTexIds
691 2, // size_t u numRboIds
692 { // vector<TestStep> initialSteps
693 {
694 [](TestContext& context)
__anon57613fd92302() 695 {
696 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
697 },
698 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
699 },
700 {
701 [](TestContext& context)
__anon57613fd92402() 702 {
703 context.renderbufferStorage(context.rboIds[0], GL_RENDERBUFFER, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
704 context.texImage2D(context.texIds[1], GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, TEXTURE_WIDTH,
705 TEXTURE_HEIGHT, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, DE_NULL);
706
707 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
708 context.rboIds[0]);
709 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
710 context.texIds[1], 0);
711 },
712 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
713 },
714 {
715 [](TestContext& context)
__anon57613fd92502() 716 {
717 context.renderbufferStorage(context.rboIds[1], GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, TEXTURE_WIDTH,
718 TEXTURE_HEIGHT);
719 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
720 GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
721
722 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 0);
723 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
724 context.rboIds[1]);
725 },
726 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
727 },
728 {
729 [](TestContext& context)
__anon57613fd92602() 730 {
731 context.renderbufferStorageMultisample(context.rboIds[1], GL_RENDERBUFFER, 2, GL_DEPTH24_STENCIL8,
732 TEXTURE_WIDTH, TEXTURE_HEIGHT);
733 },
734 expectedStatusWithExtension("GL_NV_framebuffer_mixed_samples", GL_FRAMEBUFFER_COMPLETE, GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
735 },
736 {
737 [](TestContext& context)
__anon57613fd92702() 738 {
739 context.renderbufferStorageMultisample(context.rboIds[0], GL_RENDERBUFFER, 3, GL_RGBA8, TEXTURE_WIDTH,
740 TEXTURE_HEIGHT);
741
742 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
743 context.rboIds[0]);
744 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
745 context.texIds[1], 0);
746 },
747 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
748 },
749 {
750 [](TestContext& context)
__anon57613fd92802() 751 {
752 context.renderbufferStorageMultisample(context.rboIds[0], GL_RENDERBUFFER, 0, GL_RGBA8, TEXTURE_WIDTH,
753 TEXTURE_HEIGHT);
754 },
755 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
756 }
757 },
758 DE_NULL, // StepsGeneratorFn stepsGenerator
759 },
760 {
761 "expect_equal_numsamples", // string name
762 "The value of samples for each attached target must be equal", // string description
763 apiES31, // glu::ApiType apiType
764 1, // size_t numFboIds
765 4, // size_t numTexIds
766 2, // size_t numRboIds
767 {}, // vector<TestStep> initialSteps
768 [](vector<TestStep>& steps, TestContext& testContext) // StepsGeneratorFn stepsGenerator
__anon57613fd92902() 769 {
770 GLint maxRboSamples, maxTextureSamples;
771 if (!isDifferentRboSampleCountsSupported(testContext, maxRboSamples) || !isDifferentTextureSampleCountsSupported(testContext, maxTextureSamples))
772 return;
773
774 steps.push_back(
775 {
776 [maxRboSamples, maxTextureSamples](TestContext& context)
777 {
778 // Set up textures and renderbuffers for all following steps, complete = (tex0, rbo1) or (tex1, rbo0) */
779 context.renderbufferStorageMultisample(context.rboIds[0], GL_RENDERBUFFER, maxRboSamples, GL_RGBA8,
780 TEXTURE_WIDTH, TEXTURE_HEIGHT);
781 context.renderbufferStorageMultisample(context.rboIds[1], GL_RENDERBUFFER, 1, GL_DEPTH24_STENCIL8,
782 TEXTURE_WIDTH, TEXTURE_HEIGHT);
783
784 const auto& gl = context.gl;
785 context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, context.texIds[0]);
786 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_TRUE);
787 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() failed");
788
789 context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, context.texIds[1]);
790 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_DEPTH24_STENCIL8, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_TRUE);
791 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() failed");
792
793 context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, context.texIds[2]);
794 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxTextureSamples, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_TRUE);
795 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() failed");
796
797 context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, context.texIds[3]);
798 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxTextureSamples, GL_DEPTH24_STENCIL8, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_TRUE);
799 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() failed");
800
801 context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
802
803 // Framebuffer binding for rest of this test
804 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
805 },
806 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
807 });
808 steps.push_back(
809 {
810 [](TestContext& context)
811 {
812 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
813 context.texIds[0], 0);
814 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE,
815 context.texIds[1], 0);
816 },
817 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
818 });
819 steps.push_back(
820 {
821 [](TestContext& context)
822 {
823 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE,
824 context.texIds[3], 0);
825 },
826 expectedStatusWithExtension("GL_NV_framebuffer_mixed_samples", GL_FRAMEBUFFER_COMPLETE, GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
827 });
828 steps.push_back(
829 {
830 [](TestContext& context)
831 {
832 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
833 context.rboIds[1]);
834 },
835 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
836 });
837 steps.push_back(
838 {
839 [](TestContext& context)
840 {
841 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
842 context.rboIds[0]);
843 },
844 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
845 });
846 steps.push_back(
847 {
848 [](TestContext& context)
849 {
850 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
851 context.texIds[2], 0);
852 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE,
853 context.texIds[3], 0);
854 },
855 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
856 });
857 steps.push_back(
858 {
859 [](TestContext& context)
860 {
861 const auto& gl = context.gl;
862 gl.deleteTextures(1, &context.texIds[0]);
863 GLU_EXPECT_NO_ERROR(context.gl.getError(), "glDeleteTextures() failed");
864 gl.genTextures(1, &context.texIds[0]);
865 GLU_EXPECT_NO_ERROR(context.gl.getError(), "glGenTextures() failed");
866 context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, context.texIds[0]);
867 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_FALSE);
868 GLU_EXPECT_NO_ERROR(context.gl.getError(), "glTexStorage2DMultisample() failed");
869 context.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
870 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
871 context.texIds[0], 0);
872 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE,
873 context.texIds[1], 0);
874 },
875 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
876 });
877 }, // StepsGeneratorFn stepsGenerator
878 },
879 {
880 "status_tracking", // string name
881 "Modifying framebuffer attached objects correctly updates the fbo status", // string description
882 apiES30, // glu::ApiType apiType
883 3, // size_t numFboIds
884 2, // size_t numTexIds
885 1, // size_t numRboIds
886 { // vector<TestStep> initialSteps
887 {
888 // Initial status -> missing_attachment
889 [](TestContext& context)
__anon57613fd93102() 890 {
891 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
892 },
893 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
894 },
895 {
896 // Allocate and attach texture -> complete
897 [](TestContext& context)
__anon57613fd93202() 898 {
899 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
900 GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
901 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 0);
902 },
903 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
904 },
905 {
906 // Detach texture from fbo -> missing_attachment
907 [](TestContext& context)
__anon57613fd93302() 908 {
909 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
910 },
911 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
912 },
913 {
914 // Allocate and attach renderbuffer -> complete
915 [](TestContext& context)
__anon57613fd93402() 916 {
917 context.renderbufferStorage(context.rboIds[0], GL_RENDERBUFFER, GL_RGBA8, TEXTURE_WIDTH,
918 TEXTURE_HEIGHT);
919 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
920 context.rboIds[0]);
921 },
922 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
923 },
924 {
925 // Detach renderbuffer -> incomplete
926 [](TestContext& context)
__anon57613fd93502() 927 {
928 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
929 },
930 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
931 },
932 {
933 // Switch to incomplete fb -> missing_attachment
934 [](TestContext& context)
__anon57613fd93602() 935 {
936 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[1]);
937 },
938 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
939 },
940 {
941 // Attach texture to fbo -> complete
942 [](TestContext& context)
__anon57613fd93702() 943 {
944 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 0);
945 },
946 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
947 },
948 {
949 // Change image format of attached texture -> incomplete_attachment
950 [](TestContext& context)
__anon57613fd93802() 951 {
952 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, TEXTURE_WIDTH,
953 TEXTURE_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, DE_NULL);
954 },
955 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
956 },
957 {
958 // Change image format (tex storage) -> complete
959 [](TestContext& context)
__anon57613fd93902() 960 {
961 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
962 context.gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
963 GLU_EXPECT_NO_ERROR(context.gl.getError(), "glTexStorage2D() failed");
964 context.bindTexture(GL_TEXTURE_2D, 0);
965 },
966 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
967 },
968 {
969 // Delete image -> missing_attachment
970 [](TestContext& context)
__anon57613fd93a02() 971 {
972 context.gl.deleteTextures(1, &context.texIds[0]);
973 GLU_EXPECT_NO_ERROR(context.gl.getError(), "glDeleteTextures() failed");
974 context.texIds.erase(context.texIds.begin());
975 },
976 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
977 },
978 {
979 // Recreate image in wrong format, attach to color attachment -> incomplete_attachment
980 [](TestContext& context)
__anon57613fd93b02() 981 {
982 const auto& gl = context.gl;
983 GLuint texId;
984 gl.genTextures(1, &texId);
985 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
986 context.texIds.push_back(texId);
987
988 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
989 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, TEXTURE_WIDTH,
990 TEXTURE_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, DE_NULL);
991 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 0);
992 },
993 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
994 },
995 {
996 // Format to rgba8 using copyTexImage2D from compatible fbo -> framebuffer_complete
997 [](TestContext& context)
__anon57613fd93c02() 998 {
999 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[2]);
1000 context.texImage2D(context.texIds[1], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1001 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[1], 0);
1002
1003 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
1004 const auto& gl = context.gl;
1005 gl.copyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0);
1006 GLU_EXPECT_NO_ERROR(gl.getError(), "glCopyTexImage2D() failed");
1007
1008 context.bindTexture(GL_TEXTURE_2D, 0);
1009 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
1010 },
1011 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
1012 },
1013 {
1014 // Change currently attached texture's format to compressed tex image -> incomplete_attachment (non color renderable)
1015 [](TestContext& context)
__anon57613fd93d02() 1016 {
1017 DE_ASSERT(TEXTURE_WIDTH == 16 && TEXTURE_HEIGHT == 16);
1018 static const glw::GLubyte textureDataETC2[] = // 16x16 all black RGBA8 texture in ETC2 format
1019 {
1020 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1021 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1022 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1023 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1024 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1025 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1026 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1027 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1028 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1029 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1030 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1031 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1032 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1033 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1034 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00,
1035 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0x00, 0x00
1036 };
1037 const auto& gl = context.gl;
1038 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
1039
1040 gl.compressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA8_ETC2_EAC, TEXTURE_WIDTH, TEXTURE_HEIGHT,
1041 0, DE_LENGTH_OF_ARRAY(textureDataETC2), textureDataETC2);
1042 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed");
1043
1044 context.bindTexture(GL_TEXTURE_2D, 0);
1045 },
1046 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
1047 },
1048 {
1049 // Re-attach rbo0 -> complete
1050 [](TestContext& context)
__anon57613fd93e02() 1051 {
1052 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1053 context.rboIds[0]);
1054 },
1055 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE)
1056 },
1057 {
1058 // Rbo storage to non renderable format -> incomplete_attachment
1059 [](TestContext& context)
__anon57613fd93f02() 1060 {
1061 context.renderbufferStorage(context.rboIds[0], GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, TEXTURE_WIDTH,
1062 TEXTURE_HEIGHT);
1063 },
1064 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
1065 },
1066 {
1067 // Delete rbo -> missing_attachment
1068 [](TestContext& context)
__anon57613fd94002() 1069 {
1070 context.gl.deleteRenderbuffers(1, &context.rboIds[0]);
1071 GLU_EXPECT_NO_ERROR(context.gl.getError(), "glDeleteRenderbuffers() failed");
1072 context.rboIds.erase(context.rboIds.begin());
1073 },
1074 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
1075 }
1076 },
1077 DE_NULL, // StepsGeneratorFn stepsGenerator
1078 },
1079 {
1080 "mutable_texture_missing_attachment_level", // string name
1081 "Attaching a mutable texture with undefined image for attachment level"
1082 " should be invalid", // string description
1083 apiES30, // glu::ApiType apiType
1084 1, // size_t numFboIds
1085 1, // size_t numTexIds
1086 0, // size_t numRboIds
1087 {}, // vector<TestStep> initialSteps
1088 [](vector<TestStep>& steps, TestContext&) // StepsGeneratorFn stepsGenerator
__anon57613fd94102() 1089 {
1090 DE_ASSERT(TEXTURE_WIDTH >= 16 && TEXTURE_HEIGHT >= 16);
1091 steps.push_back(
1092 {
1093 [](TestContext& context)
1094 {
1095 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
1096 },
1097 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
1098 });
1099 steps.push_back(
1100 {
1101 [](TestContext& context)
1102 {
1103
1104 context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1105 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
1106 GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
1107 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 1, GL_RGBA8, TEXTURE_WIDTH >> 1, TEXTURE_HEIGHT >> 1, 0,
1108 GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
1109 context.texImage2D(context.texIds[0], GL_TEXTURE_2D, 3, GL_RGBA8, TEXTURE_WIDTH >> 3, TEXTURE_HEIGHT >> 3, 0,
1110 GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
1111
1112 context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
1113
1114 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 2);
1115 },
1116 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
1117 });
1118 }
1119 },
1120 {
1121 "immutable_texture_any_level_as_attachment", // string name
1122 "Any level of immutable texture as attachment should be valid", // string description
1123 apiES30, // glu::ApiType apiType
1124 1, // size_t numFboIds
1125 1, // size_t numTexIds
1126 0, // size_t numRboIds
1127 {}, // vector<TestStep> initialSteps
1128 [](vector<TestStep>& steps, TestContext&) // StepsGeneratorFn stepsGenerator
__anon57613fd94402() 1129 {
1130 DE_ASSERT(TEXTURE_WIDTH >= 8 && TEXTURE_HEIGHT >= 8);
1131 steps.push_back(
1132 {
1133 [](TestContext& context)
1134 {
1135 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
1136 },
1137 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
1138 });
1139 steps.push_back(
1140 {
1141 [](TestContext& context)
1142 {
1143 context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1144 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
1145 const auto& gl = context.gl;
1146 gl.texStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
1147 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() failed");
1148 context.bindTexture(GL_TEXTURE_2D, 0);
1149
1150 context.texParameteri(context.texIds[0], GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
1151
1152 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 2);
1153 },
1154 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE),
1155 });
1156 steps.push_back(
1157 {
1158 [](TestContext& context)
1159 {
1160 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 1);
1161 },
1162 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE),
1163 });
1164 steps.push_back(
1165 {
1166 [](TestContext& context)
1167 {
1168 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context.texIds[0], 0);
1169 },
1170 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE),
1171 });
1172 }
1173 },
1174 {
1175 "cube_map_layered_attachment_valid_size_and_format", // string name
1176 "Cube map attachment with images of same size, same format and square should be valid", // string description
1177 apiES32, // glu::ApiType apiType
1178 1, // size_t numFboIds
1179 1, // size_t numTexIds
1180 0, // size_t numRboIds
1181 { // vector<TestStep> initialSteps
1182 {
1183 [](TestContext& context)
__anon57613fd94902() 1184 {
1185 context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]);
1186 for(const auto target : cubemapTextureTargets)
1187 context.texImage2D(target, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1188 context.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
1189
1190 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
1191 context.gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, context.texIds[0], 0);
1192 GLU_EXPECT_NO_ERROR(context.gl.getError(), "glFramebufferTexture() failed");
1193 },
1194 expectedStatusConstant(GL_FRAMEBUFFER_COMPLETE),
1195 }
1196 },
1197 DE_NULL, // StepsGeneratorFn stepsGenerator
1198 },
1199 {
1200 "cube_map_layered_attachment_different_formats", // string name
1201 "Cube map attachment with images of the same size, square but different formats"
1202 " should be incomplete", // string description
1203 apiES32, // glu::ApiType apiType
1204 1, // size_t numFboIds
1205 1, // size_t numTexIds
1206 0, // size_t numRboIds
1207 { // vector<TestStep> initialSteps
1208 {
1209 [](TestContext& context)
__anon57613fd94a02() 1210 {
1211 context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]);
1212 for(size_t i = 0; i < DE_LENGTH_OF_ARRAY(cubemapTextureTargets); ++i)
1213 context.texImage2D(cubemapTextureTargets[i], 0, (i % 2) ? GL_RGBA8 : GL_RGB8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, (i % 2) ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, 0);
1214 context.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
1215
1216 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
1217 context.gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, context.texIds[0], 0);
1218 GLU_EXPECT_NO_ERROR(context.gl.getError(), "glFramebufferTexture() failed");
1219 },
1220 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
1221 },
1222 {
1223 [](TestContext& context)
__anon57613fd94b02() 1224 {
1225 context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]);
1226 for(size_t i = 0; i < DE_LENGTH_OF_ARRAY(cubemapTextureTargets); ++i)
1227 context.texImage2D(cubemapTextureTargets[i], 0, (i % 2) ? GL_RGBA8 : GL_SRGB8_ALPHA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1228 context.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
1229
1230 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
1231 context.gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, context.texIds[0], 0);
1232 GLU_EXPECT_NO_ERROR(context.gl.getError(), "glFramebufferTexture() failed");
1233 },
1234 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
1235 }
1236 },
1237 DE_NULL, // StepsGeneratorFn stepsGenerator
1238 },
1239 {
1240 "cube_map_layered_attachment_different_sizes", // string name
1241 "Cube map with images of different sizes, same format and all square should"
1242 " be incomplete", // string description
1243 apiES32, // glu::ApiType apiType
1244 1, // size_t numFboIds
1245 1, // size_t numTexIds
1246 0, // size_t numRboIds
1247 { // vector<TestStep> initialSteps
1248 {
1249 [](TestContext& context)
__anon57613fd94c02() 1250 {
1251 context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]);
1252 for(size_t i = 0; i < DE_LENGTH_OF_ARRAY(cubemapTextureTargets); ++i)
1253 context.texImage2D(cubemapTextureTargets[i], 0, GL_RGBA8, (i % 2) ? TEXTURE_WIDTH : TEXTURE_WIDTH / 2, (i % 2) ? TEXTURE_HEIGHT : TEXTURE_HEIGHT / 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1254 context.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
1255
1256 context.bindFramebuffer(GL_FRAMEBUFFER, context.fboIds[0]);
1257 context.gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, context.texIds[0], 0);
1258 GLU_EXPECT_NO_ERROR(context.gl.getError(), "glFramebufferTexture() failed");
1259 },
1260 expectedStatusConstant(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
1261 },
1262 },
1263 DE_NULL, // StepsGeneratorFn stepsGenerator
1264 }
1265 };
1266
1267 class FramebufferCompletenessTestCase : public deqp::TestCase
1268 {
1269 public:
1270 FramebufferCompletenessTestCase (deqp::Context& context, const TestParams& params);
1271 virtual ~FramebufferCompletenessTestCase ();
1272
1273 virtual void init (void);
1274 virtual void deinit (void);
1275 TestNode::IterateResult iterate (void);
1276
1277 private:
1278 bool verifyFramebufferStatus (const glw::Functions& gl, const ExpectedStatusFn expectedStatusFn, const size_t stepIndex);
1279
1280 const TestParams m_params;
1281 vector<GLuint> m_fboIds;
1282 vector<GLuint> m_texIds;
1283 vector<GLuint> m_rboIds;
1284 };
1285
FramebufferCompletenessTestCase(deqp::Context & context,const TestParams & params)1286 FramebufferCompletenessTestCase::FramebufferCompletenessTestCase(deqp::Context& context, const TestParams& params)
1287 : deqp::TestCase(context, params.name.c_str(), params.description.c_str()), m_params(params)
1288 {
1289 }
1290
~FramebufferCompletenessTestCase()1291 FramebufferCompletenessTestCase::~FramebufferCompletenessTestCase()
1292 {
1293 }
1294
init(void)1295 void FramebufferCompletenessTestCase::init(void)
1296 {
1297 const auto& renderContext = m_context.getRenderContext();
1298 const auto& gl = renderContext.getFunctions();
1299
1300 if (m_params.numFboIds > 0)
1301 {
1302 m_fboIds.resize(m_params.numFboIds);
1303 gl.genFramebuffers(m_params.numFboIds, m_fboIds.data());
1304 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed");
1305 }
1306 if (m_params.numTexIds > 0)
1307 {
1308 m_texIds.resize(m_params.numTexIds);
1309 gl.genTextures(m_params.numTexIds, m_texIds.data());
1310 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
1311 }
1312 if (m_params.numRboIds > 0)
1313 {
1314 m_rboIds.resize(m_params.numRboIds);
1315 gl.genRenderbuffers(m_params.numRboIds, m_rboIds.data());
1316 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers() failed");
1317 }
1318 }
1319
deinit(void)1320 void FramebufferCompletenessTestCase::deinit(void)
1321 {
1322 const auto& renderContext = m_context.getRenderContext();
1323 const auto& gl = renderContext.getFunctions();
1324
1325 if (!m_rboIds.empty())
1326 {
1327 gl.deleteRenderbuffers(m_params.numRboIds, m_rboIds.data());
1328 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteRenderbuffers() failed");
1329 m_rboIds.clear();
1330 }
1331 if (!m_texIds.empty())
1332 {
1333 gl.deleteTextures(m_params.numTexIds, m_texIds.data());
1334 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() failed");
1335 m_texIds.clear();
1336 }
1337 if (!m_fboIds.empty())
1338 {
1339 gl.deleteFramebuffers(m_params.numFboIds, m_fboIds.data());
1340 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebufers() failed");
1341 m_fboIds.clear();
1342 }
1343 }
1344
iterate(void)1345 tcu::TestNode::IterateResult FramebufferCompletenessTestCase::iterate(void)
1346 {
1347 const auto& renderContext = m_context.getRenderContext();
1348 const auto& gl = renderContext.getFunctions();
1349 TestContext context =
1350 {
1351 renderContext, // const glu::RenderContext& renderContext
1352 gl, // const glw::Functions& gl
1353 m_fboIds, // vector<GLuint>& fboIds
1354 m_texIds, // vector<GLuint>& texIds
1355 m_rboIds // vector<GLuint>& rboIds
1356 };
1357 auto steps = vector<TestStep>(m_params.initialSteps);
1358 if (m_params.stepsGenerator != DE_NULL)
1359 m_params.stepsGenerator(steps, context);
1360
1361 if (steps.empty())
1362 {
1363 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1364 return STOP;
1365 }
1366
1367 size_t stepIndex = 0;
1368 for (const auto& step : steps)
1369 {
1370 step.testFn(context);
1371
1372 if (!verifyFramebufferStatus(gl, step.expectedFbStatus, stepIndex++))
1373 return STOP;
1374 }
1375 return STOP;
1376 }
1377
verifyFramebufferStatus(const glw::Functions & gl,const ExpectedStatusFn expectedStatusFn,const size_t stepIndex)1378 bool FramebufferCompletenessTestCase::verifyFramebufferStatus(const glw::Functions& gl, const ExpectedStatusFn expectedStatusFn,
1379 const size_t stepIndex)
1380 {
1381 static const map<GLenum, string> statusNames =
1382 {
1383 { GL_FRAMEBUFFER_COMPLETE , "GL_FRAMEBUFFER_COMPLETE" },
1384 { GL_FRAMEBUFFER_UNDEFINED , "GL_FRAMEBUFFER_UNDEFINED" },
1385 { GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT , "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT" },
1386 { GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT , "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT" },
1387 { GL_FRAMEBUFFER_UNSUPPORTED , "GL_FRAMEBUFFER_UNSUPPORTED" },
1388 { GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE , "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" },
1389 { GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS , "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS" }
1390 };
1391 const auto expectedStatus = expectedStatusFn(m_context.getContextInfo());
1392 const auto fboStatus = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
1393 GLU_EXPECT_NO_ERROR(gl.getError(), "glCheckFramebufferStatus() failed");
1394 if (fboStatus != expectedStatus)
1395 {
1396 ostringstream msg;
1397 const auto& fboStatusName = statusNames.find(fboStatus);
1398 const auto& expectedStatusName = statusNames.find(expectedStatus);
1399 msg << "Frame buffer status ("
1400 << ((fboStatusName != statusNames.end()) ? fboStatusName->second : std::to_string(fboStatus))
1401 << ") does not match the expected status ("
1402 << ((expectedStatusName != statusNames.end()) ? expectedStatusName->second : std::to_string(expectedStatus))
1403 << ") after step " << stepIndex;
1404 TCU_FAIL(msg.str().c_str());
1405 return false;
1406 }
1407 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1408 return true;
1409 }
1410
1411 } // namespace
1412
FramebufferCompletenessTests(deqp::Context & context)1413 FramebufferCompletenessTests::FramebufferCompletenessTests(deqp::Context& context)
1414 : deqp::TestCaseGroup(context, "framebuffer_completeness", "Tests for frame buffer completeness")
1415 {
1416 }
1417
init(void)1418 void FramebufferCompletenessTests::init(void)
1419 {
1420 const auto& renderContext = m_context.getRenderContext();
1421 for (const auto& test : tests)
1422 {
1423 if (!glu::contextSupports(renderContext.getType(), test.apiType))
1424 continue;
1425
1426 addChild(new FramebufferCompletenessTestCase(m_context, test));
1427 }
1428 }
1429
1430 } // namespace es3cts
1431