Home | History | Annotate | Download | only in common
      1 /*-------------------------------------------------------------------------
      2 * OpenGL Conformance Test Suite
      3 * -----------------------------
      4 *
      5 * Copyright (c) 2017 The Khronos Group Inc.
      6 *
      7 * Licensed under the Apache License, Version 2.0 (the "License");
      8 * you may not use this file except in compliance with the License.
      9 * You may obtain a copy of the License at
     10 *
     11 *      http://www.apache.org/licenses/LICENSE-2.0
     12 *
     13 * Unless required by applicable law or agreed to in writing, software
     14 * distributed under the License is distributed on an "AS IS" BASIS,
     15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16 * See the License for the specific language governing permissions and
     17 * limitations under the License.
     18 *
     19 */ /*!
     20 * \file  glcPolygonOffsetClampTests.cpp
     21 * \brief Conformance tests for the EXT_polygon_offset_clamp functionality.
     22 */ /*-------------------------------------------------------------------*/
     23 
     24 #include "glcPolygonOffsetClampTests.hpp"
     25 #include "gluContextInfo.hpp"
     26 #include "gluShaderProgram.hpp"
     27 #include "glwEnums.hpp"
     28 #include "tcuRenderTarget.hpp"
     29 #include "tcuTestLog.hpp"
     30 
     31 #include <stdio.h>
     32 
     33 using namespace glw;
     34 using namespace glu;
     35 
     36 namespace glcts
     37 {
     38 
     39 const char* poc_shader_version_450core = "#version 450 core\n\n";
     40 const char* poc_shader_version_310es   = "#version 310 es\n\n";
     41 
     42 const char* poc_vertexColor = "in highp vec3 vertex;\n"
     43 							  "\n"
     44 							  "void main()\n"
     45 							  "{\n"
     46 							  "    gl_Position = vec4(vertex, 1);\n"
     47 							  "}\n";
     48 
     49 const char* poc_fragmentColor = "out highp vec4 fragColor;\n"
     50 								"\n"
     51 								"void main()\n"
     52 								"{\n"
     53 								"    fragColor = vec4(1, 1, 1, 1);\n"
     54 								"}\n";
     55 
     56 const char* poc_vertexTexture = "in highp vec3 vertex;\n"
     57 								"in highp vec2 texCoord;\n"
     58 								"out highp vec2 varyingtexCoord;\n"
     59 								"\n"
     60 								"void main()\n"
     61 								"{\n"
     62 								"    gl_Position = vec4(vertex, 1);\n"
     63 								"    varyingtexCoord = texCoord;\n"
     64 								"}\n";
     65 
     66 const char* poc_fragmentTexture = "in highp vec2 varyingtexCoord;\n"
     67 								  "out highp vec4 fragColor;\n"
     68 								  "\n"
     69 								  "layout (location = 0) uniform highp sampler2D tex;\n"
     70 								  "\n"
     71 								  "void main()\n"
     72 								  "{\n"
     73 								  "    highp vec4 v = texture(tex, varyingtexCoord);\n"
     74 								  "    int r = int(v.r * 65536.0) % 256;\n"
     75 								  "    int g = int(v.r * 65536.0) / 256;\n"
     76 								  "    fragColor = vec4(float(r) / 255.0, float(g) / 255.0, 0.0, 1.0);\n"
     77 								  "}\n";
     78 
     79 /** Constructor.
     80 *
     81 *  @param context Rendering context
     82 *  @param name Test name
     83 *  @param description Test description
     84 */
     85 PolygonOffsetClampTestCaseBase::PolygonOffsetClampTestCaseBase(deqp::Context& context, const char* name,
     86 															   const char* description)
     87 	: TestCase(context, name, description)
     88 {
     89 	glu::ContextType contextType = m_context.getRenderContext().getType();
     90 	m_extensionSupported		 = glu::contextSupports(contextType, glu::ApiType::core(4, 6));
     91 	m_extensionSupported |= context.getContextInfo().isExtensionSupported("GL_EXT_polygon_offset_clamp");
     92 	m_extensionSupported |= context.getContextInfo().isExtensionSupported("GL_ARB_polygon_offset_clamp");
     93 }
     94 
     95 tcu::TestNode::IterateResult PolygonOffsetClampTestCaseBase::iterate()
     96 {
     97 	if (!m_extensionSupported)
     98 	{
     99 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
    100 		return STOP;
    101 	}
    102 
    103 	test(m_context.getRenderContext().getFunctions());
    104 
    105 	return STOP;
    106 }
    107 
    108 /** Constructor.
    109 *
    110 *  @param context Rendering context
    111 */
    112 PolygonOffsetClampAvailabilityTestCase::PolygonOffsetClampAvailabilityTestCase(deqp::Context& context)
    113 	: PolygonOffsetClampTestCaseBase(context, "PolygonOffsetClampAvailability",
    114 									 "Verifies if queries for GL_EXT_polygon_offset_clamp extension works properly")
    115 {
    116 }
    117 
    118 void PolygonOffsetClampAvailabilityTestCase::test(const glw::Functions& gl)
    119 {
    120 	{
    121 		glw::GLboolean data;
    122 		gl.getBooleanv(GL_POLYGON_OFFSET_CLAMP_EXT, &data);
    123 		GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv error occurred");
    124 	}
    125 	{
    126 		glw::GLint data;
    127 		gl.getIntegerv(GL_POLYGON_OFFSET_CLAMP_EXT, &data);
    128 		GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv error occurred");
    129 	}
    130 	{
    131 		glw::GLint64 data;
    132 		gl.getInteger64v(GL_POLYGON_OFFSET_CLAMP_EXT, &data);
    133 		GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv error occurred");
    134 	}
    135 	{
    136 		glw::GLfloat data;
    137 		gl.getFloatv(GL_POLYGON_OFFSET_CLAMP_EXT, &data);
    138 		GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv error occurred");
    139 	}
    140 
    141 	// OpenGL ES does not support getDoublev query
    142 	if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
    143 	{
    144 		glw::GLdouble data;
    145 		gl.getDoublev(GL_POLYGON_OFFSET_CLAMP_EXT, &data);
    146 		GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv error occurred");
    147 	}
    148 
    149 	gl.polygonOffsetClamp(1.0f, 1.0f, 0.5f);
    150 	GLU_EXPECT_NO_ERROR(gl.getError(), "polygonOffsetClamp error occurred");
    151 
    152 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    153 }
    154 
    155 /** Constructor.
    156 *
    157 *  @param context Rendering context
    158 */
    159 PolygonOffsetClampValueTestCaseBase::PolygonOffsetClampValueTestCaseBase(deqp::Context& context, const char* name,
    160 																		 const char* description)
    161 	: PolygonOffsetClampTestCaseBase(context, name, description)
    162 	, m_fbo(0)
    163 	, m_depthBuf(0)
    164 	, m_colorBuf(0)
    165 	, m_fboReadback(0)
    166 	, m_colorBufReadback(0)
    167 {
    168 }
    169 
    170 /** Initialization method that creates framebuffer with depth attachment
    171  */
    172 void PolygonOffsetClampValueTestCaseBase::init()
    173 {
    174 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    175 
    176 	gl.genTextures(1, &m_depthBuf);
    177 	GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
    178 	gl.bindTexture(GL_TEXTURE_2D, m_depthBuf);
    179 	GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
    180 	gl.texStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT16, 64, 64);
    181 	GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
    182 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    183 	GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri");
    184 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    185 	GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri");
    186 
    187 	gl.genTextures(1, &m_colorBuf);
    188 	GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
    189 	gl.bindTexture(GL_TEXTURE_2D, m_colorBuf);
    190 	GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
    191 	gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 64, 64);
    192 	GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
    193 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    194 	GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri");
    195 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    196 	GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri");
    197 
    198 	gl.genFramebuffers(1, &m_fbo);
    199 	GLU_EXPECT_NO_ERROR(gl.getError(), "genFramebuffers");
    200 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
    201 	GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
    202 	gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuf, 0);
    203 	GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
    204 	gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuf, 0);
    205 	GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
    206 
    207 	if (!glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
    208 	{
    209 		gl.genTextures(1, &m_colorBufReadback);
    210 		GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
    211 		gl.bindTexture(GL_TEXTURE_2D, m_colorBufReadback);
    212 		GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
    213 		gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 64, 64);
    214 		GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
    215 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    216 		GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri");
    217 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    218 		GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri");
    219 
    220 		gl.genFramebuffers(1, &m_fboReadback);
    221 		GLU_EXPECT_NO_ERROR(gl.getError(), "genFramebuffers");
    222 		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboReadback);
    223 		GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
    224 		gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBufReadback, 0);
    225 		GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
    226 	}
    227 
    228 	gl.viewport(0, 0, 64, 64);
    229 }
    230 
    231 /** De-Initialization method that releases
    232  */
    233 void PolygonOffsetClampValueTestCaseBase::deinit()
    234 {
    235 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    236 
    237 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
    238 	GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
    239 
    240 	if (m_fbo)
    241 		gl.deleteFramebuffers(1, &m_fbo);
    242 	if (m_depthBuf)
    243 		gl.deleteTextures(1, &m_depthBuf);
    244 	if (m_colorBuf)
    245 		gl.deleteTextures(1, &m_colorBuf);
    246 
    247 	if (!glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
    248 	{
    249 		if (m_colorBufReadback)
    250 			gl.deleteTextures(1, &m_colorBufReadback);
    251 		if (m_fboReadback)
    252 			gl.deleteFramebuffers(1, &m_fboReadback);
    253 	}
    254 }
    255 
    256 /** Testing method that verifies if depth values generated after polygon offset clamp are as expected.
    257  *
    258  *  @param gl   Function bindings
    259  */
    260 void PolygonOffsetClampValueTestCaseBase::test(const glw::Functions& gl)
    261 {
    262 	const GLfloat vertices[] = { -1.0f, -1.0f, 0.5f, -1.0f, 1.0f, 0.5f, 1.0f, -1.0f, 0.5f, 1.0f, 1.0f, 0.5f };
    263 
    264 	// Prepare shader program
    265 	std::string vertexColor;
    266 	std::string fragmentColor;
    267 	if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
    268 		vertexColor = std::string(poc_shader_version_450core);
    269 	else
    270 		vertexColor = std::string(poc_shader_version_310es);
    271 	fragmentColor   = vertexColor;
    272 
    273 	vertexColor   = vertexColor + poc_vertexColor;
    274 	fragmentColor = fragmentColor + poc_fragmentColor;
    275 
    276 	ProgramSources testSources = makeVtxFragSources(vertexColor, fragmentColor);
    277 	ShaderProgram  testProgram(gl, testSources);
    278 
    279 	if (!testProgram.isOk())
    280 	{
    281 		m_testCtx.getLog() << tcu::TestLog::Message << "TestProgram build failed.\n"
    282 						   << "Vertex: " << testProgram.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
    283 						   << "Fragment: " << testProgram.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
    284 						   << "Program: " << testProgram.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
    285 
    286 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    287 		return;
    288 	}
    289 
    290 	ShaderProgram* readDepthProgram   = DE_NULL;
    291 	GLuint		   readDepthProgramId = 0;
    292 
    293 	// Prepare shader program for reading depth buffer indirectly
    294 	if (!glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
    295 	{
    296 		std::string vertexTexture   = std::string(poc_shader_version_310es) + poc_vertexTexture;
    297 		std::string fragmentTexture = std::string(poc_shader_version_310es) + poc_fragmentTexture;
    298 
    299 		ProgramSources readDepthSources = makeVtxFragSources(vertexTexture, fragmentTexture);
    300 
    301 		readDepthProgram = new ShaderProgram(gl, readDepthSources);
    302 
    303 		if (!readDepthProgram->isOk())
    304 		{
    305 			m_testCtx.getLog() << tcu::TestLog::Message << "ReadDepthProgram build failed.\n"
    306 							   << "Vertex: " << readDepthProgram->getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
    307 							   << "Fragment: " << readDepthProgram->getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
    308 							   << "Program: " << readDepthProgram->getProgramInfo().infoLog << tcu::TestLog::EndMessage;
    309 
    310 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    311 			return;
    312 		}
    313 
    314 		readDepthProgramId = readDepthProgram->getProgram();
    315 	}
    316 
    317 	gl.useProgram(testProgram.getProgram());
    318 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
    319 
    320 	GLuint vao;
    321 	GLuint arrayBuffer;
    322 
    323 	// Setup depth testing
    324 	gl.enable(GL_DEPTH_TEST);
    325 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable");
    326 
    327 	gl.depthFunc(GL_ALWAYS);
    328 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDepthFunc");
    329 
    330 	// Generate vertex array object
    331 	gl.genVertexArrays(1, &vao);
    332 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
    333 
    334 	gl.bindVertexArray(vao);
    335 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
    336 
    337 	// Setup vertex array buffer
    338 	gl.genBuffers(1, &arrayBuffer);
    339 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
    340 
    341 	gl.bindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
    342 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
    343 
    344 	gl.bufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
    345 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
    346 
    347 	// Setup vertex attrib pointer
    348 	gl.enableVertexAttribArray(0);
    349 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
    350 
    351 	gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    352 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
    353 
    354 	// Bind framebuffer for drawing
    355 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
    356 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
    357 
    358 	bool result = true;
    359 	for (GLuint i = 0; i < m_testValues.size(); ++i)
    360 	{
    361 		// Prepare verification variables
    362 		GLfloat depthValue			  = 0.0f;
    363 		GLfloat depthValueOffset	  = 0.0f;
    364 		GLfloat depthValueOffsetClamp = 0.0f;
    365 
    366 		// Draw reference polygon
    367 		gl.disable(GL_POLYGON_OFFSET_FILL);
    368 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable");
    369 
    370 		gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    371 		GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
    372 
    373 		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
    374 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
    375 
    376 		// Get reference depth value
    377 		depthValue = readDepthValue(gl, readDepthProgramId);
    378 
    379 		// Draw polygon with depth offset
    380 		gl.enable(GL_POLYGON_OFFSET_FILL);
    381 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable");
    382 
    383 		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
    384 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
    385 
    386 		gl.polygonOffset(m_testValues[i].factor, m_testValues[i].units);
    387 		GLU_EXPECT_NO_ERROR(gl.getError(), "glPolygonOffset");
    388 
    389 		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
    390 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
    391 
    392 		depthValueOffset = readDepthValue(gl, readDepthProgramId);
    393 
    394 		// Draw reference polygon
    395 		gl.disable(GL_POLYGON_OFFSET_FILL);
    396 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable");
    397 
    398 		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
    399 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
    400 
    401 		gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    402 		GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
    403 
    404 		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
    405 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
    406 
    407 		// Draw polygon with depth offset
    408 		gl.enable(GL_POLYGON_OFFSET_FILL);
    409 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable");
    410 
    411 		gl.polygonOffsetClamp(m_testValues[i].factor, m_testValues[i].units, m_testValues[i].clamp);
    412 		GLU_EXPECT_NO_ERROR(gl.getError(), "glPolygonOffsetClamp");
    413 
    414 		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
    415 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
    416 
    417 		depthValueOffsetClamp = readDepthValue(gl, readDepthProgramId);
    418 
    419 		// Verify results
    420 		result = result && verify(i, depthValue, depthValueOffset, depthValueOffsetClamp);
    421 	}
    422 
    423 	// Cleanup
    424 	gl.disableVertexAttribArray(0);
    425 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
    426 
    427 	gl.deleteVertexArrays(1, &arrayBuffer);
    428 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays");
    429 
    430 	gl.deleteVertexArrays(1, &vao);
    431 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays");
    432 
    433 	gl.disable(GL_POLYGON_OFFSET_FILL);
    434 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable");
    435 
    436 	if (readDepthProgram)
    437 		delete readDepthProgram;
    438 
    439 	if (result)
    440 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    441 	else
    442 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    443 }
    444 
    445 /** Method .
    446  *
    447  *  @param gl   Function bindings
    448  */
    449 float PolygonOffsetClampValueTestCaseBase::readDepthValue(const glw::Functions& gl, const GLuint readDepthProgramId)
    450 {
    451 	GLfloat depthValue = 0.0f;
    452 
    453 	if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
    454 	{
    455 		gl.readPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depthValue);
    456 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
    457 	}
    458 	// OpenGL ES does not support reading pixels directly from depth buffer
    459 	else
    460 	{
    461 		// Bind framebuffer for readback
    462 		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboReadback);
    463 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
    464 
    465 		gl.disable(GL_DEPTH_TEST);
    466 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable");
    467 
    468 		gl.useProgram(readDepthProgramId);
    469 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
    470 
    471 		gl.activeTexture(GL_TEXTURE0);
    472 		GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
    473 		gl.bindTexture(GL_TEXTURE_2D, m_depthBuf);
    474 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
    475 		gl.uniform1i(0, 0);
    476 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
    477 
    478 		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
    479 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
    480 
    481 		GLubyte pixels[4];
    482 		gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    483 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
    484 
    485 		gl.enable(GL_DEPTH_TEST);
    486 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable");
    487 
    488 		// Convert read depth value to GLfloat normalized
    489 		depthValue = (GLfloat)(pixels[0] + pixels[1] * 256) / 0xFFFF;
    490 
    491 		// Bind framebuffer for drawing
    492 		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
    493 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
    494 	}
    495 
    496 	return depthValue;
    497 }
    498 
    499 /** Constructor.
    500 *
    501 *  @param context Rendering context
    502 */
    503 PolygonOffsetClampMinMaxTestCase::PolygonOffsetClampMinMaxTestCase(deqp::Context& context)
    504 	: PolygonOffsetClampValueTestCaseBase(
    505 		  context, "PolygonOffsetClampMinMax",
    506 		  "Verifies if polygon offset clamp works as expected for non-zero, finite clamp values")
    507 {
    508 }
    509 
    510 /** Initialization method that fills polygonOffset* testing values
    511  */
    512 void PolygonOffsetClampMinMaxTestCase::init()
    513 {
    514 	PolygonOffsetClampValueTestCaseBase::init();
    515 
    516 	m_testValues.clear();
    517 	m_testValues.push_back(PolygonOffsetClampValues(0.0f, -1000.0f, -0.0001f)); // Min offset case
    518 	m_testValues.push_back(PolygonOffsetClampValues(0.0f, 1000.0f, 0.0001f));   // Max offset case
    519 }
    520 
    521 /** Verification method that determines if depth values are as expected
    522  *
    523  *  @param caseNo           Case iteration number
    524  *  @param depth            Reference depth value
    525  *  @param offsetDepth      Case iteration number
    526  *  @param offsetClampDepth Case iteration number
    527  */
    528 bool PolygonOffsetClampMinMaxTestCase::verify(GLuint caseNo, GLfloat depth, GLfloat offsetDepth,
    529 											  GLfloat offsetClampDepth)
    530 {
    531 	// Min offset case
    532 	if (caseNo == 0)
    533 	{
    534 		if (depth <= offsetDepth || depth <= offsetClampDepth || offsetDepth >= offsetClampDepth)
    535 		{
    536 			m_testCtx.getLog() << tcu::TestLog::Message << "PolygonOffsetClampEXT failed at MIN offset test.\n"
    537 							   << "Expected result: "
    538 							   << "refDepth[" << depth << "] > "
    539 							   << "offsetClampDepth[" << offsetClampDepth << "] > "
    540 							   << "offsetDepth[" << offsetDepth << "]" << tcu::TestLog::EndMessage;
    541 
    542 			return false;
    543 		}
    544 	}
    545 	// Max offset case
    546 	else if (caseNo == 1)
    547 	{
    548 		if (depth >= offsetDepth || depth >= offsetClampDepth || offsetDepth <= offsetClampDepth)
    549 		{
    550 			m_testCtx.getLog() << tcu::TestLog::Message << "PolygonOffsetClampEXT failed at MAX offset test.\n"
    551 							   << "Expected result: "
    552 							   << "refDepth[" << depth << "] < "
    553 							   << "offsetClampDepth[" << offsetClampDepth << "] < "
    554 							   << "offsetDepth[" << offsetDepth << "]" << tcu::TestLog::EndMessage;
    555 
    556 			return false;
    557 		}
    558 	}
    559 	// Undefined case
    560 	else
    561 		return false;
    562 
    563 	return true;
    564 }
    565 
    566 /** Constructor.
    567 *
    568 *  @param context Rendering context
    569 */
    570 PolygonOffsetClampZeroInfinityTestCase::PolygonOffsetClampZeroInfinityTestCase(deqp::Context& context)
    571 	: PolygonOffsetClampValueTestCaseBase(
    572 		  context, "PolygonOffsetClampZeroInfinity",
    573 		  "Verifies if polygon offset clamp works as expected for zero and infinite clamp values")
    574 {
    575 }
    576 
    577 /** Initialization method that fills polygonOffset* testing values
    578  */
    579 void PolygonOffsetClampZeroInfinityTestCase::init()
    580 {
    581 	PolygonOffsetClampValueTestCaseBase::init();
    582 
    583 	m_testValues.clear();
    584 	m_testValues.push_back(PolygonOffsetClampValues(0.0f, -1000.0f, 0.0f));		 // Min offset, zero clamp case
    585 	m_testValues.push_back(PolygonOffsetClampValues(0.0f, -1000.0f, -INFINITY)); // Min Offset, infinity clamp case
    586 	m_testValues.push_back(PolygonOffsetClampValues(0.0f, 1000.0f, 0.0f));		 // Max offset, zero clamp case
    587 	m_testValues.push_back(PolygonOffsetClampValues(0.0f, 1000.0f, INFINITY));   // Max Offset, infinity clamp case
    588 }
    589 
    590 bool PolygonOffsetClampZeroInfinityTestCase::verify(GLuint caseNo, GLfloat depth, GLfloat offsetDepth,
    591 													GLfloat offsetClampDepth)
    592 {
    593 	DE_UNREF(caseNo);
    594 
    595 	if (depth == offsetDepth || depth == offsetClampDepth || offsetDepth != offsetClampDepth)
    596 	{
    597 		m_testCtx.getLog() << tcu::TestLog::Message
    598 						   << "PolygonOffsetClampEXT failed at Zero/Infinity offset clamp test.\n"
    599 						   << "Expected result: "
    600 						   << "refDepth[" << depth << "] != "
    601 						   << "(offsetClampDepth[" << offsetClampDepth << "] == "
    602 						   << "offsetDepth[" << offsetDepth << "])" << tcu::TestLog::EndMessage;
    603 
    604 		return false;
    605 	}
    606 
    607 	return true;
    608 }
    609 
    610 /** Constructor.
    611 *
    612 *  @param context Rendering context.
    613 */
    614 PolygonOffsetClamp::PolygonOffsetClamp(deqp::Context& context)
    615 	: TestCaseGroup(context, "polygon_offset_clamp",
    616 					"Verify conformance of CTS_EXT_polygon_offset_clamp implementation")
    617 {
    618 }
    619 
    620 /** Initializes the test group contents. */
    621 void PolygonOffsetClamp::init()
    622 {
    623 	addChild(new PolygonOffsetClampAvailabilityTestCase(m_context));
    624 	addChild(new PolygonOffsetClampMinMaxTestCase(m_context));
    625 	addChild(new PolygonOffsetClampZeroInfinityTestCase(m_context));
    626 }
    627 } /* glcts namespace */
    628