1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2017 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 glcRobustnessTests.cpp
21 * \brief Conformance tests for the Robustness feature functionality.
22 */ /*-------------------------------------------------------------------*/
23
24 #include "glcRobustnessTests.hpp"
25 #include "deSharedPtr.hpp"
26 #include "glcRobustBufferAccessBehaviorTests.hpp"
27 #include "gluContextInfo.hpp"
28 #include "gluPlatform.hpp"
29 #include "gluRenderContext.hpp"
30 #include "glwEnums.hpp"
31 #include "glwFunctions.hpp"
32 #include "tcuCommandLine.hpp"
33 #include "tcuTestLog.hpp"
34 #include <cstring>
35
36 using namespace glw;
37 using namespace glcts::RobustBufferAccessBehavior;
38
39 namespace glcts
40 {
41
42 namespace ResetNotificationStrategy
43 {
44
45 class RobustnessBase : public tcu::TestCase
46 {
47 public:
48 RobustnessBase(tcu::TestContext &testCtx, const char *name, const char *description, glu::ApiType apiType);
49
50 glu::RenderContext *createRobustContext(glu::ResetNotificationStrategy reset);
51
52 private:
53 glu::ApiType m_ApiType;
54 };
55
RobustnessBase(tcu::TestContext & testCtx,const char * name,const char * description,glu::ApiType apiType)56 RobustnessBase::RobustnessBase(tcu::TestContext &testCtx, const char *name, const char *description,
57 glu::ApiType apiType)
58 : tcu::TestCase(testCtx, name, description)
59 , m_ApiType(apiType)
60 {
61 }
62
createRobustContext(glu::ResetNotificationStrategy reset)63 glu::RenderContext *RobustnessBase::createRobustContext(glu::ResetNotificationStrategy reset)
64 {
65 /* Create test context to verify if GL_KHR_robustness extension is available */
66 {
67 deqp::Context context(m_testCtx, glu::ContextType(m_ApiType));
68 if (!context.getContextInfo().isExtensionSupported("GL_KHR_robustness") &&
69 !contextSupports(context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
70 {
71 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_robustness extension not supported");
72 return NULL;
73 }
74 }
75
76 glu::RenderConfig renderCfg(glu::ContextType(m_ApiType, glu::CONTEXT_ROBUST));
77 const tcu::CommandLine &commandLine = m_testCtx.getCommandLine();
78 glu::parseRenderConfig(&renderCfg, commandLine);
79
80 if (commandLine.getSurfaceType() == tcu::SURFACETYPE_WINDOW)
81 renderCfg.resetNotificationStrategy = reset;
82 else
83 throw tcu::NotSupportedError("Test not supported in non-windowed context");
84
85 /* Try to create core/es robusness context */
86 return createRenderContext(m_testCtx.getPlatform(), commandLine, renderCfg);
87 }
88
89 class NoResetNotificationCase : public RobustnessBase
90 {
91 typedef glw::GLenum(GLW_APIENTRY *PFNGLGETGRAPHICSRESETSTATUS)();
92
93 public:
NoResetNotificationCase(tcu::TestContext & testCtx,const char * name,const char * description,glu::ApiType apiType)94 NoResetNotificationCase(tcu::TestContext &testCtx, const char *name, const char *description, glu::ApiType apiType)
95 : RobustnessBase(testCtx, name, description, apiType)
96 {
97 }
98
iterate(void)99 virtual IterateResult iterate(void)
100 {
101 glu::ResetNotificationStrategy strategy = glu::RESET_NOTIFICATION_STRATEGY_NO_RESET_NOTIFICATION;
102 de::SharedPtr<glu::RenderContext> robustContext(createRobustContext(strategy));
103 if (!robustContext.get())
104 return STOP;
105
106 glw::GLint reset = 0;
107
108 const glw::Functions &gl = robustContext->getFunctions();
109 gl.getIntegerv(GL_RESET_NOTIFICATION_STRATEGY, &reset);
110 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv");
111
112 if (reset != GL_NO_RESET_NOTIFICATION)
113 {
114 m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! glGet returned wrong value [" << reset
115 << ", expected " << GL_NO_RESET_NOTIFICATION << "]." << tcu::TestLog::EndMessage;
116
117 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
118 return STOP;
119 }
120
121 glw::GLint status = gl.getGraphicsResetStatus();
122 if (status != GL_NO_ERROR)
123 {
124 m_testCtx.getLog() << tcu::TestLog::Message
125 << "Test failed! glGetGraphicsResetStatus returned wrong value [" << status
126 << ", expected " << GL_NO_ERROR << "]." << tcu::TestLog::EndMessage;
127
128 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
129 return STOP;
130 }
131
132 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
133 return STOP;
134 }
135 };
136
137 class LoseContextOnResetCase : public RobustnessBase
138 {
139 public:
LoseContextOnResetCase(tcu::TestContext & testCtx,const char * name,const char * description,glu::ApiType apiType)140 LoseContextOnResetCase(tcu::TestContext &testCtx, const char *name, const char *description, glu::ApiType apiType)
141 : RobustnessBase(testCtx, name, description, apiType)
142 {
143 }
144
iterate(void)145 virtual IterateResult iterate(void)
146 {
147 glu::ResetNotificationStrategy strategy = glu::RESET_NOTIFICATION_STRATEGY_LOSE_CONTEXT_ON_RESET;
148 de::SharedPtr<glu::RenderContext> robustContext(createRobustContext(strategy));
149 if (!robustContext.get())
150 return STOP;
151
152 glw::GLint reset = 0;
153
154 const glw::Functions &gl = robustContext->getFunctions();
155 gl.getIntegerv(GL_RESET_NOTIFICATION_STRATEGY, &reset);
156 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv");
157
158 if (reset != GL_LOSE_CONTEXT_ON_RESET)
159 {
160 m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! glGet returned wrong value [" << reset
161 << ", expected " << GL_LOSE_CONTEXT_ON_RESET << "]." << tcu::TestLog::EndMessage;
162
163 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
164 return STOP;
165 }
166
167 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
168 return STOP;
169 }
170 };
171
172 } // namespace ResetNotificationStrategy
173
174 namespace RobustBufferAccessBehavior
175 {
176
createContext(tcu::TestContext & testCtx,glu::ApiType apiType)177 static deqp::Context *createContext(tcu::TestContext &testCtx, glu::ApiType apiType)
178 {
179 deqp::Context *context = new deqp::Context(testCtx, glu::ContextType(apiType));
180 if (!context)
181 {
182 testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Pointer to context is NULL.");
183 return DE_NULL;
184 }
185
186 if (!(contextSupports(context->getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
187 (context->getContextInfo().isExtensionSupported("GL_KHR_robustness") &&
188 context->getContextInfo().isExtensionSupported("GL_KHR_robust_buffer_access_behavior"))))
189 {
190 testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
191 delete context;
192 return DE_NULL;
193 }
194
195 return context;
196 }
197
198 /** Implementation of test GetnUniformTest. Description follows:
199 *
200 * This test verifies if read uniform variables to the buffer with bufSize less than expected result with GL_INVALID_OPERATION error;
201 **/
202 class GetnUniformTest : public tcu::TestCase
203 {
204 public:
205 /* Public methods */
206 GetnUniformTest(tcu::TestContext &testCtx, glu::ApiType apiType);
~GetnUniformTest()207 virtual ~GetnUniformTest()
208 {
209 }
210
211 /* Public methods inherited from TestCase */
212 virtual tcu::TestNode::IterateResult iterate(void);
213
214 private:
215 /* Private methods */
216 std::string getComputeShader(bool glslES320);
217
218 bool verifyResult(const void *inputData, const void *resultData, int size, const char *method);
219 bool verifyError(glw::GLint error, glw::GLint expectedError, const char *method);
220
221 glu::ApiType m_ApiType;
222 };
223
224 /** Constructor
225 *
226 * @param context Test context
227 **/
GetnUniformTest(tcu::TestContext & testCtx,glu::ApiType apiType)228 GetnUniformTest::GetnUniformTest(tcu::TestContext &testCtx, glu::ApiType apiType)
229 : tcu::TestCase(testCtx, "getnuniform",
230 "Verifies if read uniform variables to the buffer with bufSize less than "
231 "expected result with GL_INVALID_OPERATION")
232 , m_ApiType(apiType)
233 {
234 /* Nothing to be done here */
235 }
236
237 /** Execute test
238 *
239 * @return tcu::TestNode::STOP
240 **/
iterate()241 tcu::TestNode::IterateResult GetnUniformTest::iterate()
242 {
243 de::SharedPtr<deqp::Context> context(createContext(m_testCtx, m_ApiType));
244 if (!context.get())
245 return STOP;
246
247 glu::RenderContext &renderContext = context->getRenderContext();
248 const Functions &gl = renderContext.getFunctions();
249
250 const GLfloat input4f[] = {1.0f, 5.4f, 3.14159f, 1.28f};
251 const GLint input3i[] = {10, -20, -30};
252 const GLuint input4ui[] = {10, 20, 30, 40};
253
254 /* Test result indicator */
255 bool test_result = true;
256
257 /* Iterate over all cases */
258 Program program(gl);
259
260 /* Compute Shader */
261 bool glslES320 = contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
262 const std::string &cs = getComputeShader(glslES320);
263
264 /* Shaders initialization */
265 program.Init(cs /* cs */, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
266 program.Use();
267
268 /* Initialize shader storage buffer */
269 GLuint buf;
270
271 gl.genBuffers(1, &buf);
272 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
273
274 gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buf);
275 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
276
277 gl.bufferData(GL_SHADER_STORAGE_BUFFER, 16, DE_NULL, GL_STREAM_DRAW);
278 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
279
280 /* passing uniform values */
281 gl.programUniform4fv(program.m_id, 11, 1, input4f);
282 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramUniform4fv");
283
284 gl.programUniform3iv(program.m_id, 12, 1, input3i);
285 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramUniform3iv");
286
287 gl.programUniform4uiv(program.m_id, 13, 1, input4ui);
288 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramUniform4uiv");
289
290 gl.dispatchCompute(1, 1, 1);
291 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
292
293 /* veryfing gfetnUniform error messages */
294 GLfloat result4f[4];
295 GLint result3i[3];
296 GLuint result4ui[4];
297
298 gl.getnUniformfv(program.m_id, 11, sizeof(GLfloat) * 4, result4f);
299 test_result = test_result && verifyResult((void *)input4f, (void *)result4f, sizeof(GLfloat) * 4,
300 "getnUniformfv [false negative]");
301 test_result = test_result && verifyError(gl.getError(), GL_NO_ERROR, "getnUniformfv [false negative]");
302
303 gl.getnUniformfv(program.m_id, 11, sizeof(GLfloat) * 3, result4f);
304 test_result = test_result && verifyError(gl.getError(), GL_INVALID_OPERATION, "getnUniformfv [false positive]");
305
306 gl.getnUniformiv(program.m_id, 12, sizeof(GLint) * 3, result3i);
307 test_result = test_result &&
308 verifyResult((void *)input3i, (void *)result3i, sizeof(GLint) * 3, "getnUniformiv [false negative]");
309 test_result = test_result && verifyError(gl.getError(), GL_NO_ERROR, "getnUniformiv [false negative]");
310
311 gl.getnUniformiv(program.m_id, 12, sizeof(GLint) * 2, result3i);
312 test_result = test_result && verifyError(gl.getError(), GL_INVALID_OPERATION, "getnUniformiv [false positive]");
313
314 gl.getnUniformuiv(program.m_id, 13, sizeof(GLuint) * 4, result4ui);
315 test_result = test_result && verifyResult((void *)input4ui, (void *)result4ui, sizeof(GLuint) * 4,
316 "getnUniformuiv [false negative]");
317 test_result = test_result && verifyError(gl.getError(), GL_NO_ERROR, "getnUniformuiv [false negative]");
318
319 gl.getnUniformuiv(program.m_id, 13, sizeof(GLuint) * 3, result4ui);
320 test_result = test_result && verifyError(gl.getError(), GL_INVALID_OPERATION, "getnUniformuiv [false positive]");
321
322 /* Set result */
323 if (true == test_result)
324 {
325 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
326 }
327 else
328 {
329 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
330 }
331
332 gl.deleteBuffers(1, &buf);
333
334 /* Done */
335 return tcu::TestNode::STOP;
336 }
337
getComputeShader(bool glslES320)338 std::string GetnUniformTest::getComputeShader(bool glslES320)
339 {
340 std::stringstream shader;
341 shader << "#version " << (glslES320 ? "320 es\n" : "450\n");
342 shader << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
343 "layout (location = 11) uniform vec4 inputf;\n"
344 "layout (location = 12) uniform ivec3 inputi;\n"
345 "layout (location = 13) uniform uvec4 inputu;\n"
346 "layout (std140, binding = 0) buffer ssbo {\n"
347 " float valuef;\n"
348 " int valuei;\n"
349 " uint valueu;\n"
350 "};\n"
351 "void main()\n"
352 "{\n"
353 " valuef = inputf.r + inputf.g + inputf.b + inputf.a;\n"
354 " valuei = inputi.r + inputi.g + inputi.b;\n"
355 " valueu = inputu.r + inputu.g + inputu.b + inputu.a;\n"
356 "}\n";
357 return shader.str();
358 }
359
verifyResult(const void * inputData,const void * resultData,int size,const char * method)360 bool GetnUniformTest::verifyResult(const void *inputData, const void *resultData, int size, const char *method)
361 {
362 int diff = memcmp(inputData, resultData, size);
363 if (diff != 0)
364 {
365 m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! " << method << " result is not as expected."
366 << tcu::TestLog::EndMessage;
367
368 return false;
369 }
370
371 return true;
372 }
373
verifyError(GLint error,GLint expectedError,const char * method)374 bool GetnUniformTest::verifyError(GLint error, GLint expectedError, const char *method)
375 {
376 if (error != expectedError)
377 {
378 m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! " << method << " throws unexpected error ["
379 << error << "]." << tcu::TestLog::EndMessage;
380
381 return false;
382 }
383
384 return true;
385 }
386
387 /** Implementation of test ReadnPixelsTest. Description follows:
388 *
389 * This test verifies if read pixels to the buffer with bufSize less than expected result with GL_INVALID_OPERATION error;
390 **/
391 class ReadnPixelsTest : public tcu::TestCase
392 {
393 public:
394 /* Public methods */
395 ReadnPixelsTest(tcu::TestContext &testCtx, glu::ApiType apiType);
~ReadnPixelsTest()396 virtual ~ReadnPixelsTest()
397 {
398 }
399
400 /* Public methods inherited from TestCase */
401 virtual tcu::TestNode::IterateResult iterate(void);
402
403 private:
404 /* Private methods */
405 void cleanTexture(deqp::Context &context, glw::GLuint texture_id);
406 bool verifyResults(deqp::Context &context);
407 bool verifyError(glw::GLint error, glw::GLint expectedError, const char *method);
408
409 glu::ApiType m_ApiType;
410 };
411
412 /** Constructor
413 *
414 * @param context Test context
415 **/
ReadnPixelsTest(tcu::TestContext & testCtx,glu::ApiType apiType)416 ReadnPixelsTest::ReadnPixelsTest(tcu::TestContext &testCtx, glu::ApiType apiType)
417 : tcu::TestCase(testCtx, "readnpixels",
418 "Verifies if read pixels to the buffer with bufSize less than expected result "
419 "with GL_INVALID_OPERATION error")
420 , m_ApiType(apiType)
421 {
422 /* Nothing to be done here */
423 }
424
425 /** Execute test
426 *
427 * @return tcu::TestNode::STOP
428 **/
iterate()429 tcu::TestNode::IterateResult ReadnPixelsTest::iterate()
430 {
431 de::SharedPtr<deqp::Context> context(createContext(m_testCtx, m_ApiType));
432 if (!context.get())
433 return STOP;
434
435 static const GLuint elements[] = {
436 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 1,
437 };
438
439 static const GLfloat vertices[] = {
440 0.0f, 0.0f, 0.0f, 1.0f, /* 0 */
441 -1.0f, 0.0f, 0.0f, 1.0f, /* 1 */
442 -1.0f, 1.0f, 0.0f, 1.0f, /* 2 */
443 0.0f, 1.0f, 0.0f, 1.0f, /* 3 */
444 1.0f, 1.0f, 0.0f, 1.0f, /* 4 */
445 1.0f, 0.0f, 0.0f, 1.0f, /* 5 */
446 1.0f, -1.0f, 0.0f, 1.0f, /* 6 */
447 0.0f, -1.0f, 0.0f, 1.0f, /* 7 */
448 -1.0f, -1.0f, 0.0f, 1.0f, /* 8 */
449 };
450
451 bool glslES320 = contextSupports(context->getRenderContext().getType(), glu::ApiType::es(3, 2));
452 std::string fs("#version ");
453 fs += (glslES320 ? "320 es\n" : "450\n");
454 fs += "layout (location = 0) out lowp uvec4 out_fs_color;\n"
455 "\n"
456 "void main()\n"
457 "{\n"
458 " out_fs_color = uvec4(1, 0, 0, 1);\n"
459 "}\n"
460 "\n";
461
462 std::string vs("#version ");
463 vs += (glslES320 ? "320 es\n" : "450\n");
464 vs += "layout (location = 0) in vec4 in_vs_position;\n"
465 "\n"
466 "void main()\n"
467 "{\n"
468 " gl_Position = in_vs_position;\n"
469 "}\n"
470 "\n";
471
472 static const GLuint height = 8;
473 static const GLuint width = 8;
474 static const GLuint n_vertices = 24;
475
476 /* GL entry points */
477 const Functions &gl = context->getRenderContext().getFunctions();
478
479 /* Test case objects */
480 Program program(gl);
481 Texture texture(gl);
482 Buffer elements_buffer(gl);
483 Buffer vertices_buffer(gl);
484 VertexArray vao(gl);
485
486 /* Vertex array initialization */
487 VertexArray::Generate(gl, vao.m_id);
488 VertexArray::Bind(gl, vao.m_id);
489
490 /* Texture initialization */
491 Texture::Generate(gl, texture.m_id);
492 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
493 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R8UI, width, height, 0);
494 Texture::Bind(gl, 0, GL_TEXTURE_2D);
495
496 /* Framebuffer initialization */
497 GLuint fbo;
498 gl.genFramebuffers(1, &fbo);
499 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
500 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
501 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
502 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.m_id, 0);
503 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
504
505 /* Buffers initialization */
506 elements_buffer.InitData(GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(elements), elements);
507 vertices_buffer.InitData(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(vertices), vertices);
508
509 /* Shaders initialization */
510 program.Init("" /* cs */, fs, "" /* gs */, "" /* tcs */, "" /* tes */, vs);
511 Program::Use(gl, program.m_id);
512
513 /* Vertex buffer initialization */
514 vertices_buffer.Bind();
515 gl.bindVertexBuffer(0 /* bindindex = location */, vertices_buffer.m_id, 0 /* offset */, 16 /* stride */);
516 gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 16, NULL);
517 gl.enableVertexAttribArray(0 /* location */);
518
519 /* Binding elements/indices buffer */
520 elements_buffer.Bind();
521
522 cleanTexture(*context, texture.m_id);
523
524 gl.drawElements(GL_TRIANGLES, n_vertices, GL_UNSIGNED_INT, 0 /* indices */);
525 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
526
527 /* Set result */
528 if (verifyResults(*context))
529 {
530 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
531 }
532 else
533 {
534 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
535 }
536
537 /* Done */
538 return tcu::TestNode::STOP;
539 }
540
541 /** Fill texture with value 128
542 *
543 * @param texture_id Id of texture
544 **/
cleanTexture(deqp::Context & context,glw::GLuint texture_id)545 void ReadnPixelsTest::cleanTexture(deqp::Context &context, glw::GLuint texture_id)
546 {
547 static const GLuint height = 8;
548 static const GLuint width = 8;
549
550 const Functions &gl = context.getRenderContext().getFunctions();
551
552 GLubyte pixels[width * height];
553 for (GLuint i = 0; i < width * height; ++i)
554 {
555 pixels[i] = 64;
556 }
557
558 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
559
560 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 0 /* depth */,
561 GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels);
562
563 /* Unbind */
564 Texture::Bind(gl, 0, GL_TEXTURE_2D);
565 }
566
567 /** Verifies glReadnPixels results
568 *
569 * @return true when glReadnPixels , false otherwise
570 **/
verifyResults(deqp::Context & context)571 bool ReadnPixelsTest::verifyResults(deqp::Context &context)
572 {
573 static const GLuint height = 8;
574 static const GLuint width = 8;
575 static const GLuint pixel_size = 4 * sizeof(GLuint);
576
577 const Functions &gl = context.getRenderContext().getFunctions();
578
579 //Valid buffer size test
580 const GLint bufSizeValid = width * height * pixel_size;
581 GLubyte pixelsValid[bufSizeValid];
582
583 gl.readnPixels(0, 0, width, height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, bufSizeValid, pixelsValid);
584 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadnPixels");
585
586 //Verify glReadnPixels result
587 for (unsigned int i = 0; i < width * height; ++i)
588 {
589 const size_t offset = i * pixel_size;
590 const GLuint value = *(GLuint *)(pixelsValid + offset);
591
592 if (value != 1)
593 {
594 context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid pixel value: " << value
595 << ". Offset: " << offset << tcu::TestLog::EndMessage;
596 return false;
597 }
598 }
599
600 //Invalid buffer size test
601 const GLint bufSizeInvalid = width * height * pixel_size - 1;
602 GLubyte pixelsInvalid[bufSizeInvalid];
603
604 gl.readnPixels(0, 0, width, height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, bufSizeInvalid, pixelsInvalid);
605 if (!verifyError(gl.getError(), GL_INVALID_OPERATION, "ReadnPixels [false positive]"))
606 return false;
607
608 return true;
609 }
610
611 /** Verify operation errors
612 *
613 * @param error OpenGL ES error code
614 * @param expectedError Expected error code
615 * @param method Method name marker
616 *
617 * @return true when error is as expected, false otherwise
618 **/
verifyError(GLint error,GLint expectedError,const char * method)619 bool ReadnPixelsTest::verifyError(GLint error, GLint expectedError, const char *method)
620 {
621 if (error != expectedError)
622 {
623 m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! " << method << " throws unexpected error ["
624 << error << "]." << tcu::TestLog::EndMessage;
625
626 return false;
627 }
628
629 return true;
630 }
631
632 } // namespace RobustBufferAccessBehavior
633
RobustnessTests(tcu::TestContext & testCtx,glu::ApiType apiType)634 RobustnessTests::RobustnessTests(tcu::TestContext &testCtx, glu::ApiType apiType)
635 : tcu::TestCaseGroup(testCtx, "robustness",
636 "Verifies API coverage and functionality of GL_KHR_robustness extension.")
637 , m_ApiType(apiType)
638 {
639 }
640
init(void)641 void RobustnessTests::init(void)
642 {
643 tcu::TestCaseGroup::init();
644
645 try
646 {
647 addChild(new ResetNotificationStrategy::NoResetNotificationCase(
648 m_testCtx, "no_reset_notification", "Verifies if NO_RESET_NOTIFICATION strategy works as expected.",
649 m_ApiType));
650 addChild(new ResetNotificationStrategy::LoseContextOnResetCase(
651 m_testCtx, "lose_context_on_reset", "Verifies if LOSE_CONTEXT_ON_RESET strategy works as expected.",
652 m_ApiType));
653
654 addChild(new RobustBufferAccessBehavior::GetnUniformTest(m_testCtx, m_ApiType));
655 addChild(new RobustBufferAccessBehavior::ReadnPixelsTest(m_testCtx, m_ApiType));
656 }
657 catch (...)
658 {
659 // Destroy context.
660 tcu::TestCaseGroup::deinit();
661 throw;
662 }
663 }
664
665 } // namespace glcts
666