xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/glcPolygonOffsetClampTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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,
454                                                           const GLuint testProgramId)
455 {
456     GLfloat depthValue = 0.0f;
457 
458     if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
459     {
460         gl.readPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depthValue);
461         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
462     }
463     // OpenGL ES does not support reading pixels directly from depth buffer
464     else
465     {
466         // Bind framebuffer for readback
467         gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboReadback);
468         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
469 
470         gl.disable(GL_DEPTH_TEST);
471         GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable");
472 
473         gl.useProgram(readDepthProgramId);
474         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
475 
476         gl.activeTexture(GL_TEXTURE0);
477         GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
478         gl.bindTexture(GL_TEXTURE_2D, m_depthBuf);
479         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
480         gl.uniform1i(0, 0);
481         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
482 
483         gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
484         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
485 
486         GLubyte pixels[4];
487         gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
488         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
489 
490         gl.enable(GL_DEPTH_TEST);
491         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable");
492 
493         // Convert read depth value to GLfloat normalized
494         depthValue = (GLfloat)(pixels[0] + pixels[1] * 256 + pixels[2] * 65536) / 0xFFFFFF;
495 
496         // Bind framebuffer for drawing
497         gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
498         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
499 
500         gl.useProgram(testProgramId);
501         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
502     }
503 
504     return depthValue;
505 }
506 
507 /** Constructor.
508  *
509  *  @param context Rendering context
510  */
PolygonOffsetClampMinMaxTestCase(deqp::Context & context)511 PolygonOffsetClampMinMaxTestCase::PolygonOffsetClampMinMaxTestCase(deqp::Context &context)
512     : PolygonOffsetClampValueTestCaseBase(
513           context, "PolygonOffsetClampMinMax",
514           "Verifies if polygon offset clamp works as expected for non-zero, finite clamp values")
515 {
516 }
517 
518 /** Initialization method that fills polygonOffset* testing values
519  */
init()520 void PolygonOffsetClampMinMaxTestCase::init()
521 {
522     PolygonOffsetClampValueTestCaseBase::init();
523 
524     m_testValues.clear();
525     m_testValues.push_back(PolygonOffsetClampValues(0.0f, -5000.0f, -0.0001f)); // Min offset case
526     m_testValues.push_back(PolygonOffsetClampValues(0.0f, 5000.0f, 0.0001f));   // Max offset case
527 }
528 
529 /** Verification method that determines if depth values are as expected
530  *
531  *  @param caseNo           Case iteration number
532  *  @param depth            Reference depth value
533  *  @param offsetDepth      Case iteration number
534  *  @param offsetClampDepth Case iteration number
535  */
verify(GLuint caseNo,GLfloat depth,GLfloat offsetDepth,GLfloat offsetClampDepth)536 bool PolygonOffsetClampMinMaxTestCase::verify(GLuint caseNo, GLfloat depth, GLfloat offsetDepth,
537                                               GLfloat offsetClampDepth)
538 {
539     // Min offset case
540     if (caseNo == 0)
541     {
542         if (depth <= offsetDepth || depth <= offsetClampDepth || offsetDepth >= offsetClampDepth)
543         {
544             m_testCtx.getLog() << tcu::TestLog::Message << "PolygonOffsetClampEXT failed at MIN offset test.\n"
545                                << "Expected result: "
546                                << "refDepth[" << depth << "] > "
547                                << "offsetClampDepth[" << offsetClampDepth << "] > "
548                                << "offsetDepth[" << offsetDepth << "]" << tcu::TestLog::EndMessage;
549 
550             return false;
551         }
552     }
553     // Max offset case
554     else if (caseNo == 1)
555     {
556         if (depth >= offsetDepth || depth >= offsetClampDepth || offsetDepth <= offsetClampDepth)
557         {
558             m_testCtx.getLog() << tcu::TestLog::Message << "PolygonOffsetClampEXT failed at MAX offset test.\n"
559                                << "Expected result: "
560                                << "refDepth[" << depth << "] < "
561                                << "offsetClampDepth[" << offsetClampDepth << "] < "
562                                << "offsetDepth[" << offsetDepth << "]" << tcu::TestLog::EndMessage;
563 
564             return false;
565         }
566     }
567     // Undefined case
568     else
569         return false;
570 
571     return true;
572 }
573 
574 /** Constructor.
575  *
576  *  @param context Rendering context
577  */
PolygonOffsetClampZeroInfinityTestCase(deqp::Context & context)578 PolygonOffsetClampZeroInfinityTestCase::PolygonOffsetClampZeroInfinityTestCase(deqp::Context &context)
579     : PolygonOffsetClampValueTestCaseBase(
580           context, "PolygonOffsetClampZeroInfinity",
581           "Verifies if polygon offset clamp works as expected for zero and infinite clamp values")
582 {
583 }
584 
585 /** Initialization method that fills polygonOffset* testing values
586  */
init()587 void PolygonOffsetClampZeroInfinityTestCase::init()
588 {
589     PolygonOffsetClampValueTestCaseBase::init();
590 
591     m_testValues.clear();
592     m_testValues.push_back(PolygonOffsetClampValues(0.0f, -1000.0f, 0.0f));      // Min offset, zero clamp case
593     m_testValues.push_back(PolygonOffsetClampValues(0.0f, -1000.0f, -INFINITY)); // Min Offset, infinity clamp case
594     m_testValues.push_back(PolygonOffsetClampValues(0.0f, 1000.0f, 0.0f));       // Max offset, zero clamp case
595     m_testValues.push_back(PolygonOffsetClampValues(0.0f, 1000.0f, INFINITY));   // Max Offset, infinity clamp case
596 }
597 
verify(GLuint caseNo,GLfloat depth,GLfloat offsetDepth,GLfloat offsetClampDepth)598 bool PolygonOffsetClampZeroInfinityTestCase::verify(GLuint caseNo, GLfloat depth, GLfloat offsetDepth,
599                                                     GLfloat offsetClampDepth)
600 {
601     DE_UNREF(caseNo);
602 
603     if (depth == offsetDepth || depth == offsetClampDepth || offsetDepth != offsetClampDepth)
604     {
605         m_testCtx.getLog() << tcu::TestLog::Message
606                            << "PolygonOffsetClampEXT failed at Zero/Infinity offset clamp test.\n"
607                            << "Expected result: "
608                            << "refDepth[" << depth << "] != "
609                            << "(offsetClampDepth[" << offsetClampDepth << "] == "
610                            << "offsetDepth[" << offsetDepth << "])" << tcu::TestLog::EndMessage;
611 
612         return false;
613     }
614 
615     return true;
616 }
617 
618 /** Constructor.
619  *
620  *  @param context Rendering context.
621  */
PolygonOffsetClamp(deqp::Context & context)622 PolygonOffsetClamp::PolygonOffsetClamp(deqp::Context &context)
623     : TestCaseGroup(context, "polygon_offset_clamp",
624                     "Verify conformance of CTS_EXT_polygon_offset_clamp implementation")
625 {
626 }
627 
628 /** Initializes the test group contents. */
init()629 void PolygonOffsetClamp::init()
630 {
631     addChild(new PolygonOffsetClampAvailabilityTestCase(m_context));
632     addChild(new PolygonOffsetClampMinMaxTestCase(m_context));
633     addChild(new PolygonOffsetClampZeroInfinityTestCase(m_context));
634 }
635 } // namespace glcts
636