• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2015-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 
24 /**
25  * \file  gl3cGLSLnoperspectiveTests.cpp
26  * \brief Implements conformance tests for "GLSL no perspective" functionality.
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "gl3cGLSLnoperspectiveTests.hpp"
30 #include "gluContextInfo.hpp"
31 #include "glwFunctions.hpp"
32 #include "tcuTestLog.hpp"
33 
34 namespace gl3cts
35 {
36 /** Compiles shader
37  *
38  * @param context     Context of test framework
39  * @param shader_id   Shader id
40  * @param shader_code Shader source code
41  **/
compile_shader(deqp::Context & context,glw::GLuint shader_id,const glw::GLchar * shader_code)42 void compile_shader(deqp::Context& context, glw::GLuint shader_id, const glw::GLchar* shader_code)
43 {
44 	/* GL entry points */
45 	const glw::Functions& gl = context.getRenderContext().getFunctions();
46 
47 	/* Compilation status */
48 	glw::GLint status = GL_FALSE;
49 
50 	/* Set source code */
51 	gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
52 	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
53 
54 	/* Compile */
55 	gl.compileShader(shader_id);
56 	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
57 
58 	/* Get compilation status */
59 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
60 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
61 
62 	/* Log compilation error */
63 	if (GL_TRUE != status)
64 	{
65 		glw::GLint				 length = 0;
66 		std::vector<glw::GLchar> message;
67 
68 		/* Error log length */
69 		gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
70 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
71 
72 		/* Prepare storage */
73 		message.resize(length);
74 
75 		/* Get error log */
76 		gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
77 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
78 
79 		/* Log */
80 		context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
81 										  << &message[0] << tcu::TestLog::EndMessage
82 										  << tcu::TestLog::KernelSource(shader_code);
83 
84 		TCU_FAIL("Failed to compile shader");
85 	}
86 }
87 
88 /** Creates and compiles shader
89  *
90  * @param context Context of test framework
91  * @param stage   Shader stage
92  * @param code    Shader source code
93  *
94  * @return Id of created shader
95  **/
prepare_shader(deqp::Context & context,glw::GLenum stage,const glw::GLchar * code)96 glw::GLuint prepare_shader(deqp::Context& context, glw::GLenum stage, const glw::GLchar* code)
97 {
98 	/* GL entry points */
99 	const glw::Functions& gl = context.getRenderContext().getFunctions();
100 
101 	/* Compilation status */
102 	glw::GLuint id = 0;
103 
104 	/* Create */
105 	id = gl.createShader(stage);
106 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
107 
108 	try
109 	{
110 		compile_shader(context, id, code);
111 	}
112 	catch (const std::exception& exc)
113 	{
114 		gl.deleteShader(id);
115 		GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteShader");
116 
117 		TCU_FAIL(exc.what());
118 	}
119 
120 	return id;
121 }
122 
123 /** Attach shaders and link program
124  *
125  * @param context            Context of test framework
126  * @param fragment_shader_id Id of fragment shader
127  * @param vertex_shader_id   Id of vertex shader
128  * @param program_object_id  Id of program object
129  **/
link_program(deqp::Context & context,glw::GLuint fragment_shader_id,glw::GLuint vertex_shader_id,glw::GLuint program_object_id)130 void link_program(deqp::Context& context, glw::GLuint fragment_shader_id, glw::GLuint vertex_shader_id,
131 				  glw::GLuint program_object_id)
132 {
133 	/* GL entry points */
134 	const glw::Functions& gl = context.getRenderContext().getFunctions();
135 
136 	/* Link status */
137 	glw::GLint status = GL_FALSE;
138 
139 	/* Attach shaders */
140 	if (0 != fragment_shader_id)
141 	{
142 		gl.attachShader(program_object_id, fragment_shader_id);
143 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
144 	}
145 
146 	if (0 != vertex_shader_id)
147 	{
148 		gl.attachShader(program_object_id, vertex_shader_id);
149 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
150 	}
151 
152 	/* Link */
153 	gl.linkProgram(program_object_id);
154 	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
155 
156 	/* Get link status */
157 	gl.getProgramiv(program_object_id, GL_LINK_STATUS, &status);
158 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
159 
160 	/* Log link error */
161 	if (GL_TRUE != status)
162 	{
163 		glw::GLint				 length = 0;
164 		std::vector<glw::GLchar> message;
165 
166 		/* Get error log length */
167 		gl.getProgramiv(program_object_id, GL_INFO_LOG_LENGTH, &length);
168 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
169 
170 		message.resize(length);
171 
172 		/* Get error log */
173 		gl.getProgramInfoLog(program_object_id, length, 0, &message[0]);
174 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
175 
176 		/* Log */
177 		context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
178 										  << &message[0] << tcu::TestLog::EndMessage;
179 
180 		TCU_FAIL("Failed to link program");
181 	}
182 }
183 
184 /** Create and build program
185  *
186  * @param context              Context of test framework
187  * @param fragment_shader_code Fragment shader source code
188  * @param vertex_shader_code   Vertex shader source code
189  *
190  * @return Id of program object
191  **/
prepare_program(deqp::Context & context,const glw::GLchar * fragment_shader_code,const glw::GLchar * vertex_shader_code)192 glw::GLuint prepare_program(deqp::Context& context, const glw::GLchar* fragment_shader_code,
193 							const glw::GLchar* vertex_shader_code)
194 {
195 	/* GL entry points */
196 	const glw::Functions& gl = context.getRenderContext().getFunctions();
197 
198 	glw::GLuint fragment_shader_id = 0;
199 	glw::GLuint program_object_id  = 0;
200 	glw::GLuint vertex_shader_id   = 0;
201 
202 	try
203 	{
204 		/* Create shader objects and compile */
205 		if (0 != fragment_shader_code)
206 		{
207 			fragment_shader_id = prepare_shader(context, GL_FRAGMENT_SHADER, fragment_shader_code);
208 		}
209 
210 		if (0 != vertex_shader_code)
211 		{
212 			vertex_shader_id = prepare_shader(context, GL_VERTEX_SHADER, vertex_shader_code);
213 		}
214 
215 		/* Create program object */
216 		program_object_id = gl.createProgram();
217 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
218 
219 		/* Link program */
220 		link_program(context, fragment_shader_id, vertex_shader_id, program_object_id);
221 	}
222 	catch (const std::exception& exc)
223 	{
224 		if (0 != program_object_id)
225 			gl.deleteProgram(program_object_id);
226 		if (0 != fragment_shader_id)
227 			gl.deleteShader(fragment_shader_id);
228 		if (0 != vertex_shader_id)
229 			gl.deleteShader(vertex_shader_id);
230 
231 		TCU_FAIL(exc.what());
232 	}
233 
234 	/* Shader ids can now be deleted */
235 	if (0 != fragment_shader_id)
236 		gl.deleteShader(fragment_shader_id);
237 	if (0 != vertex_shader_id)
238 		gl.deleteShader(vertex_shader_id);
239 
240 	/* Done */
241 	return program_object_id;
242 }
243 
244 /** Constructor.
245  *
246  *  @param context Rendering context.
247  *
248  **/
FunctionalTest(deqp::Context & context)249 FunctionalTest::FunctionalTest(deqp::Context& context)
250 	: TestCase(context, "functionaltest", "Verifies that interpolation qualifier has imact on results of rendering")
251 {
252 	/* Left blank intentionally */
253 }
254 
255 /** Executes test iteration.
256  *
257  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
258  */
iterate()259 tcu::TestNode::IterateResult FunctionalTest::iterate()
260 {
261 	static const char* vs_default = "#version 130\n"
262 									"\n"
263 									"in vec4 in_position;\n"
264 									"in vec4 in_color;\n"
265 									"\n"
266 									"out vec4 vs_fs_color;\n"
267 									"\n"
268 									"void main()\n"
269 									"{\n"
270 									"    gl_Position = in_position;\n"
271 									"    vs_fs_color = in_color;\n"
272 									"}\n"
273 									"\n";
274 
275 	static const char* vs_flat = "#version 130\n"
276 								 "\n"
277 								 "in vec4 in_position;\n"
278 								 "in vec4 in_color;\n"
279 								 "\n"
280 								 "flat out vec4 vs_fs_color;\n"
281 								 "\n"
282 								 "void main()\n"
283 								 "{\n"
284 								 "    gl_Position = in_position;\n"
285 								 "    vs_fs_color = in_color;\n"
286 								 "}\n"
287 								 "\n";
288 
289 	static const char* vs_noperspective = "#version 130\n"
290 										  "\n"
291 										  "in vec4 in_position;\n"
292 										  "in vec4 in_color;\n"
293 										  "\n"
294 										  "noperspective out vec4 vs_fs_color;\n"
295 										  "\n"
296 										  "void main()\n"
297 										  "{\n"
298 										  "    gl_Position = in_position;\n"
299 										  "    vs_fs_color = in_color;\n"
300 										  "}\n"
301 										  "\n";
302 
303 	static const char* vs_smooth = "#version 130\n"
304 								   "\n"
305 								   "in vec4 in_position;\n"
306 								   "in vec4 in_color;\n"
307 								   "\n"
308 								   "smooth out vec4 vs_fs_color;\n"
309 								   "\n"
310 								   "void main()\n"
311 								   "{\n"
312 								   "    gl_Position = in_position;\n"
313 								   "    vs_fs_color = in_color;\n"
314 								   "}\n"
315 								   "\n";
316 
317 	static const char* fs_default = "#version 130\n"
318 									"\n"
319 									"in vec4 vs_fs_color;\n"
320 									"\n"
321 									"out vec4 out_color;\n"
322 									"\n"
323 									"void main()\n"
324 									"{\n"
325 									"    out_color = vs_fs_color;\n"
326 									"}\n"
327 									"\n";
328 
329 	static const char* fs_flat = "#version 130\n"
330 								 "\n"
331 								 "flat in vec4 vs_fs_color;\n"
332 								 "\n"
333 								 "out vec4 out_color;\n"
334 								 "\n"
335 								 "void main()\n"
336 								 "{\n"
337 								 "    out_color = vs_fs_color;\n"
338 								 "}\n"
339 								 "\n";
340 
341 	static const char* fs_noperspective = "#version 130\n"
342 										  "\n"
343 										  "noperspective in vec4 vs_fs_color;\n"
344 										  "\n"
345 										  "out vec4 out_color;\n"
346 										  "\n"
347 										  "void main()\n"
348 										  "{\n"
349 										  "    out_color = vs_fs_color;\n"
350 										  "}\n"
351 										  "\n";
352 
353 	static const char* fs_smooth = "#version 130\n"
354 								   "\n"
355 								   "smooth in vec4 vs_fs_color;\n"
356 								   "\n"
357 								   "out vec4 out_color;\n"
358 								   "\n"
359 								   "void main()\n"
360 								   "{\n"
361 								   "    out_color = vs_fs_color;\n"
362 								   "}\n"
363 								   "\n";
364 
365 	static const glw::GLfloat positions_data[] = { -1.0f, 1.0f,  -1.0f, 1.0f, 3.0f, 3.0f,  3.0f, 3.0f,
366 												   -1.0f, -1.0f, -1.0f, 1.0f, 3.0f, -3.0f, 3.0f, 3.0f };
367 	static const glw::GLubyte colors_data[] = { 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
368 												0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
369 
370 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
371 
372 	static const char* shaders[][2] = { { vs_noperspective, fs_noperspective },
373 										{ vs_default, fs_default },
374 										{ vs_flat, fs_flat },
375 										{ vs_smooth, fs_smooth } };
376 	static const size_t		  n_shaders			= sizeof(shaders) / sizeof(shaders[0]);
377 	static const size_t		  noperspective_idx = 0;
378 	static const glw::GLsizei w					= 64;
379 	static const glw::GLsizei h					= 64;
380 	static const glw::GLsizei image_length		= w * h;
381 
382 	bool test_result = true;
383 
384 	glw::GLuint po_ids[n_shaders]  = { 0 };
385 	glw::GLuint tex_ids[n_shaders] = { 0 };
386 	glw::GLuint fbo_ids[n_shaders] = { 0 };
387 	glw::GLuint vab_id			   = 0;
388 	glw::GLuint vao_id			   = 0;
389 
390 	try
391 	{
392 		/* Buffer */
393 		gl.genBuffers(1, &vab_id);
394 		GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
395 
396 		gl.bindBuffer(GL_ARRAY_BUFFER, vab_id);
397 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
398 
399 		gl.bufferData(GL_ARRAY_BUFFER, sizeof(colors_data) + sizeof(positions_data), 0 /* data */, GL_STATIC_DRAW);
400 		GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
401 
402 		gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, sizeof(positions_data) /* size */, positions_data);
403 		GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
404 
405 		gl.bufferSubData(GL_ARRAY_BUFFER, sizeof(positions_data) /* offset */, sizeof(colors_data) /* size */,
406 						 colors_data);
407 		GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
408 
409 		/* FBOs */
410 		gl.genFramebuffers(n_shaders, fbo_ids);
411 		GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
412 
413 		/* Textures */
414 		gl.genTextures(n_shaders, tex_ids);
415 		GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
416 
417 		/* VAO */
418 		gl.genVertexArrays(1, &vao_id);
419 		GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
420 
421 		gl.bindVertexArray(vao_id);
422 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays");
423 
424 		for (size_t i = 0; i < n_shaders; ++i)
425 		{
426 			/* Program */
427 			po_ids[i] = prepare_program(m_context, shaders[i][1], shaders[i][0]);
428 
429 			/* Texture */
430 			gl.bindTexture(GL_TEXTURE_2D, tex_ids[i]);
431 			GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
432 
433 			gl.texImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, w, h, 0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE,
434 						  0 /* data */);
435 			GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
436 
437 			gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
438 
439 			gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
440 			GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
441 
442 			/* FBO */
443 			gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_ids[i]);
444 			GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
445 
446 			gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_ids[i], 0 /* level */);
447 			GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
448 
449 			/* Viewport */
450 			gl.viewport(0, 0, w, h);
451 			GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
452 
453 			/* VAO */
454 			glw::GLint in_position_loc = gl.getAttribLocation(po_ids[i], "in_position");
455 			glw::GLint in_color_loc	= gl.getAttribLocation(po_ids[i], "in_color");
456 			GLU_EXPECT_NO_ERROR(gl.getError(), "GetAttribLocation");
457 			if ((-1 == in_position_loc) || (-1 == in_color_loc))
458 			{
459 				TCU_FAIL("Attributes are not available");
460 			}
461 
462 			gl.vertexAttribPointer(in_position_loc, 4 /* size */, GL_FLOAT, GL_FALSE /* normalizeed */, 0 /* stride */,
463 								   0 /* offset */);
464 			GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribPointer");
465 
466 			gl.vertexAttribPointer(in_color_loc, 4 /* size */, GL_UNSIGNED_BYTE, GL_TRUE /* normalizeed */,
467 								   0 /* stride */, (glw::GLvoid*)sizeof(positions_data) /* offset */);
468 			GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribPointer");
469 
470 			gl.enableVertexAttribArray(in_position_loc);
471 			GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray");
472 
473 			gl.enableVertexAttribArray(in_color_loc);
474 			GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray");
475 
476 			/* Clear */
477 			gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
478 			GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor");
479 
480 			gl.clear(GL_COLOR_BUFFER_BIT);
481 			GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
482 
483 			/* Activate program */
484 			gl.useProgram(po_ids[i]);
485 			GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
486 
487 			/* Draw */
488 			gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
489 			GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
490 
491 			/* Disable VAO */
492 			gl.disableVertexAttribArray(in_position_loc);
493 			GLU_EXPECT_NO_ERROR(gl.getError(), "DisableVertexAttribArray");
494 
495 			gl.disableVertexAttribArray(in_color_loc);
496 			GLU_EXPECT_NO_ERROR(gl.getError(), "DisableVertexAttribArray");
497 		}
498 
499 		/* Verify results */
500 		{
501 			/* Storage for images */
502 			std::vector<glw::GLuint> fbo_data;
503 			std::vector<glw::GLuint> noperspective_data;
504 
505 			fbo_data.resize(image_length);
506 			noperspective_data.resize(image_length);
507 
508 			/* Get noperspective image */
509 			gl.bindTexture(GL_TEXTURE_2D, tex_ids[noperspective_idx]);
510 			GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
511 
512 			gl.getTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &noperspective_data[0]);
513 			GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
514 
515 			/* Compare noperspective with the rest */
516 			for (size_t i = 0; i < n_shaders; ++i)
517 			{
518 				/* Skip noperspective */
519 				if (noperspective_idx == i)
520 				{
521 					continue;
522 				}
523 
524 				gl.bindTexture(GL_TEXTURE_2D, tex_ids[i]);
525 				GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
526 
527 				gl.getTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &fbo_data[0]);
528 				GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
529 
530 				bool are_same = true;
531 
532 				for (size_t pixel = 0; pixel < image_length; ++pixel)
533 				{
534 					const glw::GLuint left  = noperspective_data[pixel];
535 					const glw::GLuint right = fbo_data[pixel];
536 
537 					if (left != right)
538 					{
539 						are_same = false;
540 						break;
541 					}
542 				}
543 
544 				if (true == are_same)
545 				{
546 					test_result = false;
547 					break;
548 				}
549 			}
550 		}
551 
552 		gl.bindBuffer(GL_ARRAY_BUFFER, 0);
553 		gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
554 		gl.bindTexture(GL_TEXTURE_2D, 0);
555 		gl.bindVertexArray(0);
556 		gl.useProgram(0);
557 
558 		gl.deleteBuffers(1, &vab_id);
559 		vab_id = 0;
560 
561 		gl.deleteVertexArrays(1, &vao_id);
562 		vao_id = 0;
563 
564 		gl.deleteFramebuffers(n_shaders, fbo_ids);
565 		gl.deleteTextures(n_shaders, tex_ids);
566 
567 		for (size_t idx = 0; idx < n_shaders; ++idx)
568 		{
569 			fbo_ids[idx] = 0;
570 			tex_ids[idx] = 0;
571 		}
572 
573 		for (size_t i = 0; i < n_shaders; ++i)
574 		{
575 			if (0 != po_ids[i])
576 			{
577 				gl.deleteProgram(po_ids[i]);
578 				po_ids[i] = 0;
579 			}
580 		}
581 	}
582 	catch (...)
583 	{
584 		/* Unbind */
585 		gl.bindBuffer(GL_ARRAY_BUFFER, 0);
586 
587 		gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
588 
589 		gl.bindTexture(GL_TEXTURE_2D, 0);
590 
591 		gl.bindVertexArray(0);
592 
593 		gl.useProgram(0);
594 
595 		/* Delete */
596 		if (0 != vao_id)
597 		{
598 			gl.deleteVertexArrays(1, &vao_id);
599 		}
600 
601 		if (0 != vab_id)
602 		{
603 			gl.deleteBuffers(1, &vab_id);
604 		}
605 
606 		if (0 != fbo_ids[0])
607 		{
608 			gl.deleteFramebuffers(n_shaders, fbo_ids);
609 		}
610 
611 		for (size_t i = 0; i < n_shaders; ++i)
612 		{
613 			if (0 != po_ids[i])
614 			{
615 				gl.deleteProgram(po_ids[i]);
616 			}
617 		}
618 
619 		if (0 != tex_ids[0])
620 		{
621 			gl.deleteTextures(n_shaders, tex_ids);
622 		}
623 
624 		/* Clean any error */
625 		gl.getError();
626 
627 		/* Rethrow */
628 		throw;
629 	}
630 
631 	/* Set test result */
632 	if (true == test_result)
633 	{
634 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
635 	}
636 	else
637 	{
638 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
639 	}
640 
641 	/* Clean */
642 	{
643 		/* Unbind */
644 		gl.bindBuffer(GL_ARRAY_BUFFER, 0);
645 
646 		gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
647 
648 		gl.bindTexture(GL_TEXTURE_2D, 0);
649 
650 		gl.bindVertexArray(0);
651 
652 		gl.useProgram(0);
653 
654 		/* Delete */
655 		if (0 != vao_id)
656 		{
657 			gl.deleteVertexArrays(1, &vao_id);
658 		}
659 
660 		if (0 != vab_id)
661 		{
662 			gl.deleteBuffers(1, &vab_id);
663 		}
664 
665 		if (0 != fbo_ids[0])
666 		{
667 			gl.deleteFramebuffers(1, fbo_ids);
668 		}
669 
670 		for (size_t i = 0; i < n_shaders; ++i)
671 		{
672 			if (0 != po_ids[i])
673 			{
674 				gl.deleteProgram(po_ids[i]);
675 			}
676 		}
677 
678 		if (0 != tex_ids[0])
679 		{
680 			gl.deleteTextures(1, tex_ids);
681 		}
682 	}
683 
684 	/* Clean any error */
685 	gl.getError();
686 
687 	/* Done */
688 	return STOP;
689 }
690 
691 /** Constructor.
692  *
693  *  @param context Rendering context.
694  **/
GLSLnoperspectiveTests(deqp::Context & context)695 GLSLnoperspectiveTests::GLSLnoperspectiveTests(deqp::Context& context)
696 	: TestCaseGroup(context, "glsl_noperspective", "Verifies \"GLSL_noperspective\" functionality")
697 {
698 	/* Left blank on purpose */
699 }
700 
701 /** Initializes a gpu_shader_5 test group.
702  *
703  **/
init(void)704 void GLSLnoperspectiveTests::init(void)
705 {
706 	addChild(new FunctionalTest(m_context));
707 }
708 } /* gl3cts namespace */
709