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