1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2021 Google Inc.
6 * Copyright (c) 2021 The Khronos Group Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 */ /*!
21 * \file glcCompressedFormatTests.cpp
22 * \brief Tests for OpenGL ES 3.1 and 3.2 compressed image formats
23 */ /*-------------------------------------------------------------------*/
24
25 #include "glcCompressedFormatTests.hpp"
26
27 #include "gluDefs.hpp"
28 #include "glwEnums.hpp"
29 #include "glwFunctions.hpp"
30
31 #include "gluShaderProgram.hpp"
32 #include "gluPixelTransfer.hpp"
33 #include "gluStrUtil.hpp"
34
35 #include "tcuResource.hpp"
36 #include "tcuSurface.hpp"
37 #include "tcuImageCompare.hpp"
38 #include "tcuTestLog.hpp"
39 #include "tcuStringTemplate.hpp"
40
41 #include "deUniquePtr.hpp"
42
43 #include <algorithm>
44 #include <map>
45 #include <vector>
46 #include <memory>
47 #include <functional>
48 #include <fstream>
49
50 namespace glcts
51 {
52 namespace
53 {
54 using namespace glw;
55 using namespace glu;
56 using namespace tcu;
57 using namespace std;
58
59 struct FormatInfo
60 {
61 ApiType minApi;
62 const char *name;
63 GLenum internalFormat;
64 GLenum format;
65 GLenum sizedFormat;
66 bool issRGB;
67 IVec2 blockSize;
68 };
69
70 const ApiType gles31 = ApiType::es(3, 1);
71 const ApiType gles32 = ApiType::es(3, 2);
72
73 // List of compressed texture formats (table 8.17)
74 const FormatInfo compressedFormats[] = {
75 // ETC (table C.2)
76 // minApi, name , internalFormat , format , sizedFormat , issRGB , blockSize
77 {gles31, "r11_eac", GL_COMPRESSED_R11_EAC, GL_RED, GL_R8, false, {4, 4}},
78 {gles31, "signed_r11_eac", GL_COMPRESSED_SIGNED_R11_EAC, GL_RED, GL_R8, false, {4, 4}},
79 {gles31, "rg11_eac", GL_COMPRESSED_RG11_EAC, GL_RG, GL_RG8, false, {4, 4}},
80 {gles31, "signed_rg11_eac", GL_COMPRESSED_SIGNED_RG11_EAC, GL_RG, GL_RG8, false, {4, 4}},
81 {gles31, "rgb8_etc2", GL_COMPRESSED_RGB8_ETC2, GL_RGB, GL_RGB8, false, {4, 4}},
82 {gles31, "srgb8_etc2", GL_COMPRESSED_SRGB8_ETC2, GL_RGB, GL_SRGB8, true, {4, 4}},
83 {gles31,
84 "rgb8_punchthrough_alpha1_etc2",
85 GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
86 GL_RGBA,
87 GL_RGBA8,
88 false,
89 {4, 4}},
90 {gles31,
91 "srgb8_punchthrough_alpha1_etc2",
92 GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
93 GL_RGBA,
94 GL_SRGB8_ALPHA8,
95 true,
96 {4, 4}},
97 {gles31, "rgba8_etc2_eac", GL_COMPRESSED_RGBA8_ETC2_EAC, GL_RGBA, GL_RGBA8, false, {4, 4}},
98 {gles31, "srgb8_alpha8_etc2_eac", GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_RGBA, GL_SRGB8_ALPHA8, true, {4, 4}},
99 // ASTC (table C.1)
100 // minApi, name , internalFormat , format , sizedFormat , issRGB , blockSize
101 {gles32, "rgba_astc_4x4", GL_COMPRESSED_RGBA_ASTC_4x4, GL_RGBA, GL_RGBA8, false, {4, 4}},
102 {gles32, "rgba_astc_5x4", GL_COMPRESSED_RGBA_ASTC_5x4, GL_RGBA, GL_RGBA8, false, {5, 4}},
103 {gles32, "rgba_astc_5x5", GL_COMPRESSED_RGBA_ASTC_5x5, GL_RGBA, GL_RGBA8, false, {5, 5}},
104 {gles32, "rgba_astc_6x5", GL_COMPRESSED_RGBA_ASTC_6x5, GL_RGBA, GL_RGBA8, false, {6, 5}},
105 {gles32, "rgba_astc_6x6", GL_COMPRESSED_RGBA_ASTC_6x6, GL_RGBA, GL_RGBA8, false, {6, 6}},
106 {gles32, "rgba_astc_8x5", GL_COMPRESSED_RGBA_ASTC_8x5, GL_RGBA, GL_RGBA8, false, {8, 5}},
107 {gles32, "rgba_astc_8x6", GL_COMPRESSED_RGBA_ASTC_8x6, GL_RGBA, GL_RGBA8, false, {8, 6}},
108 {gles32, "rgba_astc_8x8", GL_COMPRESSED_RGBA_ASTC_8x8, GL_RGBA, GL_RGBA8, false, {8, 8}},
109 {gles32, "rgba_astc_10x5", GL_COMPRESSED_RGBA_ASTC_10x5, GL_RGBA, GL_RGBA8, false, {10, 5}},
110 {gles32, "rgba_astc_10x6", GL_COMPRESSED_RGBA_ASTC_10x6, GL_RGBA, GL_RGBA8, false, {10, 6}},
111 {gles32, "rgba_astc_10x8", GL_COMPRESSED_RGBA_ASTC_10x8, GL_RGBA, GL_RGBA8, false, {10, 8}},
112 {gles32, "rgba_astc_10x10", GL_COMPRESSED_RGBA_ASTC_10x10, GL_RGBA, GL_RGBA8, false, {10, 10}},
113 {gles32, "rgba_astc_12x10", GL_COMPRESSED_RGBA_ASTC_12x10, GL_RGBA, GL_RGBA8, false, {12, 10}},
114 {gles32, "rgba_astc_12x12", GL_COMPRESSED_RGBA_ASTC_12x12, GL_RGBA, GL_RGBA8, false, {12, 12}},
115 {gles32, "srgb8_alpha8_astc_4x4", GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4, GL_RGBA, GL_SRGB8_ALPHA8, true, {4, 4}},
116 {gles32, "srgb8_alpha8_astc_5x4", GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4, GL_RGBA, GL_SRGB8_ALPHA8, true, {5, 4}},
117 {gles32, "srgb8_alpha8_astc_5x5", GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5, GL_RGBA, GL_SRGB8_ALPHA8, true, {5, 5}},
118 {gles32, "srgb8_alpha8_astc_6x5", GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5, GL_RGBA, GL_SRGB8_ALPHA8, true, {6, 5}},
119 {gles32, "srgb8_alpha8_astc_6x6", GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6, GL_RGBA, GL_SRGB8_ALPHA8, true, {6, 6}},
120 {gles32, "srgb8_alpha8_astc_8x5", GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5, GL_RGBA, GL_SRGB8_ALPHA8, true, {8, 5}},
121 {gles32, "srgb8_alpha8_astc_8x6", GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6, GL_RGBA, GL_SRGB8_ALPHA8, true, {8, 6}},
122 {gles32, "srgb8_alpha8_astc_8x8", GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8, GL_RGBA, GL_SRGB8_ALPHA8, true, {8, 8}},
123 {gles32, "srgb8_alpha8_astc_10x5", GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5, GL_RGBA, GL_SRGB8_ALPHA8, true, {10, 5}},
124 {gles32, "srgb8_alpha8_astc_10x6", GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6, GL_RGBA, GL_SRGB8_ALPHA8, true, {10, 6}},
125 {gles32, "srgb8_alpha8_astc_10x8", GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8, GL_RGBA, GL_SRGB8_ALPHA8, true, {10, 8}},
126 {gles32,
127 "srgb8_alpha8_astc_10x10",
128 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10,
129 GL_RGBA,
130 GL_SRGB8_ALPHA8,
131 true,
132 {10, 10}},
133 {gles32,
134 "srgb8_alpha8_astc_12x10",
135 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10,
136 GL_RGBA,
137 GL_SRGB8_ALPHA8,
138 true,
139 {12, 10}},
140 {gles32,
141 "srgb8_alpha8_astc_12x12",
142 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12,
143 GL_RGBA,
144 GL_SRGB8_ALPHA8,
145 true,
146 {12, 12}},
147 };
148
149 struct UnsizedFormatInfo
150 {
151 GLenum format;
152 GLenum dataType;
153 };
154
155 const map<GLenum, UnsizedFormatInfo> unsizedFormats = {{GL_RGBA32UI, {GL_RGBA_INTEGER, GL_UNSIGNED_INT}},
156 {GL_RGBA32I, {GL_RGBA_INTEGER, GL_INT}},
157 {GL_RGBA32F, {GL_RGBA, GL_FLOAT}},
158 {GL_RGBA16F, {GL_RGBA, GL_FLOAT}},
159 {GL_RG32F, {GL_RG, GL_FLOAT}},
160 {GL_RGBA16UI, {GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}},
161 {GL_RG32UI, {GL_RG_INTEGER, GL_UNSIGNED_INT}},
162 {GL_RGBA16I, {GL_RGBA_INTEGER, GL_SHORT}},
163 {GL_RG32I, {GL_RG_INTEGER, GL_INT}}};
164
165 const vector<pair<vector<GLenum>, vector<GLenum>>> copyFormats = {
166 // Table 16.3 - copy between compressed and uncompressed
167 // 128bit texel / block size
168 {{GL_RGBA32UI, GL_RGBA32I, GL_RGBA32F},
169 {
170 GL_COMPRESSED_RGBA8_ETC2_EAC,
171 GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
172 GL_COMPRESSED_RG11_EAC,
173 GL_COMPRESSED_SIGNED_RG11_EAC,
174 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4,
175 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4,
176 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5,
177 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5,
178 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6,
179 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5,
180 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6,
181 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8,
182 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5,
183 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6,
184 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8,
185 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10,
186 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10,
187 GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12,
188 }},
189 // 64bit texel / block size
190 {{GL_RGBA16F, GL_RG32F, GL_RGBA16UI, GL_RG32UI, GL_RGBA16I, GL_RG32I},
191 {GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC,
192 GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2}},
193 // Table 16.4 - only entries for compressed formats are included
194 {{GL_COMPRESSED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC}, {}},
195 {{GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC}, {}},
196 {{GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2}, {}},
197 {{GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2}, {}},
198 {{GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC}, {}},
199 {{GL_COMPRESSED_RGBA_ASTC_4x4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4}, {}},
200 {{GL_COMPRESSED_RGBA_ASTC_5x4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4}, {}},
201 {{GL_COMPRESSED_RGBA_ASTC_5x5, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5}, {}},
202 {{GL_COMPRESSED_RGBA_ASTC_6x5, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5}, {}},
203 {{GL_COMPRESSED_RGBA_ASTC_6x6, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6}, {}},
204 {{GL_COMPRESSED_RGBA_ASTC_8x5, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5}, {}},
205 {{GL_COMPRESSED_RGBA_ASTC_8x6, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6}, {}},
206 {{GL_COMPRESSED_RGBA_ASTC_8x8, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8}, {}},
207 {{GL_COMPRESSED_RGBA_ASTC_10x5, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5}, {}},
208 {{GL_COMPRESSED_RGBA_ASTC_10x6, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6}, {}},
209 {{GL_COMPRESSED_RGBA_ASTC_10x8, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8}, {}},
210 {{GL_COMPRESSED_RGBA_ASTC_10x10, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10}, {}},
211 {{GL_COMPRESSED_RGBA_ASTC_12x10, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10}, {}},
212 {{GL_COMPRESSED_RGBA_ASTC_12x12, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12}, {}}};
213
214 #include "glcCompressedFormatTests_data.inl"
215
216 const float vertexPositions[] = {
217 -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
218 };
219
220 const float vertexTexCoords[] = {
221 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
222 };
223
224 const char *vertexShader = "${VERSION}\n"
225 "in highp vec4 in_position;\n"
226 "in highp vec2 in_texCoord;\n"
227 "out highp vec2 v_texCoord;\n"
228 "void main (void)\n"
229 "{\n"
230 " gl_Position = in_position;\n"
231 " v_texCoord = in_texCoord;\n"
232 "}\n";
233
234 const char *fragmentShader = "${VERSION}\n"
235 "uniform highp vec4 offset;\n"
236 "uniform highp vec4 scale;\n"
237 "uniform highp sampler2D sampler;\n"
238 "in highp vec2 v_texCoord;\n"
239 "layout(location = 0) out highp vec4 out_color;\n"
240 "void main (void)\n"
241 "{\n"
242 " out_color = texture(sampler, v_texCoord) * scale + offset;\n"
243 "}\n";
244
245 struct OffsetInfo
246 {
247 Vec4 offset;
248 Vec4 scale;
249 };
250
251 const OffsetInfo defaultOffset{{0.0f, 0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}};
252 const map<GLenum, OffsetInfo> offsets = {
253 {GL_COMPRESSED_SIGNED_R11_EAC, {{0.5f, 0.0f, 0.0f, 0.0f}, {0.5f, 0.0f, 0.0f, 1.0f}}},
254 {GL_COMPRESSED_SIGNED_RG11_EAC, {{0.5f, 0.5f, 0.0f, 0.0f}, {0.5f, 0.5f, 0.0f, 1.0f}}}};
255
256 class SharedData
257 {
258 public:
259 explicit SharedData(deqp::Context &context);
260 virtual ~SharedData();
261
262 void init();
263 void deinit();
264
265 GLuint programId() const;
266 GLuint texId(int index) const;
267 GLuint vaoId() const;
268 GLuint offsetLoc() const;
269 GLuint scaleLoc() const;
270
271 private:
272 deqp::Context &m_context;
273 size_t m_initCount;
274 vector<GLuint> m_texIds;
275 shared_ptr<ShaderProgram> m_program;
276 GLuint m_vaoId;
277 GLuint m_vboIds[2];
278 GLuint m_offsetLoc;
279 GLuint m_scaleLoc;
280
281 SharedData(const SharedData &other) = delete;
282 SharedData &operator=(const SharedData &other) = delete;
283 };
284
SharedData(deqp::Context & context)285 SharedData::SharedData(deqp::Context &context) : m_context(context), m_initCount(0)
286 {
287 }
288
~SharedData()289 SharedData::~SharedData()
290 {
291 DE_ASSERT(m_initCount <= 0);
292 }
293
init()294 void SharedData::init()
295 {
296 ++m_initCount;
297 if (m_initCount > 1)
298 return;
299
300 const auto &gl = m_context.getRenderContext().getFunctions();
301 // program
302 const bool supportsES32 = contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
303 const auto glslVersion =
304 getGLSLVersionDeclaration(supportsES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES);
305 const auto args = map<string, string>{{"VERSION", glslVersion}};
306 const auto vs = StringTemplate(vertexShader).specialize(args);
307 const auto fs = StringTemplate(fragmentShader).specialize(args);
308 m_program = make_shared<ShaderProgram>(m_context.getRenderContext(),
309 ProgramSources() << glu::VertexSource(vs) << glu::FragmentSource(fs));
310 if (!m_program->isOk())
311 throw runtime_error("Compiling shader program failed");
312
313 const auto program = m_program->getProgram();
314 const auto positionLoc = gl.getAttribLocation(program, "in_position");
315 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation() failed");
316 const auto texCoordLoc = gl.getAttribLocation(program, "in_texCoord");
317 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation() failed");
318 m_offsetLoc = gl.getUniformLocation(program, "offset");
319 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation() failed");
320 m_scaleLoc = gl.getUniformLocation(program, "scale");
321 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation() failed");
322
323 // buffers
324 gl.genBuffers(DE_LENGTH_OF_ARRAY(m_vboIds), m_vboIds);
325 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
326
327 gl.bindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
328 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
329
330 gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
331 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
332
333 gl.bindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
334 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
335
336 gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexTexCoords), vertexTexCoords, GL_STATIC_DRAW);
337 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
338
339 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
340 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
341
342 // vertex array objects
343 gl.genVertexArrays(1, &m_vaoId);
344 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed");
345
346 gl.bindVertexArray(m_vaoId);
347 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed");
348
349 gl.bindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
350 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
351
352 gl.enableVertexAttribArray(positionLoc);
353 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() failed");
354
355 gl.vertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
356 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() failed");
357
358 gl.bindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
359 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
360
361 gl.enableVertexAttribArray(texCoordLoc);
362 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() failed");
363
364 gl.vertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
365 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() failed");
366
367 gl.bindVertexArray(0);
368 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed");
369 }
370
deinit()371 void SharedData::deinit()
372 {
373 DE_ASSERT(m_initCount > 0);
374 --m_initCount;
375
376 if (m_initCount > 0)
377 return;
378
379 const auto &gl = m_context.getRenderContext().getFunctions();
380 gl.deleteBuffers(1, &m_vaoId);
381 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers() failed");
382
383 gl.deleteBuffers(DE_LENGTH_OF_ARRAY(m_vboIds), m_vboIds);
384 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers() failed");
385
386 gl.deleteTextures((glw::GLsizei)m_texIds.size(), m_texIds.data());
387 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() failed");
388 }
389
programId() const390 GLuint SharedData::programId() const
391 {
392 return m_program->getProgram();
393 }
394
texId(int index) const395 GLuint SharedData::texId(int index) const
396 {
397 return m_texIds[index];
398 }
399
vaoId() const400 GLuint SharedData::vaoId() const
401 {
402 return m_vaoId;
403 }
404
offsetLoc() const405 GLuint SharedData::offsetLoc() const
406 {
407 return m_offsetLoc;
408 }
409
scaleLoc() const410 GLuint SharedData::scaleLoc() const
411 {
412 return m_scaleLoc;
413 }
414
415 struct
416 {
417 const GLsizei width = 8;
418 const GLsizei height = 8;
419 const GLsizei depth = 6;
420 const vector<uint8_t> data = {
421 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
422 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
423 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
424 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
425 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
426 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
427 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
428 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
429 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
430 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
431 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
432 };
433 } invalidTexture;
434
435 struct ApiTestContext
436 {
437 TestLog &log;
438 const glw::Functions ≷
439 vector<GLuint> &texIds;
440 vector<GLuint> &bufferIds;
441 const Archive &archive;
442
443 void bindTexture(GLenum target, GLuint texId);
444 };
445
bindTexture(GLenum target,GLuint texId)446 void ApiTestContext::bindTexture(GLenum target, GLuint texId)
447 {
448 gl.bindTexture(target, texId);
449 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed");
450 }
451
452 typedef function<void(ApiTestContext &)> ApiCaseFn;
453
454 struct ApiCaseStep
455 {
456 ApiCaseFn code;
457 GLenum expectedError;
458 };
459
460 typedef function<void(deqp::Context &, vector<ApiCaseStep> &)> ApiCaseStepGeneratorFn;
461
462 struct ApiCaseParams
463 {
464 ApiType minApi;
465 string name;
466 string description;
467 size_t texIdsCount;
468 size_t bufferIdsCount;
469 vector<ApiCaseStep> steps;
470 ApiCaseStepGeneratorFn stepsGenerator;
471 };
472
473 const GLenum cubemapFaces[] = {
474 GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
475 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
476 };
477
478 struct ImageInfo
479 {
480 GLuint width;
481 GLuint height;
482 vector<GLubyte> data;
483 };
484
loadImage(const Archive & archive,GLenum format,size_t imageIndex)485 ImageInfo loadImage(const Archive &archive, GLenum format, size_t imageIndex)
486 {
487 const auto data = imageData.find(format);
488 if (data == imageData.end())
489 {
490 ostringstream msg;
491 msg << "No image data found for format: " << format;
492 TCU_FAIL(msg.str().c_str());
493 }
494 if (imageIndex >= data->second.size())
495 {
496 ostringstream msg;
497 msg << "Image index out of range for format: " << format << " index: " << imageIndex;
498 TCU_FAIL(msg.str().c_str());
499 }
500 const de::UniquePtr<Resource> resource(archive.getResource(data->second[imageIndex].path.c_str()));
501 if (!resource || resource->getSize() <= 0)
502 TCU_FAIL("Failed to read file: " + data->second[imageIndex].path);
503 ImageInfo result;
504 result.width = data->second[imageIndex].width;
505 result.height = data->second[imageIndex].height;
506 const auto size = resource->getSize();
507 result.data.resize(size);
508 resource->setPosition(0);
509 resource->read(result.data.data(), size);
510 return result;
511 }
512
setTextureParameters(const glw::Functions & gl,GLenum target)513 void setTextureParameters(const glw::Functions &gl, GLenum target)
514 {
515 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
516 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
517 gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
518 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
519 gl.texParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
520 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
521 gl.texParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
522 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
523 const auto repeatMode = GL_CLAMP_TO_EDGE;
524 gl.texParameteri(target, GL_TEXTURE_WRAP_S, repeatMode);
525 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
526 gl.texParameteri(target, GL_TEXTURE_WRAP_T, repeatMode);
527 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
528 gl.texParameteri(target, GL_TEXTURE_WRAP_R, repeatMode);
529 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed");
530 }
531
532 ApiCaseParams apiTests[] = {
533 {
534 gles31, // ApiType minApi;
535 "invalid_target", // string name;
536 "Invalid texture target for compressed format", // string description;
537 1, // size_t texIdsCount;
538 0, // size_t bufferIdsCount;
539 {
540 // vector<ApiCaseStep> steps;
__anon705257c80302() 541 {[](ApiTestContext &context) { context.bindTexture(GL_TEXTURE_3D, context.texIds[0]); }, GL_NO_ERROR},
542 {[](ApiTestContext &context)
__anon705257c80402() 543 {
544 context.gl.compressedTexImage2D(GL_TEXTURE_3D, 0, GL_COMPRESSED_RGB8_ETC2, invalidTexture.width,
545 invalidTexture.height, 0, (glw::GLsizei)invalidTexture.data.size(),
546 invalidTexture.data.data());
547 },
548 GL_INVALID_ENUM},
549 {[](ApiTestContext &context)
__anon705257c80502() 550 {
551 context.gl.compressedTexSubImage2D(GL_TEXTURE_3D, 0, 0, 0, invalidTexture.width, invalidTexture.height,
552 GL_COMPRESSED_RGB8_ETC2, (glw::GLsizei)invalidTexture.data.size(),
553 invalidTexture.data.data());
554 },
555 GL_INVALID_ENUM},
556 },
557 DE_NULL, // ApiCaseStepGeneratorFn stepsGenerator;
558 },
559 {gles31, // ApiType minApi;
560 "invalid_width_or_height", // string name;
561 "Different values for width and height for cubemap texture target", // string description;
562 1, // size_t texIdsCount;
563 0, // size_t bufferIdsCount;
564 { // vector<ApiCaseStep> steps;
__anon705257c80602() 565 {[](ApiTestContext &context) { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]); }, GL_NO_ERROR}},
566 [](deqp::Context &, vector<ApiCaseStep> &steps) // ApiCaseStepGeneratorFn stepsGenerator;
__anon705257c80702() 567 {
568 steps.push_back({[](ApiTestContext &context) { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]); },
569 GL_NO_ERROR});
570 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(cubemapFaces); ++i)
571 {
572 steps.push_back({[i](ApiTestContext &context)
573 {
574 context.gl.compressedTexImage2D(
575 cubemapFaces[i], 0, GL_COMPRESSED_RGB8_ETC2, invalidTexture.width - i % 2,
576 invalidTexture.height - (i + 1) % 2, 0, (glw::GLsizei)invalidTexture.data.size(),
577 invalidTexture.data.data());
578 },
579 GL_INVALID_VALUE});
580 steps.push_back({[i](ApiTestContext &context)
581 {
582 const auto format = GL_COMPRESSED_RGB8_ETC2;
583 const GLsizei blockSize = 4;
584 const GLsizei blockDataSize = 8;
585 const auto data = loadImage(context.archive, format, 0);
586 const auto &gl = context.gl;
587 gl.compressedTexImage2D(cubemapFaces[i], 0, format, data.width, data.height, 0,
588 (glw::GLsizei)data.data.size(), data.data.data());
589 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed");
590
591 const auto updateWidth = invalidTexture.width - (i % 2) * blockSize;
592 const auto updateHeight = invalidTexture.height - ((i + 1) % 2) * blockSize;
593 const auto updateDataSize =
594 (updateWidth / blockSize) * (updateHeight / blockSize) * blockDataSize;
595 DE_ASSERT(updateDataSize <= invalidTexture.data.size());
596 context.gl.compressedTexSubImage2D(
597 cubemapFaces[i], 0, 0, 0, (glw::GLsizei)updateWidth, (glw::GLsizei)updateHeight,
598 format, (glw::GLsizei)updateDataSize, invalidTexture.data.data());
599 },
600 GL_NO_ERROR});
601 }
602 }},
603 {
604 gles32, // ApiType minApi;
605 "invalid_width_or_height_array", // string name;
606 "Different values for width and height for cubemap texture target", // string description;
607 1, // size_t texIdsCount;
608 0, // size_t bufferIdsCount;
609 { // vector<ApiCaseStep> steps;
__anon705257c80b02() 610 {[](ApiTestContext &context) { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]); }, GL_NO_ERROR},
611 {[](ApiTestContext &context)
__anon705257c80c02() 612 {
613 context.gl.compressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_COMPRESSED_RGB8_ETC2,
614 invalidTexture.width - 1, invalidTexture.height, 6, 0,
615 (glw::GLsizei)invalidTexture.data.size(), invalidTexture.data.data());
616 },
617 GL_INVALID_VALUE}},
618 DE_NULL, // ApiCaseStepGeneratorFn stepsGenerator;
619 },
620 {gles31, // ApiType minApi;
621 "invalid_size_value_negative", // string name;
622 "Negative width, height or imageSize for compressed texture image", // string description;
623 3, // size_t texIdsCount;
624 0, // size_t bufferIdsCount;
625 {}, // vector<ApiCaseStep> steps;
626 [](deqp::Context &testContext, vector<ApiCaseStep> &steps) // ApiCaseStepGeneratorFn stepsGenerator;
__anon705257c80d02() 627 {
628 auto format = GL_COMPRESSED_RGB8_ETC2;
629 const auto data = loadImage(testContext.getTestContext().getArchive(), format, 0);
630 steps.push_back({[format, data](ApiTestContext &context)
631 {
632 DE_ASSERT(context.texIds.size() >= 3);
633 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
634 context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, -1, 0,
635 (glw::GLsizei)data.data.size(), data.data.data());
636 },
637 GL_INVALID_VALUE});
638 steps.push_back({[format, data](ApiTestContext &context)
639 {
640 context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0,
641 (glw::GLsizei)data.data.size(), data.data.data());
642 },
643 GL_NO_ERROR});
644 steps.push_back({[format, data](ApiTestContext &context)
645 {
646 context.gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, data.width, -1, format,
647 (glw::GLsizei)data.data.size(), data.data.data());
648 },
649 GL_INVALID_VALUE});
650 steps.push_back({[format, data](ApiTestContext &context)
651 {
652 DE_ASSERT(context.texIds.size() >= 3);
653 context.bindTexture(GL_TEXTURE_2D, context.texIds[1]);
654 context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, -276, data.height, 0,
655 (glw::GLsizei)data.data.size(), data.data.data());
656 },
657 GL_INVALID_VALUE});
658 steps.push_back({[format, data](ApiTestContext &context)
659 {
660 context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0,
661 (glw::GLsizei)data.data.size(), data.data.data());
662 },
663 GL_NO_ERROR});
664 steps.push_back({[format, data](ApiTestContext &context)
665 {
666 context.gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, -276, data.height, format,
667 (glw::GLsizei)data.data.size(), data.data.data());
668 },
669 GL_INVALID_VALUE});
670 steps.push_back({[format, data](ApiTestContext &context)
671 {
672 DE_ASSERT(context.texIds.size() >= 3);
673 context.bindTexture(GL_TEXTURE_2D, context.texIds[2]);
674 context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0,
675 -66543, data.data.data());
676 },
677 GL_INVALID_VALUE});
678 steps.push_back({[format, data](ApiTestContext &context)
679 {
680 context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0,
681 (glw::GLsizei)data.data.size(), data.data.data());
682 },
683 GL_NO_ERROR});
684 steps.push_back({[format, data](ApiTestContext &context)
685 {
686 context.gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, data.width, data.height,
687 format, -66543, data.data.data());
688 },
689 GL_INVALID_VALUE});
690 }},
691 {
692 gles31, // ApiType minApi;
693 "invalid_border_nonzero", // string name;
694 "Non zero border values are not supported", // string description;
695 2, // size_t texIdsCount;
696 0, // size_t bufferIdsCount;
697 {
698 // vector<ApiCaseStep> steps;
699 {[](ApiTestContext &context)
__anon705257c81702() 700 {
701 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
702 context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, invalidTexture.width,
703 invalidTexture.height, 1, (glw::GLsizei)invalidTexture.data.size(),
704 invalidTexture.data.data());
705 },
706 GL_INVALID_VALUE},
707 },
708 [](deqp::Context &, vector<ApiCaseStep> &steps) // ApiCaseStepGeneratorFn stepsGenerator;
__anon705257c81802() 709 {
710 for (size_t j = 0; j < DE_LENGTH_OF_ARRAY(cubemapFaces); ++j)
711 steps.push_back({[j](ApiTestContext &context)
712 {
713 context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[1]);
714 context.gl.compressedTexImage2D(cubemapFaces[j], 0, GL_COMPRESSED_RGB8_ETC2,
715 invalidTexture.width, invalidTexture.height, 1,
716 (glw::GLsizei)invalidTexture.data.size(),
717 invalidTexture.data.data());
718 },
719 GL_INVALID_VALUE});
720 },
721 },
722 {
723 gles32, // ApiType minApi;
724 "invalid_border_nonzero_array", // string name;
725 "Non zero border values are not supported", // string description;
726 1, // size_t texIdsCount;
727 0, // size_t bufferIdsCount;
728 {
729 // vector<ApiCaseStep> steps;
730 {[](ApiTestContext &context)
__anon705257c81a02() 731 {
732 context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]);
733 context.gl.compressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_COMPRESSED_RGB8_ETC2,
734 invalidTexture.width, invalidTexture.height, invalidTexture.depth, 1,
735 (glw::GLsizei)invalidTexture.data.size(), invalidTexture.data.data());
736 },
737 GL_INVALID_VALUE},
738 },
739 DE_NULL, // ApiCaseStepGeneratorFn stepsGenerator;
740 },
741 {
742 gles31, // ApiType minApi;
743 "invalid_format_mismatch", // string name;
744 "Subimage format differs from previously specified texture format", // string description;
745 1, // size_t texIdsCount;
746 0, // size_t bufferIdsCount;
747 {
748 // vector<ApiCaseStep> steps;
749 {[](ApiTestContext &context)
__anon705257c81b02() 750 {
751 const auto &gl = context.gl;
752 const auto format0 = GL_COMPRESSED_RGB8_ETC2;
753 const auto data0 = loadImage(context.archive, format0, 0);
754 const auto format1 = GL_COMPRESSED_R11_EAC;
755 const auto data1 = loadImage(context.archive, format1, 0);
756 DE_ASSERT(data0.width == data1.width && data0.height == data1.height);
757
758 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
759
760 gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format0, data0.width, data0.height, 0,
761 (glw::GLsizei)data0.data.size(), data0.data.data());
762 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed");
763 gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, data1.width, data1.height, format1,
764 (glw::GLsizei)data1.data.size(), data1.data.data());
765 },
766 GL_INVALID_OPERATION},
767 },
768 DE_NULL, // ApiCaseStepGeneratorFn stepsGenerator;
769 },
770 {gles31, // ApiType minApi;
771 "invalid_target_3d", // string name;
772 "Invalid texture target for compressed texture", // string description;
773 1, // size_t texIdsCount;
774 0, // size_t bufferIdsCount;
775 {}, // vector<ApiCaseStep> steps;
776 [](deqp::Context &testContext, vector<ApiCaseStep> &steps) // ApiCaseStepGeneratorFn stepsGenerator;
__anon705257c81c02() 777 {
778 for (auto i = 0; i < DE_LENGTH_OF_ARRAY(compressedFormats); ++i)
779 {
780 if (!contextSupports(testContext.getRenderContext().getType(), compressedFormats[i].minApi))
781 continue;
782
783 const auto data =
784 loadImage(testContext.getTestContext().getArchive(), compressedFormats[i].internalFormat, 0);
785 steps.push_back(
786 {[](ApiTestContext &context) { context.bindTexture(GL_TEXTURE_2D, context.texIds[0]); }, GL_NO_ERROR});
787 steps.push_back({[i, data](ApiTestContext &context)
788 {
789 context.gl.compressedTexImage3D(GL_TEXTURE_2D, 0, compressedFormats[i].internalFormat,
790 data.width, data.height, 1, 0,
791 (glw::GLsizei)data.data.size(), data.data.data());
792 },
793 GL_INVALID_ENUM});
794 steps.push_back({[i, data](ApiTestContext &context)
795 {
796 context.gl.compressedTexSubImage3D(GL_TEXTURE_2D, 0, 0, 0, 0, data.width, data.height,
797 1, compressedFormats[i].internalFormat,
798 (glw::GLsizei)data.data.size(), data.data.data());
799 },
800 GL_INVALID_ENUM});
801 }
802 }},
803 {gles31, // ApiType minApi;
804 "texstorage_accepts_compressed_format", // string name;
805 "TexStorage should accept compressed format", // string description;
806 DE_LENGTH_OF_ARRAY(compressedFormats), // size_t texIdsCount;
807 0, // size_t bufferIdsCount;
808 {}, // vector<ApiCaseStep> steps;
809 [](deqp::Context &testContext, vector<ApiCaseStep> &steps) // ApiCaseStepGeneratorFn stepsGenerator;
__anon705257c82002() 810 {
811 for (auto i = 0; i < DE_LENGTH_OF_ARRAY(compressedFormats); ++i)
812 {
813 if (!contextSupports(testContext.getRenderContext().getType(), compressedFormats[i].minApi))
814 continue;
815
816 steps.push_back({[i](ApiTestContext &context)
817 {
818 const auto &gl = context.gl;
819 const size_t textureWidth = 240;
820 const size_t textureHeight = 240;
821 context.bindTexture(GL_TEXTURE_2D, context.texIds[i]);
822 gl.texStorage2D(GL_TEXTURE_2D, 1, compressedFormats[i].internalFormat, textureWidth,
823 textureHeight);
824 },
825 GL_NO_ERROR});
826 }
827 }},
828 {gles31, // ApiType minApi;
829 "invalid_teximage_with_compressed_format", // string name;
830 "TexImage should not accept compressed format", // string description;
831 2, // size_t texIdsCount;
832 0, // size_t bufferIdsCount;
833 {}, // vector<ApiCaseStep> steps;
834 [](deqp::Context &testContext, vector<ApiCaseStep> &steps) // ApiCaseStepGeneratorFn stepsGenerator;
__anon705257c82202() 835 {
836 for (auto i = 0; i < DE_LENGTH_OF_ARRAY(compressedFormats); ++i)
837 {
838 const auto format = compressedFormats[i];
839 if (!contextSupports(testContext.getRenderContext().getType(), format.minApi))
840 continue;
841
842 const auto data = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 0);
843 steps.push_back({[format, data](ApiTestContext &context)
844 {
845 const auto &gl = context.gl;
846 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
847 gl.texImage2D(GL_TEXTURE_2D, 0, format.internalFormat, data.width, data.height, 0,
848 format.format, GL_UNSIGNED_BYTE, data.data.data());
849 },
850 GL_INVALID_VALUE});
851 steps.push_back({[format, data](ApiTestContext &context)
852 {
853 const auto &gl = context.gl;
854 context.bindTexture(GL_TEXTURE_3D, context.texIds[1]);
855 gl.texImage3D(GL_TEXTURE_3D, 0, format.internalFormat, data.width, data.height, 1, 0,
856 format.format, GL_UNSIGNED_BYTE, data.data.data());
857 },
858 GL_INVALID_VALUE});
859 }
860 }},
861 {gles31, // ApiType minApi;
862 "invalid_format", // string name;
863 "Uncompressed internal format for compressed texture", // string description;
864 2, // size_t texIdsCount;
865 0, // size_t bufferIdsCount;
866 { // vector<ApiCaseStep> steps;
__anon705257c82502() 867 {[](ApiTestContext &context) { context.bindTexture(GL_TEXTURE_2D, context.texIds[1]); }, GL_NO_ERROR},
868 {[](ApiTestContext &context)
__anon705257c82602() 869 {
870 context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, invalidTexture.width, invalidTexture.height, 0,
871 (glw::GLsizei)invalidTexture.data.size(), invalidTexture.data.data());
872 },
873 GL_INVALID_ENUM},
874 {[](ApiTestContext &context)
__anon705257c82702() 875 {
876 context.gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, invalidTexture.width, invalidTexture.height,
877 GL_RGB, (glw::GLsizei)invalidTexture.data.size(),
878 invalidTexture.data.data());
879 },
880 GL_INVALID_OPERATION},
881 {[](ApiTestContext &context)
__anon705257c82802() 882 {
883 const GLenum format = GL_COMPRESSED_RGB8_ETC2;
884 const auto data = loadImage(context.archive, format, 0);
885 const auto &gl = context.gl;
886 gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0, (glw::GLsizei)data.data.size(),
887 data.data.data());
888 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed");
889
890 context.gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, invalidTexture.width, invalidTexture.height,
891 GL_RGB, (glw::GLsizei)invalidTexture.data.size(),
892 invalidTexture.data.data());
893 },
894 GL_INVALID_OPERATION},
__anon705257c82902() 895 {[](ApiTestContext &context) { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]); }, GL_NO_ERROR}},
896 [](deqp::Context &, vector<ApiCaseStep> &steps) // ApiCaseStepGeneratorFn stepsGenerator;
__anon705257c82a02() 897 {
898 for (size_t j = 0; j < DE_LENGTH_OF_ARRAY(cubemapFaces); ++j)
899 {
900 steps.push_back({[j](ApiTestContext &context)
901 {
902 context.gl.compressedTexImage2D(
903 cubemapFaces[j], 0, GL_RGB, invalidTexture.width, invalidTexture.height, 0,
904 (glw::GLsizei)invalidTexture.data.size(), invalidTexture.data.data());
905 },
906 GL_INVALID_ENUM});
907 steps.push_back({[j](ApiTestContext &context)
908 {
909 const GLenum format = GL_COMPRESSED_RGB8_ETC2;
910 const auto data = loadImage(context.archive, format, 0);
911 const auto &gl = context.gl;
912 gl.compressedTexImage2D(cubemapFaces[j], 0, format, data.width, data.height, 0,
913 (glw::GLsizei)data.data.size(), data.data.data());
914 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed");
915
916 context.gl.compressedTexSubImage2D(
917 cubemapFaces[j], 0, 0, 0, invalidTexture.width, invalidTexture.height, GL_RGB,
918 (glw::GLsizei)invalidTexture.data.size(), invalidTexture.data.data());
919 },
920 GL_INVALID_OPERATION});
921 }
922 }},
923 {
924 gles32, // ApiType minApi;
925 "invalid_format_array", // string name;
926 "Uncompressed internal format for compressed texture", // string description;
927 1, // size_t texIdsCount;
928 0, // size_t bufferIdsCount;
929 { // vector<ApiCaseStep> steps;
__anon705257c82d02() 930 {[](ApiTestContext &context) { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]); }, GL_NO_ERROR},
931 {[](ApiTestContext &context)
__anon705257c82e02() 932 {
933 context.gl.compressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGB, invalidTexture.width,
934 invalidTexture.height, 6, 0, (glw::GLsizei)invalidTexture.data.size(),
935 invalidTexture.data.data());
936 },
937 GL_INVALID_ENUM},
938 {[](ApiTestContext &context)
__anon705257c82f02() 939 {
940 const GLenum format = GL_COMPRESSED_RGB8_ETC2;
941 const auto data = loadImage(context.archive, format, 0);
942 const auto &gl = context.gl;
943 vector<GLubyte> arrayData;
944 arrayData.reserve(6 * data.data.size());
945 for (size_t k = 0; k < 6; ++k)
946 std::copy(data.data.begin(), data.data.end(), std::back_inserter(arrayData));
947
948 context.gl.compressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, format, data.width, data.height, 6, 0,
949 (glw::GLsizei)arrayData.size(), arrayData.data());
950 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage3D() failed");
951
952 context.gl.compressedTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, invalidTexture.width,
953 invalidTexture.height, 6, GL_RGB,
954 (glw::GLsizei)invalidTexture.data.size(), invalidTexture.data.data());
955 context.gl.compressedTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, invalidTexture.width,
956 invalidTexture.height, 6, GL_RGB,
957 (glw::GLsizei)invalidTexture.data.size(), invalidTexture.data.data());
958 },
959 GL_INVALID_OPERATION}},
960 DE_NULL // ApiCaseStepGeneratorFn stepsGenerator;
961 },
962 {
963 gles31, // ApiType minApi;
964 "invalid_too_small_unpack_buffer", // string name;
965 "Pixel unpack buffer with not enough space for required texture data", // string description;
966 1, // size_t texIdsCount;
967 1, // size_t bufferIdsCount;
968 { // vector<ApiCaseStep> steps;
969 {[](ApiTestContext &context)
__anon705257c83002() 970 {
971 const GLenum format = GL_COMPRESSED_RGB8_ETC2;
972 const auto data = loadImage(context.archive, format, 0);
973 const auto &gl = context.gl;
974
975 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
976 gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, context.bufferIds[0]);
977 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
978 gl.bufferData(GL_PIXEL_UNPACK_BUFFER, data.data.size() / 2, data.data.data(), GL_STATIC_READ);
979 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
980 gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0,
981 (glw::GLsizei)data.data.size(), 0);
982 },
983 GL_INVALID_OPERATION},
984 {[](ApiTestContext &context)
__anon705257c83102() 985 {
986 const GLenum format = GL_COMPRESSED_RGB8_ETC2;
987 const auto data = loadImage(context.archive, format, 0);
988 const auto &gl = context.gl;
989
990 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
991 gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
992 gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format, data.width, data.height, 0,
993 (glw::GLsizei)data.data.size(), data.data.data());
994 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed");
995 gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, context.bufferIds[0]);
996 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
997 gl.bufferData(GL_PIXEL_UNPACK_BUFFER, data.data.size() / 2, data.data.data(), GL_STATIC_READ);
998 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
999 gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, data.width, data.height, format,
1000 (glw::GLsizei)data.data.size(), 0);
1001 },
1002 GL_INVALID_OPERATION}},
1003 DE_NULL // ApiCaseStepGeneratorFn stepsGenerator;
1004 },
1005 {gles31, // ApiType minApi;
1006 "invalid_inconsistent_data_size", // string name;
1007 "Data size is not consistent with texture internal format and dimensions", // string description;
1008 1, // size_t texIdsCount;
1009 0, // size_t bufferIdsCount;
1010 {}, // vector<ApiCaseStep> steps;
1011 [](deqp::Context &testContext, vector<ApiCaseStep> &steps) // ApiCaseStepGeneratorFn stepsGenerator;
__anon705257c83202() 1012 {
1013 for (auto i = 0; i < DE_LENGTH_OF_ARRAY(compressedFormats); ++i)
1014 {
1015 const auto &format = compressedFormats[i];
1016 if (!contextSupports(testContext.getRenderContext().getType(), format.minApi))
1017 continue;
1018
1019 const auto data0 = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 0);
1020 const auto data1 = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 1);
1021
1022 steps.push_back({[format, data0](ApiTestContext &context)
1023 {
1024 const auto &gl = context.gl;
1025 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
1026 gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format.internalFormat, data0.width - 12,
1027 data0.height - 12, 0, (glw::GLsizei)data0.data.size(),
1028 data0.data.data());
1029 },
1030 GL_INVALID_VALUE});
1031 }
1032 }},
1033 {gles32, // ApiType minApi;
1034 "invalid_inconsistent_data_size_array", // string name;
1035 "Data size is not consistent with texture internal format and dimensions", // string description;
1036 2, // size_t texIdsCount;
1037 0, // size_t bufferIdsCount;
1038 {}, // vector<ApiCaseStep> steps;
1039 [](deqp::Context &testContext, vector<ApiCaseStep> &steps) // ApiCaseStepGeneratorFn stepsGenerator;
__anon705257c83402() 1040 {
1041 for (auto i = 0; i < DE_LENGTH_OF_ARRAY(compressedFormats); ++i)
1042 {
1043 const auto &format = compressedFormats[i];
1044 if (!contextSupports(testContext.getRenderContext().getType(), format.minApi))
1045 continue;
1046
1047 const auto data0 = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 0);
1048 const auto data1 = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 1);
1049 steps.push_back({[format, data0](ApiTestContext &context)
1050 { context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[0]); },
1051 GL_NO_ERROR});
1052 for (size_t j = 0; j < DE_LENGTH_OF_ARRAY(cubemapFaces); ++j)
1053 steps.push_back({[j, format, data0](ApiTestContext &context)
1054 {
1055 context.gl.compressedTexImage2D(
1056 cubemapFaces[j], 0, format.internalFormat, data0.width, data0.height, 0,
1057 (glw::GLsizei)data0.data.size(), data0.data.data());
1058 },
1059 GL_NO_ERROR});
1060 steps.push_back({[format, data0](ApiTestContext &context)
1061 {
1062 vector<GLubyte> arrayData;
1063 arrayData.reserve(6 * data0.data.size());
1064 for (size_t k = 0; k < 6; ++k)
1065 std::copy(data0.data.begin(), data0.data.end(), std::back_inserter(arrayData));
1066 context.bindTexture(GL_TEXTURE_CUBE_MAP, context.texIds[1]);
1067 context.gl.compressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, format.internalFormat,
1068 data0.width, data0.height, 6, 0,
1069 (glw::GLsizei)arrayData.size(), arrayData.data());
1070 },
1071 GL_NO_ERROR});
1072 steps.push_back({[format, data1](ApiTestContext &context)
1073 {
1074 context.gl.compressedTexSubImage3D(
1075 GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, data1.width, data1.height, 1,
1076 format.internalFormat, (glw::GLsizei)data1.data.size() - 1, data1.data.data());
1077 },
1078 GL_INVALID_VALUE});
1079 }
1080 }},
1081 {gles31, // ApiType minApi;
1082 "invalid_offset_or_size", // string name;
1083 "Offset or image size not aligned with block size", // string description;
1084 1, // size_t texIdsCount;
1085 0, // size_t bufferIdsCount;
1086 {}, // vector<ApiCaseStep> steps;
1087 [](deqp::Context &testContext, vector<ApiCaseStep> &steps) // ApiCaseStepGeneratorFn stepsGenerator;
__anon705257c83902() 1088 {
1089 for (auto i = 0; i < DE_LENGTH_OF_ARRAY(compressedFormats); ++i)
1090 {
1091 const auto &format = compressedFormats[i];
1092 if (!contextSupports(testContext.getRenderContext().getType(), format.minApi))
1093 continue;
1094
1095 const auto data0 = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 0);
1096 const auto data1 = loadImage(testContext.getTestContext().getArchive(), format.internalFormat, 1);
1097 steps.push_back({[format, data0](ApiTestContext &context)
1098 {
1099 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
1100 context.gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format.internalFormat, data0.width,
1101 data0.height, 0, (glw::GLsizei)data0.data.size(),
1102 data0.data.data());
1103 },
1104 GL_NO_ERROR});
1105 steps.push_back({[format, data1](ApiTestContext &context)
1106 {
1107 context.gl.compressedTexImage2D(GL_TEXTURE_2D, 1, format.internalFormat, data1.width,
1108 data1.height, 0, (glw::GLsizei)data1.data.size(),
1109 data1.data.data());
1110 },
1111 GL_NO_ERROR});
1112 steps.push_back({[format, data1](ApiTestContext &context)
1113 {
1114 context.gl.compressedTexSubImage2D(
1115 GL_TEXTURE_2D, 0, format.blockSize.x() - 2, 0, data1.width, data1.height,
1116 format.internalFormat, (glw::GLsizei)data1.data.size(), data1.data.data());
1117 },
1118 GL_INVALID_OPERATION});
1119 steps.push_back({[format, data1](ApiTestContext &context)
1120 {
1121 context.gl.compressedTexSubImage2D(
1122 GL_TEXTURE_2D, 0, 0, format.blockSize.y() - 2, data1.width, data1.height,
1123 format.internalFormat, (glw::GLsizei)data1.data.size(), data1.data.data());
1124 },
1125 GL_INVALID_OPERATION});
1126 }
1127 }},
1128 {gles32, // ApiType minApi;
1129 "copy_compressed_to_uncompressed", // string name;
1130 "Copying pixels from compressed to uncompressed texture", // string description;
1131 2, // size_t texIdsCount;
1132 0, // size_t bufferIdsCount;
1133 {}, // vector<ApiCaseStep> steps;
1134 [](deqp::Context &, vector<ApiCaseStep> &steps) // ApiCaseStepGeneratorFn stepsGenerator;
__anon705257c83e02() 1135 {
1136 for (const auto &format : copyFormats)
1137 {
1138 if (format.second.empty())
1139 continue;
1140 for (const auto &uncompressedFormat : format.first)
1141 {
1142 for (const auto &compressedFormat : format.second)
1143 {
1144 steps.push_back(
1145 {[uncompressedFormat, compressedFormat](ApiTestContext &context)
1146 {
1147 const auto &gl = context.gl;
1148 const auto &image = imageData.at(compressedFormat);
1149 const auto &unsizedInfo = unsizedFormats.at(uncompressedFormat);
1150 const auto textureData = loadImage(context.archive, compressedFormat, 0);
1151 const auto compressedInfo = find_if(begin(compressedFormats), end(compressedFormats),
1152 [compressedFormat](const FormatInfo &fmt)
1153 { return fmt.internalFormat == compressedFormat; });
1154
1155 DE_ASSERT((GLsizei)textureData.width == image[0].width &&
1156 (GLsizei)textureData.height == image[0].height);
1157 DE_ASSERT(compressedInfo != end(compressedFormats));
1158
1159 const auto targetWidth = image[0].width / compressedInfo->blockSize[0];
1160 const auto targetHeight = image[0].height / compressedInfo->blockSize[1];
1161
1162 context.log << TestLog::Message << "Copying from "
1163 << getTextureFormatStr(compressedFormat).toString() << " " << image[0].width
1164 << "x" << image[0].height << " to "
1165 << getTextureFormatStr(uncompressedFormat).toString() << " " << targetWidth
1166 << "x" << targetHeight << TestLog::EndMessage;
1167
1168 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
1169 gl.texImage2D(GL_TEXTURE_2D, 0, uncompressedFormat, targetWidth, targetHeight, 0,
1170 unsizedInfo.format, unsizedInfo.dataType, 0);
1171 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() failed");
1172 setTextureParameters(context.gl, GL_TEXTURE_2D);
1173
1174 context.bindTexture(GL_TEXTURE_2D, context.texIds[1]);
1175 gl.compressedTexImage2D(GL_TEXTURE_2D, 0, compressedFormat, image[0].width,
1176 image[0].height, 0, (glw::GLsizei)textureData.data.size(),
1177 textureData.data.data());
1178 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed");
1179 setTextureParameters(context.gl, GL_TEXTURE_2D);
1180
1181 context.bindTexture(GL_TEXTURE_2D, 0);
1182
1183 gl.copyImageSubData(context.texIds[1], GL_TEXTURE_2D, 0, 0, 0, 0, context.texIds[0],
1184 GL_TEXTURE_2D, 0, 0, 0, 0, image[0].width, image[0].height, 1);
1185 },
1186 GL_NO_ERROR});
1187 }
1188 }
1189 }
1190 }},
1191 {gles32, // ApiType minApi;
1192 "copy_uncompressed_to_compressed", // string name;
1193 "Copying pixels from uncompressed to compressed texture", // string description;
1194 2, // size_t texIdsCount;
1195 0, // size_t bufferIdsCount;
1196 {}, // vector<ApiCaseStep> steps;
1197 [](deqp::Context &, vector<ApiCaseStep> &steps) // ApiCaseStepGeneratorFn stepsGenerator;
__anon705257c84102() 1198 {
1199 for (const auto &format : copyFormats)
1200 {
1201 if (format.second.empty())
1202 continue;
1203 for (const auto &uncompressedFormat : format.first)
1204 {
1205 for (const auto &compressedFormat : format.second)
1206 {
1207 steps.push_back(
1208 {[uncompressedFormat, compressedFormat](ApiTestContext &context)
1209 {
1210 const auto &gl = context.gl;
1211 const auto &image = imageData.at(compressedFormat);
1212 const auto &unsizedInfo = unsizedFormats.at(uncompressedFormat);
1213 const auto textureData = loadImage(context.archive, compressedFormat, 0);
1214 const auto compressedInfo = find_if(begin(compressedFormats), end(compressedFormats),
1215 [compressedFormat](const FormatInfo &fmt)
1216 { return fmt.internalFormat == compressedFormat; });
1217
1218 DE_ASSERT(compressedInfo != end(compressedFormats));
1219 const auto sourceWidth = image[0].width / compressedInfo->blockSize[0];
1220 const auto sourceHeight = image[0].height / compressedInfo->blockSize[1];
1221
1222 DE_ASSERT((GLsizei)textureData.width == image[0].width &&
1223 (GLsizei)textureData.height == image[0].height);
1224
1225 context.log << TestLog::Message << "Copying from "
1226 << getTextureFormatStr(uncompressedFormat).toString() << " " << sourceWidth
1227 << "x" << sourceHeight << " to "
1228 << getTextureFormatStr(compressedFormat).toString() << " " << image[0].width
1229 << "x" << image[0].height << TestLog::EndMessage;
1230
1231 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
1232 gl.texImage2D(GL_TEXTURE_2D, 0, uncompressedFormat, sourceWidth, sourceHeight, 0,
1233 unsizedInfo.format, unsizedInfo.dataType, 0);
1234 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() failed");
1235 setTextureParameters(context.gl, GL_TEXTURE_2D);
1236
1237 context.bindTexture(GL_TEXTURE_2D, context.texIds[1]);
1238 gl.compressedTexImage2D(GL_TEXTURE_2D, 0, compressedFormat, image[0].width,
1239 image[0].height, 0, (glw::GLsizei)textureData.data.size(),
1240 textureData.data.data());
1241 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed");
1242 setTextureParameters(context.gl, GL_TEXTURE_2D);
1243
1244 context.bindTexture(GL_TEXTURE_2D, 0);
1245 gl.copyImageSubData(context.texIds[0], GL_TEXTURE_2D, 0, 0, 0, 0, context.texIds[1],
1246 GL_TEXTURE_2D, 0, 0, 0, 0, sourceWidth, sourceHeight, 1);
1247 },
1248 GL_NO_ERROR});
1249 }
1250 }
1251 }
1252 }},
1253 {gles32, // ApiType minApi;
1254 "copy_compressed_to_compressed", // string name;
1255 "Copying of pixels between compatible compressed texture formats", // string description;
1256 2, // size_t texIdsCount;
1257 0, // size_t bufferIdsCount;
1258 {}, // vector<ApiCaseStep> steps;
1259 [](deqp::Context &, vector<ApiCaseStep> &steps) // ApiCaseStepGeneratorFn stepsGenerator;
__anon705257c84402() 1260 {
1261 for (const auto &format : copyFormats)
1262 {
1263 if (!format.second.empty())
1264 continue;
1265 for (const auto &format0 : format.first)
1266 {
1267 for (const auto &format1 : format.first)
1268 {
1269 steps.push_back(
1270 {[format0, format1](ApiTestContext &context)
1271 {
1272 const auto &gl = context.gl;
1273 const auto image0 = loadImage(context.archive, format0, 0);
1274 const auto image1 = loadImage(context.archive, format1, 1);
1275
1276 DE_ASSERT(image0.width == 2 * image1.width && image0.height == 2 * image1.height);
1277
1278 context.bindTexture(GL_TEXTURE_2D, context.texIds[0]);
1279 gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format0, image0.width, image0.height, 0,
1280 (glw::GLsizei)image0.data.size(), image0.data.data());
1281 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed");
1282 setTextureParameters(context.gl, GL_TEXTURE_2D);
1283
1284 context.bindTexture(GL_TEXTURE_2D, context.texIds[1]);
1285 gl.compressedTexImage2D(GL_TEXTURE_2D, 0, format1, image1.width, image1.height, 0,
1286 (glw::GLsizei)image1.data.size(), image1.data.data());
1287 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed");
1288 setTextureParameters(context.gl, GL_TEXTURE_2D);
1289
1290 context.bindTexture(GL_TEXTURE_2D, 0);
1291
1292 gl.copyImageSubData(context.texIds[1], GL_TEXTURE_2D, 0, 0, 0, 0, context.texIds[0],
1293 GL_TEXTURE_2D, 0, 0, 0, 0, image1.width, image1.height, 1);
1294 },
1295 GL_NO_ERROR});
1296 }
1297 }
1298 }
1299 }}};
1300
1301 class CompressedApiTest : public deqp::TestCase
1302 {
1303 public:
1304 explicit CompressedApiTest(deqp::Context &context, const ApiCaseParams ¶ms);
1305 virtual ~CompressedApiTest();
1306
1307 virtual void init(void) override;
1308 virtual void deinit(void) override;
1309
1310 virtual IterateResult iterate(void) override;
1311
1312 private:
1313 ApiCaseParams m_params;
1314 vector<GLuint> m_texIds;
1315 vector<GLuint> m_bufferIds;
1316 };
1317
CompressedApiTest(deqp::Context & context,const ApiCaseParams & params)1318 CompressedApiTest::CompressedApiTest(deqp::Context &context, const ApiCaseParams ¶ms)
1319 : deqp::TestCase(context, params.name.c_str(), params.description.c_str())
1320 , m_params(params)
1321 {
1322 }
1323
~CompressedApiTest()1324 CompressedApiTest::~CompressedApiTest()
1325 {
1326 }
1327
init(void)1328 void CompressedApiTest::init(void)
1329 {
1330 const auto &gl = m_context.getRenderContext().getFunctions();
1331 if (m_params.texIdsCount > 0)
1332 {
1333 m_texIds.resize(m_params.texIdsCount);
1334 gl.genTextures((glw::GLsizei)m_texIds.size(), m_texIds.data());
1335 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
1336 m_bufferIds.resize(m_params.bufferIdsCount);
1337 gl.genBuffers((glw::GLsizei)m_bufferIds.size(), m_bufferIds.data());
1338 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
1339 }
1340 }
1341
deinit(void)1342 void CompressedApiTest::deinit(void)
1343 {
1344 const auto &gl = m_context.getRenderContext().getFunctions();
1345 if (!m_bufferIds.empty())
1346 {
1347 gl.deleteBuffers((glw::GLsizei)m_bufferIds.size(), m_bufferIds.data());
1348 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers() failed");
1349 m_bufferIds.erase(m_bufferIds.begin(), m_bufferIds.end());
1350 }
1351 if (!m_texIds.empty())
1352 {
1353 gl.deleteTextures((glw::GLsizei)m_texIds.size(), m_texIds.data());
1354 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() failed");
1355 m_texIds.erase(m_texIds.begin(), m_texIds.end());
1356 }
1357 }
1358
iterate(void)1359 CompressedApiTest::IterateResult CompressedApiTest::iterate(void)
1360 {
1361 const auto &gl = m_context.getRenderContext().getFunctions();
1362 ApiTestContext caseContext = {m_context.getTestContext().getLog(), gl, m_texIds, m_bufferIds,
1363 m_context.getTestContext().getArchive()};
1364 vector<ApiCaseStep> steps(m_params.steps);
1365 if (m_params.stepsGenerator)
1366 m_params.stepsGenerator(m_context, steps);
1367 size_t stepIndex = 0;
1368 for (const auto &step : steps)
1369 {
1370 step.code(caseContext);
1371 const auto errorCode = gl.getError();
1372 if (errorCode != step.expectedError)
1373 {
1374 ostringstream msg;
1375 msg << "Got wrong error code: " << glu::getErrorStr(errorCode)
1376 << ", expected: " << glu::getErrorStr(step.expectedError) << " after step " << stepIndex;
1377 TCU_FAIL(msg.str().c_str());
1378 }
1379 ++stepIndex;
1380 }
1381 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1382 return IterateResult::STOP;
1383 }
1384
1385 class CompressedFormatTest : public deqp::TestCase
1386 {
1387 public:
1388 CompressedFormatTest(deqp::Context &context, shared_ptr<SharedData> data, const FormatInfo &format);
1389 virtual ~CompressedFormatTest();
1390
1391 virtual void init(void);
1392 virtual void deinit(void);
1393 virtual IterateResult iterate(void);
1394
1395 private:
1396 Surface drawTestImage(const glw::Functions &gl, GLuint texId, GLsizei width, GLsizei height);
1397
1398 shared_ptr<SharedData> m_data;
1399 const FormatInfo &formatInfo;
1400 };
1401
CompressedFormatTest(deqp::Context & context,shared_ptr<SharedData> data,const FormatInfo & format)1402 CompressedFormatTest::CompressedFormatTest(deqp::Context &context, shared_ptr<SharedData> data,
1403 const FormatInfo &format)
1404 : deqp::TestCase(context, format.name, "Test rendering of compressed format ")
1405 , m_data(data)
1406 , formatInfo(format)
1407 {
1408 }
1409
~CompressedFormatTest()1410 CompressedFormatTest::~CompressedFormatTest()
1411 {
1412 }
1413
init(void)1414 void CompressedFormatTest::init(void)
1415 {
1416 m_data->init();
1417 }
1418
deinit(void)1419 void CompressedFormatTest::deinit(void)
1420 {
1421 m_data->deinit();
1422 }
1423
drawTestImage(const glw::Functions & gl,GLuint texId,GLsizei width,GLsizei height)1424 Surface CompressedFormatTest::drawTestImage(const glw::Functions &gl, GLuint texId, GLsizei width, GLsizei height)
1425 {
1426 gl.clearColor(1.0f, 0.2f, 1.0f, 1.0f);
1427 gl.clear(GL_COLOR_BUFFER_BIT);
1428 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() failed");
1429
1430 gl.disable(GL_BLEND);
1431 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() failed");
1432
1433 gl.bindTexture(GL_TEXTURE_2D, texId);
1434 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed");
1435
1436 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
1437 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
1438
1439 gl.bindTexture(GL_TEXTURE_2D, 0);
1440 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed");
1441
1442 Surface result(width, height);
1443 readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
1444 return result;
1445 }
1446
iterate(void)1447 CompressedFormatTest::IterateResult CompressedFormatTest::iterate(void)
1448 {
1449 const auto &archive = m_context.getTestContext().getArchive();
1450 const auto image0 = loadImage(archive, formatInfo.internalFormat, 0);
1451 const auto image1 = loadImage(archive, formatInfo.internalFormat, 1);
1452 const auto image2 = loadImage(archive, formatInfo.internalFormat, 2);
1453
1454 DE_ASSERT(image0.width == 2 * image1.width && image0.height == 2 * image1.height && image0.width % 4 == 0 &&
1455 image0.height % 4 == 0 && image0.width == image2.width && image0.height == image2.height);
1456
1457 const auto &gl = m_context.getRenderContext().getFunctions();
1458
1459 GLuint texIds[2];
1460 gl.genTextures(DE_LENGTH_OF_ARRAY(texIds), texIds);
1461 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
1462
1463 GLuint fboId;
1464 gl.genFramebuffers(1, &fboId);
1465 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed");
1466
1467 GLuint rboId;
1468 gl.genRenderbuffers(1, &rboId);
1469 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers() failed");
1470
1471 gl.bindRenderbuffer(GL_RENDERBUFFER, rboId);
1472 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer() failed");
1473
1474 const GLenum bufferFormats[2][2] = {{GL_RGB8, GL_SRGB8_ALPHA8}, {GL_RGBA8, GL_SRGB8_ALPHA8}};
1475 const bool hasAlpha = formatInfo.format == GL_RGBA;
1476 gl.renderbufferStorage(GL_RENDERBUFFER, bufferFormats[hasAlpha][formatInfo.issRGB], image0.width, image0.height);
1477 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage() failed");
1478
1479 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
1480
1481 gl.bindFramebuffer(GL_FRAMEBUFFER, fboId);
1482 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() failed");
1483
1484 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboId);
1485 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer() failed");
1486
1487 gl.viewport(0, 0, image0.width, image0.height);
1488 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed");
1489
1490 gl.useProgram(m_data->programId());
1491 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed");
1492
1493 gl.uniform4fv(m_data->offsetLoc(), 1, defaultOffset.offset.getPtr());
1494 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed");
1495 gl.uniform4fv(m_data->scaleLoc(), 1, defaultOffset.scale.getPtr());
1496 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed");
1497
1498 gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1499 GLU_EXPECT_NO_ERROR(gl.getError(), "glBlendFunc() failed");
1500 gl.disable(GL_BLEND);
1501 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() failed");
1502
1503 // reference image
1504 gl.bindTexture(GL_TEXTURE_2D, texIds[0]);
1505 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed");
1506 gl.texImage2D(GL_TEXTURE_2D, 0, formatInfo.sizedFormat, image2.width, image2.height, 0, formatInfo.format,
1507 GL_UNSIGNED_BYTE, image2.data.data());
1508 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() failed");
1509 setTextureParameters(gl, GL_TEXTURE_2D);
1510
1511 // compressed image
1512 gl.bindTexture(GL_TEXTURE_2D, texIds[1]);
1513 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed");
1514 gl.compressedTexImage2D(GL_TEXTURE_2D, 0, formatInfo.internalFormat, image0.width, image0.height, 0,
1515 (glw::GLsizei)image0.data.size(), image0.data.data());
1516 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D() failed");
1517 gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image1.width, image1.height, formatInfo.internalFormat,
1518 (glw::GLsizei)image1.data.size(), image1.data.data());
1519 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexSubImage2D() failed");
1520 setTextureParameters(gl, GL_TEXTURE_2D);
1521
1522 gl.bindTexture(GL_TEXTURE_2D, 0);
1523 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed");
1524
1525 gl.bindVertexArray(m_data->vaoId());
1526 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed");
1527
1528 gl.useProgram(m_data->programId());
1529 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed");
1530
1531 gl.uniform4fv(m_data->offsetLoc(), 1, defaultOffset.offset.getPtr());
1532 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed");
1533 gl.uniform4fv(m_data->scaleLoc(), 1, defaultOffset.scale.getPtr());
1534 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed");
1535 const auto referenceImage = drawTestImage(gl, texIds[0], image0.width, image0.height);
1536
1537 const auto &offsetIt = offsets.find(formatInfo.internalFormat);
1538 const auto &offset = offsetIt != offsets.end() ? offsetIt->second : defaultOffset;
1539 gl.uniform4fv(m_data->offsetLoc(), 1, offset.offset.getPtr());
1540 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed");
1541 gl.uniform4fv(m_data->scaleLoc(), 1, offset.scale.getPtr());
1542 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() failed");
1543 const auto compressedImage = drawTestImage(gl, texIds[1], image0.width, image0.height);
1544
1545 gl.disable(GL_BLEND);
1546 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() failed");
1547
1548 gl.bindTexture(GL_TEXTURE_2D, 0);
1549 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindtexture() failed");
1550
1551 gl.deleteRenderbuffers(1, &rboId);
1552 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteRenderbuffers() failed");
1553
1554 gl.deleteTextures(DE_LENGTH_OF_ARRAY(texIds), texIds);
1555 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() failed");
1556
1557 gl.deleteFramebuffers(1, &fboId);
1558 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers() failed");
1559
1560 if (!fuzzyCompare(m_testCtx.getLog(), "compressed_vs_uncompressed", "Image comparison result", referenceImage,
1561 compressedImage, 0.0f, CompareLogMode::COMPARE_LOG_ON_ERROR))
1562 TCU_FAIL("Rendered image comparison failed.");
1563
1564 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1565 return IterateResult::STOP;
1566 }
1567
1568 } // namespace
1569
CompressedFormatTests(deqp::Context & context)1570 CompressedFormatTests::CompressedFormatTests(deqp::Context &context)
1571 : deqp::TestCaseGroup(context, "compressed_format", "Tests for compressed image formats")
1572 {
1573 }
1574
~CompressedFormatTests(void)1575 CompressedFormatTests::~CompressedFormatTests(void)
1576 {
1577 }
1578
init(void)1579 void CompressedFormatTests::init(void)
1580 {
1581 const auto apiGroup = new TestCaseGroup(m_context, "api", "Api call return values");
1582 addChild(apiGroup);
1583 for (const auto &apiCase : apiTests)
1584 if (glu::contextSupports(m_context.getRenderContext().getType(), apiCase.minApi))
1585 apiGroup->addChild(new CompressedApiTest(m_context, apiCase));
1586
1587 const auto formatGroup = new TestCaseGroup(m_context, "format", "Compressed format textures");
1588 addChild(formatGroup);
1589 const auto sharedData = make_shared<SharedData>(m_context);
1590 for (const auto &formatInfo : compressedFormats)
1591 if (glu::contextSupports(m_context.getRenderContext().getType(), formatInfo.minApi))
1592 formatGroup->addChild(new CompressedFormatTest(m_context, sharedData, formatInfo));
1593 }
1594
1595 } // namespace glcts
1596