• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
PolygonOffsetClampTestCaseBase(deqp::Context & context,const char * name,const char * description)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 
iterate()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 */
PolygonOffsetClampAvailabilityTestCase(deqp::Context & context)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 
test(const glw::Functions & gl)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 */
PolygonOffsetClampValueTestCaseBase(deqp::Context & context,const char * name,const char * description)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  */
init()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  */
deinit()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  */
test(const glw::Functions & gl)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  */
readDepthValue(const glw::Functions & gl,const GLuint readDepthProgramId)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 */
PolygonOffsetClampMinMaxTestCase(deqp::Context & context)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  */
init()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  */
verify(GLuint caseNo,GLfloat depth,GLfloat offsetDepth,GLfloat offsetClampDepth)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 */
PolygonOffsetClampZeroInfinityTestCase(deqp::Context & context)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  */
init()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 
verify(GLuint caseNo,GLfloat depth,GLfloat offsetDepth,GLfloat offsetClampDepth)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 */
PolygonOffsetClamp(deqp::Context & context)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. */
init()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