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