xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/glcCompressedFormatTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 &gl;
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 &params);
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 &params)
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