Relax GLES3 internal format queries for GLES31 compatibility.
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fInternalFormatQueryTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
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 Internal format query tests
22  *//*--------------------------------------------------------------------*/
23
24 #include "es31fInternalFormatQueryTests.hpp"
25 #include "tcuTestLog.hpp"
26 #include "gluRenderContext.hpp"
27 #include "gluStrUtil.hpp"
28 #include "gluContextInfo.hpp"
29 #include "glwFunctions.hpp"
30 #include "glwEnums.hpp"
31
32 namespace deqp
33 {
34 namespace gles31
35 {
36 namespace Functional
37 {
38 namespace
39 {
40
41 class FormatSamplesCase : public TestCase
42 {
43 public:
44         enum FormatType
45         {
46                 FORMAT_COLOR,
47                 FORMAT_INT,
48                 FORMAT_DEPTH_STENCIL
49         };
50
51                                                 FormatSamplesCase       (Context& ctx, const char* name, const char* desc, glw::GLenum texTarget, glw::GLenum internalFormat, FormatType type);
52 private:
53         void                            init                            (void);
54         IterateResult           iterate                         (void);
55
56         const glw::GLenum       m_target;
57         const glw::GLenum       m_internalFormat;
58         const FormatType        m_type;
59 };
60
61 FormatSamplesCase::FormatSamplesCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, glw::GLenum internalFormat, FormatType type)
62         : TestCase                      (ctx, name, desc)
63         , m_target                      (target)
64         , m_internalFormat      (internalFormat)
65         , m_type                        (type)
66 {
67         DE_ASSERT(m_target == GL_TEXTURE_2D_MULTISAMPLE                 ||
68                           m_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY   ||
69                           m_target == GL_RENDERBUFFER);
70 }
71
72 void FormatSamplesCase::init (void)
73 {
74         const bool isTextureTarget = (m_target == GL_TEXTURE_2D_MULTISAMPLE) ||
75                                                                  (m_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
76
77         if (m_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY && !m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"))
78                 throw tcu::NotSupportedError("Test requires OES_texture_storage_multisample_2d_array extension");
79
80         // stencil8 textures are not supported without GL_OES_texture_stencil8 extension
81         if (isTextureTarget && m_internalFormat == GL_STENCIL_INDEX8 && !m_context.getContextInfo().isExtensionSupported("GL_OES_texture_stencil8"))
82                 throw tcu::NotSupportedError("Test requires GL_OES_texture_stencil8 extension");
83 }
84
85 FormatSamplesCase::IterateResult FormatSamplesCase::iterate (void)
86 {
87         const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
88         bool                                    error                   = false;
89         glw::GLint                              maxSamples              = 0;
90         glw::GLint                              numSampleCounts = 0;
91
92         // Lowest limit
93         {
94                 const glw::GLenum samplesEnum = (m_type == FORMAT_COLOR) ? (GL_MAX_COLOR_TEXTURE_SAMPLES) : (m_type == FORMAT_INT) ? (GL_MAX_INTEGER_SAMPLES) : (GL_MAX_DEPTH_TEXTURE_SAMPLES);
95                 m_testCtx.getLog() << tcu::TestLog::Message << "Format must support sample count of " << glu::getGettableStateStr(samplesEnum) << tcu::TestLog::EndMessage;
96
97                 gl.getIntegerv(samplesEnum, &maxSamples);
98                 GLU_EXPECT_NO_ERROR(gl.getError(), "get MAX_*_SAMPLES");
99
100                 m_testCtx.getLog() << tcu::TestLog::Message << glu::getGettableStateStr(samplesEnum) << " = " << maxSamples << tcu::TestLog::EndMessage;
101
102                 if (maxSamples < 1)
103                 {
104                         m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: minimum value of "  << glu::getGettableStateStr(samplesEnum) << " is 1" << tcu::TestLog::EndMessage;
105                         error = true;
106                 }
107         }
108
109         // Number of sample counts
110         {
111                 gl.getInternalformativ(m_target, m_internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);
112                 GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_NUM_SAMPLE_COUNTS");
113
114                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_NUM_SAMPLE_COUNTS = " << numSampleCounts << tcu::TestLog::EndMessage;
115
116                 if (numSampleCounts < 1)
117                 {
118                         m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Format MUST support some multisample configuration, got GL_NUM_SAMPLE_COUNTS = " << numSampleCounts << tcu::TestLog::EndMessage;
119                         error = true;
120                 }
121         }
122
123         // Sample counts
124         {
125                 tcu::MessageBuilder             samplesMsg(&m_testCtx.getLog());
126                 std::vector<glw::GLint> samples;
127
128                 if (numSampleCounts > 0)
129                 {
130                         samples.resize(numSampleCounts, -1);
131
132                         gl.getInternalformativ(m_target, m_internalFormat, GL_SAMPLES, numSampleCounts, &samples[0]);
133                         GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_SAMPLES");
134                 }
135                 else
136                         TCU_FAIL("glGetInternalFormativ() reported 0 supported sample counts");
137
138                 // make a pretty log
139
140                 samplesMsg << "GL_SAMPLES = [";
141                 for (int ndx = 0; ndx < numSampleCounts; ++ndx)
142                 {
143                         if (ndx)
144                                 samplesMsg << ", ";
145                         samplesMsg << samples[ndx];
146                 }
147                 samplesMsg << "]" << tcu::TestLog::EndMessage;
148
149                 // Samples are in order
150                 for (int ndx = 1; ndx < numSampleCounts; ++ndx)
151                 {
152                         if (samples[ndx-1] <= samples[ndx])
153                         {
154                                 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Samples must be ordered descending." << tcu::TestLog::EndMessage;
155                                 error = true;
156                                 break;
157                         }
158                 }
159
160                 // samples are positive
161                 for (int ndx = 1; ndx < numSampleCounts; ++ndx)
162                 {
163                         if (samples[ndx-1] <= 0)
164                         {
165                                 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Only positive SAMPLES allowed." << tcu::TestLog::EndMessage;
166                                 error = true;
167                                 break;
168                         }
169                 }
170
171                 // maxSamples must be supported
172                 if (samples[0] < maxSamples)
173                 {
174                         m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: MAX_*_SAMPLES must be supported." << tcu::TestLog::EndMessage;
175                         error = true;
176                 }
177         }
178
179         // Result
180         if (!error)
181                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
182         else
183                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid value");
184
185         return STOP;
186 }
187
188 class NumSampleCountsBufferCase : public TestCase
189 {
190 public:
191                                         NumSampleCountsBufferCase       (Context& ctx, const char* name, const char* desc);
192
193 private:
194         IterateResult   iterate                                         (void);
195 };
196
197 NumSampleCountsBufferCase::NumSampleCountsBufferCase (Context& ctx, const char* name, const char* desc)
198         : TestCase(ctx, name, desc)
199 {
200 }
201
202 NumSampleCountsBufferCase::IterateResult NumSampleCountsBufferCase::iterate (void)
203 {
204         const glw::GLint                defaultValue    = -123; // queries always return positive values
205         const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
206         bool                                    error                   = false;
207
208         // Query to larger buffer
209         {
210                 glw::GLint buffer[2] = { defaultValue, defaultValue };
211
212                 m_testCtx.getLog() << tcu::TestLog::Message << "Querying GL_NUM_SAMPLE_COUNTS to larger-than-needed buffer." << tcu::TestLog::EndMessage;
213                 gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 2, buffer);
214                 GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_NUM_SAMPLE_COUNTS");
215
216                 if (buffer[1] != defaultValue)
217                 {
218                         m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: trailing values were modified." << tcu::TestLog::EndMessage;
219                         error = true;
220                 }
221         }
222
223         // Query to empty buffer
224         {
225                 glw::GLint buffer[1] = { defaultValue };
226
227                 m_testCtx.getLog() << tcu::TestLog::Message << "Querying GL_NUM_SAMPLE_COUNTS to zero-sized buffer." << tcu::TestLog::EndMessage;
228                 gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 0, buffer);
229                 GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_NUM_SAMPLE_COUNTS");
230
231                 if (buffer[0] != defaultValue)
232                 {
233                         m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Query wrote over buffer bounds." << tcu::TestLog::EndMessage;
234                         error = true;
235                 }
236         }
237
238         // Result
239         if (!error)
240                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
241         else
242                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected buffer modification");
243
244         return STOP;
245 }
246
247 class SamplesBufferCase : public TestCase
248 {
249 public:
250                                         SamplesBufferCase       (Context& ctx, const char* name, const char* desc);
251
252 private:
253         IterateResult   iterate                         (void);
254 };
255
256 SamplesBufferCase::SamplesBufferCase (Context& ctx, const char* name, const char* desc)
257         : TestCase(ctx, name, desc)
258 {
259 }
260
261 SamplesBufferCase::IterateResult SamplesBufferCase::iterate (void)
262 {
263         const glw::GLint                defaultValue    = -123; // queries always return positive values
264         const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
265         bool                                    error                   = false;
266
267         glw::GLint                              numSampleCounts = 0;
268
269         // Number of sample counts
270         {
271                 gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);
272                 GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_NUM_SAMPLE_COUNTS");
273
274                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_NUM_SAMPLE_COUNTS = " << numSampleCounts << tcu::TestLog::EndMessage;
275         }
276
277         if (numSampleCounts < 1)
278         {
279                 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Format MUST support some multisample configuration, got GL_NUM_SAMPLE_COUNTS = " << numSampleCounts << tcu::TestLog::EndMessage;
280                 error = true;
281         }
282         else
283         {
284                 // Query to larger buffer
285                 {
286                         std::vector<glw::GLint> buffer(numSampleCounts + 1, defaultValue);
287
288                         m_testCtx.getLog() << tcu::TestLog::Message << "Querying GL_SAMPLES to larger-than-needed buffer." << tcu::TestLog::EndMessage;
289                         gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, (glw::GLsizei)buffer.size(), &buffer[0]);
290                         GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_SAMPLES");
291
292                         if (buffer.back() != defaultValue)
293                         {
294                                 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: trailing value was modified." << tcu::TestLog::EndMessage;
295                                 error = true;
296                         }
297                 }
298
299                 // Query to smaller buffer
300                 if (numSampleCounts > 2)
301                 {
302                         glw::GLint buffer[3] = { defaultValue, defaultValue, defaultValue };
303
304                         m_testCtx.getLog() << tcu::TestLog::Message << "Querying GL_SAMPLES to buffer with bufSize=2." << tcu::TestLog::EndMessage;
305                         gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, 2, buffer);
306                         GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_SAMPLES");
307
308                         if (buffer[2] != defaultValue)
309                         {
310                                 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Query wrote over buffer bounds." << tcu::TestLog::EndMessage;
311                                 error = true;
312                         }
313                 }
314
315                 // Query to empty buffer
316                 {
317                         glw::GLint buffer[1] = { defaultValue };
318
319                         m_testCtx.getLog() << tcu::TestLog::Message << "Querying GL_SAMPLES to zero-sized buffer." << tcu::TestLog::EndMessage;
320                         gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, 0, buffer);
321                         GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_SAMPLES");
322
323                         if (buffer[0] != defaultValue)
324                         {
325                                 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Query wrote over buffer bounds." << tcu::TestLog::EndMessage;
326                                 error = true;
327                         }
328                 }
329         }
330
331         // Result
332         if (!error)
333                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
334         else
335                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected buffer modification");
336
337         return STOP;
338 }
339
340 } // anonymous
341
342 InternalFormatQueryTests::InternalFormatQueryTests (Context& context)
343         : TestCaseGroup(context, "internal_format", "Internal format queries")
344 {
345 }
346
347 InternalFormatQueryTests::~InternalFormatQueryTests (void)
348 {
349 }
350
351 void InternalFormatQueryTests::init (void)
352 {
353         static const struct InternalFormat
354         {
355                 const char*                                             name;
356                 glw::GLenum                                             format;
357                 FormatSamplesCase::FormatType   type;
358         } internalFormats[] =
359         {
360                 // color renderable
361                 { "r8",                                         GL_R8,                                  FormatSamplesCase::FORMAT_COLOR                 },
362                 { "rg8",                                        GL_RG8,                                 FormatSamplesCase::FORMAT_COLOR                 },
363                 { "rgb8",                                       GL_RGB8,                                FormatSamplesCase::FORMAT_COLOR                 },
364                 { "rgb565",                                     GL_RGB565,                              FormatSamplesCase::FORMAT_COLOR                 },
365                 { "rgba4",                                      GL_RGBA4,                               FormatSamplesCase::FORMAT_COLOR                 },
366                 { "rgb5_a1",                            GL_RGB5_A1,                             FormatSamplesCase::FORMAT_COLOR                 },
367                 { "rgba8",                                      GL_RGBA8,                               FormatSamplesCase::FORMAT_COLOR                 },
368                 { "rgb10_a2",                           GL_RGB10_A2,                    FormatSamplesCase::FORMAT_COLOR                 },
369                 { "rgb10_a2ui",                         GL_RGB10_A2UI,                  FormatSamplesCase::FORMAT_INT                   },
370                 { "srgb8_alpha8",                       GL_SRGB8_ALPHA8,                FormatSamplesCase::FORMAT_COLOR                 },
371                 { "r8i",                                        GL_R8I,                                 FormatSamplesCase::FORMAT_INT                   },
372                 { "r8ui",                                       GL_R8UI,                                FormatSamplesCase::FORMAT_INT                   },
373                 { "r16i",                                       GL_R16I,                                FormatSamplesCase::FORMAT_INT                   },
374                 { "r16ui",                                      GL_R16UI,                               FormatSamplesCase::FORMAT_INT                   },
375                 { "r32i",                                       GL_R32I,                                FormatSamplesCase::FORMAT_INT                   },
376                 { "r32ui",                                      GL_R32UI,                               FormatSamplesCase::FORMAT_INT                   },
377                 { "rg8i",                                       GL_RG8I,                                FormatSamplesCase::FORMAT_INT                   },
378                 { "rg8ui",                                      GL_RG8UI,                               FormatSamplesCase::FORMAT_INT                   },
379                 { "rg16i",                                      GL_RG16I,                               FormatSamplesCase::FORMAT_INT                   },
380                 { "rg16ui",                                     GL_RG16UI,                              FormatSamplesCase::FORMAT_INT                   },
381                 { "rg32i",                                      GL_RG32I,                               FormatSamplesCase::FORMAT_INT                   },
382                 { "rg32ui",                                     GL_RG32UI,                              FormatSamplesCase::FORMAT_INT                   },
383                 { "rgba8i",                                     GL_RGBA8I,                              FormatSamplesCase::FORMAT_INT                   },
384                 { "rgba8ui",                            GL_RGBA8UI,                             FormatSamplesCase::FORMAT_INT                   },
385                 { "rgba16i",                            GL_RGBA16I,                             FormatSamplesCase::FORMAT_INT                   },
386                 { "rgba16ui",                           GL_RGBA16UI,                    FormatSamplesCase::FORMAT_INT                   },
387                 { "rgba32i",                            GL_RGBA32I,                             FormatSamplesCase::FORMAT_INT                   },
388                 { "rgba32ui",                           GL_RGBA32UI,                    FormatSamplesCase::FORMAT_INT                   },
389
390                 // depth renderable
391                 { "depth_component16",          GL_DEPTH_COMPONENT16,   FormatSamplesCase::FORMAT_DEPTH_STENCIL },
392                 { "depth_component24",          GL_DEPTH_COMPONENT24,   FormatSamplesCase::FORMAT_DEPTH_STENCIL },
393                 { "depth_component32f",         GL_DEPTH_COMPONENT32F,  FormatSamplesCase::FORMAT_DEPTH_STENCIL },
394                 { "depth24_stencil8",           GL_DEPTH24_STENCIL8,    FormatSamplesCase::FORMAT_DEPTH_STENCIL },
395                 { "depth32f_stencil8",          GL_DEPTH32F_STENCIL8,   FormatSamplesCase::FORMAT_DEPTH_STENCIL },
396
397                 // stencil renderable
398                 { "stencil_index8",                     GL_STENCIL_INDEX8,              FormatSamplesCase::FORMAT_DEPTH_STENCIL }
399                 // DEPTH24_STENCIL8,  duplicate
400                 // DEPTH32F_STENCIL8  duplicate
401         };
402
403         static const struct
404         {
405                 const char*     name;
406                 deUint32        target;
407         } textureTargets[] =
408         {
409                 { "renderbuffer",                                       GL_RENDERBUFFER                                 },
410                 { "texture_2d_multisample",                     GL_TEXTURE_2D_MULTISAMPLE               },
411                 { "texture_2d_multisample_array",       GL_TEXTURE_2D_MULTISAMPLE_ARRAY },
412         };
413
414         for (int groupNdx = 0; groupNdx < DE_LENGTH_OF_ARRAY(textureTargets); ++groupNdx)
415         {
416                 tcu::TestCaseGroup* const       group           = new tcu::TestCaseGroup(m_testCtx, textureTargets[groupNdx].name, glu::getInternalFormatTargetName(textureTargets[groupNdx].target));
417                 const glw::GLenum                       texTarget       = textureTargets[groupNdx].target;
418
419                 addChild(group);
420
421                 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(internalFormats); ++caseNdx)
422                 {
423                         const std::string name = std::string(internalFormats[caseNdx].name) + "_samples";
424                         const std::string desc = std::string("Verify GL_SAMPLES of ") + internalFormats[caseNdx].name;
425
426                         group->addChild(new FormatSamplesCase(m_context, name.c_str(), desc.c_str(), texTarget, internalFormats[caseNdx].format, internalFormats[caseNdx].type));
427                 }
428         }
429
430         // Check buffer sizes are honored
431         {
432                 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "partial_query", "Query data to too short a buffer");
433
434                 addChild(group);
435
436                 group->addChild(new NumSampleCountsBufferCase   (m_context, "num_sample_counts",        "Query GL_NUM_SAMPLE_COUNTS to too short a buffer"));
437                 group->addChild(new SamplesBufferCase                   (m_context, "samples",                          "Query GL_SAMPLES to too short a buffer"));
438         }
439 }
440
441 } // Functional
442 } // gles31
443 } // deqp