• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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), m_ApiType(apiType)
59 {
60 }
61 
createRobustContext(glu::ResetNotificationStrategy reset)62 glu::RenderContext* RobustnessBase::createRobustContext(glu::ResetNotificationStrategy reset)
63 {
64 	/* Create test context to verify if GL_KHR_robustness extension is available */
65 	{
66 		deqp::Context context(m_testCtx, glu::ContextType(m_ApiType));
67 		if (!context.getContextInfo().isExtensionSupported("GL_KHR_robustness") &&
68 			!contextSupports(context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
69 		{
70 			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED,
71 									"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 } // ResetNotificationStrategy namespace
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", "Verifies if read uniform variables to the buffer with bufSize less than "
230 											"expected result with GL_INVALID_OPERATION")
231 	, m_ApiType(apiType)
232 {
233 	/* Nothing to be done here */
234 }
235 
236 /** Execute test
237  *
238  * @return tcu::TestNode::STOP
239  **/
iterate()240 tcu::TestNode::IterateResult GetnUniformTest::iterate()
241 {
242 	de::SharedPtr<deqp::Context> context(createContext(m_testCtx, m_ApiType));
243 	if (!context.get())
244 		return STOP;
245 
246 	glu::RenderContext& renderContext = context->getRenderContext();
247 	const Functions& gl = renderContext.getFunctions();
248 
249 	const GLfloat input4f[]  = { 1.0f, 5.4f, 3.14159f, 1.28f };
250 	const GLint   input3i[]  = { 10, -20, -30 };
251 	const GLuint  input4ui[] = { 10, 20, 30, 40 };
252 
253 	/* Test result indicator */
254 	bool test_result = true;
255 
256 	/* Iterate over all cases */
257 	Program program(gl);
258 
259 	/* Compute Shader */
260 	bool			   glslES320 = contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
261 	const std::string& cs		 = getComputeShader(glslES320);
262 
263 	/* Shaders initialization */
264 	program.Init(cs /* cs */, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
265 	program.Use();
266 
267 	/* Initialize shader storage buffer */
268 	GLuint buf;
269 
270 	gl.genBuffers(1, &buf);
271 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
272 
273 	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buf);
274 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
275 
276 	gl.bufferData(GL_SHADER_STORAGE_BUFFER, 16, DE_NULL, GL_STREAM_DRAW);
277 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
278 
279 	/* passing uniform values */
280 	gl.programUniform4fv(program.m_id, 11, 1, input4f);
281 	GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramUniform4fv");
282 
283 	gl.programUniform3iv(program.m_id, 12, 1, input3i);
284 	GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramUniform3iv");
285 
286 	gl.programUniform4uiv(program.m_id, 13, 1, input4ui);
287 	GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramUniform4uiv");
288 
289 	gl.dispatchCompute(1, 1, 1);
290 	GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
291 
292 	/* veryfing gfetnUniform error messages */
293 	GLfloat result4f[4];
294 	GLint   result3i[3];
295 	GLuint  result4ui[4];
296 
297 	gl.getnUniformfv(program.m_id, 11, sizeof(GLfloat) * 4, result4f);
298 	test_result = test_result &&
299 				  verifyResult((void*)input4f, (void*)result4f, sizeof(GLfloat) * 4, "getnUniformfv [false negative]");
300 	test_result = test_result && verifyError(gl.getError(), GL_NO_ERROR, "getnUniformfv [false negative]");
301 
302 	gl.getnUniformfv(program.m_id, 11, sizeof(GLfloat) * 3, result4f);
303 	test_result = test_result && verifyError(gl.getError(), GL_INVALID_OPERATION, "getnUniformfv [false positive]");
304 
305 	gl.getnUniformiv(program.m_id, 12, sizeof(GLint) * 3, result3i);
306 	test_result = test_result &&
307 				  verifyResult((void*)input3i, (void*)result3i, sizeof(GLint) * 3, "getnUniformiv [false negative]");
308 	test_result = test_result && verifyError(gl.getError(), GL_NO_ERROR, "getnUniformiv [false negative]");
309 
310 	gl.getnUniformiv(program.m_id, 12, sizeof(GLint) * 2, result3i);
311 	test_result = test_result && verifyError(gl.getError(), GL_INVALID_OPERATION, "getnUniformiv [false positive]");
312 
313 	gl.getnUniformuiv(program.m_id, 13, sizeof(GLuint) * 4, result4ui);
314 	test_result = test_result && verifyResult((void*)input4ui, (void*)result4ui, sizeof(GLuint) * 4,
315 											  "getnUniformuiv [false negative]");
316 	test_result = test_result && verifyError(gl.getError(), GL_NO_ERROR, "getnUniformuiv [false negative]");
317 
318 	gl.getnUniformuiv(program.m_id, 13, sizeof(GLuint) * 3, result4ui);
319 	test_result = test_result && verifyError(gl.getError(), GL_INVALID_OPERATION, "getnUniformuiv [false positive]");
320 
321 	/* Set result */
322 	if (true == test_result)
323 	{
324 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
325 	}
326 	else
327 	{
328 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
329 	}
330 
331 	gl.deleteBuffers(1, &buf);
332 
333 	/* Done */
334 	return tcu::TestNode::STOP;
335 }
336 
getComputeShader(bool glslES320)337 std::string GetnUniformTest::getComputeShader(bool glslES320)
338 {
339 	std::stringstream shader;
340 	shader << "#version " << (glslES320 ? "320 es\n" : "450\n");
341 	shader << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
342 		  "layout (location = 11) uniform vec4 inputf;\n"
343 		  "layout (location = 12) uniform ivec3 inputi;\n"
344 		  "layout (location = 13) uniform uvec4 inputu;\n"
345 		  "layout (std140, binding = 0) buffer ssbo {\n"
346 		  "   float valuef;\n"
347 		  "   int valuei;\n"
348 		  "   uint valueu;\n"
349 		  "};\n"
350 		  "void main()\n"
351 		  "{\n"
352 		  "   valuef = inputf.r + inputf.g + inputf.b + inputf.a;\n"
353 		  "   valuei = inputi.r + inputi.g + inputi.b;\n"
354 		  "   valueu = inputu.r + inputu.g + inputu.b + inputu.a;\n"
355 		  "}\n";
356 	return shader.str();
357 }
358 
verifyResult(const void * inputData,const void * resultData,int size,const char * method)359 bool GetnUniformTest::verifyResult(const void* inputData, const void* resultData, int size, const char* method)
360 {
361 	int diff = memcmp(inputData, resultData, size);
362 	if (diff != 0)
363 	{
364 		m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! " << method << " result is not as expected."
365 						   << tcu::TestLog::EndMessage;
366 
367 		return false;
368 	}
369 
370 	return true;
371 }
372 
verifyError(GLint error,GLint expectedError,const char * method)373 bool GetnUniformTest::verifyError(GLint error, GLint expectedError, const char* method)
374 {
375 	if (error != expectedError)
376 	{
377 		m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! " << method << " throws unexpected error ["
378 						   << error << "]." << tcu::TestLog::EndMessage;
379 
380 		return false;
381 	}
382 
383 	return true;
384 }
385 
386 /** Implementation of test ReadnPixelsTest. Description follows:
387  *
388  * This test verifies if read pixels to the buffer with bufSize less than expected result with GL_INVALID_OPERATION error;
389  **/
390 class ReadnPixelsTest : public tcu::TestCase
391 {
392 public:
393 	/* Public methods */
394 	ReadnPixelsTest(tcu::TestContext& testCtx, glu::ApiType apiType);
~ReadnPixelsTest()395 	virtual ~ReadnPixelsTest()
396 	{
397 	}
398 
399 	/* Public methods inherited from TestCase */
400 	virtual tcu::TestNode::IterateResult iterate(void);
401 
402 private:
403 	/* Private methods */
404 	void cleanTexture(deqp::Context& context, glw::GLuint texture_id);
405 	bool verifyResults(deqp::Context& context);
406 	bool verifyError(glw::GLint error, glw::GLint expectedError, const char* method);
407 
408 	glu::ApiType m_ApiType;
409 };
410 
411 /** Constructor
412  *
413  * @param context Test context
414  **/
ReadnPixelsTest(tcu::TestContext & testCtx,glu::ApiType apiType)415 ReadnPixelsTest::ReadnPixelsTest(tcu::TestContext& testCtx, glu::ApiType apiType)
416 	: tcu::TestCase(testCtx, "readnpixels",
417 					"Verifies if read pixels to the buffer with bufSize less than expected result "
418 					"with GL_INVALID_OPERATION error")
419 	, m_ApiType(apiType)
420 {
421 	/* Nothing to be done here */
422 }
423 
424 /** Execute test
425  *
426  * @return tcu::TestNode::STOP
427  **/
iterate()428 tcu::TestNode::IterateResult ReadnPixelsTest::iterate()
429 {
430 	de::SharedPtr<deqp::Context> context(createContext(m_testCtx, m_ApiType));
431 	if (!context.get())
432 		return STOP;
433 
434 	static const GLuint elements[] = {
435 		0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 1,
436 	};
437 
438 	static const GLfloat vertices[] = {
439 		0.0f,  0.0f,  0.0f, 1.0f, /* 0 */
440 		-1.0f, 0.0f,  0.0f, 1.0f, /* 1 */
441 		-1.0f, 1.0f,  0.0f, 1.0f, /* 2 */
442 		0.0f,  1.0f,  0.0f, 1.0f, /* 3 */
443 		1.0f,  1.0f,  0.0f, 1.0f, /* 4 */
444 		1.0f,  0.0f,  0.0f, 1.0f, /* 5 */
445 		1.0f,  -1.0f, 0.0f, 1.0f, /* 6 */
446 		0.0f,  -1.0f, 0.0f, 1.0f, /* 7 */
447 		-1.0f, -1.0f, 0.0f, 1.0f, /* 8 */
448 	};
449 
450 	bool glslES320 = contextSupports(context->getRenderContext().getType(), glu::ApiType::es(3, 2));
451 	std::string fs("#version ");
452 	fs += (glslES320 ? "320 es\n" : "450\n");
453 	fs += "layout (location = 0) out lowp uvec4 out_fs_color;\n"
454 		  "\n"
455 		  "void main()\n"
456 		  "{\n"
457 		  "	out_fs_color = uvec4(1, 0, 0, 1);\n"
458 		  "}\n"
459 		  "\n";
460 
461 	std::string vs("#version ");
462 	vs += (glslES320 ? "320 es\n" : "450\n");
463 	vs += "layout (location = 0) in vec4 in_vs_position;\n"
464 		  "\n"
465 		  "void main()\n"
466 		  "{\n"
467 		  "	gl_Position = in_vs_position;\n"
468 		  "}\n"
469 		  "\n";
470 
471 	static const GLuint height	 = 8;
472 	static const GLuint width	  = 8;
473 	static const GLuint n_vertices = 24;
474 
475 	/* GL entry points */
476 	const Functions& gl = context->getRenderContext().getFunctions();
477 
478 	/* Test case objects */
479 	Program		program(gl);
480 	Texture		texture(gl);
481 	Buffer		elements_buffer(gl);
482 	Buffer		vertices_buffer(gl);
483 	VertexArray vao(gl);
484 
485 	/* Vertex array initialization */
486 	VertexArray::Generate(gl, vao.m_id);
487 	VertexArray::Bind(gl, vao.m_id);
488 
489 	/* Texture initialization */
490 	Texture::Generate(gl, texture.m_id);
491 	Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
492 	Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R8UI, width, height, 0);
493 	Texture::Bind(gl, 0, GL_TEXTURE_2D);
494 
495 	/* Framebuffer initialization */
496 	GLuint fbo;
497 	gl.genFramebuffers(1, &fbo);
498 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
499 	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
500 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
501 	gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.m_id, 0);
502 	GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
503 
504 	/* Buffers initialization */
505 	elements_buffer.InitData(GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(elements), elements);
506 	vertices_buffer.InitData(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(vertices), vertices);
507 
508 	/* Shaders initialization */
509 	program.Init("" /* cs */, fs, "" /* gs */, "" /* tcs */, "" /* tes */, vs);
510 	Program::Use(gl, program.m_id);
511 
512 	/* Vertex buffer initialization */
513 	vertices_buffer.Bind();
514 	gl.bindVertexBuffer(0 /* bindindex = location */, vertices_buffer.m_id, 0 /* offset */, 16 /* stride */);
515 	gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 16, NULL);
516 	gl.enableVertexAttribArray(0 /* location */);
517 
518 	/* Binding elements/indices buffer */
519 	elements_buffer.Bind();
520 
521 	cleanTexture(*context, texture.m_id);
522 
523 	gl.drawElements(GL_TRIANGLES, n_vertices, GL_UNSIGNED_INT, 0 /* indices */);
524 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
525 
526 	/* Set result */
527 	if (verifyResults(*context))
528 	{
529 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
530 	}
531 	else
532 	{
533 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
534 	}
535 
536 	/* Done */
537 	return tcu::TestNode::STOP;
538 }
539 
540 /** Fill texture with value 128
541  *
542  * @param texture_id Id of texture
543  **/
cleanTexture(deqp::Context & context,glw::GLuint texture_id)544 void ReadnPixelsTest::cleanTexture(deqp::Context& context, glw::GLuint texture_id)
545 {
546 	static const GLuint height = 8;
547 	static const GLuint width  = 8;
548 
549 	const Functions& gl = context.getRenderContext().getFunctions();
550 
551 	GLubyte pixels[width * height];
552 	for (GLuint i = 0; i < width * height; ++i)
553 	{
554 		pixels[i] = 64;
555 	}
556 
557 	Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
558 
559 	Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level  */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 0 /* depth */,
560 					  GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels);
561 
562 	/* Unbind */
563 	Texture::Bind(gl, 0, GL_TEXTURE_2D);
564 }
565 
566 /** Verifies glReadnPixels results
567  *
568  * @return true when glReadnPixels , false otherwise
569  **/
verifyResults(deqp::Context & context)570 bool ReadnPixelsTest::verifyResults(deqp::Context& context)
571 {
572 	static const GLuint height	 = 8;
573 	static const GLuint width	  = 8;
574 	static const GLuint pixel_size = 4 * sizeof(GLuint);
575 
576 	const Functions& gl = context.getRenderContext().getFunctions();
577 
578 	//Valid buffer size test
579 	const GLint bufSizeValid = width * height * pixel_size;
580 	GLubyte		pixelsValid[bufSizeValid];
581 
582 	gl.readnPixels(0, 0, width, height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, bufSizeValid, pixelsValid);
583 	GLU_EXPECT_NO_ERROR(gl.getError(), "ReadnPixels");
584 
585 	//Verify glReadnPixels result
586 	for (unsigned int i = 0; i < width * height; ++i)
587 	{
588 		const size_t offset = i * pixel_size;
589 		const GLuint value  = *(GLuint*)(pixelsValid + offset);
590 
591 		if (value != 1)
592 		{
593 			context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid pixel value: " << value
594 											  << ". Offset: " << offset << tcu::TestLog::EndMessage;
595 			return false;
596 		}
597 	}
598 
599 	//Invalid buffer size test
600 	const GLint bufSizeInvalid = width * height * pixel_size - 1;
601 	GLubyte		pixelsInvalid[bufSizeInvalid];
602 
603 	gl.readnPixels(0, 0, width, height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, bufSizeInvalid, pixelsInvalid);
604 	if (!verifyError(gl.getError(), GL_INVALID_OPERATION, "ReadnPixels [false positive]"))
605 		return false;
606 
607 	return true;
608 }
609 
610 /** Verify operation errors
611  *
612  * @param error OpenGL ES error code
613  * @param expectedError Expected error code
614  * @param method Method name marker
615  *
616  * @return true when error is as expected, false otherwise
617  **/
verifyError(GLint error,GLint expectedError,const char * method)618 bool ReadnPixelsTest::verifyError(GLint error, GLint expectedError, const char* method)
619 {
620 	if (error != expectedError)
621 	{
622 		m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! " << method << " throws unexpected error ["
623 						   << error << "]." << tcu::TestLog::EndMessage;
624 
625 		return false;
626 	}
627 
628 	return true;
629 }
630 
631 } // RobustBufferAccessBehavior namespace
632 
RobustnessTests(tcu::TestContext & testCtx,glu::ApiType apiType)633 RobustnessTests::RobustnessTests(tcu::TestContext& testCtx, glu::ApiType apiType)
634 	: tcu::TestCaseGroup(testCtx, "robustness",
635 						 "Verifies API coverage and functionality of GL_KHR_robustness extension.")
636 	, m_ApiType(apiType)
637 {
638 }
639 
init(void)640 void RobustnessTests::init(void)
641 {
642 	tcu::TestCaseGroup::init();
643 
644 	try
645 	{
646 		addChild(new ResetNotificationStrategy::NoResetNotificationCase(
647 			m_testCtx, "no_reset_notification", "Verifies if NO_RESET_NOTIFICATION strategy works as expected.",
648 			m_ApiType));
649 		addChild(new ResetNotificationStrategy::LoseContextOnResetCase(
650 			m_testCtx, "lose_context_on_reset", "Verifies if LOSE_CONTEXT_ON_RESET strategy works as expected.",
651 			m_ApiType));
652 
653 		addChild(new RobustBufferAccessBehavior::GetnUniformTest(m_testCtx, m_ApiType));
654 		addChild(new RobustBufferAccessBehavior::ReadnPixelsTest(m_testCtx, m_ApiType));
655 	}
656 	catch (...)
657 	{
658 		// Destroy context.
659 		tcu::TestCaseGroup::deinit();
660 		throw;
661 	}
662 }
663 
664 } // glcts namespace
665