1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2024 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 glcTextureStorageCompressedDataTests.cpp
27 * \brief Conformance tests for the textureStorage functionality.
28 */ /*-------------------------------------------------------------------*/
29
30 #include "deMath.h"
31
32 #include "glcTextureStorageTests.hpp"
33 #include "gluContextInfo.hpp"
34 #include "gluDefs.hpp"
35 #include "gluStrUtil.hpp"
36 #include "glwEnums.hpp"
37 #include "glwFunctions.hpp"
38 #include "tcuRenderTarget.hpp"
39 #include "tcuTestLog.hpp"
40
41 #include <cmath>
42
43 using namespace glw;
44 using namespace glu;
45
46 namespace glcts
47 {
48 /** Constructor.
49 *
50 * @param context Rendering context
51 */
TextureStorageCompressedDataTestCase(deqp::Context & context)52 TextureStorageCompressedDataTestCase::TextureStorageCompressedDataTestCase(deqp::Context &context)
53 : TestCase(context, "compressed_data", "Verifies compressed texture data loading functionality")
54 , m_isContextES(false)
55 , m_testSupported(false)
56 , m_texture2D(0)
57 , m_textureCubeMap(0)
58 , m_texture3D(0)
59 , m_texture2DArray(0)
60 , m_textureSize2D(512)
61 , m_textureSize3D(64)
62 , m_maxTexturePixels(0)
63 {
64 }
65
66 /** Stub deinit method. */
deinit()67 void TextureStorageCompressedDataTestCase::deinit()
68 {
69 /* Left blank intentionally */
70 }
71
72 /** Stub init method */
init()73 void TextureStorageCompressedDataTestCase::init()
74 {
75 const glu::RenderContext &renderContext = m_context.getRenderContext();
76 m_isContextES = glu::isContextTypeES(renderContext.getType());
77
78 m_textureLevels2D = (int)std::floor(std::log2f((float)m_textureSize2D)) + 1;
79 m_textureLevels3D = (int)std::floor(std::log2f((float)m_textureSize3D)) + 1;
80
81 /* create largest used 2D/3D texture */
82 m_maxTexturePixels = std::max(4 * m_textureSize2D * m_textureSize2D,
83 4 * m_textureSize3D * m_textureSize3D * m_textureSize3D); /* RGBA, thus 4x */
84 m_texData = std::vector<GLfloat>(4 * m_maxTexturePixels, 0.f); /* f32 or (u)i32, which are 4 bytes per pixel */
85
86 auto contextType = m_context.getRenderContext().getType();
87 if (!m_isContextES)
88 {
89 m_testSupported = (m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_storage") &&
90 (glu::contextSupports(contextType, glu::ApiType::core(3, 0)) ||
91 glu::contextSupports(contextType, glu::ApiType::core(3, 1)))) ||
92 glu::contextSupports(contextType, glu::ApiType::core(4, 2));
93 }
94 else
95 m_testSupported = true;
96 }
97
iterate_gl()98 bool TextureStorageCompressedDataTestCase::iterate_gl()
99 {
100 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
101 bool ret = true;
102 int curTextureSize = 0;
103
104 struct formats
105 {
106 GLenum intFormat;
107 GLenum format;
108 GLenum type;
109 GLboolean allowedWithTex3D;
110 } formats[] = {{GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_BYTE, GL_FALSE},
111 {GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_UNSIGNED_BYTE, GL_FALSE},
112 {GL_R16_SNORM, GL_RED, GL_UNSIGNED_BYTE, GL_TRUE},
113 {GL_R8_SNORM, GL_RED, GL_UNSIGNED_BYTE, GL_TRUE},
114 {GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_BYTE, GL_FALSE},
115 {GL_COMPRESSED_SIGNED_RED_RGTC1, GL_RED, GL_UNSIGNED_BYTE, GL_FALSE}};
116
117 GLenum format[] = {GL_RED, GL_RG, GL_RGB, GL_RGBA};
118
119 GLenum cubeMapTarget[] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
120 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
121 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
122
123 /* test with TEXTURE_2D target */
124 m_testCtx.getLog() << tcu::TestLog::Message
125 << "testing TEXTURE_2D compressed texture loading with each internal format\n"
126 << tcu::TestLog::EndMessage;
127
128 for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++)
129 {
130 gl.genTextures(1, &m_texture2D);
131 GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
132
133 gl.bindTexture(GL_TEXTURE_2D, m_texture2D);
134 GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
135
136 gl.texStorage2D(GL_TEXTURE_2D, m_textureLevels2D, formats[i].intFormat, m_textureSize2D, m_textureSize2D);
137 GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
138
139 /* test each format and level*/
140 for (size_t j = 0; j < sizeof(format) / sizeof(format[0]); j++)
141 {
142 curTextureSize = m_textureSize2D;
143
144 for (size_t k = 0; k < (size_t)m_textureLevels2D; k++)
145 {
146 gl.texSubImage2D(GL_TEXTURE_2D, k, 0, 0, curTextureSize, curTextureSize, format[j], formats[i].type,
147 m_texData.data());
148 GLU_EXPECT_NO_ERROR(gl.getError(), "texSubImage2D");
149
150 curTextureSize /= 2;
151 }
152 }
153 gl.deleteTextures(1, &m_texture2D);
154 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
155 }
156
157 /* test with TEXTURE_CUBE_MAP target */
158 m_testCtx.getLog() << tcu::TestLog::Message
159 << "testing TEXTURE_CUBE_MAP compressed texture loading with each internal format\n"
160 << tcu::TestLog::EndMessage;
161
162 for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++)
163 {
164 gl.genTextures(1, &m_textureCubeMap);
165 GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
166
167 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textureCubeMap);
168 GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
169
170 gl.texStorage2D(GL_TEXTURE_CUBE_MAP, m_textureLevels2D, formats[i].intFormat, m_textureSize2D, m_textureSize2D);
171 GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
172
173 /* test each format, cubemap face and level */
174 for (size_t j = 0; j < sizeof(format) / sizeof(format[0]); j++)
175 {
176 for (size_t k = 0; k < 6; k++)
177 {
178 curTextureSize = m_textureSize2D;
179
180 for (size_t l = 0; l < (size_t)m_textureLevels2D; l++)
181 {
182 gl.texSubImage2D(cubeMapTarget[k], l, 0, 0, curTextureSize, curTextureSize, format[j],
183 formats[i].type, m_texData.data());
184 GLU_EXPECT_NO_ERROR(gl.getError(), "texSubImage2D");
185
186 curTextureSize /= 2;
187 }
188 }
189 }
190 gl.deleteTextures(1, &m_textureCubeMap);
191 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
192 }
193
194 /* test with TEXTURE_3D target */
195 m_testCtx.getLog() << tcu::TestLog::Message
196 << "testing TEXTURE_3D compressed texture loading with each internal format\n"
197 << tcu::TestLog::EndMessage;
198
199 for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++)
200 {
201 if (formats[i].format != GL_DEPTH_COMPONENT && formats[i].format != GL_DEPTH_STENCIL)
202 {
203 gl.genTextures(1, &m_texture3D);
204 GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
205
206 gl.bindTexture(GL_TEXTURE_3D, m_texture3D);
207 GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
208
209 gl.texStorage3D(GL_TEXTURE_3D, m_textureLevels3D, formats[i].intFormat, m_textureSize3D, m_textureSize3D,
210 m_textureSize3D);
211
212 if (formats[i].allowedWithTex3D)
213 {
214 GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage3D");
215
216 /* test each format and level */
217 for (size_t j = 0; j < sizeof(format) / sizeof(format[0]); j++)
218 {
219 curTextureSize = m_textureSize3D;
220
221 for (size_t k = 0; k < (size_t)m_textureLevels3D; k++)
222 {
223 gl.texSubImage3D(GL_TEXTURE_3D, k, 0, 0, 0, curTextureSize, curTextureSize, curTextureSize,
224 format[j], formats[i].type, m_texData.data());
225 GLU_EXPECT_NO_ERROR(gl.getError(), "texSubImage3D");
226
227 curTextureSize /= 2;
228 }
229 }
230 }
231 else
232 {
233 /* Using glTexStorage3D with a TEXTURE_3D target and a compressed internal
234 format should generate INVALID_OPERATION. See Khronos bug 11239. */
235 auto err = gl.getError();
236 if (err != GL_INVALID_OPERATION)
237 {
238 m_testCtx.getLog() << tcu::TestLog::Message
239 << "texStorage3D failed, expected GL_INVALID_OPERATION got "
240 << glu::getErrorName(err) << tcu::TestLog::EndMessage;
241 ret = false;
242 }
243 }
244 gl.deleteTextures(1, &m_texture3D);
245 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
246 }
247 }
248
249 /* test with TEXTURE_2D_ARRAY target */
250 m_testCtx.getLog() << tcu::TestLog::Message
251 << "testing TEXTURE_2D_ARRAY compressed texture loading with each internal format\n"
252 << tcu::TestLog::EndMessage;
253
254 for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++)
255 {
256 gl.genTextures(1, &m_texture2DArray);
257 GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
258
259 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_texture2DArray);
260 GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
261
262 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, m_textureLevels3D, formats[i].intFormat, m_textureSize3D, m_textureSize3D,
263 m_textureSize3D);
264 GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage3D");
265
266 /* test each format and level */
267 for (size_t j = 0; j < sizeof(format) / sizeof(format[0]); j++)
268 {
269 curTextureSize = m_textureSize3D;
270
271 for (size_t k = 0; k < (size_t)m_textureLevels3D; k++)
272 {
273 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, k, 0, 0, 0, curTextureSize, curTextureSize, curTextureSize,
274 format[j], formats[i].type, m_texData.data());
275 GLU_EXPECT_NO_ERROR(gl.getError(), "texSubImage3D");
276
277 curTextureSize /= 2;
278 }
279 }
280 gl.deleteTextures(1, &m_texture2DArray);
281 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
282 }
283
284 return ret;
285 }
286
iterate_gles()287 bool TextureStorageCompressedDataTestCase::iterate_gles()
288 {
289 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
290 bool ret = true;
291
292 int curTextureSize = 0, curDataSize = 0;
293
294 struct formats
295 {
296 GLenum intFormat;
297 int bytesPerBlock;
298 } formats[] = {{GL_COMPRESSED_R11_EAC, 8},
299 {GL_COMPRESSED_SIGNED_R11_EAC, 8},
300 {GL_COMPRESSED_RG11_EAC, 16},
301 {GL_COMPRESSED_SIGNED_RG11_EAC, 16},
302 {GL_COMPRESSED_RGB8_ETC2, 8},
303 {GL_COMPRESSED_SRGB8_ETC2, 8},
304 {GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 8},
305 {GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 8},
306 {GL_COMPRESSED_RGBA8_ETC2_EAC, 16},
307 {GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 16}};
308
309 GLenum cubeMapTarget[] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
310 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
311 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
312
313 /* test with TEXTURE_2D target */
314 m_testCtx.getLog() << tcu::TestLog::Message
315 << "testing TEXTURE_2D compressed texture loading with each internal format\n"
316 << tcu::TestLog::EndMessage;
317
318 for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++)
319 {
320 gl.genTextures(1, &m_texture2D);
321 GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
322
323 gl.bindTexture(GL_TEXTURE_2D, m_texture2D);
324 GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
325
326 gl.texStorage2D(GL_TEXTURE_2D, m_textureLevels2D, formats[i].intFormat, m_textureSize2D, m_textureSize2D);
327 GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
328
329 curTextureSize = m_textureSize2D;
330
331 for (size_t k = 0; k < (size_t)m_textureLevels2D; k++)
332 {
333 curDataSize = std::max(curTextureSize / 4, 1) * std::max(curTextureSize / 4, 1);
334 curDataSize *= formats[i].bytesPerBlock;
335
336 gl.compressedTexSubImage2D(GL_TEXTURE_2D, k, 0, 0, curTextureSize, curTextureSize, formats[i].intFormat,
337 curDataSize, m_texData.data());
338 GLU_EXPECT_NO_ERROR(gl.getError(), "texSubImage3D");
339
340 curTextureSize /= 2;
341 }
342
343 gl.deleteTextures(1, &m_texture2D);
344 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
345 }
346
347 /* test with TEXTURE_CUBE_MAP target */
348 m_testCtx.getLog() << tcu::TestLog::Message
349 << "testing TEXTURE_CUBE_MAP compressed texture loading with each internal format\n"
350 << tcu::TestLog::EndMessage;
351
352 for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++)
353 {
354 gl.genTextures(1, &m_textureCubeMap);
355 GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
356
357 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textureCubeMap);
358 GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
359
360 gl.texStorage2D(GL_TEXTURE_CUBE_MAP, m_textureLevels2D, formats[i].intFormat, m_textureSize2D, m_textureSize2D);
361 GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
362
363 /* test each cubemap face and level */
364 for (size_t k = 0; k < 6; k++)
365 {
366 curTextureSize = m_textureSize2D;
367
368 for (size_t l = 0; l < (size_t)m_textureLevels2D; l++)
369 {
370 curDataSize = std::max(curTextureSize / 4, 1) * std::max(curTextureSize / 4, 1);
371 curDataSize *= formats[i].bytesPerBlock;
372
373 gl.compressedTexSubImage2D(cubeMapTarget[k], l, 0, 0, curTextureSize, curTextureSize,
374 formats[i].intFormat, curDataSize, m_texData.data());
375 GLU_EXPECT_NO_ERROR(gl.getError(), "texSubImage2D");
376
377 curTextureSize /= 2;
378 }
379 }
380
381 gl.deleteTextures(1, &m_textureCubeMap);
382 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
383 }
384
385 /* test with TEXTURE_2D_ARRAY target */
386 m_testCtx.getLog() << tcu::TestLog::Message
387 << "testing TEXTURE_2D_ARRAY compressed texture loading with each internal format\n"
388 << tcu::TestLog::EndMessage;
389
390 for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++)
391 {
392 gl.genTextures(1, &m_texture2DArray);
393 GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
394
395 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_texture2DArray);
396 GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
397
398 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, m_textureLevels3D, formats[i].intFormat, m_textureSize3D, m_textureSize3D,
399 m_textureSize3D);
400 GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage3D");
401
402 /* test each level */
403 curTextureSize = m_textureSize3D;
404
405 for (size_t k = 0; k < (size_t)m_textureLevels3D; k++)
406 {
407 curDataSize = std::max(curTextureSize / 4, 1) * std::max(curTextureSize / 4, 1) * curTextureSize;
408 curDataSize *= formats[i].bytesPerBlock;
409
410 gl.compressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, k, 0, 0, 0, curTextureSize, curTextureSize, curTextureSize,
411 formats[i].intFormat, curDataSize, m_texData.data());
412 GLU_EXPECT_NO_ERROR(gl.getError(), "compressedTexSubImage3D");
413
414 curTextureSize /= 2;
415 }
416 gl.deleteTextures(1, &m_texture2DArray);
417 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
418 }
419
420 return ret;
421 }
422
423 /** Executes test iteration.
424 *
425 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
426 */
iterate()427 tcu::TestNode::IterateResult TextureStorageCompressedDataTestCase::iterate()
428 {
429 bool ret = true;
430
431 if (!m_testSupported)
432 {
433 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
434 /* This test should only be executed if we're running a GL4.2 context or
435 * GL_EXT_texture_storage extension is supported */
436 throw tcu::NotSupportedError("TextureStorageCompressedDataTestCase is not supported");
437 }
438
439 if (m_isContextES)
440 {
441 ret = iterate_gles();
442 }
443 else
444 {
445 ret = iterate_gl();
446 }
447
448 if (ret)
449 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
450 else
451 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
452 return STOP;
453 }
454
455 /** Constructor.
456 *
457 * @param context Rendering context.
458 */
TextureStorageTests(deqp::Context & context)459 TextureStorageTests::TextureStorageTests(deqp::Context &context)
460 : TestCaseGroup(context, "texture_storage", "Verify conformance of texture storage functionality")
461 {
462 }
463
464 /** Initializes the test group contents. */
init()465 void TextureStorageTests::init()
466 {
467 addChild(new TextureStorageCompressedDataTestCase(m_context));
468 }
469
470 } // namespace glcts
471