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 ≷
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 ¶ms);
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 ¶ms)
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