Home | History | Annotate | Download | only in gl
      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 /* Includes. */
     25 #include "gl4cConditionalRenderInvertedTests.hpp"
     26 #include "gluContextInfo.hpp"
     27 #include "gluDefs.hpp"
     28 #include "gluRenderContext.hpp"
     29 #include "gluStrUtil.hpp"
     30 #include "tcuTestLog.hpp"
     31 
     32 /******************************** Test Group Implementation       ********************************/
     33 
     34 /** @brief Context Flush Control tests group constructor.
     35  *
     36  *  @param [in] context     OpenGL context.
     37  */
     38 gl4cts::ConditionalRenderInverted::Tests::Tests(deqp::Context& context)
     39 	: TestCaseGroup(context, "conditional_render_inverted", "Conditional Render Inverted Test Suite")
     40 {
     41 	/* Intentionally left blank */
     42 }
     43 
     44 /** @brief Context Flush Control tests initializer. */
     45 void gl4cts::ConditionalRenderInverted::Tests::init()
     46 {
     47 	addChild(new gl4cts::ConditionalRenderInverted::CoverageTest(m_context));
     48 	addChild(new gl4cts::ConditionalRenderInverted::FunctionalTest(m_context));
     49 }
     50 
     51 /******************************** Coverage Tests Implementation   ********************************/
     52 
     53 /** @brief API coverage tests constructor.
     54  *
     55  *  @param [in] context     OpenGL context.
     56  */
     57 gl4cts::ConditionalRenderInverted::CoverageTest::CoverageTest(deqp::Context& context)
     58 	: deqp::TestCase(context, "coverage", "Conditional Render Inverted Coverage Test"), m_qo_id(0)
     59 {
     60 	/* Intentionally left blank. */
     61 }
     62 
     63 /** @brief Iterate API coverage tests.
     64  *
     65  *  @return Iteration result.
     66  */
     67 tcu::TestNode::IterateResult gl4cts::ConditionalRenderInverted::CoverageTest::iterate()
     68 {
     69 	/* OpenGL support query. */
     70 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
     71 	bool is_arb_conditional_render_inverted =
     72 		m_context.getContextInfo().isExtensionSupported("GL_ARB_conditional_render_inverted");
     73 
     74 	/* Running tests. */
     75 	bool is_ok	= true;
     76 	bool is_error = false;
     77 
     78 	/* This test should only be executed if we're running a GL4.5 context or related extension is available */
     79 	try
     80 	{
     81 		if (is_at_least_gl_45 || is_arb_conditional_render_inverted)
     82 		{
     83 			/* Prepare common objects. */
     84 			createQueryObject();
     85 
     86 			/* Test cases. */
     87 			static const glw::GLenum modes[] = { GL_QUERY_WAIT_INVERTED, GL_QUERY_NO_WAIT_INVERTED,
     88 												 GL_QUERY_BY_REGION_WAIT_INVERTED,
     89 												 GL_QUERY_BY_REGION_NO_WAIT_INVERTED };
     90 
     91 			static const glw::GLuint modes_count = sizeof(modes) / sizeof(modes[0]);
     92 
     93 			/* Iterate over the test cases. */
     94 			for (glw::GLuint i = 0; i < modes_count; ++i)
     95 			{
     96 				is_ok &= test(modes[i]);
     97 			}
     98 		}
     99 	}
    100 	catch (...)
    101 	{
    102 		is_ok	= false;
    103 		is_error = true;
    104 	}
    105 
    106 	/* Cleanup. */
    107 	clean();
    108 
    109 	/* Result's setup. */
    110 	if (is_ok)
    111 	{
    112 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    113 	}
    114 	else
    115 	{
    116 		if (is_error)
    117 		{
    118 			m_context.getTestContext().getLog()
    119 				<< tcu::TestLog::Message
    120 				<< "Internal error has occured during Conditional Render Inverted Coverage Test."
    121 				<< tcu::TestLog::EndMessage;
    122 
    123 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Test error.");
    124 		}
    125 		else
    126 		{
    127 			m_context.getTestContext().getLog() << tcu::TestLog::Message
    128 												<< "The Conditional Render Inverted Coverage Test has failed."
    129 												<< tcu::TestLog::EndMessage;
    130 
    131 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    132 		}
    133 	}
    134 
    135 	return STOP;
    136 }
    137 
    138 /** @brief Create query object.
    139  */
    140 void gl4cts::ConditionalRenderInverted::CoverageTest::createQueryObject()
    141 {
    142 	/* Shortcut for GL functionality. */
    143 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    144 
    145 	/* Create valid query object. */
    146 	gl.genQueries(1, &m_qo_id);
    147 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries() call failed.");
    148 
    149 	gl.beginQuery(GL_SAMPLES_PASSED, m_qo_id);
    150 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery() call failed.");
    151 
    152 	gl.endQuery(GL_SAMPLES_PASSED);
    153 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery() call failed.");
    154 }
    155 
    156 /** @brief Clean query object and error values.
    157  */
    158 void gl4cts::ConditionalRenderInverted::CoverageTest::clean()
    159 {
    160 	/* Shortcut for GL functionality. */
    161 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    162 
    163 	/* Clean query object. */
    164 	gl.deleteQueries(1, &m_qo_id);
    165 
    166 	m_qo_id = 0;
    167 
    168 	/* Make sure no errors are left. */
    169 	while (gl.getError())
    170 		;
    171 }
    172 
    173 /** @brief Test that glBeginConditionalRender accept mode.
    174  *
    175  *  @param [in] mode    Render condition mode.
    176  *
    177  *  @return True if glBeginConditionalRender did not generate an error, false otherwise.
    178  */
    179 bool gl4cts::ConditionalRenderInverted::CoverageTest::test(glw::GLenum mode)
    180 {
    181 	/* Shortcut for GL functionality. */
    182 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    183 
    184 	/* Default return value;*/
    185 	bool is_no_error = true;
    186 
    187 	/* Test. */
    188 	gl.beginConditionalRender(m_qo_id, mode);
    189 
    190 	while (GL_NO_ERROR != gl.getError())
    191 	{
    192 		is_no_error = false;
    193 	}
    194 
    195 	/* Clean up. */
    196 	if (is_no_error)
    197 	{
    198 		gl.endConditionalRender();
    199 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndConditionalRender() call failed.");
    200 	}
    201 
    202 	/* Logging. */
    203 	if (!is_no_error)
    204 	{
    205 		m_context.getTestContext().getLog() << tcu::TestLog::Message
    206 											<< "glBeginConditionalRender failed when used with mode "
    207 											<< Utilities::modeToChars(mode) << "." << tcu::TestLog::EndMessage;
    208 	}
    209 
    210 	/* Return test result. */
    211 	return is_no_error;
    212 }
    213 
    214 /******************************** Functional Test Implementation   ********************************/
    215 
    216 /** @brief Functional test constructor.
    217  *
    218  *  @param [in] context     OpenGL context.
    219  */
    220 gl4cts::ConditionalRenderInverted::FunctionalTest::FunctionalTest(deqp::Context& context)
    221 	: deqp::TestCase(context, "functional", "Conditional Render Inverted Functional Test")
    222 	, m_fbo_id(0)
    223 	, m_rbo_id(0)
    224 	, m_vao_id(0)
    225 	, m_po_id(0)
    226 	, m_qo_id(0)
    227 {
    228 	/* Intentionally left blank. */
    229 }
    230 
    231 /** @brief Iterate Functional test cases.
    232  *
    233  *  @return Iteration result.
    234  */
    235 tcu::TestNode::IterateResult gl4cts::ConditionalRenderInverted::FunctionalTest::iterate()
    236 {
    237 	/* OpenGL support query. */
    238 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
    239 	bool is_arb_conditional_render_inverted =
    240 		m_context.getContextInfo().isExtensionSupported("GL_ARB_conditional_render_inverted");
    241 
    242 	/* Running tests. */
    243 	bool is_ok	= true;
    244 	bool is_error = false;
    245 
    246 	/* This test should only be executed if we're running a GL4.5 context or related extension is available */
    247 	try
    248 	{
    249 		if (is_at_least_gl_45 || is_arb_conditional_render_inverted)
    250 		{
    251 			/* Test cases. */
    252 			static const bool render_cases[] = { false, true };
    253 
    254 			static const glw::GLuint render_cases_count = sizeof(render_cases) / sizeof(render_cases[0]);
    255 
    256 			static const glw::GLenum query_cases[] = { GL_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED };
    257 
    258 			static const glw::GLuint query_cases_count = sizeof(query_cases) / sizeof(query_cases[0]);
    259 
    260 			static const glw::GLenum modes[] = { GL_QUERY_WAIT_INVERTED, GL_QUERY_NO_WAIT_INVERTED,
    261 												 GL_QUERY_BY_REGION_WAIT_INVERTED,
    262 												 GL_QUERY_BY_REGION_NO_WAIT_INVERTED };
    263 
    264 			static const glw::GLuint modes_count = sizeof(modes) / sizeof(modes[0]);
    265 
    266 			/* Creating common objects. */
    267 			createProgram();
    268 			createView();
    269 			createVertexArrayObject();
    270 
    271 			/* Iterating over test cases. */
    272 			for (glw::GLuint i = 0; i < render_cases_count; ++i)
    273 			{
    274 				for (glw::GLuint j = 0; j < query_cases_count; ++j)
    275 				{
    276 					for (glw::GLuint k = 0; k < modes_count; ++k)
    277 					{
    278 						createQueryObject();
    279 
    280 						setupColor(1.f);
    281 						setupPassSwitch(render_cases[i]);
    282 						clearView();
    283 						draw(false, query_cases[j]);
    284 
    285 						if (render_cases[i] == fragmentsPassed())
    286 						{
    287 							setupColor(0.f);
    288 							setupPassSwitch(true);
    289 							draw(true, modes[k]);
    290 
    291 							glw::GLfloat expected_value = (render_cases[i]) ? 1.f : 0.f;
    292 							glw::GLfloat resulted_value = readPixel();
    293 
    294 							if (de::abs(expected_value - resulted_value) > 0.0078125f /* Precission (1/128) */)
    295 							{
    296 								m_context.getTestContext().getLog()
    297 									<< tcu::TestLog::Message << "The functional test's expected value ("
    298 									<< expected_value << ") is different than resulted value (" << resulted_value
    299 									<< "). The tested mode was " << Utilities::modeToChars(modes[k])
    300 									<< ". Query was done for target " << Utilities::queryTargetToChars(query_cases[j])
    301 									<< ", and the test was prepared to " << ((render_cases[i]) ? "pass" : "discard")
    302 									<< " all fragments." << tcu::TestLog::EndMessage;
    303 
    304 								is_ok = false;
    305 							}
    306 						}
    307 						else
    308 						{
    309 							is_ok = false;
    310 						}
    311 
    312 						cleanQueryObject();
    313 					}
    314 				}
    315 			}
    316 		}
    317 	}
    318 	catch (...)
    319 	{
    320 		is_ok	= false;
    321 		is_error = true;
    322 
    323 		cleanQueryObject();
    324 	}
    325 
    326 	/* Clean-up. */
    327 	cleanProgramViewAndVAO();
    328 
    329 	/* Result's setup. */
    330 	if (is_ok)
    331 	{
    332 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    333 	}
    334 	else
    335 	{
    336 		if (is_error)
    337 		{
    338 			m_context.getTestContext().getLog()
    339 				<< tcu::TestLog::Message
    340 				<< "Internal error has occured during Conditional Render Inverted Functional Test."
    341 				<< tcu::TestLog::EndMessage;
    342 
    343 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Test error.");
    344 		}
    345 		else
    346 		{
    347 			m_context.getTestContext().getLog() << tcu::TestLog::Message
    348 												<< "The Conditional Render Inverted Functional Test has failed."
    349 												<< tcu::TestLog::EndMessage;
    350 
    351 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail.");
    352 		}
    353 	}
    354 
    355 	return STOP;
    356 }
    357 
    358 /** @brief Compile and link test's GLSL program.
    359  */
    360 void gl4cts::ConditionalRenderInverted::FunctionalTest::createProgram()
    361 {
    362 	/* Shortcut for GL functionality. */
    363 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    364 
    365 	struct Shader
    366 	{
    367 		glw::GLchar const* const source;
    368 		glw::GLenum const		 type;
    369 		glw::GLuint				 id;
    370 	} shader[] = { { s_vertex_shader, GL_VERTEX_SHADER, 0 }, { s_fragment_shader, GL_FRAGMENT_SHADER, 0 } };
    371 
    372 	glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
    373 
    374 	try
    375 	{
    376 		/* Create program. */
    377 		m_po_id = gl.createProgram();
    378 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
    379 
    380 		/* Shader compilation. */
    381 
    382 		for (glw::GLuint i = 0; i < shader_count; ++i)
    383 		{
    384 			if (DE_NULL != shader[i].source)
    385 			{
    386 				shader[i].id = gl.createShader(shader[i].type);
    387 
    388 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
    389 
    390 				gl.attachShader(m_po_id, shader[i].id);
    391 
    392 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
    393 
    394 				gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
    395 
    396 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
    397 
    398 				gl.compileShader(shader[i].id);
    399 
    400 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
    401 
    402 				glw::GLint status = GL_FALSE;
    403 
    404 				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
    405 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
    406 
    407 				if (GL_FALSE == status)
    408 				{
    409 					throw 0;
    410 				}
    411 			}
    412 		}
    413 
    414 		/* Link. */
    415 		gl.linkProgram(m_po_id);
    416 
    417 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
    418 
    419 		glw::GLint status = GL_FALSE;
    420 
    421 		gl.getProgramiv(m_po_id, GL_LINK_STATUS, &status);
    422 
    423 		if (GL_TRUE == status)
    424 		{
    425 			for (glw::GLuint i = 0; i < shader_count; ++i)
    426 			{
    427 				if (shader[i].id)
    428 				{
    429 					gl.detachShader(m_po_id, shader[i].id);
    430 
    431 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
    432 				}
    433 			}
    434 		}
    435 		else
    436 		{
    437 			throw 0;
    438 		}
    439 	}
    440 	catch (...)
    441 	{
    442 		if (m_po_id)
    443 		{
    444 			gl.deleteProgram(m_po_id);
    445 
    446 			m_po_id = 0;
    447 		}
    448 	}
    449 
    450 	for (glw::GLuint i = 0; i < shader_count; ++i)
    451 	{
    452 		if (0 != shader[i].id)
    453 		{
    454 			gl.deleteShader(shader[i].id);
    455 
    456 			shader[i].id = 0;
    457 		}
    458 	}
    459 
    460 	if (m_po_id)
    461 	{
    462 		gl.useProgram(m_po_id);
    463 
    464 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
    465 	}
    466 }
    467 
    468 /** @brief Create and bind framebuffer with renderbuffer color attachment.
    469  */
    470 void gl4cts::ConditionalRenderInverted::FunctionalTest::createView()
    471 {
    472 	/* Shortcut for GL functionality. */
    473 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    474 
    475 	/* Prepare framebuffer. */
    476 	gl.clearColor(0.5f, 0.5f, 0.5f, 0.5f);
    477 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
    478 
    479 	gl.genFramebuffers(1, &m_fbo_id);
    480 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
    481 
    482 	gl.genRenderbuffers(1, &m_rbo_id);
    483 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
    484 
    485 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
    486 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
    487 
    488 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
    489 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
    490 
    491 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
    492 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
    493 
    494 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
    495 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
    496 
    497 	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    498 	{
    499 		throw 0;
    500 	}
    501 
    502 	gl.viewport(0, 0, s_view_size, s_view_size);
    503 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
    504 }
    505 
    506 /** @brief Create test's query object.
    507  */
    508 void gl4cts::ConditionalRenderInverted::FunctionalTest::createQueryObject()
    509 {
    510 	/* Shortcut for GL functionality. */
    511 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    512 
    513 	/* Create valid query object. */
    514 	gl.genQueries(1, &m_qo_id);
    515 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries() call failed.");
    516 }
    517 
    518 /** @brief Setup color uniform of the test's program.
    519  */
    520 void gl4cts::ConditionalRenderInverted::FunctionalTest::setupColor(const glw::GLfloat red)
    521 {
    522 	/* Shortcut for GL functionality. */
    523 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    524 
    525 	/* Fetch where to set. */
    526 	glw::GLuint location = gl.getUniformLocation(m_po_id, s_color_uniform_name);
    527 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call failed.");
    528 
    529 	/* Set. */
    530 	gl.uniform1f(location, red);
    531 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f() call failed.");
    532 }
    533 
    534 /** @brief Setup pass or discard switch uniform of the test's program.
    535  */
    536 void gl4cts::ConditionalRenderInverted::FunctionalTest::setupPassSwitch(const bool shall_pass)
    537 {
    538 	/* Shortcut for GL functionality. */
    539 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    540 
    541 	/* Fetch where to set. */
    542 	glw::GLuint location = gl.getUniformLocation(m_po_id, s_pass_switch_uniform_name);
    543 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call failed.");
    544 
    545 	/* Set. */
    546 	gl.uniform1i(location, (int)shall_pass);
    547 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f() call failed.");
    548 }
    549 
    550 /** @brief Draw full screen within query or conditional block.
    551  *
    552  *  @param [in] conditional_or_query_draw       If true draw will be done in conditional rendering block, otherwise in query block.
    553  *  @param [in] condition_mode_or_query_target  The param needed by query or conditional block - target or mode.
    554  */
    555 void gl4cts::ConditionalRenderInverted::FunctionalTest::draw(const bool		   conditional_or_query_draw,
    556 															 const glw::GLenum condition_mode_or_query_target)
    557 {
    558 	/* Shortcut for GL functionality. */
    559 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    560 
    561 	if (conditional_or_query_draw)
    562 	{
    563 		gl.beginConditionalRender(m_qo_id, condition_mode_or_query_target);
    564 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginConditionalRender() call failed.");
    565 	}
    566 	else
    567 	{
    568 		gl.beginQuery(condition_mode_or_query_target, m_qo_id);
    569 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery() call failed.");
    570 	}
    571 
    572 	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
    573 
    574 	if (conditional_or_query_draw)
    575 	{
    576 		gl.endConditionalRender();
    577 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndConditionalRender() call failed.");
    578 	}
    579 	else
    580 	{
    581 		gl.endQuery(condition_mode_or_query_target);
    582 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery() call failed.");
    583 	}
    584 }
    585 
    586 /** @brief Check if any fragments have passed rendering.
    587  *
    588  *  @return True if any sample passed, false otherwise.
    589  */
    590 bool gl4cts::ConditionalRenderInverted::FunctionalTest::fragmentsPassed()
    591 {
    592 	/* Shortcut for GL functionality. */
    593 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    594 
    595 	/* Fetch result. */
    596 	glw::GLint result = -1;
    597 
    598 	gl.getQueryObjectiv(m_qo_id, GL_QUERY_RESULT, &result);
    599 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectiv() call failed.");
    600 
    601 	/* Check for unusual errors. */
    602 	if (-1 == result)
    603 	{
    604 		throw 0;
    605 	}
    606 
    607 	/* Return results. */
    608 	return (result > 0);
    609 }
    610 
    611 /** @brief Read framebuffer's first pixel red component (left, bottom).
    612  *
    613  *  @return Red value of the pixel.
    614  */
    615 glw::GLfloat gl4cts::ConditionalRenderInverted::FunctionalTest::readPixel()
    616 {
    617 	/* Shortcut for GL functionality. */
    618 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    619 
    620 	glw::GLfloat red = -1.f;
    621 
    622 	gl.readPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &red);
    623 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
    624 
    625 	return red;
    626 }
    627 
    628 /** @brief Destroy test's query object.
    629  */
    630 void gl4cts::ConditionalRenderInverted::FunctionalTest::cleanQueryObject()
    631 {
    632 	/* Shortcut for GL functionality. */
    633 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    634 
    635 	/* Clean query object. */
    636 	if (m_qo_id)
    637 	{
    638 		gl.deleteQueries(1, &m_qo_id);
    639 
    640 		m_qo_id = 0;
    641 	}
    642 }
    643 
    644 /** @brief Create test's empty Vertex Array Object.
    645  */
    646 void gl4cts::ConditionalRenderInverted::FunctionalTest::createVertexArrayObject()
    647 {
    648 	/* Shortcut for GL functionality. */
    649 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    650 
    651 	/* Create and bind vertex array. */
    652 	gl.genVertexArrays(1, &m_vao_id);
    653 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
    654 
    655 	gl.bindVertexArray(m_vao_id);
    656 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
    657 }
    658 
    659 /** @brief Destroy test's Vertex Array Object.
    660  */
    661 void gl4cts::ConditionalRenderInverted::FunctionalTest::cleanProgramViewAndVAO()
    662 {
    663 	/* Shortcut for GL functionality. */
    664 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    665 
    666 	/* Deleting view. */
    667 	if (m_fbo_id)
    668 	{
    669 		gl.deleteFramebuffers(1, &m_fbo_id);
    670 
    671 		m_fbo_id = 0;
    672 	}
    673 
    674 	if (m_rbo_id)
    675 	{
    676 		gl.deleteRenderbuffers(1, &m_rbo_id);
    677 
    678 		m_rbo_id = 0;
    679 	}
    680 
    681 	if (m_vao_id)
    682 	{
    683 		gl.deleteVertexArrays(1, &m_vao_id);
    684 
    685 		m_vao_id = 0;
    686 	}
    687 }
    688 
    689 /** @brief Destroy test's framebuffer with related objects.
    690  */
    691 void gl4cts::ConditionalRenderInverted::FunctionalTest::clearView()
    692 {
    693 	/* Shortcut for GL functionality. */
    694 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    695 
    696 	/* Clear screen. */
    697 	gl.clear(GL_COLOR_BUFFER_BIT);
    698 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
    699 }
    700 
    701 const glw::GLchar gl4cts::ConditionalRenderInverted::FunctionalTest::s_vertex_shader[] =
    702 	"#version 130\n"
    703 	"\n"
    704 	"void main()\n"
    705 	"{\n"
    706 	"    switch(gl_VertexID % 4)\n"
    707 	"    {\n"
    708 	"    case 0:\n"
    709 	"       gl_Position = vec4(-1.0, -1.0,  0.0,  1.0);\n"
    710 	"       break;\n"
    711 	"    case 1:\n"
    712 	"       gl_Position = vec4( 1.0, -1.0,  0.0,  1.0);\n"
    713 	"       break;\n"
    714 	"    case 2:\n"
    715 	"       gl_Position = vec4(-1.0,  1.0,  0.0,  1.0);\n"
    716 	"       break;\n"
    717 	"    case 3:\n"
    718 	"       gl_Position = vec4( 1.0,  1.0,  0.0,  1.0);\n"
    719 	"       break;\n"
    720 	"    }\n"
    721 	"}\n";
    722 
    723 const glw::GLchar gl4cts::ConditionalRenderInverted::FunctionalTest::s_fragment_shader[] = "#version 130\n"
    724 																						   "\n"
    725 																						   "uniform float color;\n"
    726 																						   "uniform int   shall_pass;\n"
    727 																						   "\n"
    728 																						   "out vec4 pixel;\n"
    729 																						   "\n"
    730 																						   "void main()\n"
    731 																						   "{\n"
    732 																						   "    if(0 == shall_pass)\n"
    733 																						   "    {\n"
    734 																						   "        discard;\n"
    735 																						   "    }\n"
    736 																						   "\n"
    737 																						   "    pixel = vec4(color);\n"
    738 																						   "}\n";
    739 
    740 const glw::GLchar gl4cts::ConditionalRenderInverted::FunctionalTest::s_color_uniform_name[] = "color";
    741 
    742 const glw::GLchar gl4cts::ConditionalRenderInverted::FunctionalTest::s_pass_switch_uniform_name[] = "shall_pass";
    743 
    744 const glw::GLuint gl4cts::ConditionalRenderInverted::FunctionalTest::s_view_size = 1;
    745 
    746 /******************************** Utilities Implementation   ********************************/
    747 
    748 /** @brief Return string representation of condional rendering mode.
    749  *
    750  *  @param [in] mode    Render condition mode.
    751  *
    752  *  @return Constant C-String representation of mode.
    753  */
    754 const glw::GLchar* gl4cts::ConditionalRenderInverted::Utilities::modeToChars(glw::GLenum mode)
    755 {
    756 	/* Const name values. */
    757 	static const glw::GLchar* query_wait_inverted_mode_name				 = "GL_QUERY_WAIT_INVERTED";
    758 	static const glw::GLchar* query_no_wait_inverted_mode_name			 = "GL_QUERY_NO_WAIT_INVERTED";
    759 	static const glw::GLchar* query_by_region_wait_inverted_mode_name	= "GL_QUERY_BY_REGION_WAIT_INVERTED";
    760 	static const glw::GLchar* query_by_region_no_wait_inverted_mode_name = "GL_QUERY_BY_REGION_NO_WAIT_INVERTED";
    761 	static const glw::GLchar* invalid_mode_name							 = "unknow mode";
    762 
    763 	/* Return proper value. */
    764 	if (GL_QUERY_WAIT_INVERTED == mode)
    765 	{
    766 		return query_wait_inverted_mode_name;
    767 	}
    768 
    769 	if (GL_QUERY_NO_WAIT_INVERTED == mode)
    770 	{
    771 		return query_no_wait_inverted_mode_name;
    772 	}
    773 
    774 	if (GL_QUERY_BY_REGION_WAIT_INVERTED == mode)
    775 	{
    776 		return query_by_region_wait_inverted_mode_name;
    777 	}
    778 
    779 	if (GL_QUERY_BY_REGION_NO_WAIT_INVERTED == mode)
    780 	{
    781 		return query_by_region_no_wait_inverted_mode_name;
    782 	}
    783 
    784 	/* If not, return invalid name. */
    785 	return invalid_mode_name;
    786 }
    787 
    788 /** @brief Return string representation of glBeginQuery's target.
    789  *
    790  *  @param [in] mode    Render condition mode.
    791  *
    792  *  @return Constant C-String representation of mode.
    793  */
    794 const glw::GLchar* gl4cts::ConditionalRenderInverted::Utilities::queryTargetToChars(glw::GLenum mode)
    795 {
    796 	/* Const name values. */
    797 	static const glw::GLchar* any_samples_name	= "GL_ANY_SAMPLES_PASSED";
    798 	static const glw::GLchar* samples_name		  = "GL_SAMPLES_PASSED";
    799 	static const glw::GLchar* invalid_target_name = "unknow mode";
    800 
    801 	/* Return proper value. */
    802 	if (GL_ANY_SAMPLES_PASSED == mode)
    803 	{
    804 		return any_samples_name;
    805 	}
    806 
    807 	if (GL_SAMPLES_PASSED == mode)
    808 	{
    809 		return samples_name;
    810 	}
    811 
    812 	/* If not, return invalid name. */
    813 	return invalid_target_name;
    814 }
    815