Always apply flat qualifier to double inputs, same as int/uint
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcPolygonOffsetClampTests.cpp
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 */