• 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 	/* Calculate number of depth units from depth bits. */
359 	GLint depth_bits = 0;
360 	gl.getIntegerv(GL_DEPTH_BITS, &depth_bits);
361 	float num_units = (float)(1 << depth_bits);
362 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv");
363 
364 	bool result = true;
365 	for (GLuint i = 0; i < m_testValues.size(); ++i)
366 	{
367 		// Prepare verification variables
368 		GLfloat depthValue			  = 0.0f;
369 		GLfloat depthValueOffset	  = 0.0f;
370 		GLfloat depthValueOffsetClamp = 0.0f;
371 
372 		// Draw reference polygon
373 		gl.disable(GL_POLYGON_OFFSET_FILL);
374 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable");
375 
376 		gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
377 		GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
378 
379 		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
380 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
381 
382 		// Get reference depth value
383 		depthValue = readDepthValue(gl, readDepthProgramId);
384 
385 		// Draw polygon with depth offset
386 		gl.enable(GL_POLYGON_OFFSET_FILL);
387 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable");
388 
389 		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
390 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
391 
392 		gl.polygonOffset(m_testValues[i].factor, m_testValues[i].units * num_units);
393 		GLU_EXPECT_NO_ERROR(gl.getError(), "glPolygonOffset");
394 
395 		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
396 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
397 
398 		depthValueOffset = readDepthValue(gl, readDepthProgramId);
399 
400 		// Draw reference polygon
401 		gl.disable(GL_POLYGON_OFFSET_FILL);
402 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable");
403 
404 		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
405 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
406 
407 		gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
408 		GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
409 
410 		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
411 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
412 
413 		// Draw polygon with depth offset
414 		gl.enable(GL_POLYGON_OFFSET_FILL);
415 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable");
416 
417 		gl.polygonOffsetClamp(m_testValues[i].factor, m_testValues[i].units * num_units, m_testValues[i].clamp);
418 		GLU_EXPECT_NO_ERROR(gl.getError(), "glPolygonOffsetClamp");
419 
420 		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
421 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
422 
423 		depthValueOffsetClamp = readDepthValue(gl, readDepthProgramId);
424 
425 		// Verify results
426 		result = result && verify(i, depthValue, depthValueOffset, depthValueOffsetClamp);
427 	}
428 
429 	// Cleanup
430 	gl.disableVertexAttribArray(0);
431 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
432 
433 	gl.deleteVertexArrays(1, &arrayBuffer);
434 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays");
435 
436 	gl.deleteVertexArrays(1, &vao);
437 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays");
438 
439 	gl.disable(GL_POLYGON_OFFSET_FILL);
440 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable");
441 
442 	if (readDepthProgram)
443 		delete readDepthProgram;
444 
445 	if (result)
446 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
447 	else
448 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
449 }
450 
451 /** Method .
452  *
453  *  @param gl   Function bindings
454  */
readDepthValue(const glw::Functions & gl,const GLuint readDepthProgramId)455 float PolygonOffsetClampValueTestCaseBase::readDepthValue(const glw::Functions& gl, const GLuint readDepthProgramId)
456 {
457 	GLfloat depthValue = 0.0f;
458 
459 	if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
460 	{
461 		gl.readPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depthValue);
462 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
463 	}
464 	// OpenGL ES does not support reading pixels directly from depth buffer
465 	else
466 	{
467 		// Bind framebuffer for readback
468 		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboReadback);
469 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
470 
471 		gl.disable(GL_DEPTH_TEST);
472 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable");
473 
474 		gl.useProgram(readDepthProgramId);
475 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
476 
477 		gl.activeTexture(GL_TEXTURE0);
478 		GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
479 		gl.bindTexture(GL_TEXTURE_2D, m_depthBuf);
480 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
481 		gl.uniform1i(0, 0);
482 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
483 
484 		gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
485 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
486 
487 		GLubyte pixels[4];
488 		gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
489 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
490 
491 		gl.enable(GL_DEPTH_TEST);
492 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable");
493 
494 		// Convert read depth value to GLfloat normalized
495 		depthValue = (GLfloat)(pixels[0] + pixels[1] * 256) / 0xFFFF;
496 
497 		// Bind framebuffer for drawing
498 		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
499 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
500 	}
501 
502 	return depthValue;
503 }
504 
505 /** Constructor.
506 *
507 *  @param context Rendering context
508 */
PolygonOffsetClampMinMaxTestCase(deqp::Context & context)509 PolygonOffsetClampMinMaxTestCase::PolygonOffsetClampMinMaxTestCase(deqp::Context& context)
510 	: PolygonOffsetClampValueTestCaseBase(
511 		  context, "PolygonOffsetClampMinMax",
512 		  "Verifies if polygon offset clamp works as expected for non-zero, finite clamp values")
513 {
514 }
515 
516 /** Initialization method that fills polygonOffset* testing values
517  */
init()518 void PolygonOffsetClampMinMaxTestCase::init()
519 {
520 	PolygonOffsetClampValueTestCaseBase::init();
521 
522 	m_testValues.clear();
523 	m_testValues.push_back(PolygonOffsetClampValues(0.0f, -1000.0f / 65536.0f, -0.0001f)); // Min offset case
524 	m_testValues.push_back(PolygonOffsetClampValues(0.0f, 1000.0f / 65536.0f, 0.0001f));   // Max offset case
525 }
526 
527 /** Verification method that determines if depth values are as expected
528  *
529  *  @param caseNo           Case iteration number
530  *  @param depth            Reference depth value
531  *  @param offsetDepth      Case iteration number
532  *  @param offsetClampDepth Case iteration number
533  */
verify(GLuint caseNo,GLfloat depth,GLfloat offsetDepth,GLfloat offsetClampDepth)534 bool PolygonOffsetClampMinMaxTestCase::verify(GLuint caseNo, GLfloat depth, GLfloat offsetDepth,
535 											  GLfloat offsetClampDepth)
536 {
537 	// Min offset case
538 	if (caseNo == 0)
539 	{
540 		if (depth <= offsetDepth || depth <= offsetClampDepth || offsetDepth >= offsetClampDepth)
541 		{
542 			m_testCtx.getLog() << tcu::TestLog::Message << "PolygonOffsetClampEXT failed at MIN offset test.\n"
543 							   << "Expected result: "
544 							   << "refDepth[" << depth << "] > "
545 							   << "offsetClampDepth[" << offsetClampDepth << "] > "
546 							   << "offsetDepth[" << offsetDepth << "]" << tcu::TestLog::EndMessage;
547 
548 			return false;
549 		}
550 	}
551 	// Max offset case
552 	else if (caseNo == 1)
553 	{
554 		if (depth >= offsetDepth || depth >= offsetClampDepth || offsetDepth <= offsetClampDepth)
555 		{
556 			m_testCtx.getLog() << tcu::TestLog::Message << "PolygonOffsetClampEXT failed at MAX offset test.\n"
557 							   << "Expected result: "
558 							   << "refDepth[" << depth << "] < "
559 							   << "offsetClampDepth[" << offsetClampDepth << "] < "
560 							   << "offsetDepth[" << offsetDepth << "]" << tcu::TestLog::EndMessage;
561 
562 			return false;
563 		}
564 	}
565 	// Undefined case
566 	else
567 		return false;
568 
569 	return true;
570 }
571 
572 /** Constructor.
573 *
574 *  @param context Rendering context
575 */
PolygonOffsetClampZeroInfinityTestCase(deqp::Context & context)576 PolygonOffsetClampZeroInfinityTestCase::PolygonOffsetClampZeroInfinityTestCase(deqp::Context& context)
577 	: PolygonOffsetClampValueTestCaseBase(
578 		  context, "PolygonOffsetClampZeroInfinity",
579 		  "Verifies if polygon offset clamp works as expected for zero and infinite clamp values")
580 {
581 }
582 
583 /** Initialization method that fills polygonOffset* testing values
584  */
init()585 void PolygonOffsetClampZeroInfinityTestCase::init()
586 {
587 	PolygonOffsetClampValueTestCaseBase::init();
588 
589 	m_testValues.clear();
590 	m_testValues.push_back(PolygonOffsetClampValues(0.0f, -1000.0f / 65536.0f, 0.0f));		 // Min offset, zero clamp case
591 	m_testValues.push_back(PolygonOffsetClampValues(0.0f, -1000.0f / 65536.0f, -INFINITY)); // Min Offset, infinity clamp case
592 	m_testValues.push_back(PolygonOffsetClampValues(0.0f, 1000.0f / 65536.0f, 0.0f));		 // Max offset, zero clamp case
593 	m_testValues.push_back(PolygonOffsetClampValues(0.0f, 1000.0f / 65536.0f, INFINITY));   // Max Offset, infinity clamp case
594 }
595 
verify(GLuint caseNo,GLfloat depth,GLfloat offsetDepth,GLfloat offsetClampDepth)596 bool PolygonOffsetClampZeroInfinityTestCase::verify(GLuint caseNo, GLfloat depth, GLfloat offsetDepth,
597 													GLfloat offsetClampDepth)
598 {
599 	DE_UNREF(caseNo);
600 
601 	if (depth == offsetDepth || depth == offsetClampDepth || offsetDepth != offsetClampDepth)
602 	{
603 		m_testCtx.getLog() << tcu::TestLog::Message
604 						   << "PolygonOffsetClampEXT failed at Zero/Infinity offset clamp test.\n"
605 						   << "Expected result: "
606 						   << "refDepth[" << depth << "] != "
607 						   << "(offsetClampDepth[" << offsetClampDepth << "] == "
608 						   << "offsetDepth[" << offsetDepth << "])" << tcu::TestLog::EndMessage;
609 
610 		return false;
611 	}
612 
613 	return true;
614 }
615 
616 /** Constructor.
617 *
618 *  @param context Rendering context.
619 */
PolygonOffsetClamp(deqp::Context & context)620 PolygonOffsetClamp::PolygonOffsetClamp(deqp::Context& context)
621 	: TestCaseGroup(context, "polygon_offset_clamp",
622 					"Verify conformance of CTS_EXT_polygon_offset_clamp implementation")
623 {
624 }
625 
626 /** Initializes the test group contents. */
init()627 void PolygonOffsetClamp::init()
628 {
629 	addChild(new PolygonOffsetClampAvailabilityTestCase(m_context));
630 	addChild(new PolygonOffsetClampMinMaxTestCase(m_context));
631 	addChild(new PolygonOffsetClampZeroInfinityTestCase(m_context));
632 }
633 } /* glcts namespace */
634