Home | History | Annotate | Download | only in geometry_shader
      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 #include "esextcGeometryShaderOutput.hpp"
     25 
     26 #include "gluContextInfo.hpp"
     27 #include "glwEnums.hpp"
     28 #include "glwFunctions.hpp"
     29 #include "tcuTestLog.hpp"
     30 
     31 namespace glcts
     32 {
     33 
     34 /* Shared shaders */
     35 const char* const GeometryShaderOutput::m_fragment_shader_code_white_color = "${VERSION}\n"
     36 																			 "\n"
     37 																			 "precision highp float;\n"
     38 																			 "\n"
     39 																			 "out vec4 color;\n"
     40 																			 "\n"
     41 																			 "void main()\n"
     42 																			 "{\n"
     43 																			 "    color = vec4(1, 1, 1, 1);\n"
     44 																			 "}\n";
     45 
     46 const char* const GeometryShaderOutput::m_vertex_shader_code_two_vec4 = "${VERSION}\n"
     47 																		"\n"
     48 																		"precision highp float;\n"
     49 																		"\n"
     50 																		"out vec4 v1;\n"
     51 																		"out vec4 v2;\n"
     52 																		"\n"
     53 																		"void main()\n"
     54 																		"{\n"
     55 																		"   v1 = vec4(-0.5, -0.5, 0, 1);\n"
     56 																		"   v2 = vec4( 0.5,  0.5, 0, 1);\n"
     57 																		"}\n";
     58 
     59 const char* const GeometryShaderOutput::m_vertex_shader_code_vec4_0_0_0_1 = "${VERSION}\n"
     60 																			"\n"
     61 																			"precision highp float;\n"
     62 																			"\n"
     63 																			"void main()\n"
     64 																			"{\n"
     65 																			"   gl_Position = vec4(0, 0, 0, 1);\n"
     66 																			"}\n";
     67 
     68 /* Shaders for GeometryShaderDuplicateOutputLayoutQualifierTest */
     69 const char* const GeometryShaderDuplicateOutputLayoutQualifierTest::m_geometry_shader_code =
     70 	"${VERSION}\n"
     71 	"\n"
     72 	"${GEOMETRY_SHADER_REQUIRE}\n"
     73 	"\n"
     74 	"layout(points)                            in;\n"
     75 	"layout(triangle_strip, max_vertices = 60) out;\n"
     76 	"layout(points)                            out;\n"
     77 	"\n"
     78 	"in vec4 v1[];\n"
     79 	"in vec4 v2[];\n"
     80 	"\n"
     81 	"void main()\n"
     82 	"{\n"
     83 	"    gl_Position = v1[0] + vec4(-0.1, -0.1, 0, 0);\n"
     84 	"    EmitVertex();\n"
     85 	"    gl_Position = v1[0] + vec4(0.1, -0.1, 0, 0);\n"
     86 	"    EmitVertex();\n"
     87 	"    gl_Position = v1[0] + vec4(0.1, 0.1, 0, 0);\n"
     88 	"    EmitVertex();\n"
     89 	"    EndPrimitive();\n"
     90 	"\n"
     91 	"    gl_Position = v2[0] + vec4(-0.1, -0.1, 0, 0);\n"
     92 	"    EmitVertex();\n"
     93 	"    gl_Position = v2[0] + vec4(-0.1, 0.1, 0, 0);\n"
     94 	"    EmitVertex();\n"
     95 	"    gl_Position = v2[0] + vec4(0.1, 0.1, 0, 0);\n"
     96 	"    EmitVertex();\n"
     97 	"    EndPrimitive();\n"
     98 	"}\n";
     99 
    100 /* Shaders for GeometryShaderDuplicateMaxVerticesLayoutQualifierTest */
    101 const char* const GeometryShaderDuplicateMaxVerticesLayoutQualifierTest::m_geometry_shader_code =
    102 	"${VERSION}\n"
    103 	"\n"
    104 	"${GEOMETRY_SHADER_REQUIRE}\n"
    105 	"\n"
    106 	"layout(points)                            in;\n"
    107 	"layout(triangle_strip, max_vertices = 60) out;\n"
    108 	"layout(max_vertices = 20)                 out;\n"
    109 	"\n"
    110 	"in vec4 v1[];\n"
    111 	"in vec4 v2[];\n"
    112 	"\n"
    113 	"void main()\n"
    114 	"{\n"
    115 	"    gl_Position = v1[0] + vec4(-0.1, -0.1, 0, 0);\n"
    116 	"    EmitVertex();\n"
    117 	"    gl_Position = v1[0] + vec4(0.1, -0.1, 0, 0);\n"
    118 	"    EmitVertex();\n"
    119 	"    gl_Position = v1[0] + vec4(0.1, 0.1, 0, 0);\n"
    120 	"    EmitVertex();\n"
    121 	"    EndPrimitive();\n"
    122 	"\n"
    123 	"    gl_Position = v2[0] + vec4(-0.1, -0.1, 0, 0);\n"
    124 	"    EmitVertex();\n"
    125 	"    gl_Position = v2[0] + vec4(-0.1, 0.1, 0, 0);\n"
    126 	"    EmitVertex();\n"
    127 	"    gl_Position = v2[0] + vec4(0.1, 0.1, 0, 0);\n"
    128 	"    EmitVertex();\n"
    129 	"    EndPrimitive();\n"
    130 	"}\n";
    131 
    132 /* Shaders for GeometryShaderIfVertexEmitIsDoneAtEndTest */
    133 const char* const GeometryShaderIfVertexEmitIsDoneAtEndTest::m_geometry_shader_code =
    134 	"${VERSION}\n"
    135 	"\n"
    136 	"${GEOMETRY_SHADER_REQUIRE}\n"
    137 	"\n"
    138 	"precision highp float;\n"
    139 	"\n"
    140 	"layout(points)                            in;\n"
    141 	"layout(triangle_strip, max_vertices = 60) out;\n"
    142 	"\n"
    143 	"in vec4 v1[];\n"
    144 	"\n"
    145 	"void main()\n"
    146 	"{\n"
    147 	"    gl_Position = vec4(-1, -1, 0, 1);\n"
    148 	"    EmitVertex();\n"
    149 	"    gl_Position = vec4(-1, 1, 0, 1);\n"
    150 	"    EmitVertex();\n"
    151 	"    gl_Position = vec4(1, 1, 0, 1);\n"
    152 	"    EndPrimitive();\n"
    153 	"}\n";
    154 
    155 /* Shaders for GeometryShaderMissingEndPrimitiveCallTest */
    156 const char* const GeometryShaderMissingEndPrimitiveCallTest::m_geometry_shader_code =
    157 	"${VERSION}\n"
    158 	"\n"
    159 	"${GEOMETRY_SHADER_REQUIRE}\n"
    160 	"\n"
    161 	"layout(points)                            in;\n"
    162 	"layout(triangle_strip, max_vertices = 60) out;\n"
    163 	"\n"
    164 	"void main()\n"
    165 	"{\n"
    166 	"    gl_Position = vec4(-1, -1.004, 0, 1);\n"
    167 	"    EmitVertex();\n"
    168 	"    gl_Position = vec4(-1, 1, 0, 1);\n"
    169 	"    EmitVertex();\n"
    170 	"    gl_Position = vec4(1.004, 1, 0, 1);\n"
    171 	"    EmitVertex();\n"
    172 	"}\n";
    173 
    174 /* Shaders for GeometryShaderMissingEndPrimitiveCallForSinglePrimitiveTest */
    175 const char* const GeometryShaderMissingEndPrimitiveCallForSinglePrimitiveTest::m_geometry_shader_code =
    176 	"${VERSION}\n"
    177 	"\n"
    178 	"${GEOMETRY_SHADER_REQUIRE}\n"
    179 	"${GEOMETRY_POINT_SIZE_ENABLE}\n"
    180 	"\n"
    181 	"layout(points)                   in;\n"
    182 	"layout(points, max_vertices = 1) out;\n"
    183 	"\n"
    184 	"void main()\n"
    185 	"{\n"
    186 	"    gl_Position  = vec4(-1, -1, 0, 1);\n"
    187 	"    gl_PointSize = 2.0f;\n"
    188 	"    EmitVertex();\n"
    189 	"}\n";
    190 
    191 /* Definitions used by all test cases */
    192 #define TEXTURE_HEIGHT (16)
    193 #define TEXTURE_PIXEL_SIZE (4)
    194 #define TEXTURE_WIDTH (16)
    195 
    196 /** Constructor
    197  *
    198  *  @param context       Test context
    199  *  @param name          Test case's name
    200  *  @param description   Test case's description
    201  **/
    202 GeometryShaderOutput::GeometryShaderOutput(Context& context, const ExtParameters& extParams, const char* name,
    203 										   const char* description)
    204 	: TestCaseBase(context, extParams, name, description)
    205 {
    206 	/* Left blank on purpose */
    207 }
    208 
    209 /** Constructor
    210  *
    211  *  @param context       Test context
    212  *  @param name          Test case's name
    213  *  @param description   Test case's desricption
    214  **/
    215 GeometryShaderDuplicateOutputLayoutQualifierTest::GeometryShaderDuplicateOutputLayoutQualifierTest(
    216 	Context& context, const ExtParameters& extParams, const char* name, const char* description)
    217 	: GeometryShaderOutput(context, extParams, name, description)
    218 {
    219 	/* Nothing to be done here */
    220 }
    221 
    222 /** Executes the test.
    223  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    224  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
    225  *  Note the function throws exception should an error occur!
    226  **/
    227 tcu::TestCase::IterateResult GeometryShaderDuplicateOutputLayoutQualifierTest::iterate()
    228 {
    229 	if (!m_is_geometry_shader_extension_supported)
    230 	{
    231 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
    232 	}
    233 
    234 	/* Verify the program does not build. */
    235 	bool result = doesProgramBuild(1, &m_fragment_shader_code_white_color, 1, &m_geometry_shader_code, 1,
    236 								   &m_vertex_shader_code_two_vec4);
    237 
    238 	if (false == result)
    239 	{
    240 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    241 	}
    242 	else
    243 	{
    244 		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid program was linked successfully."
    245 						   << tcu::TestLog::EndMessage;
    246 
    247 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    248 	}
    249 
    250 	return STOP;
    251 }
    252 
    253 /** Constructor
    254  *
    255  *  @param context       Test context
    256  *  @param name          Test case's name
    257  *  @param description   Test case's desricption
    258  **/
    259 GeometryShaderDuplicateMaxVerticesLayoutQualifierTest::GeometryShaderDuplicateMaxVerticesLayoutQualifierTest(
    260 	Context& context, const ExtParameters& extParams, const char* name, const char* description)
    261 	: GeometryShaderOutput(context, extParams, name, description)
    262 {
    263 	/* Nothing to be done here */
    264 }
    265 
    266 /** Executes the test.
    267  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    268  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
    269  *  Note the function throws exception should an error occur!
    270  **/
    271 tcu::TestCase::IterateResult GeometryShaderDuplicateMaxVerticesLayoutQualifierTest::iterate()
    272 {
    273 	if (!m_is_geometry_shader_extension_supported)
    274 	{
    275 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
    276 	}
    277 
    278 	/* Verify the program does not build. */
    279 	bool result = doesProgramBuild(1, &m_fragment_shader_code_white_color, 1, &m_geometry_shader_code, 1,
    280 								   &m_vertex_shader_code_two_vec4);
    281 
    282 	if (false == result)
    283 	{
    284 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    285 	}
    286 	else
    287 	{
    288 		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid program was linked successfully."
    289 						   << tcu::TestLog::EndMessage;
    290 
    291 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    292 	}
    293 
    294 	return STOP;
    295 }
    296 
    297 /** Constructor
    298  *
    299  *  @param context                  Test context
    300  *  @param name                     Test case's name
    301  *  @param description              Test case's desricption
    302  *  @param geometry_shader_code     Code of geometry shader
    303  **/
    304 GeometryShaderOutputRenderingBase::GeometryShaderOutputRenderingBase(Context& context, const ExtParameters& extParams,
    305 																	 const char* name, const char* description,
    306 																	 const char* geometry_shader_code)
    307 	: GeometryShaderOutput(context, extParams, name, description)
    308 	, m_geometry_shader_code(geometry_shader_code)
    309 	, m_program_object_id(0)
    310 	, m_vertex_shader_id(0)
    311 	, m_fragment_shader_id(0)
    312 	, m_geometry_shader_id(0)
    313 	, m_vao_id(0)
    314 	, m_fbo_id(0)
    315 	, m_color_tex_id(0)
    316 {
    317 	/* Left blank on purpose */
    318 }
    319 
    320 /** Initialize test case
    321  *
    322  **/
    323 void GeometryShaderOutputRenderingBase::initTest()
    324 {
    325 	if (!m_is_geometry_shader_extension_supported)
    326 	{
    327 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
    328 	}
    329 
    330 	/* GL functions */
    331 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    332 
    333 	/* Create shader objects */
    334 	m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
    335 	m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
    336 	m_vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
    337 
    338 	/* Create program object */
    339 	m_program_object_id = gl.createProgram();
    340 
    341 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create program object");
    342 
    343 	/* Build the program object */
    344 	if (false == buildProgram(m_program_object_id, m_fragment_shader_id, 1, &m_fragment_shader_code_white_color,
    345 							  m_geometry_shader_id, 1, &m_geometry_shader_code, m_vertex_shader_id, 1,
    346 							  &m_vertex_shader_code_vec4_0_0_0_1))
    347 	{
    348 		TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
    349 	}
    350 
    351 	/* Set up texture object and a FBO */
    352 	gl.genTextures(1, &m_color_tex_id);
    353 	gl.genFramebuffers(1, &m_fbo_id);
    354 
    355 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create framebuffer");
    356 
    357 	if (false ==
    358 		setupFramebufferWithTextureAsAttachment(m_fbo_id, m_color_tex_id, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT))
    359 	{
    360 		TCU_FAIL("Failed to setup framebuffer");
    361 	}
    362 
    363 	/* Set up a vertex array object */
    364 	gl.genVertexArrays(1, &m_vao_id);
    365 	gl.bindVertexArray(m_vao_id);
    366 
    367 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
    368 	{
    369 		gl.enable(GL_PROGRAM_POINT_SIZE);
    370 	}
    371 
    372 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
    373 }
    374 
    375 /** Executes the test.
    376  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    377  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
    378  *  Note the function throws exception should an error occur!
    379  **/
    380 tcu::TestCase::IterateResult GeometryShaderOutputRenderingBase::iterate()
    381 {
    382 	initTest();
    383 
    384 	/* Variables used for image verification purposes */
    385 	unsigned char result_image[TEXTURE_HEIGHT * TEXTURE_WIDTH * TEXTURE_PIXEL_SIZE];
    386 
    387 	/* GL functions */
    388 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    389 
    390 	/* Render */
    391 	gl.useProgram(m_program_object_id);
    392 
    393 	gl.clearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
    394 	gl.clear(GL_COLOR_BUFFER_BIT);
    395 
    396 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer");
    397 
    398 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
    399 
    400 	GLU_EXPECT_NO_ERROR(gl.getError(), "Call drawArrays() failed");
    401 
    402 	/* Extract image from FBO */
    403 	gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, result_image);
    404 
    405 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color buffer");
    406 
    407 	/* Run verification */
    408 	if (true == verifyResult(result_image, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_PIXEL_SIZE))
    409 	{
    410 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    411 	}
    412 	else
    413 	{
    414 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    415 	}
    416 
    417 	return STOP;
    418 }
    419 
    420 /** Deinitialize test case
    421  *
    422  **/
    423 void GeometryShaderOutputRenderingBase::deinit()
    424 {
    425 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    426 
    427 	/* Reset OpenGL ES state */
    428 	gl.useProgram(0);
    429 	gl.bindVertexArray(0);
    430 	gl.bindTexture(GL_TEXTURE_2D, 0);
    431 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
    432 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
    433 	{
    434 		gl.disable(GL_PROGRAM_POINT_SIZE);
    435 	}
    436 
    437 	if (m_program_object_id != 0)
    438 	{
    439 		gl.deleteProgram(m_program_object_id);
    440 	}
    441 
    442 	if (m_fragment_shader_id != 0)
    443 	{
    444 		gl.deleteShader(m_fragment_shader_id);
    445 	}
    446 
    447 	if (m_geometry_shader_id != 0)
    448 	{
    449 		gl.deleteShader(m_geometry_shader_id);
    450 	}
    451 
    452 	if (m_vertex_shader_id != 0)
    453 	{
    454 		gl.deleteShader(m_vertex_shader_id);
    455 	}
    456 
    457 	if (m_vao_id != 0)
    458 	{
    459 		gl.deleteVertexArrays(1, &m_vao_id);
    460 	}
    461 
    462 	if (m_color_tex_id != 0)
    463 	{
    464 		gl.deleteTextures(1, &m_color_tex_id);
    465 	}
    466 
    467 	if (m_fbo_id != 0)
    468 	{
    469 		gl.deleteFramebuffers(1, &m_fbo_id);
    470 	}
    471 
    472 	/* Release base class */
    473 	TestCaseBase::deinit();
    474 }
    475 
    476 /** Constructor
    477  *
    478  *  @param context       Test context
    479  *  @param name          Test case's name
    480  *  @param description   Test case's desricption
    481  **/
    482 GeometryShaderIfVertexEmitIsDoneAtEndTest::GeometryShaderIfVertexEmitIsDoneAtEndTest(Context&			  context,
    483 																					 const ExtParameters& extParams,
    484 																					 const char*		  name,
    485 																					 const char*		  description)
    486 	: GeometryShaderOutputRenderingBase(context, extParams, name, description, m_geometry_shader_code)
    487 {
    488 	/* Left blank on purpose */
    489 }
    490 
    491 /** Verifies result of draw call
    492  *
    493  *  @param result_image Image data
    494  *  @param width        Image width
    495  *  @param height       Image height
    496  *  @param pixel_size   Size of single pixel in bytes
    497  *
    498  *  @return true  if test succeded
    499  *          false if the test failed
    500  *          Note the function throws exception should an error occur!
    501  **/
    502 bool GeometryShaderIfVertexEmitIsDoneAtEndTest::verifyResult(const unsigned char* result_image, unsigned int width,
    503 															 unsigned int height, unsigned int pixel_size) const
    504 {
    505 	/* Check if the data was modified during the rendering process */
    506 	for (unsigned int y = 0; y < height; ++y)
    507 	{
    508 		for (unsigned int x = 0; x < width; ++x)
    509 		{
    510 			if (false == comparePixel(result_image, x, y, width, height, pixel_size))
    511 			{
    512 				m_testCtx.getLog() << tcu::TestLog::Message
    513 								   << "Vertex emitted without a corresponding EmitVertex() call made"
    514 								   << tcu::TestLog::EndMessage;
    515 
    516 				return false;
    517 			}
    518 		}
    519 	}
    520 
    521 	/* Done */
    522 	return true;
    523 }
    524 
    525 /** Constructor
    526  *
    527  *  @param context       Test context
    528  *  @param name          Test case's name
    529  *  @param description   Test case's desricption
    530  **/
    531 GeometryShaderMissingEndPrimitiveCallTest::GeometryShaderMissingEndPrimitiveCallTest(Context&			  context,
    532 																					 const ExtParameters& extParams,
    533 																					 const char*		  name,
    534 																					 const char*		  description)
    535 	: GeometryShaderOutputRenderingBase(context, extParams, name, description, m_geometry_shader_code)
    536 {
    537 	/* Left blank on purpose */
    538 }
    539 
    540 /** Verifies result of draw call
    541  *
    542  *  @param result_image Image data
    543  *  @param width        Image width
    544  *  @param height       Image height
    545  *  @param pixel_size   Size of single pixel in bytes
    546  *
    547  *  @return true  if test succeded
    548  *          false if the test failed
    549  **/
    550 bool GeometryShaderMissingEndPrimitiveCallTest::verifyResult(const unsigned char* result_image, unsigned int width,
    551 															 unsigned int height, unsigned int pixel_size) const
    552 {
    553 	/* Image size */
    554 	const unsigned int left   = 0;
    555 	const unsigned int right  = width - 1;
    556 	const unsigned int bottom = 0;
    557 	const unsigned int top	= height - 1;
    558 
    559 	/* Verification */
    560 	if ((true == comparePixel(result_image, left, bottom, width, height, pixel_size, 255, 255, 255, 255)) &&
    561 		(true == comparePixel(result_image, left, top, width, height, pixel_size, 255, 255, 255, 255)) &&
    562 		(true == comparePixel(result_image, right, top, width, height, pixel_size, 255, 255, 255, 255)) &&
    563 		(true == comparePixel(result_image, right, bottom, width, height, pixel_size, 0, 0, 0, 0)))
    564 	{
    565 		return true;
    566 	}
    567 	else
    568 	{
    569 		m_testCtx.getLog() << tcu::TestLog::Message << "EndPrimitive() is not called at the end of geometry shader"
    570 						   << tcu::TestLog::EndMessage;
    571 
    572 		return false;
    573 	}
    574 }
    575 
    576 /** Constructor
    577  *
    578  *  @param context       Test context
    579  *  @param name          Test case's name
    580  *  @param description   Test case's desricption
    581  **/
    582 GeometryShaderMissingEndPrimitiveCallForSinglePrimitiveTest::
    583 	GeometryShaderMissingEndPrimitiveCallForSinglePrimitiveTest(Context& context, const ExtParameters& extParams,
    584 																const char* name, const char* description)
    585 	: GeometryShaderOutputRenderingBase(context, extParams, name, description, m_geometry_shader_code)
    586 {
    587 	/* Left blank on purpose */
    588 }
    589 
    590 /** Executes the test.
    591  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    592  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
    593  *  Note the function throws exception should an error occur!
    594  **/
    595 tcu::TestCase::IterateResult GeometryShaderMissingEndPrimitiveCallForSinglePrimitiveTest::iterate()
    596 {
    597 	if (!m_is_geometry_shader_point_size_supported)
    598 	{
    599 		throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
    600 	}
    601 
    602 	return GeometryShaderOutputRenderingBase::iterate();
    603 }
    604 
    605 /** Verifies result of draw call
    606  *
    607  *  @param result_image Image data
    608  *  @param width        Image width
    609  *  @param height       Image height
    610  *  @param pixel_size   Size of single pixel in bytes
    611  *
    612  *  @return true  if test succeded
    613  *          false if the test failed
    614  *          Note the function throws exception should an error occur!
    615  **/
    616 bool GeometryShaderMissingEndPrimitiveCallForSinglePrimitiveTest::verifyResult(const unsigned char* result_image,
    617 																			   unsigned int width, unsigned int height,
    618 																			   unsigned int pixel_size) const
    619 {
    620 	/* Image size */
    621 	const unsigned int left   = 0;
    622 	const unsigned int right  = width - 1;
    623 	const unsigned int bottom = 0;
    624 	const unsigned int top	= height - 1;
    625 
    626 	/* Verification */
    627 	if ((true == comparePixel(result_image, left, bottom, width, height, pixel_size, 255, 255, 255, 255)) &&
    628 		(true == comparePixel(result_image, left, top, width, height, pixel_size, 0, 0, 0, 0)) &&
    629 		(true == comparePixel(result_image, right, top, width, height, pixel_size, 0, 0, 0, 0)) &&
    630 		(true == comparePixel(result_image, right, bottom, width, height, pixel_size, 0, 0, 0, 0)))
    631 	{
    632 		return true;
    633 	}
    634 	else
    635 	{
    636 		m_testCtx.getLog() << tcu::TestLog::Message << "EndPrimitive() is not done for a single primitive"
    637 						   << tcu::TestLog::EndMessage;
    638 
    639 		return false;
    640 	}
    641 }
    642 
    643 } // namespace glcts
    644