1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 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
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 /**
25  */ /*!
26  * \file  es31cTextureStorageMultisampleGLCoverageTests.cpp
27  * \brief Implements coverage tests for multisample textures. (ES3.1 only)
28  */ /*-------------------------------------------------------------------*/
29 
30 #include "es31cTextureStorageMultisampleGLCoverageTests.hpp"
31 #include "gluContextInfo.hpp"
32 #include "gluDefs.hpp"
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 #include "tcuRenderTarget.hpp"
36 #include "tcuTestLog.hpp"
37 
38 #include <string>
39 #include <vector>
40 
41 namespace glcts
42 {
43 /** Constructor.
44  *
45  *  @param context Rendering context handle.
46  **/
GLCoverageExtensionSpecificEnumsAreRecognizedTest(Context & context)47 GLCoverageExtensionSpecificEnumsAreRecognizedTest::GLCoverageExtensionSpecificEnumsAreRecognizedTest(Context &context)
48     : TestCase(context, "extension_specific_enums_are_recognized",
49                "GL_MAX_SAMPLE_MASK_WORDS, GL_MAX_COLOR_TEXTURE_SAMPLES, GL_MAX_DEPTH_TEXTURE_SAMPLES"
50                ", GL_MAX_INTEGER_SAMPLES, GL_TEXTURE_BINDING_2D_MULTISAMPLE and"
51                " GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES enums are recognized.")
52     , gl_oes_texture_storage_multisample_2d_array_supported(GL_FALSE)
53     , to_id_2d_multisample(0)
54     , to_id_2d_multisample_array(0)
55 {
56     /* Left blank on purpose */
57 }
58 
59 /* Deinitializes ES objects that may have been created while the test executed. */
deinit()60 void GLCoverageExtensionSpecificEnumsAreRecognizedTest::deinit()
61 {
62     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
63 
64     if (to_id_2d_multisample != 0)
65     {
66         gl.deleteTextures(1, &to_id_2d_multisample);
67 
68         to_id_2d_multisample = 0;
69     }
70 
71     if (to_id_2d_multisample_array != 0)
72     {
73         gl.deleteTextures(1, &to_id_2d_multisample_array);
74 
75         to_id_2d_multisample_array = 0;
76     }
77 
78     /* Call base class' deinit() */
79     TestCase::deinit();
80 }
81 
82 /** Executes test iteration.
83  *
84  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
85  */
iterate()86 tcu::TestNode::IterateResult GLCoverageExtensionSpecificEnumsAreRecognizedTest::iterate()
87 {
88     gl_oes_texture_storage_multisample_2d_array_supported =
89         m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
90 
91     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
92 
93     /* Iterate through all pnames that need to be verified */
94     const glw::GLenum pnames[]  = {GL_MAX_SAMPLE_MASK_WORDS, GL_MAX_COLOR_TEXTURE_SAMPLES, GL_MAX_DEPTH_TEXTURE_SAMPLES,
95                                    GL_MAX_INTEGER_SAMPLES};
96     const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]);
97 
98     for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname)
99     {
100         const float epsilon = (float)1e-5;
101         glw::GLenum pname   = pnames[n_pname];
102 
103         /* Test glGetIntegerv() */
104         glw::GLint int_value = -1;
105 
106         gl.getIntegerv(pname, &int_value);
107         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() reported an error for a valid pname");
108 
109         if (int_value < 1)
110         {
111             m_testCtx.getLog() << tcu::TestLog::Message << "An invalid integer value " << int_value
112                                << " was reported for pname [" << pname << "]." << tcu::TestLog::EndMessage;
113 
114             TCU_FAIL("Invalid integer value reported for pname.");
115         }
116 
117         /* Test glGetBooleanv() */
118         glw::GLboolean bool_value = GL_TRUE;
119 
120         gl.getBooleanv(pname, &bool_value);
121         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() reported an error for a valid pname");
122 
123         if ((int_value != 0 && bool_value == GL_FALSE) || (int_value == 0 && bool_value != GL_FALSE))
124         {
125             m_testCtx.getLog() << tcu::TestLog::Message << "An invalid boolean value [" << bool_value << "]"
126                                << " was reported for pname [" << pname << "]"
127                                << " (integer value reported for the same property:" << int_value << ")"
128                                << tcu::TestLog::EndMessage;
129 
130             TCU_FAIL("Invalid boolean value reported for pname.");
131         }
132 
133         /* Test glGetFloatv() */
134         glw::GLfloat float_value = -1.0f;
135 
136         gl.getFloatv(pname, &float_value);
137         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() reported an error for a valid pname");
138 
139         if (de::abs(float_value - float(int_value)) > epsilon)
140         {
141             m_testCtx.getLog() << tcu::TestLog::Message << "An invalid floating-point value [" << float_value << "]"
142                                << " was reported for pname        [" << pname << "]"
143                                << " (integer value reported for the same property:" << int_value << ")"
144                                << tcu::TestLog::EndMessage;
145 
146             TCU_FAIL("Invalid floating-point value reported for pname.");
147         }
148     } /* for (all pnames) */
149 
150     /* Verify default multisample texture bindings are valid */
151     glw::GLboolean bool_value = GL_TRUE;
152     const float epsilon       = (float)1e-5;
153     glw::GLfloat float_value  = 1.0f;
154     glw::GLint int_value      = 1;
155 
156     gl.getBooleanv(GL_TEXTURE_BINDING_2D_MULTISAMPLE, &bool_value);
157     gl.getFloatv(GL_TEXTURE_BINDING_2D_MULTISAMPLE, &float_value);
158     gl.getIntegerv(GL_TEXTURE_BINDING_2D_MULTISAMPLE, &int_value);
159 
160     GLU_EXPECT_NO_ERROR(gl.getError(),
161                         "GL_TEXTURE_BINDING_2D_MULTISAMPLE pname was not recognized by one of the glGet*() functions");
162 
163     if (bool_value != GL_FALSE || de::abs(float_value) > epsilon || int_value != 0)
164     {
165         TCU_FAIL("Default GL_TEXTURE_BINDING_2D_MULTISAMPLE value is invalid");
166     }
167 
168     if (gl_oes_texture_storage_multisample_2d_array_supported)
169     {
170         bool_value  = GL_TRUE;
171         float_value = 1.0f;
172         int_value   = 1;
173 
174         gl.getBooleanv(GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES, &bool_value);
175         gl.getFloatv(GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES, &float_value);
176         gl.getIntegerv(GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES, &int_value);
177 
178         GLU_EXPECT_NO_ERROR(
179             gl.getError(),
180             "GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES pname was not recognized by one of the glGet*() functions");
181 
182         if (bool_value != GL_FALSE || de::abs(float_value) > epsilon || int_value != 0)
183         {
184             TCU_FAIL("Default GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES value is invalid");
185         }
186     }
187 
188     /* Generate two texture objects we will later bind to multisample texture targets to
189      * verify the values reported for corresponding pnames have also changed.
190      */
191     gl.genTextures(1, &to_id_2d_multisample);
192 
193     if (gl_oes_texture_storage_multisample_2d_array_supported)
194     {
195         gl.genTextures(1, &to_id_2d_multisample_array);
196     }
197 
198     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
199 
200     /* Now bind the IDs to relevant texture targets */
201     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample);
202 
203     if (gl_oes_texture_storage_multisample_2d_array_supported)
204     {
205         gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_2d_multisample_array);
206     }
207 
208     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed");
209 
210     /* Verify new bindings are reported */
211     bool_value  = GL_FALSE;
212     float_value = 0.0f;
213     int_value   = 0;
214 
215     gl.getBooleanv(GL_TEXTURE_BINDING_2D_MULTISAMPLE, &bool_value);
216     gl.getFloatv(GL_TEXTURE_BINDING_2D_MULTISAMPLE, &float_value);
217     gl.getIntegerv(GL_TEXTURE_BINDING_2D_MULTISAMPLE, &int_value);
218 
219     GLU_EXPECT_NO_ERROR(gl.getError(),
220                         "GL_TEXTURE_BINDING_2D_MULTISAMPLE pname was not recognized by one of the glGet*() functions");
221 
222     glw::GLfloat expected_float_value = float(to_id_2d_multisample);
223 
224     if (bool_value != GL_TRUE || de::abs(float_value - expected_float_value) > epsilon ||
225         (glw::GLuint)int_value != to_id_2d_multisample)
226     {
227         TCU_FAIL("GL_TEXTURE_BINDING_2D_MULTISAMPLE value is invalid");
228     }
229 
230     if (gl_oes_texture_storage_multisample_2d_array_supported)
231     {
232         bool_value  = GL_FALSE;
233         float_value = 0.0f;
234         int_value   = 0;
235 
236         gl.getBooleanv(GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES, &bool_value);
237         gl.getFloatv(GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES, &float_value);
238         gl.getIntegerv(GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES, &int_value);
239 
240         GLU_EXPECT_NO_ERROR(
241             gl.getError(),
242             "GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES pname was not recognized by one of the glGet*() functions");
243 
244         expected_float_value = float(to_id_2d_multisample_array);
245 
246         if (bool_value != GL_TRUE || de::abs(float_value - expected_float_value) > epsilon ||
247             (glw::GLuint)int_value != to_id_2d_multisample_array)
248         {
249             TCU_FAIL("GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES value is invalid");
250         }
251     }
252 
253     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
254     return STOP;
255 }
256 
257 /** Constructor.
258  *
259  *  @param context Rendering context handle.
260  **/
261 GLCoverageGLGetTexParameterReportsCorrectDefaultValuesForMultisampleTextureTargets::
GLCoverageGLGetTexParameterReportsCorrectDefaultValuesForMultisampleTextureTargets(Context & context)262     GLCoverageGLGetTexParameterReportsCorrectDefaultValuesForMultisampleTextureTargets(Context &context)
263     : TestCase(context, "get_tex_parameter_reports_correct_default_values_for_multisample_texture_targets",
264                "glGetTexParameter*() report correct default values for multisample texture targets.")
265     , gl_oes_texture_storage_multisample_2d_array_supported(GL_FALSE)
266     , to_id_2d(0)
267     , to_id_2d_array(0)
268 {
269     /* Left blank on purpose */
270 }
271 
272 /* Deinitializes test-specific ES objects */
deinit()273 void GLCoverageGLGetTexParameterReportsCorrectDefaultValuesForMultisampleTextureTargets::deinit()
274 {
275     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
276 
277     if (to_id_2d != 0)
278     {
279         gl.deleteTextures(1, &to_id_2d);
280 
281         to_id_2d = 0;
282     }
283 
284     if (to_id_2d_array != 0)
285     {
286         gl.deleteTextures(1, &to_id_2d_array);
287 
288         to_id_2d_array = 0;
289     }
290 
291     /* Call base test class' deinit() */
292     TestCase::deinit();
293 }
294 
295 /** Executes test iteration.
296  *
297  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
298  */
299 tcu::TestNode::IterateResult GLCoverageGLGetTexParameterReportsCorrectDefaultValuesForMultisampleTextureTargets::
iterate()300     iterate()
301 {
302     gl_oes_texture_storage_multisample_2d_array_supported =
303         m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
304 
305     const float epsilon      = (float)1e-5;
306     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
307 
308     /* Generate texture objects */
309     gl.genTextures(1, &to_id_2d);
310 
311     if (gl_oes_texture_storage_multisample_2d_array_supported)
312     {
313         gl.genTextures(1, &to_id_2d_array);
314     }
315 
316     GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glGenTextures() call failed");
317 
318     /* Bind the texture objects to multisample texture targets */
319     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_2d);
320 
321     if (gl_oes_texture_storage_multisample_2d_array_supported)
322     {
323         gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_2d_array);
324     }
325 
326     GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glBindTexture() call failed");
327 
328     /* Initialize texture storage */
329     gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
330                                GL_RGBA8, 4,                  /* width */
331                                4,                            /* height */
332                                GL_TRUE);                     /* fixedsamplelocations */
333 
334     if (gl_oes_texture_storage_multisample_2d_array_supported)
335     {
336         gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */
337                                    GL_RGBA8, 4,                            /* width */
338                                    4,                                      /* height */
339                                    4,                                      /* depth */
340                                    GL_TRUE);                               /* fixedsamplelocations */
341     }
342 
343     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture storage initialization failed");
344 
345     /* List of supported texture targets when the extension is not present. */
346     glw::GLenum texture_targets_without_extension[] = {GL_TEXTURE_2D_MULTISAMPLE};
347 
348     /* List of supported texture targets when the extension is present. */
349     glw::GLenum texture_targets_with_extension[] = {GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES};
350 
351     /* Iterate through all the texture targets supported for the specific case. */
352     glw::GLenum *texture_targets = NULL;
353 
354     unsigned int n_texture_targets = 0;
355 
356     if (gl_oes_texture_storage_multisample_2d_array_supported)
357     {
358         n_texture_targets = sizeof(texture_targets_with_extension) / sizeof(texture_targets_with_extension[0]);
359         texture_targets   = texture_targets_with_extension;
360     }
361     else
362     {
363         n_texture_targets = sizeof(texture_targets_without_extension) / sizeof(texture_targets_without_extension[0]);
364         texture_targets   = texture_targets_without_extension;
365     }
366 
367     for (unsigned int n_texture_target = 0; n_texture_target < n_texture_targets; ++n_texture_target)
368     {
369         glw::GLenum target = texture_targets[n_texture_target];
370 
371         /* Iterate through all texture parameters */
372         const glw::GLenum texture_parameters[] = {
373             GL_TEXTURE_BASE_LEVEL, GL_TEXTURE_IMMUTABLE_FORMAT, GL_TEXTURE_MAX_LEVEL, GL_TEXTURE_SWIZZLE_R,
374             GL_TEXTURE_SWIZZLE_G,  GL_TEXTURE_SWIZZLE_B,        GL_TEXTURE_SWIZZLE_A,
375 
376             /* The following are sampler states, hence are left out */
377 
378             // GL_TEXTURE_COMPARE_FUNC,
379             // GL_TEXTURE_COMPARE_MODE,
380             // GL_TEXTURE_MAG_FILTER,
381             // GL_TEXTURE_MAX_LOD,
382             // GL_TEXTURE_MIN_FILTER,
383             // GL_TEXTURE_MIN_LOD,
384             // GL_TEXTURE_WRAP_S,
385             // GL_TEXTURE_WRAP_T,
386             // GL_TEXTURE_WRAP_R
387         };
388         const unsigned int n_texture_parameters = sizeof(texture_parameters) / sizeof(texture_parameters[0]);
389 
390         for (unsigned int n_texture_parameter = 0; n_texture_parameter < n_texture_parameters; ++n_texture_parameter)
391         {
392             glw::GLenum texture_parameter = texture_parameters[n_texture_parameter];
393 
394             /* Query implementation for the parameter values for texture target considered */
395             glw::GLint expected_int_value = 0;
396             glw::GLfloat float_value      = 0.0f;
397             glw::GLint int_value          = 0;
398 
399             gl.getTexParameterfv(target, texture_parameter, &float_value);
400             gl.getTexParameteriv(target, texture_parameter, &int_value);
401 
402             GLU_EXPECT_NO_ERROR(gl.getError(), "Either of the glGetTexParameter*() calls generated an error");
403 
404             /* Verify the value is valid */
405             switch (texture_parameter)
406             {
407             case GL_TEXTURE_BASE_LEVEL:
408                 expected_int_value = 0;
409                 break;
410             case GL_TEXTURE_COMPARE_FUNC:
411                 expected_int_value = GL_LEQUAL;
412                 break;
413             case GL_TEXTURE_COMPARE_MODE:
414                 expected_int_value = GL_NONE;
415                 break;
416             case GL_TEXTURE_IMMUTABLE_FORMAT:
417                 expected_int_value = GL_TRUE;
418                 break;
419             case GL_TEXTURE_MAG_FILTER:
420                 expected_int_value = GL_LINEAR;
421                 break;
422             case GL_TEXTURE_MAX_LEVEL:
423                 expected_int_value = 1000;
424                 break;
425             case GL_TEXTURE_MAX_LOD:
426                 expected_int_value = 1000;
427                 break;
428             case GL_TEXTURE_MIN_FILTER:
429                 expected_int_value = GL_NEAREST_MIPMAP_LINEAR;
430                 break;
431             case GL_TEXTURE_MIN_LOD:
432                 expected_int_value = -1000;
433                 break;
434             case GL_TEXTURE_SWIZZLE_R:
435                 expected_int_value = GL_RED;
436                 break;
437             case GL_TEXTURE_SWIZZLE_G:
438                 expected_int_value = GL_GREEN;
439                 break;
440             case GL_TEXTURE_SWIZZLE_B:
441                 expected_int_value = GL_BLUE;
442                 break;
443             case GL_TEXTURE_SWIZZLE_A:
444                 expected_int_value = GL_ALPHA;
445                 break;
446             case GL_TEXTURE_WRAP_S:
447                 expected_int_value = GL_REPEAT;
448                 break;
449             case GL_TEXTURE_WRAP_T:
450                 expected_int_value = GL_REPEAT;
451                 break;
452             case GL_TEXTURE_WRAP_R:
453                 expected_int_value = GL_REPEAT;
454                 break;
455 
456             default:
457             {
458                 TCU_FAIL("Unrecognized texture parameter name");
459             }
460             } /* switch (texture_parameter) */
461 
462             /* Verify integer value the implementation returned */
463             if (expected_int_value != int_value)
464             {
465                 m_testCtx.getLog() << tcu::TestLog::Message << "Implementation returned an invalid integer value of "
466                                    << int_value << " instead of the expected value " << expected_int_value
467                                    << " for property " << texture_parameter << " of texture target " << target
468                                    << tcu::TestLog::EndMessage;
469 
470                 TCU_FAIL("Invalid integer value returned by glGetTexParameteriv()");
471             }
472 
473             /* Verify floating-point value the implementation returned */
474             if (de::abs(float(expected_int_value) - float_value) > epsilon)
475             {
476                 m_testCtx.getLog() << tcu::TestLog::Message
477                                    << "Implementation returned an invalid floating-point value of " << float_value
478                                    << " instead of the expected value " << expected_int_value << " for property "
479                                    << texture_parameter << " of texture target " << target << tcu::TestLog::EndMessage;
480 
481                 TCU_FAIL("Invalid floating-point value returned by glGetTexParameteriv()");
482             }
483         } /* for (all texture parameters) */
484     }     /* for (all texture targets) */
485 
486     /* All done */
487     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
488     return STOP;
489 }
490 
491 /** Constructor.
492  *
493  *  @param context Rendering context handle.
494  **/
GLCoverageGLSampleMaskModeStatusIsReportedCorrectlyTest(Context & context)495 GLCoverageGLSampleMaskModeStatusIsReportedCorrectlyTest::GLCoverageGLSampleMaskModeStatusIsReportedCorrectlyTest(
496     Context &context)
497     : TestCase(context, "gl_sample_mask_mode_status_is_reported_correctly",
498                "glGet*() calls report correct disabled/enabled status of GL_SAMPLE_MASK mode.")
499 {
500     /* Left blank on purpose */
501 }
502 
503 /** Executes test iteration.
504  *
505  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
506  */
iterate()507 tcu::TestNode::IterateResult GLCoverageGLSampleMaskModeStatusIsReportedCorrectlyTest::iterate()
508 {
509     const float epsilon      = (float)1e-5;
510     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
511 
512     /* Check GL_SAMPLE_MASK is disabled by default */
513     glw::GLint enabled = gl.isEnabled(GL_SAMPLE_MASK);
514     GLU_EXPECT_NO_ERROR(gl.getError(), "Unexpected error generated by glIsEnabled(GL_SAMPLE_MASK) call.");
515 
516     if (enabled != GL_FALSE)
517     {
518         TCU_FAIL("GL_SAMPLE_MASK mode is considered enabled by default which is incorrect.");
519     }
520 
521     /* Verify glGet*() calls also report the mode to be disabled */
522     glw::GLboolean bool_value = GL_TRUE;
523     glw::GLfloat float_value  = 1.0f;
524     glw::GLint int_value      = 1;
525 
526     gl.getBooleanv(GL_SAMPLE_MASK, &bool_value);
527     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() reported an error when queried for GL_SAMPLE_MASK property");
528 
529     if (bool_value != GL_FALSE)
530     {
531         TCU_FAIL("Invalid boolean value reported for GL_SAMPLE_MASK property");
532     }
533 
534     gl.getFloatv(GL_SAMPLE_MASK, &float_value);
535     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() reported an error when queried for GL_SAMPLE_MASK property");
536 
537     if (de::abs(float_value - float(GL_FALSE)) > epsilon)
538     {
539         TCU_FAIL("Invalid float value reported for GL_SAMPLE_MASK property");
540     }
541 
542     gl.getIntegerv(GL_SAMPLE_MASK, &int_value);
543     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() reported an error when queried for GL_SAMPLE_MASK property");
544 
545     if (int_value != GL_FALSE)
546     {
547         TCU_FAIL("Invalid integer value reported for GL_SAMPLE_MASK property");
548     }
549 
550     /* Enable GL_SAMPLE_MASK mode */
551     gl.enable(GL_SAMPLE_MASK);
552 
553     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK) call generated an unexpected error");
554 
555     /* Verify values reported by glIsEnabled(), as well as GL getters is still correct */
556     enabled = gl.isEnabled(GL_SAMPLE_MASK);
557     GLU_EXPECT_NO_ERROR(gl.getError(), "glIsEnabled(GL_SAMPLE_MASK) call generated an unexpected error");
558 
559     if (enabled != GL_TRUE)
560     {
561         TCU_FAIL(
562             "glIsEnabled(GL_SAMPLE_MASK) did not report GL_TRUE after a successful glEnable(GL_SAMPLE_MASK) call.");
563     }
564 
565     gl.getBooleanv(GL_SAMPLE_MASK, &bool_value);
566     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() reported an error when queried for GL_SAMPLE_MASK property");
567 
568     if (bool_value != GL_TRUE)
569     {
570         TCU_FAIL("Invalid boolean value reported for GL_SAMPLE_MASK property");
571     }
572 
573     gl.getFloatv(GL_SAMPLE_MASK, &float_value);
574     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() reported an error when queried for GL_SAMPLE_MASK property");
575 
576     if (de::abs(float_value - float(GL_TRUE)) > epsilon)
577     {
578         TCU_FAIL("Invalid float value reported for GL_SAMPLE_MASK property");
579     }
580 
581     gl.getIntegerv(GL_SAMPLE_MASK, &int_value);
582     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() reported an error when queried for GL_SAMPLE_MASK property");
583 
584     if (int_value != GL_TRUE)
585     {
586         TCU_FAIL("Invalid integer value reported for GL_SAMPLE_MASK property");
587     }
588 
589     /* Disable the mode and see if the getters react accordingly */
590     gl.disable(GL_SAMPLE_MASK);
591     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable(GL_SAMPLE_MASK) call generated an unexpected error");
592 
593     enabled = gl.isEnabled(GL_SAMPLE_MASK);
594     GLU_EXPECT_NO_ERROR(gl.getError(), "glIsEnabled(GL_SAMPLE_MASK) call generated an unexpected error");
595 
596     if (enabled != GL_FALSE)
597     {
598         TCU_FAIL(
599             "glIsEnabled(GL_SAMPLE_MASK) did not report GL_FALSE after a successful glDisable(GL_SAMPLE_MASK) call.");
600     }
601 
602     gl.getBooleanv(GL_SAMPLE_MASK, &bool_value);
603     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() reported an error when queried for GL_SAMPLE_MASK property");
604 
605     if (bool_value != GL_FALSE)
606     {
607         TCU_FAIL("Invalid boolean value reported for GL_SAMPLE_MASK property");
608     }
609 
610     gl.getFloatv(GL_SAMPLE_MASK, &float_value);
611     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() reported an error when queried for GL_SAMPLE_MASK property");
612 
613     if (de::abs(float_value - float(GL_FALSE)) > epsilon)
614     {
615         TCU_FAIL("Invalid float value reported for GL_SAMPLE_MASK property");
616     }
617 
618     gl.getIntegerv(GL_SAMPLE_MASK, &int_value);
619     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() reported an error when queried for GL_SAMPLE_MASK property");
620 
621     if (int_value != GL_FALSE)
622     {
623         TCU_FAIL("Invalid integer value reported for GL_SAMPLE_MASK property");
624     }
625 
626     /* All good! */
627     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
628     return STOP;
629 }
630 
631 /** Constructor.
632  *
633  *  @param context Rendering context handle.
634  **/
635 GLCoverageGLTexParameterHandlersAcceptZeroBaseLevelForExtensionSpecificTextureTargetsTest::
GLCoverageGLTexParameterHandlersAcceptZeroBaseLevelForExtensionSpecificTextureTargetsTest(Context & context)636     GLCoverageGLTexParameterHandlersAcceptZeroBaseLevelForExtensionSpecificTextureTargetsTest(Context &context)
637     : TestCase(context, "gl_tex_parameter_handlers_accept_zero_base_level",
638                "glTexParameter*() calls should not generate an error if zero base "
639                "level is requested for 2D multisample or 2D multisample array texture targets.")
640     , are_2d_array_multisample_tos_supported(false)
641     , to_id_2d(0)
642     , to_id_2d_array(0)
643 {
644     /* Left blank on purpose */
645 }
646 
647 /* Deinitializes texture objects created specifically for this test case. */
deinit()648 void GLCoverageGLTexParameterHandlersAcceptZeroBaseLevelForExtensionSpecificTextureTargetsTest::deinit()
649 {
650     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
651 
652     if (to_id_2d != 0)
653     {
654         gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
655         gl.deleteTextures(1, &to_id_2d);
656     }
657 
658     if (to_id_2d_array != 0)
659     {
660         gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 0);
661         gl.deleteTextures(1, &to_id_2d_array);
662     }
663 
664     /* Call base class' deinit() */
665     TestCase::deinit();
666 }
667 
668 /* Initializes test instance: creates test-specific texture objects. */
initInternals()669 void GLCoverageGLTexParameterHandlersAcceptZeroBaseLevelForExtensionSpecificTextureTargetsTest::initInternals()
670 {
671     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
672 
673     /* Generate texture objects */
674     gl.genTextures(1, &to_id_2d);
675 
676     if (are_2d_array_multisample_tos_supported)
677     {
678         gl.genTextures(1, &to_id_2d_array);
679     }
680 
681     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate texture object(s)");
682 
683     /* Bind the texture objects to extension-specific texture targets */
684     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_2d);
685 
686     if (are_2d_array_multisample_tos_supported)
687     {
688         gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_2d_array);
689     }
690 
691     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind texture object(s) to corresponding texture target(s).");
692 }
693 
694 /** Executes test iteration.
695  *
696  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
697  */
698 tcu::TestNode::IterateResult GLCoverageGLTexParameterHandlersAcceptZeroBaseLevelForExtensionSpecificTextureTargetsTest::
iterate()699     iterate()
700 {
701     are_2d_array_multisample_tos_supported =
702         m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
703 
704     initInternals();
705 
706     /* Initialize texture storage for 2D multisample texture object */
707     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
708 
709     gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2 /* samples */, GL_RGBA8, 4, /* width */
710                                4,                                                       /* height */
711                                GL_TRUE /* fixedsamplelocations */);
712 
713     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up an immutable 2D multisample texture object");
714 
715     /* Initialize texture storage for 2D multisample array texture object */
716     if (are_2d_array_multisample_tos_supported)
717     {
718         gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2 /* samples */, GL_RGBA8, 4 /* width */,
719                                    4 /* height */, 4 /* depth */, GL_TRUE /* fixedsamplelocations */);
720 
721         GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up an immutable 2D multisample array texture object");
722     }
723 
724     /* Force a zero base level setting for 2D multisample texture using all available glTexParameter*() entry-points */
725     glw::GLfloat zero_float = 0.0f;
726     glw::GLint zero_int     = 0;
727 
728     gl.texParameterf(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_BASE_LEVEL, 0.0f);
729     gl.texParameterfv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_BASE_LEVEL, &zero_float);
730     gl.texParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_BASE_LEVEL, 0);
731     gl.texParameteriv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_BASE_LEVEL, &zero_int);
732 
733     GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glTexParameter*() call reported an error.");
734 
735     /* Do the same for 2D multisample array texture */
736     if (are_2d_array_multisample_tos_supported)
737     {
738         gl.texParameterf(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_BASE_LEVEL, 0.0f);
739         gl.texParameterfv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_BASE_LEVEL, &zero_float);
740         gl.texParameteri(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_BASE_LEVEL, 0);
741         gl.texParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_TEXTURE_BASE_LEVEL, &zero_int);
742 
743         GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glTexParameter*() call reported an error.");
744     }
745 
746     /* All good! */
747     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
748     return STOP;
749 }
750 } // namespace glcts
751