1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */ /*!
20 * \file
21 * \brief
22 */ /*-------------------------------------------------------------------*/
23 #include "es31cFramebufferNoAttachmentsTests.hpp"
24 #include "gluContextInfo.hpp"
25 #include "gluDefs.hpp"
26 #include "gluStrUtil.hpp"
27 #include "glw.h"
28 #include "glwFunctions.hpp"
29 #include "tcuTestLog.hpp"
30
31 namespace glcts
32 {
33
34 using glcts::Context;
35 using std::string;
36 using std::vector;
37 using tcu::TestLog;
38
39 // I tried to find something like this, but failed
checkErrorEqualsExpected(GLenum err,GLenum expected,const char * msg,const char * file,int line)40 void checkErrorEqualsExpected(GLenum err, GLenum expected, const char *msg, const char *file, int line)
41 {
42 if (err != expected)
43 {
44 std::ostringstream msgStr;
45 msgStr << "glGetError() returned " << glu::getErrorStr(err) << ", expected " << glu::getErrorStr(expected);
46
47 if (msg)
48 msgStr << " in '" << msg << "'";
49
50 if (err == GL_OUT_OF_MEMORY)
51 throw glu::OutOfMemoryError(msgStr.str().c_str(), "", file, line);
52 else
53 throw glu::Error(err, msgStr.str().c_str(), "", file, line);
54 }
55 }
56
57 #define GLU_EXPECT_ERROR(ERR, EXPECTED, MSG) checkErrorEqualsExpected((ERR), EXPECTED, MSG, __FILE__, __LINE__)
58
59 // Contains expect_fbo_status()
60 class FramebufferNoAttachmentsBaseCase : public TestCase
61 {
62 public:
63 FramebufferNoAttachmentsBaseCase(Context &context, const char *name, const char *description);
64 ~FramebufferNoAttachmentsBaseCase();
65
66 protected:
67 void expect_fbo_status(GLenum target, GLenum expected_status, const char *fail_message);
68 };
69
FramebufferNoAttachmentsBaseCase(Context & context,const char * name,const char * description)70 FramebufferNoAttachmentsBaseCase::FramebufferNoAttachmentsBaseCase(Context &context, const char *name,
71 const char *description)
72 : TestCase(context, name, description)
73 {
74 }
75
~FramebufferNoAttachmentsBaseCase()76 FramebufferNoAttachmentsBaseCase::~FramebufferNoAttachmentsBaseCase()
77 {
78 }
79
80 // API tests
81 class FramebufferNoAttachmentsApiCase : public FramebufferNoAttachmentsBaseCase
82 {
83 public:
84 FramebufferNoAttachmentsApiCase(Context &context, const char *name, const char *description);
85 ~FramebufferNoAttachmentsApiCase();
86
87 IterateResult iterate();
88
89 private:
90 void begin_fbo_no_attachments(GLenum target);
91 void begin_fbo_with_multisample_renderbuffer(GLenum target);
92 void begin_fbo(GLenum target, unsigned test_case);
93 void end_fbo(GLenum target);
94
95 private:
96 GLuint m_fbo;
97 GLuint m_renderbuffer;
98 GLuint m_texture;
99 };
100
FramebufferNoAttachmentsApiCase(Context & context,const char * name,const char * description)101 FramebufferNoAttachmentsApiCase::FramebufferNoAttachmentsApiCase(Context &context, const char *name,
102 const char *description)
103 : FramebufferNoAttachmentsBaseCase(context, name, description)
104 , m_fbo(0)
105 , m_renderbuffer(0)
106 , m_texture(0)
107 {
108 }
109
~FramebufferNoAttachmentsApiCase()110 FramebufferNoAttachmentsApiCase::~FramebufferNoAttachmentsApiCase()
111 {
112 }
113
expect_fbo_status(GLenum target,GLenum expected_status,const char * fail_message)114 void FramebufferNoAttachmentsBaseCase::expect_fbo_status(GLenum target, GLenum expected_status,
115 const char *fail_message)
116 {
117 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
118 GLenum error;
119
120 error = gl.getError();
121 if (error != GL_NO_ERROR)
122 {
123 std::ostringstream msgStr;
124 msgStr << "Error before glCheckFramebufferStatus() for '" << fail_message << "'\n";
125
126 GLU_EXPECT_NO_ERROR(error, "Error before glCheckFramebufferStatus()");
127 }
128
129 TCU_CHECK_MSG(gl.checkFramebufferStatus(target) == expected_status, fail_message);
130
131 error = gl.getError();
132 if (error != GL_NO_ERROR)
133 {
134 std::ostringstream msgStr;
135 msgStr << "Error after glCheckFramebufferStatus() for '" << fail_message << "'\n";
136
137 GLU_EXPECT_NO_ERROR(error, "Error after glCheckFramebufferStatus()");
138 }
139 }
140
begin_fbo_no_attachments(GLenum target)141 void FramebufferNoAttachmentsApiCase::begin_fbo_no_attachments(GLenum target)
142 {
143 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
144
145 gl.genFramebuffers(1, &m_fbo);
146 gl.bindFramebuffer(target, m_fbo);
147
148 // A freshly created framebuffer with no attachment is expected to be incomplete
149 // until default width and height is set.
150 expect_fbo_status(target, GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
151 "error setting up framebuffer with multisample attachment");
152 }
153
begin_fbo_with_multisample_renderbuffer(GLenum target)154 void FramebufferNoAttachmentsApiCase::begin_fbo_with_multisample_renderbuffer(GLenum target)
155 {
156 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
157
158 gl.genFramebuffers(1, &m_fbo);
159 gl.bindFramebuffer(target, m_fbo);
160 gl.genRenderbuffers(1, &m_renderbuffer);
161 gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
162 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, 101, 102);
163 gl.framebufferRenderbuffer(target, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffer);
164 expect_fbo_status(target, GL_FRAMEBUFFER_COMPLETE, "framebuffer with an attachment should be complete");
165 }
166
begin_fbo(GLenum target,unsigned test_case)167 void FramebufferNoAttachmentsApiCase::begin_fbo(GLenum target, unsigned test_case)
168 {
169 switch (test_case)
170 {
171 case 0:
172 begin_fbo_no_attachments(target);
173 break;
174 case 1:
175 begin_fbo_with_multisample_renderbuffer(target);
176 break;
177 }
178 }
179
end_fbo(GLenum target)180 void FramebufferNoAttachmentsApiCase::end_fbo(GLenum target)
181 {
182 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
183
184 gl.bindFramebuffer(target, 0);
185 gl.deleteFramebuffers(1, &m_fbo);
186 gl.deleteRenderbuffers(1, &m_renderbuffer);
187 gl.deleteTextures(1, &m_texture);
188 GLU_EXPECT_NO_ERROR(gl.getError(), "error deleting framebuffer / renderbuffer / texture");
189 m_fbo = 0;
190 m_renderbuffer = 0;
191 m_texture = 0;
192 }
193
iterate()194 FramebufferNoAttachmentsApiCase::IterateResult FramebufferNoAttachmentsApiCase::iterate()
195 {
196 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
197 bool isOk = true;
198 GLint binding;
199
200 GLenum targets[] = {
201 GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER,
202 GL_FRAMEBUFFER // equivalent to DRAW_FRAMEBUFFER
203 };
204 GLenum bindings[] = {
205 GL_DRAW_FRAMEBUFFER_BINDING, GL_READ_FRAMEBUFFER_BINDING,
206 GL_FRAMEBUFFER_BINDING // equivalent to DRAW_FRAMEBUFFER_BINDING
207 };
208 GLenum pnames[] = {GL_FRAMEBUFFER_DEFAULT_WIDTH, GL_FRAMEBUFFER_DEFAULT_HEIGHT, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
209 GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS};
210 GLenum enums_invalid_list[] = {GL_NOTEQUAL,
211 GL_FRONT_FACE,
212 GL_PACK_ROW_LENGTH,
213 GL_FIXED,
214 GL_LINEAR_MIPMAP_NEAREST,
215 GL_RGBA4,
216 GL_TEXTURE_MAX_LOD,
217 GL_RG32F,
218 GL_ALIASED_POINT_SIZE_RANGE,
219 GL_VERTEX_ATTRIB_ARRAY_TYPE,
220 GL_DRAW_BUFFER7,
221 GL_MAX_COMBINED_UNIFORM_BLOCKS,
222 GL_MAX_VARYING_COMPONENTS,
223 GL_SRGB,
224 GL_RGB8UI,
225 GL_IMAGE_BINDING_NAME,
226 GL_TEXTURE_2D_MULTISAMPLE,
227 GL_COMPRESSED_R11_EAC,
228 GL_BUFFER_DATA_SIZE};
229
230 GLint default_values[] = {0, 0, 0, GL_FALSE};
231 GLint valid_values[] = {103, 104, 4, GL_TRUE};
232 GLint min_values[] = {0, 0, 0, -1}; // Skip min_value test for boolean
233 GLint max_values[] = {0, 0, 0, -1}; // Skip max_value test for boolean.
234
235 unsigned num_targets = sizeof(targets) / sizeof(GLenum);
236 unsigned num_pnames = sizeof(pnames) / sizeof(GLenum);
237 unsigned num_enums_invalid_list = sizeof(enums_invalid_list) / sizeof(GLenum);
238
239 // Check for extra pnames allowed from supported extensions.
240 vector<GLenum> pnames_ext;
241 if (m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader") ||
242 m_context.getContextInfo().isExtensionSupported("GL_OES_geometry_shader"))
243 {
244 pnames_ext.push_back(GL_FRAMEBUFFER_DEFAULT_LAYERS);
245 }
246
247 // "Random" invalid enums distributed roughly evenly throughout 16bit enum number range.
248 vector<GLenum> enums_invalid;
249 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader") &&
250 !m_context.getContextInfo().isExtensionSupported("GL_OES_geometry_shader"))
251 {
252 enums_invalid.push_back(GL_FRAMEBUFFER_DEFAULT_LAYERS);
253 }
254 for (unsigned i = 0; i < num_enums_invalid_list; ++i)
255 {
256 enums_invalid.push_back(enums_invalid_list[i]);
257 }
258
259 gl.getIntegerv(GL_MAX_FRAMEBUFFER_WIDTH, &max_values[0]);
260 gl.getIntegerv(GL_MAX_FRAMEBUFFER_HEIGHT, &max_values[1]);
261 gl.getIntegerv(GL_MAX_FRAMEBUFFER_SAMPLES, &max_values[2]);
262 GLU_EXPECT_NO_ERROR(
263 gl.getError(),
264 "Querying GL_MAX_FRAMEBUFFER_WIDTH / GL_MAX_FRAMEBUFFER_HEIGHT / GL_MAX_FRAMEBUFFER_SAMPLES failed");
265
266 TCU_CHECK_MSG(max_values[0] >= 2048, "GL_MAX_FRAMEBUFFER_WIDTH does not meet minimum requirements");
267
268 TCU_CHECK_MSG(max_values[1] >= 2048, "GL_MAX_FRAMEBUFFER_HEIGHT does not meet minimum requirements");
269
270 TCU_CHECK_MSG(max_values[2] >= 4, "GL_MAX_FRAMEBUFFER_SAMPLES does not meet minimum requirements");
271
272 // It is valid to ask for number of samples > 0 and get
273 // implementation defined value which is above the requested
274 // value. We can use simple equality comparison by using
275 // reported maximum number of samples in our valid value
276 // set and get test.
277 valid_values[2] = max_values[2];
278
279 // Invalid target
280 for (unsigned i = 0; i < enums_invalid.size(); ++i)
281 {
282 GLenum target = enums_invalid[i];
283 bool is_valid = false;
284 for (unsigned j = 0; j < num_targets; ++j)
285 {
286 if (target == targets[j])
287 {
288 is_valid = true;
289 break;
290 }
291 }
292
293 if (is_valid)
294 continue;
295
296 for (unsigned j = 0; j < num_pnames; ++j)
297 {
298 gl.framebufferParameteri(target, pnames[j], valid_values[j]);
299 GLU_EXPECT_ERROR(gl.getError(), GL_INVALID_ENUM,
300 "Using glFramebufferParameteri() with invalid target should set GL_INVALID_ENUM");
301 }
302 }
303
304 // For all valid targets
305 for (unsigned i = 0; i < num_targets; ++i)
306 {
307 GLenum target = targets[i];
308
309 glGetIntegerv(bindings[i], &binding);
310 GLU_EXPECT_NO_ERROR(gl.getError(), "Valid call to glGetIntegerv() "
311 "should not set GL error");
312
313 // Using default framebuffer - GL_INVALID_OPERATION
314 for (unsigned j = 0; j < num_pnames; ++j)
315 {
316 GLint get_value = ~0;
317 GLenum pname = pnames[j];
318
319 gl.framebufferParameteri(target, pname, valid_values[j]);
320 if (binding == 0)
321 {
322 GLU_EXPECT_ERROR(gl.getError(), GL_INVALID_OPERATION,
323 "Using glFramebufferParameteri() on default framebuffer "
324 "should set GL_INVALID_OPERATION");
325 }
326 else
327 {
328 GLU_EXPECT_NO_ERROR(gl.getError(), "Valid call to glGetFramebufferParameteriv() "
329 "should not set GL error");
330 }
331
332 gl.getFramebufferParameteriv(target, pname, &get_value);
333
334 if (binding == 0)
335 {
336 GLU_EXPECT_ERROR(gl.getError(), GL_INVALID_OPERATION,
337 "Using glGetFramebufferParameteriv() on default framebuffer "
338 "should set GL_INVALID_OPERATION");
339 TCU_CHECK_MSG(get_value == ~0, "failed call to glGetFramebufferParameteriv() "
340 "should not modify params");
341 }
342 else
343 {
344 GLU_EXPECT_NO_ERROR(gl.getError(), "Valid call to glGetFramebufferParameteriv() "
345 "should not set GL error");
346 }
347 }
348
349 // j == 0 : fbo without attachments
350 // j == 1 : fbo with a multisample attachment
351 for (unsigned j = 0; j < 2; ++j)
352 {
353 glGetIntegerv(bindings[i], &binding);
354 GLU_EXPECT_NO_ERROR(gl.getError(), "Valid call to glGetIntegerv() "
355 "should not set GL error");
356
357 if (binding == 0)
358 {
359 // Check FBO status of default framebuffer
360 // TODO Check presence of default framebuffer - default framebuffer is complete
361 // only if it exists
362 expect_fbo_status(target, GL_FRAMEBUFFER_COMPLETE, "Default framebuffer should be complete");
363 }
364
365 // Invalid pname - GL_INVALID_VALUE
366 begin_fbo(target, j);
367 for (unsigned k = 0; k < enums_invalid.size(); ++k)
368 {
369 GLenum pname = enums_invalid[k];
370 bool is_valid = false;
371 for (unsigned m = 0; m < num_pnames; ++m)
372 {
373 if (pname == pnames[m])
374 {
375 is_valid = true;
376 break;
377 }
378 }
379
380 // Ignore any pnames that are added by extensions.
381 for (unsigned m = 0; m < pnames_ext.size(); ++m)
382 {
383 if (pname == pnames_ext[m])
384 {
385 is_valid = true;
386 break;
387 }
388 }
389
390 if (is_valid)
391 continue;
392
393 GLint get_value = ~0;
394
395 gl.framebufferParameteri(target, pname, 0);
396 GLU_EXPECT_ERROR(gl.getError(), GL_INVALID_ENUM,
397 "Calling glFramebufferParameteri() with invalid pname "
398 "should set GL_INVALID_ENUM");
399
400 gl.getFramebufferParameteriv(target, pname, &get_value);
401 GLU_EXPECT_ERROR(gl.getError(), GL_INVALID_ENUM,
402 "Calling glGetFramebufferParameteriv() with invalid pname "
403 "should set GL_INVALID_ENUM");
404
405 TCU_CHECK_MSG(get_value == ~0, "Calling glGetFramebufferParameteriv() with invalid pname "
406 "should not modify params");
407 }
408 end_fbo(target);
409
410 // Valid set and get
411 begin_fbo(target, j);
412 {
413 for (unsigned k = 0; k < num_pnames; ++k)
414 {
415 GLint get_value = ~0;
416
417 gl.framebufferParameteri(target, pnames[k], valid_values[k]);
418 GLU_EXPECT_NO_ERROR(gl.getError(), "Valid call to glFramebufferParameteri() "
419 "should not set GL error");
420
421 gl.getFramebufferParameteriv(target, pnames[k], &get_value);
422 GLU_EXPECT_NO_ERROR(gl.getError(), "Valid call to glGetFramebufferParameteriv() "
423 "should not set GL error");
424
425 TCU_CHECK_MSG(get_value == valid_values[k],
426 "glGetFramebufferParameteriv() "
427 "should have returned the value set with glFramebufferParameteri()");
428 }
429
430 // After valid set, check FBO status of user FBO
431 expect_fbo_status(target, GL_FRAMEBUFFER_COMPLETE,
432 "Framebuffer should be complete after setting valid valid");
433 }
434 end_fbo(target);
435
436 // Negative or too large values - GL_INVALID_VALUE
437 // Also check for correct default values
438 begin_fbo(target, j);
439 for (unsigned k = 0; k < num_pnames; ++k)
440 {
441 GLint get_value = ~0;
442 GLenum pname = pnames[k];
443
444 if (min_values[k] >= 0)
445 {
446 gl.framebufferParameteri(target, pname, min_values[k] - 1);
447 GLU_EXPECT_ERROR(gl.getError(), GL_INVALID_VALUE,
448 "Calling glFramebufferParameteri() with negative value "
449 "should set GL_INVALID_VALUE");
450 }
451
452 gl.getFramebufferParameteriv(target, pname, &get_value);
453 GLU_EXPECT_NO_ERROR(gl.getError(), "Valid call to glGetFramebufferParameteriv() "
454 "should not set GL error");
455
456 TCU_CHECK_MSG(get_value == default_values[k], "glGetFramebufferParameteriv() "
457 "did not return a valid default value");
458
459 get_value = ~0;
460 if (max_values[k] >= 0)
461 {
462 gl.framebufferParameteri(target, pname, max_values[k] + 1);
463 GLU_EXPECT_ERROR(gl.getError(), GL_INVALID_VALUE,
464 "Calling glFramebufferParameteri() too large value "
465 "should set GL_INVALID_VALUE");
466 }
467
468 gl.getFramebufferParameteriv(target, pname, &get_value);
469 GLU_EXPECT_NO_ERROR(gl.getError(), "Valid call to glGetFramebufferParameteriv() "
470 "should not set GL error");
471
472 TCU_CHECK_MSG(get_value == default_values[k], "glGetFramebufferParameteriv() "
473 "did not return a valid default value");
474 }
475 end_fbo(target);
476 }
477 }
478
479 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail");
480 return STOP;
481 }
482
483 // Draw with imageStore, validate that framebuffer
484 // default width and height is respected.
485 class FramebufferNoAttachmentsRenderCase : public FramebufferNoAttachmentsBaseCase
486 {
487 public:
488 FramebufferNoAttachmentsRenderCase(Context &context, const char *name, const char *description);
489
490 IterateResult iterate();
491 void deinit(void);
492
493 private:
494 GLuint m_program;
495 GLuint m_vertex_shader;
496 GLuint m_fragment_shader;
497 GLuint m_vao;
498 GLuint m_framebuffer;
499 GLuint m_texture;
500 };
501
FramebufferNoAttachmentsRenderCase(Context & context,const char * name,const char * description)502 FramebufferNoAttachmentsRenderCase::FramebufferNoAttachmentsRenderCase(Context &context, const char *name,
503 const char *description)
504 : FramebufferNoAttachmentsBaseCase(context, name, description)
505 , m_program(0)
506 , m_vertex_shader(0)
507 , m_fragment_shader(0)
508 , m_vao(0)
509 , m_framebuffer(0)
510 , m_texture(0)
511 {
512 }
513
deinit(void)514 void FramebufferNoAttachmentsRenderCase::deinit(void)
515 {
516 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
517 gl.deleteShader(m_vertex_shader);
518 gl.deleteShader(m_fragment_shader);
519 gl.deleteProgram(m_program);
520 gl.deleteVertexArrays(1, &m_vao);
521 gl.deleteTextures(1, &m_texture);
522 gl.deleteFramebuffers(1, &m_framebuffer);
523 }
524
iterate()525 FramebufferNoAttachmentsRenderCase::IterateResult FramebufferNoAttachmentsRenderCase::iterate()
526 {
527 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
528 int max_fragment_image_uniforms;
529 bool isOk = true;
530
531 // Check GL_MAX_FRAGMENT_IMAGE_UNIFORMS, we need at least one
532 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms);
533 GLU_EXPECT_NO_ERROR(gl.getError(), "Querying GL_MAX_FRAGMENT_IMAGE_UNIFORMS");
534
535 if (max_fragment_image_uniforms < 1)
536 {
537 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_MAX_FRAGMENT_IMAGE_UNIFORMS<1");
538 return STOP;
539 }
540
541 // Create program and VAO
542 {
543 const char *vs_source = "#version 310 es\n"
544 "void main()\n"
545 "{\n"
546 " if (gl_VertexID == 0) gl_Position = vec4(-1, -1, 0, 1);\n"
547 " else if (gl_VertexID == 1) gl_Position = vec4(-1, 1, 0, 1);\n"
548 " else if (gl_VertexID == 2) gl_Position = vec4( 1, 1, 0, 1);\n"
549 " else gl_Position = vec4( 1, -1, 0, 1);\n"
550 "}\n";
551
552 const char *fs_source = "#version 310 es\n"
553 "precision highp uimage2D;\n"
554 "layout(r32ui) uniform uimage2D data;\n"
555 "void main()\n"
556 "{\n"
557 " ivec2 image_info = ivec2(gl_FragCoord.xy);\n"
558 " imageStore(data, image_info, uvec4(1, 2, 3, 4));\n"
559 "}\n";
560
561 m_program = gl.createProgram();
562 m_vertex_shader = gl.createShader(GL_VERTEX_SHADER);
563 m_fragment_shader = gl.createShader(GL_FRAGMENT_SHADER);
564 gl.shaderSource(m_vertex_shader, 1, &vs_source, NULL);
565 gl.compileShader(m_vertex_shader);
566 gl.attachShader(m_program, m_vertex_shader);
567 gl.shaderSource(m_fragment_shader, 1, &fs_source, NULL);
568 gl.compileShader(m_fragment_shader);
569 gl.attachShader(m_program, m_fragment_shader);
570 gl.linkProgram(m_program);
571 gl.useProgram(m_program);
572 gl.genVertexArrays(1, &m_vao);
573 gl.bindVertexArray(m_vao);
574 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating program and VAO");
575 }
576
577 // Create framebuffer with no attachments
578 gl.genFramebuffers(1, &m_framebuffer);
579 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer);
580 gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 32);
581 gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 32);
582 expect_fbo_status(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE, "Creating framebuffer with no attachments");
583
584 // Create texture and clear it, temporarily attaching to FBO
585 {
586 GLuint zero[] = {0, 0, 0, 0};
587 gl.genTextures(1, &m_texture);
588 gl.bindTexture(GL_TEXTURE_2D, m_texture);
589 gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 64, 64);
590 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
591 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
592 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
593 gl.viewport(0, 0, 64, 64);
594 gl.clearBufferuiv(GL_COLOR, 0, zero);
595 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
596 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating and clearing texture");
597 }
598
599 // Draw using storeImage
600 gl.drawBuffers(0, NULL);
601 gl.viewport(0, 0, 64, 64);
602 gl.bindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
603 gl.drawArrays(GL_TRIANGLE_FAN, 0, 4);
604 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
605 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw with imageStore");
606
607 // Read and validate texture contents
608 {
609 GLuint pixels[64 * 64 * 4];
610 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
611 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_framebuffer);
612 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
613 expect_fbo_status(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE, "ReadPixels to texture for validation");
614 gl.readPixels(0, 0, 64, 64, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
615 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels");
616
617 for (unsigned y = 0; y < 64; ++y)
618 {
619 for (unsigned x = 0; x < 64; ++x)
620 {
621 GLuint expected_value = (x < 32) && (y < 32) ? 1 : 0;
622 GLuint value = pixels[(y * 64 + x) * 4];
623 TCU_CHECK_MSG(value == expected_value, "Validating draw with imageStore");
624 }
625 }
626 }
627
628 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail");
629 return STOP;
630 }
631
FramebufferNoAttachmentsTests(Context & context)632 FramebufferNoAttachmentsTests::FramebufferNoAttachmentsTests(Context &context)
633 : TestCaseGroup(context, "framebuffer_no_attachments", "Framebuffer no attachments tests")
634 {
635 }
636
~FramebufferNoAttachmentsTests(void)637 FramebufferNoAttachmentsTests::~FramebufferNoAttachmentsTests(void)
638 {
639 }
640
init(void)641 void FramebufferNoAttachmentsTests::init(void)
642 {
643 addChild(new FramebufferNoAttachmentsApiCase(m_context, "api", "Basic API verification"));
644
645 addChild(new FramebufferNoAttachmentsRenderCase(m_context, "render", "Rendering with imageStore"));
646 }
647
648 } // namespace glcts
649