• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 /*!
25  * \file esextcTessellationShaderPrimitiveCoverage.cpp
26  * \brief TessellationShadePrimitiveCoverage (Test 31)
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "esextcTessellationShaderPrimitiveCoverage.hpp"
30 #include "esextcTessellationShaderUtils.hpp"
31 #include "gluContextInfo.hpp"
32 #include "gluDefs.hpp"
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 #include "tcuTestLog.hpp"
36 #include <cstdarg>
37 #include <cstddef>
38 #include <cstdlib>
39 
40 namespace glcts
41 {
42 
43 /* Vertex shader */
44 const char* TessellationShaderPrimitiveCoverage::m_vs_code = "${VERSION}\n"
45 															 "\n"
46 															 "precision highp float;\n"
47 															 "\n"
48 															 "layout(location = 0) in vec4 position;\n"
49 															 "\n"
50 															 "void main()\n"
51 															 "{\n"
52 															 "    gl_Position = position;\n"
53 															 "}\n";
54 
55 /* Tessellation Control Shaders' source code  */
56 const char* TessellationShaderPrimitiveCoverage::m_quad_tessellation_tcs_code =
57 	"${VERSION}\n"
58 	"\n"
59 	"${TESSELLATION_SHADER_REQUIRE}\n"
60 	"\n"
61 	"precision highp float;\n"
62 	"\n"
63 	"layout(vertices = 4) out;\n"
64 	"\n"
65 	"uniform vec2 innerLevel;"
66 	"uniform vec4 outerLevel;"
67 	"\n"
68 	"void main()\n"
69 	"{\n"
70 	"    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
71 	"\n"
72 	"    gl_TessLevelInner[0] = innerLevel.x;\n"
73 	"    gl_TessLevelInner[1] = innerLevel.y;\n"
74 	"    gl_TessLevelOuter[0] = outerLevel.x;\n"
75 	"    gl_TessLevelOuter[1] = outerLevel.y;\n"
76 	"    gl_TessLevelOuter[2] = outerLevel.z;\n"
77 	"    gl_TessLevelOuter[3] = outerLevel.w;\n"
78 	"}\n";
79 
80 /* Tessellation Evaluation Shaders' source code  */
81 const char* TessellationShaderPrimitiveCoverage::m_quad_tessellation_tes_code =
82 	"${VERSION}\n"
83 	"\n"
84 	"${TESSELLATION_SHADER_REQUIRE}\n"
85 	"\n"
86 	"precision highp float;\n"
87 	"\n"
88 	"layout (quads) in;\n"
89 	"\n"
90 	"void main()\n"
91 	"{\n"
92 	"    gl_Position = gl_in[0].gl_Position * (1.0 - gl_TessCoord.x) * (1.0 - "
93 	"gl_TessCoord.y)\n" /* Specifying the vertex's position */
94 	"                + gl_in[1].gl_Position * (      gl_TessCoord.x) * (1.0 - "
95 	"gl_TessCoord.y)\n" /* using the bilinear interpolation */
96 	"                + gl_in[2].gl_Position * (      gl_TessCoord.x) * (      "
97 	"gl_TessCoord.y)\n"
98 	"                + gl_in[3].gl_Position * (1.0 - gl_TessCoord.x) * (      "
99 	"gl_TessCoord.y);\n"
100 	"}\n";
101 
102 /* Tessellation Control Shaders' source code  */
103 const char* TessellationShaderPrimitiveCoverage::m_triangles_tessellation_tcs_code =
104 	"${VERSION}\n"
105 	"\n"
106 	"${TESSELLATION_SHADER_REQUIRE}\n"
107 	"\n"
108 	"precision highp float;\n"
109 	"\n"
110 	"layout(vertices = 3) out;\n"
111 	"\n"
112 	"uniform vec2 innerLevel;"
113 	"uniform vec4 outerLevel;"
114 	"\n"
115 	"void main()\n"
116 	"{\n"
117 	"    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
118 	"\n"
119 	"    gl_TessLevelInner[0] = innerLevel.x;\n"
120 	"    gl_TessLevelInner[1] = innerLevel.y;\n"
121 	"    gl_TessLevelOuter[0] = outerLevel.x;\n"
122 	"    gl_TessLevelOuter[1] = outerLevel.y;\n"
123 	"    gl_TessLevelOuter[2] = outerLevel.z;\n"
124 	"    gl_TessLevelOuter[3] = outerLevel.w;\n"
125 	"}\n";
126 
127 /* Tessellation Evaluation Shader code for triangle test */
128 const char* TessellationShaderPrimitiveCoverage::m_triangles_tessellation_tes_code =
129 	"${VERSION}\n"
130 	"\n"
131 	"${TESSELLATION_SHADER_REQUIRE}\n"
132 	"\n"
133 	"precision highp float;\n"
134 	"\n"
135 	"layout (triangles) in;\n"
136 	"\n"
137 	"void main()\n"
138 	"{\n"
139 	"    gl_Position = gl_in[0].gl_Position * gl_TessCoord.x\n" /* Specifying the vertex's position */
140 	"                + gl_in[1].gl_Position * gl_TessCoord.y\n" /* using the barycentric interpolation */
141 	"                + gl_in[2].gl_Position * gl_TessCoord.z;\n"
142 	"}\n";
143 
144 /* Fragment Shader code */
145 const char* TessellationShaderPrimitiveCoverage::m_fs_code = "${VERSION}\n"
146 															 "\n"
147 															 "precision highp float;\n"
148 															 "\n"
149 															 "uniform highp vec4 stencil_fail_color;\n"
150 															 "\n"
151 															 "layout(location = 0) out highp vec4 color;\n"
152 															 "\n"
153 															 "void main()\n"
154 															 "{\n"
155 															 "    color = stencil_fail_color;\n"
156 															 "}\n";
157 
158 /* A clear color used to set up framebuffer */
159 const glw::GLfloat TessellationShaderPrimitiveCoverage::m_clear_color[4] = {
160 	255.f / 255.f, /* red   */
161 	128.f / 255.f, /* green */
162 	64.f / 255.f,  /* blue  */
163 	32.f / 255.f   /* alpha */
164 };
165 
166 /* A color used to draw differences between the tesselated primitive
167  * and the reference primitive (when stencil test passes)
168  */
169 const glw::GLfloat TessellationShaderPrimitiveCoverage::m_stencil_pass_color[4] = {
170 	32.f / 255.f,  /* red   */
171 	64.f / 255.f,  /* green */
172 	128.f / 255.f, /* blue  */
173 	255.f / 255.f  /* alpha */
174 };
175 
176 /* Rendering area height */
177 const glw::GLuint TessellationShaderPrimitiveCoverage::m_height =
178 	2048; /* minimum maximum as required by ES specification */
179 /* Number of components as used for color attachment */
180 const glw::GLuint TessellationShaderPrimitiveCoverage::m_n_components = 4;
181 /* Rendering area width */
182 const glw::GLuint TessellationShaderPrimitiveCoverage::m_width =
183 	2048; /* minimum maximum as required by ES specification */
184 
185 /* Buffer size for fetched pixels */
186 const glw::GLuint TessellationShaderPrimitiveCoverage::m_rendered_data_buffer_size = m_width	/* width */
187 																					 * m_height /* height */
188 																					 * m_n_components /* components */;
189 
190 /** Constructor
191  *
192  * @param context     Test context
193  * @param name        Test case's name
194  * @param description Test case's description
195  **/
TessellationShaderPrimitiveCoverage(Context & context,const ExtParameters & extParams)196 TessellationShaderPrimitiveCoverage::TessellationShaderPrimitiveCoverage(Context&			  context,
197 																		 const ExtParameters& extParams)
198 	: TestCaseBase(context, extParams, "primitive_coverage",
199 				   "Verifies that no fragments are generated more than once when the "
200 				   "rendering pipeline (consisting of TC+TE stages) generates a "
201 				   "tessellated full-screen quad or two tessellated triangles.")
202 	, m_vao_id(0)
203 	, m_quad_tessellation_po_id(0)
204 	, m_stencil_verification_po_id(0)
205 	, m_triangles_tessellation_po_id(0)
206 	, m_bo_id(0)
207 	, m_fs_id(0)
208 	, m_quad_tessellation_tcs_id(0)
209 	, m_quad_tessellation_tes_id(0)
210 	, m_triangles_tessellation_tcs_id(0)
211 	, m_triangles_tessellation_tes_id(0)
212 	, m_vs_id(0)
213 	, m_fbo_id(0)
214 	, m_color_rbo_id(0)
215 	, m_stencil_rbo_id(0)
216 	, m_rendered_data_buffer(DE_NULL)
217 {
218 	/* Nothing to be done here */
219 }
220 
221 /** Deinitializes all ES objects created for the test. */
deinit(void)222 void TessellationShaderPrimitiveCoverage::deinit(void)
223 {
224 	/* Deinitialize base class */
225 	TestCaseBase::deinit();
226 
227 	if (!m_is_tessellation_shader_supported)
228 	{
229 		return;
230 	}
231 
232 	/* Retrieve ES entry-points */
233 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
234 
235 	/* Reset OpenGL ES state */
236 	gl.useProgram(0);
237 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
238 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
239 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
240 	gl.disable(GL_STENCIL_TEST);
241 	gl.bindVertexArray(0);
242 
243 	/* Reset GL_PATCH_VERTICES_EXT to the default value. */
244 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
245 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed!");
246 
247 	/* Delete buffers */
248 	if (m_rendered_data_buffer != DE_NULL)
249 	{
250 		free(m_rendered_data_buffer);
251 
252 		m_rendered_data_buffer = DE_NULL;
253 	}
254 
255 	/* Delete program and shader objects */
256 	if (m_quad_tessellation_po_id != 0)
257 	{
258 		gl.deleteProgram(m_quad_tessellation_po_id);
259 
260 		m_quad_tessellation_po_id = 0;
261 	}
262 
263 	if (m_stencil_verification_po_id != 0)
264 	{
265 		gl.deleteProgram(m_stencil_verification_po_id);
266 
267 		m_stencil_verification_po_id = 0;
268 	}
269 
270 	if (m_triangles_tessellation_po_id != 0)
271 	{
272 		gl.deleteProgram(m_triangles_tessellation_po_id);
273 
274 		m_triangles_tessellation_po_id = 0;
275 	}
276 
277 	if (m_fs_id != 0)
278 	{
279 		gl.deleteShader(m_fs_id);
280 
281 		m_fs_id = 0;
282 	}
283 
284 	if (m_quad_tessellation_tcs_id != 0)
285 	{
286 		gl.deleteShader(m_quad_tessellation_tcs_id);
287 
288 		m_quad_tessellation_tcs_id = 0;
289 	}
290 
291 	if (m_quad_tessellation_tes_id != 0)
292 	{
293 		gl.deleteShader(m_quad_tessellation_tes_id);
294 
295 		m_quad_tessellation_tes_id = 0;
296 	}
297 
298 	if (m_triangles_tessellation_tcs_id != 0)
299 	{
300 		gl.deleteShader(m_triangles_tessellation_tcs_id);
301 
302 		m_triangles_tessellation_tcs_id = 0;
303 	}
304 
305 	if (m_triangles_tessellation_tes_id != 0)
306 	{
307 		gl.deleteShader(m_triangles_tessellation_tes_id);
308 
309 		m_triangles_tessellation_tes_id = 0;
310 	}
311 
312 	if (m_vs_id != 0)
313 	{
314 		gl.deleteShader(m_vs_id);
315 
316 		m_vs_id = 0;
317 	}
318 
319 	/* Delete framebuffer and renderbuffer objects */
320 	if (m_fbo_id != 0)
321 	{
322 		gl.deleteFramebuffers(1, &m_fbo_id);
323 
324 		m_fbo_id = 0;
325 	}
326 
327 	if (m_color_rbo_id != 0)
328 	{
329 		gl.deleteRenderbuffers(1, &m_color_rbo_id);
330 
331 		m_color_rbo_id = 0;
332 	}
333 
334 	if (m_stencil_rbo_id != 0)
335 	{
336 		gl.deleteRenderbuffers(1, &m_stencil_rbo_id);
337 
338 		m_stencil_rbo_id = 0;
339 	}
340 
341 	/* Delete buffer objects */
342 	if (m_bo_id != 0)
343 	{
344 		gl.deleteBuffers(1, &m_bo_id);
345 
346 		m_bo_id = 0;
347 	}
348 
349 	if (m_vao_id != 0)
350 	{
351 		gl.deleteVertexArrays(1, &m_vao_id);
352 
353 		m_vao_id = 0;
354 	}
355 }
356 
357 /** Initializes the test.
358  *
359  *  Note the function throws exception should an error occur!
360  **/
initTest(void)361 void TessellationShaderPrimitiveCoverage::initTest(void)
362 {
363 	/* Skip if GL_EXT_tessellation_shader extension is not supported. */
364 	if (!m_is_tessellation_shader_supported)
365 	{
366 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
367 	}
368 
369 	/* Retrieve ES entry-points */
370 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
371 
372 	/* Generate and bind VAO */
373 	gl.genVertexArrays(1, &m_vao_id);
374 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
375 
376 	gl.bindVertexArray(m_vao_id);
377 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
378 
379 	/* Initialize objects used by the test */
380 	initProgramObjects();
381 	initFramebuffer();
382 	initBufferObjects();
383 
384 	/* setup of pixels buffer for fetching data*/
385 	m_rendered_data_buffer = (glw::GLubyte*)malloc(m_rendered_data_buffer_size);
386 
387 	/* Enable stencil test. */
388 	gl.enable(GL_STENCIL_TEST);
389 	GLU_EXPECT_NO_ERROR(gl.getError(), "Stencil test could not be enabled!");
390 
391 	/* Set up viewport */
392 	gl.viewport(0 /* x */, 0 /* y */, m_width, m_height);
393 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed!");
394 }
395 
396 /** Initializes program objects used by the test.
397  *
398  *  Note the function throws exception should an error occur!
399  **/
initProgramObjects(void)400 void TessellationShaderPrimitiveCoverage::initProgramObjects(void)
401 {
402 	/* Retrieve ES entry-points */
403 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
404 
405 	/* Create program objects needed for the test */
406 	m_stencil_verification_po_id = gl.createProgram();
407 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed!");
408 
409 	m_quad_tessellation_po_id = gl.createProgram();
410 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed!");
411 
412 	m_triangles_tessellation_po_id = gl.createProgram();
413 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed!");
414 
415 	/* Set up shader objects */
416 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
417 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_VERTEX_SHADER) failed!");
418 
419 	m_quad_tessellation_tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
420 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_TESS_CONTROL_SHADER_EXT) failed!");
421 
422 	m_quad_tessellation_tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
423 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_TESS_EVALUATION_SHADER_EXT) failed!");
424 
425 	m_triangles_tessellation_tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
426 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_TESS_CONTROL_SHADER_EXT) failed!");
427 
428 	m_triangles_tessellation_tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
429 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_TESS_EVALUATION_SHADER_EXT) failed!");
430 
431 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
432 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_FRAGMENT_SHADER) failed!");
433 
434 	/* Build a program object that does not define the tessellation stage */
435 	if (!buildProgram(m_stencil_verification_po_id, m_vs_id, 1, &m_vs_code, m_fs_id, 1, &m_fs_code))
436 	{
437 		TCU_FAIL("Could not create a program object");
438 	}
439 
440 	/* Build a program object that uses quad tessellation */
441 	if (!buildProgram(m_quad_tessellation_po_id, m_vs_id, 1, &m_vs_code, m_quad_tessellation_tcs_id, 1,
442 					  &m_quad_tessellation_tcs_code, m_quad_tessellation_tes_id, 1, &m_quad_tessellation_tes_code,
443 					  m_fs_id, 1, &m_fs_code))
444 	{
445 		TCU_FAIL("Could not create a program object");
446 	}
447 
448 	/* Build a program object that uses triangle tessellation */
449 	if (!buildProgram(m_triangles_tessellation_po_id, m_vs_id, 1, &m_vs_code, m_triangles_tessellation_tcs_id, 1,
450 					  &m_triangles_tessellation_tcs_code, m_triangles_tessellation_tes_id, 1,
451 					  &m_triangles_tessellation_tes_code, m_fs_id, 1, &m_fs_code))
452 	{
453 		TCU_FAIL("Could not create a program object");
454 	}
455 }
456 
457 /** Initializes a framebuffer object.
458  *
459  *  Note the function throws exception should an error occur!
460  **/
initFramebuffer(void)461 void TessellationShaderPrimitiveCoverage::initFramebuffer(void)
462 {
463 	/* Retrieve ES entry-points. */
464 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
465 
466 	/* Framebuffer setup */
467 	gl.genFramebuffers(1, &m_fbo_id);
468 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed!");
469 
470 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
471 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() failed!");
472 
473 	/* Set up a renderbuffer object and bind it as a color attachment to the
474 	 * framebuffer object */
475 	gl.genRenderbuffers(1, &m_color_rbo_id);
476 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers() failed!");
477 
478 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_color_rbo_id);
479 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed!");
480 
481 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, m_width, m_height);
482 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage() failed!");
483 
484 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_rbo_id);
485 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer() failed!");
486 
487 	/* Set up a renderbuffer object and bind it as a stencil attachment to
488 	 * the framebuffer object */
489 	gl.genRenderbuffers(1, &m_stencil_rbo_id);
490 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers() failed!");
491 
492 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_stencil_rbo_id);
493 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed!");
494 
495 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, m_width, m_height);
496 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage() failed!");
497 
498 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencil_rbo_id);
499 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer() failed!");
500 
501 	gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
502 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed!");
503 
504 	/* Check framebuffer completness */
505 	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
506 	{
507 		TCU_FAIL("Test framebuffer has been reported as incomplete");
508 	}
509 }
510 
511 /** Initializes buffer objects used by the test.
512  *
513  *  Note the function throws exception should an error occur!
514  **/
initBufferObjects(void)515 void TessellationShaderPrimitiveCoverage::initBufferObjects(void)
516 {
517 	/* Retrieve ES entry-points */
518 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
519 
520 	/* Set up an array of vertices that will be fed into vertex shader */
521 	glw::GLfloat vertices[6 /* vertices */ * m_n_components /* components */] = {
522 		-1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f,
523 		-1.0f, 0.0f, 1.0f,		 /* A half-screen triangle (patch) (CCW) is defined until here */
524 		1.0f,  1.0f, 0.0f, 1.0f, /* A full screen quad (patch) (CCW) is defined until here */
525 		-1.0f, 1.0f, 0.0f, 1.0f, 1.0f,  -1.0f, 0.0f, 1.0f /* A full screen quad (2 triangles) (CCW) is defined until here */
526 	};
527 
528 	/* Configure a buffer object to hold vertex data */
529 	gl.genBuffers(1, &m_bo_id);
530 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed!");
531 
532 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
533 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
534 
535 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
536 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed!");
537 
538 	/* Configure "position" vertex attribute array and enable it */
539 	gl.vertexAttribPointer(0,		 /* index */
540 						   4,		 /* size */
541 						   GL_FLOAT, /* type */
542 						   GL_FALSE, /* normalized */
543 						   0,		 /* stride */
544 						   0);		 /* pointer */
545 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() failed!");
546 
547 	gl.enableVertexAttribArray(0);
548 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() failed!");
549 }
550 
551 /** The function:
552  *
553  *  1) Clears the FBO's color/stencil attachments with zeros;
554  *  2) Issues a draw call using a program object, for which either triangles or quads
555  *     tessellation has been enabled. This draw call updates both color and stencil
556  *     buffers of the framebuffer: fragment shader stores vec4(1) in the color attachment
557  *     and stencil index is set to 0x1 for all affected fragments;
558  *  3) Issues a draw call using another program object, this time without tessellation
559  *     stage enabled. Stencil test is configured to only pass those fragments, for which
560  *     stencil index is not equal to 0xFF.
561  *
562  *  Note the function throws exception should an error occur!
563  *
564  *  @param po_id                   program object handle to draw tesselated primitive
565  *  @param n_patch_vertices        number of input vertices for a single patch (must
566  *                                 be 3 for triangles or 4 for quads).
567  *  @param n_draw_call_vertices    number of input vertices for a reference draw call
568  *                                 (must be 3 for triangle or 6 for quad (2 triangles)).
569  *  @param inner_levels            array of the inner tessellation levels
570  *  @param outer_levels            array of the outer tessellation levels
571  *
572  *  @return false if the test failed, or true if test passed.
573  **/
drawPatch(glw::GLuint po_id,glw::GLuint n_patch_vertices,glw::GLuint n_draw_call_vertices,const glw::GLfloat inner_levels[],const glw::GLfloat outer_levels[])574 void TessellationShaderPrimitiveCoverage::drawPatch(glw::GLuint po_id, glw::GLuint n_patch_vertices,
575 													glw::GLuint n_draw_call_vertices, const glw::GLfloat inner_levels[],
576 													const glw::GLfloat outer_levels[])
577 {
578 	/* Sanity check */
579 	DE_ASSERT(n_draw_call_vertices == 3 || n_draw_call_vertices == 6);
580 
581 	/* Retrieve ES entry-points */
582 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
583 
584 	/* Activate user-provided program object with tessellation stage defined*/
585 	gl.useProgram(po_id);
586 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!");
587 
588 	/* Set up tessellation levels */
589 	glw::GLint innerLevelUniformLocation = -1;
590 	glw::GLint outerLevelUniformLocation = -1;
591 
592 	innerLevelUniformLocation = gl.getUniformLocation(po_id, "innerLevel");
593 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() failed!");
594 
595 	outerLevelUniformLocation = gl.getUniformLocation(po_id, "outerLevel");
596 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() failed!");
597 
598 	gl.uniform2fv(innerLevelUniformLocation, 1 /* count */, inner_levels);
599 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform2fv() failed!");
600 
601 	gl.uniform4fv(outerLevelUniformLocation, 1 /* count */, outer_levels);
602 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed!");
603 
604 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, n_patch_vertices);
605 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed!");
606 
607 	/* Set up clear color */
608 	gl.clearColor(m_clear_color[0],  /* red */
609 				  m_clear_color[1],  /* green */
610 				  m_clear_color[2],  /* blue */
611 				  m_clear_color[3]); /* alpha */
612 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() failed!");
613 
614 	/* Set up fragment color to be used for the first stage */
615 	glw::GLint stencilPassColorUniformLocation = -1;
616 
617 	stencilPassColorUniformLocation = gl.getUniformLocation(po_id, "stencil_fail_color");
618 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() failed!");
619 
620 	gl.uniform4fv(stencilPassColorUniformLocation, 1, m_stencil_pass_color);
621 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed!");
622 
623 	/* Draw to stencil buffer */
624 	gl.clearStencil(0 /* s */);
625 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearStencil() failed!");
626 
627 	gl.clear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
628 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() failed!");
629 
630 	gl.stencilOp(GL_REPLACE /* sfail */, GL_KEEP /* dpfail */, GL_KEEP /* dppass */);
631 	GLU_EXPECT_NO_ERROR(gl.getError(), "glStencilOp() failed!");
632 
633 	gl.stencilFunc(GL_NEVER /* func */, 1 /* ref */, 0xFF /* mask */);
634 	GLU_EXPECT_NO_ERROR(gl.getError(), "glStencilFunc() failed!");
635 
636 	gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, n_patch_vertices);
637 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
638 
639 	/* Now verify the stencil buffer data contents by doing another
640 	 * full-screen draw call. This time without any tessellation.
641 	 * The pass will output fragments of predefined color, if stencil
642 	 * test passes (which will only happen if the stencil buffer is
643 	 * not filled with predefined index value).
644 	 */
645 	gl.useProgram(m_stencil_verification_po_id);
646 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!");
647 
648 	/* Color setup for 2nd program*/
649 	stencilPassColorUniformLocation = gl.getUniformLocation(m_stencil_verification_po_id, "stencil_fail_color");
650 
651 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() failed!");
652 
653 	gl.uniform4fv(stencilPassColorUniformLocation, 1 /* count */, m_stencil_pass_color);
654 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed!");
655 
656 	/* Draw to framebuffer */
657 	gl.stencilOp(GL_KEEP /* sfail */, GL_KEEP /* dpfail */, GL_KEEP /* dppass */);
658 	GLU_EXPECT_NO_ERROR(gl.getError(), "glStencilOp() failed!");
659 
660 	gl.stencilFunc(GL_NOTEQUAL /* func */, 1 /* ref */, 0xFF /* mask */);
661 	GLU_EXPECT_NO_ERROR(gl.getError(), "glStencilFunc() failed!");
662 
663 	gl.drawArrays(GL_TRIANGLES, 0 /* first */, n_draw_call_vertices);
664 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
665 }
666 
667 /** Retrieves data from test FBO's zeroth color attachment and verifies
668  *  no cracks are present.
669  *
670  *  Note the function throws exception should an error occur!
671  *
672  *  @return false if the check failed or true if check passed.
673  **/
verifyDrawBufferContents(void)674 bool TessellationShaderPrimitiveCoverage::verifyDrawBufferContents(void)
675 {
676 	/* Retrieve ES entry-points */
677 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
678 
679 	/* Fetch the data */
680 	gl.readBuffer(GL_COLOR_ATTACHMENT0);
681 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadBuffer() failed");
682 
683 	gl.readPixels(0,						  /* x */
684 				  0,						  /* y */
685 				  m_height, m_width, GL_RGBA, /* format */
686 				  GL_UNSIGNED_BYTE,			  /* type */
687 				  m_rendered_data_buffer);
688 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed");
689 
690 	/* Verify result data */
691 	bool result = true;
692 
693 	for (glw::GLuint n_pixel = 0; n_pixel < (m_rendered_data_buffer_size >> 2); n_pixel += m_n_components)
694 	{
695 		glw::GLubyte expected_result_ubyte[] = { (glw::GLubyte)(m_clear_color[0] * 255.0f),
696 												 (glw::GLubyte)(m_clear_color[1] * 255.0f),
697 												 (glw::GLubyte)(m_clear_color[2] * 255.0f),
698 												 (glw::GLubyte)(m_clear_color[3] * 255.0f) };
699 		glw::GLubyte rendered_result_ubyte[] = { m_rendered_data_buffer[n_pixel + 0],
700 												 m_rendered_data_buffer[n_pixel + 1],
701 												 m_rendered_data_buffer[n_pixel + 2],
702 												 m_rendered_data_buffer[n_pixel + 3] };
703 
704 		if (memcmp(expected_result_ubyte, rendered_result_ubyte, sizeof(rendered_result_ubyte)) != 0)
705 		{
706 			m_testCtx.getLog() << tcu::TestLog::Message << "Rendered pixel at index (" << n_pixel << ") of value"
707 																									 " ("
708 							   << rendered_result_ubyte[0] << ", " << rendered_result_ubyte[1] << ", "
709 							   << rendered_result_ubyte[2] << ", " << rendered_result_ubyte[3]
710 							   << ") does not match expected pixel"
711 								  " ("
712 							   << expected_result_ubyte[0] << ", " << expected_result_ubyte[1] << ", "
713 							   << expected_result_ubyte[2] << ", " << expected_result_ubyte[3] << ")"
714 							   << tcu::TestLog::EndMessage;
715 
716 			result = false;
717 
718 			break;
719 		} /* if (rendered pixel is invalid) */
720 	}	 /* for (all pixels) */
721 
722 	return result;
723 }
724 
725 /** Executes the test.
726  *
727  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
728  *
729  *  Note the function throws exception should an error occur!
730  *
731  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
732  **/
iterate(void)733 tcu::TestNode::IterateResult TessellationShaderPrimitiveCoverage::iterate(void)
734 {
735 	/* Retriveing GL. */
736 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
737 
738 	/* Initialize test */
739 	initTest();
740 
741 	bool has_test_passed = true;
742 
743 	/* Define tessellation level values that we will use to draw single tessellated primitive */
744 	const glw::GLfloat inner_tess_levels_single[] = { 1.0f, 1.0f };
745 	const glw::GLfloat outer_tess_levels_single[] = { 1.0f, 1.0f, 1.0f, 1.0f };
746 
747 	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */
748 	glw::GLint gl_max_tess_gen_level_value = 0;
749 
750 	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value);
751 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
752 
753 	/* Verify no cracks can be found if a degenerate triangle
754 	 * is outputted by the tessellator */
755 	drawPatch(m_triangles_tessellation_po_id, 3 /* n_patch_vertices */, 3 /* n_triangle_vertices */,
756 			  inner_tess_levels_single, outer_tess_levels_single);
757 
758 	has_test_passed &= verifyDrawBufferContents();
759 
760 	/* Verify no cracks can be found if multiple triangles
761 	 * are outputted by the tessellator.
762 	 */
763 	_tessellation_levels_set levels_sets = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode(
764 		TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES, gl_max_tess_gen_level_value,
765 		TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE);
766 
767 	for (_tessellation_levels_set_const_iterator set_iterator = levels_sets.begin(); set_iterator != levels_sets.end();
768 		 set_iterator++)
769 	{
770 		const _tessellation_levels& set = *set_iterator;
771 
772 		drawPatch(m_triangles_tessellation_po_id, 3 /* n_patch_vertices */, 3 /* n_triangle_vertices */, set.inner,
773 				  set.outer);
774 
775 		has_test_passed &= verifyDrawBufferContents();
776 	}
777 
778 	/* Verify no cracks can be found if a degenerate quad
779 	 * is outputted by the tessellator.
780 	 */
781 	drawPatch(m_quad_tessellation_po_id, 4 /* n_patch_vertices */, 6 /* n_triangle_vertices (quad == 2 triangles) */,
782 			  inner_tess_levels_single, outer_tess_levels_single);
783 
784 	has_test_passed &= verifyDrawBufferContents();
785 
786 	/* Verify no cracks can be found if multiple triangles
787 	 * (to which the generated quads will be broken into)
788 	 * are outputted by the tessellator.
789 	 */
790 	levels_sets = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode(
791 		TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS, gl_max_tess_gen_level_value,
792 		TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE);
793 
794 	for (_tessellation_levels_set_const_iterator set_iterator = levels_sets.begin(); set_iterator != levels_sets.end();
795 		 set_iterator++)
796 	{
797 		const _tessellation_levels& set = *set_iterator;
798 
799 		drawPatch(m_quad_tessellation_po_id, 4 /* n_patch_vertices */,
800 				  6 /* n_triangle_vertices (quad == 2 triangles) */, set.inner, set.outer);
801 		has_test_passed &= verifyDrawBufferContents();
802 	}
803 
804 	/* Has the test passed? */
805 	if (has_test_passed)
806 	{
807 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
808 	}
809 	else
810 	{
811 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
812 	}
813 
814 	return STOP;
815 }
816 
817 } /* namespace glcts */
818