• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file  esextcTextureCubeMapArrayETC2Support.cpp
21  * \brief texture_cube_map_array ETC2 support (Test 10)
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "esextcTextureCubeMapArrayETC2Support.hpp"
25 #include "glcTestCase.hpp"
26 #include "gluDefs.hpp"
27 #include "gluPixelTransfer.hpp"
28 #include "glwEnums.inl"
29 #include "glwTypes.inl"
30 #include "tcuImageCompare.hpp"
31 #include "tcuRenderTarget.hpp"
32 #include "tcuSurface.hpp"
33 #include "tcuTestLog.hpp"
34 
35 namespace glcts
36 {
37 
38 enum TextureSize
39 {
40 	RENDER_WIDTH  = 8,
41 	RENDER_HEIGHT = 8
42 };
43 
44 /** Constructor
45  *
46  * @param context       Test context
47  * @param name          Test case's name
48  * @param description   Test case's description
49  **/
TextureCubeMapArrayETC2Support(Context & context,const ExtParameters & extParams,const char * name,const char * description)50 TextureCubeMapArrayETC2Support::TextureCubeMapArrayETC2Support(Context& context, const ExtParameters& extParams,
51 															   const char* name, const char* description)
52 	: TestCaseBase(context, extParams, name, description), m_fbo(0), m_rbo(0), m_vao(0), m_texture(0), m_program(0)
53 {
54 }
55 
56 /** Deinitializes test
57  *
58  **/
deinit(void)59 void TextureCubeMapArrayETC2Support::deinit(void)
60 {
61 	glcts::TestCaseBase::deinit();
62 }
63 
64 /** @brief Iterate Functional Test cases.
65  *
66  *  @return Iteration result.
67  */
iterate(void)68 tcu::TestCase::IterateResult TextureCubeMapArrayETC2Support::iterate(void)
69 {
70 	prepareFramebuffer();
71 	prepareProgram();
72 	prepareVertexArrayObject();
73 	prepareTexture();
74 	draw();
75 
76 	if (isRenderedImageValid())
77 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
78 	else
79 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
80 
81 	clean();
82 	return STOP;
83 }
84 
85 /** @brief Bind default framebuffer object.
86  *
87  *  @note The function may throw if unexpected error has occured.
88  */
prepareFramebuffer()89 void TextureCubeMapArrayETC2Support::prepareFramebuffer()
90 {
91 	/* Shortcut for GL functionality */
92 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
93 
94 	gl.genRenderbuffers(1, &m_rbo);
95 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
96 
97 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
98 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
99 
100 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, RENDER_WIDTH, RENDER_HEIGHT);
101 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
102 
103 	gl.genFramebuffers(1, &m_fbo);
104 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
105 
106 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
107 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
108 
109 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
110 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
111 }
112 
113 /** @brief Function generate and bind empty vertex array object.
114  *
115  *  @note The function may throw if unexpected error has occured.
116  */
prepareVertexArrayObject()117 void TextureCubeMapArrayETC2Support::prepareVertexArrayObject()
118 {
119 	/* Shortcut for GL functionality */
120 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
121 
122 	gl.genVertexArrays(1, &m_vao);
123 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
124 
125 	gl.bindVertexArray(m_vao);
126 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
127 }
128 
129 /** @brief Function builds test's GLSL program.
130  *         If succeded, the program will be set to be used.
131  *
132  *  @note The function may throw if unexpected error has occured.
133  */
prepareProgram()134 void TextureCubeMapArrayETC2Support::prepareProgram()
135 {
136 	/* Shortcut for GL functionality */
137 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
138 
139 	struct Shader
140 	{
141 		glw::GLchar const* const source;
142 		glw::GLenum const		 type;
143 		glw::GLuint				 id;
144 	} shader[] = { { s_vertex_shader, GL_VERTEX_SHADER, 0 }, { s_fragment_shader, GL_FRAGMENT_SHADER, 0 } };
145 
146 	bool			  programPreparationFailed = false;
147 	glw::GLuint const shader_count			   = sizeof(shader) / sizeof(shader[0]);
148 
149 	/* Create program. */
150 	m_program = gl.createProgram();
151 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
152 
153 	/* Shader compilation. */
154 	for (glw::GLuint i = 0; i < shader_count; ++i)
155 	{
156 		if (DE_NULL != shader[i].source)
157 		{
158 			shader[i].id = gl.createShader(shader[i].type);
159 
160 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
161 
162 			gl.attachShader(m_program, shader[i].id);
163 
164 			GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
165 
166 			glu::ContextType contextType = m_context.getRenderContext().getType();
167 			glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(contextType);
168 			std::string		 shaderSource(glu::getGLSLVersionDeclaration(glslVersion));
169 			shaderSource += shader[i].source;
170 			const char* source = shaderSource.c_str();
171 
172 			gl.shaderSource(shader[i].id, 1, &source, NULL);
173 
174 			GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
175 
176 			gl.compileShader(shader[i].id);
177 
178 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
179 
180 			glw::GLint status = GL_FALSE;
181 
182 			gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
183 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
184 
185 			if (GL_FALSE == status)
186 			{
187 				glw::GLint log_size = 0;
188 				gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
189 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
190 
191 				glw::GLchar* log_text = new glw::GLchar[log_size];
192 
193 				gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
194 
195 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation error, log:\n"
196 													<< log_text << "\n"
197 													<< "Shader source code:\n"
198 													<< shaderSource << "\n"
199 													<< tcu::TestLog::EndMessage;
200 
201 				delete[] log_text;
202 
203 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
204 
205 				programPreparationFailed = true;
206 				break;
207 			}
208 		}
209 	}
210 
211 	if (programPreparationFailed)
212 	{
213 		if (m_program)
214 		{
215 			gl.deleteProgram(m_program);
216 			m_program = 0;
217 		}
218 	}
219 	else
220 	{
221 		/* Link. */
222 		gl.linkProgram(m_program);
223 
224 		GLU_EXPECT_NO_ERROR(gl.getError(), "glLlinkProgram call failed.");
225 
226 		glw::GLint status = GL_FALSE;
227 
228 		gl.getProgramiv(m_program, GL_LINK_STATUS, &status);
229 
230 		if (GL_TRUE == status)
231 		{
232 			for (glw::GLuint i = 0; i < shader_count; ++i)
233 			{
234 				if (shader[i].id)
235 				{
236 					gl.detachShader(m_program, shader[i].id);
237 
238 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
239 				}
240 			}
241 		}
242 		else
243 		{
244 			glw::GLint log_size = 0;
245 
246 			gl.getProgramiv(m_program, GL_INFO_LOG_LENGTH, &log_size);
247 
248 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
249 
250 			glw::GLchar* log_text = new glw::GLchar[log_size];
251 
252 			gl.getProgramInfoLog(m_program, log_size, NULL, &log_text[0]);
253 
254 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
255 												<< log_text << "\n"
256 												<< tcu::TestLog::EndMessage;
257 
258 			delete[] log_text;
259 
260 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
261 
262 			programPreparationFailed = true;
263 		}
264 	}
265 
266 	for (glw::GLuint i = 0; i < shader_count; ++i)
267 	{
268 		if (0 != shader[i].id)
269 		{
270 			gl.deleteShader(shader[i].id);
271 			shader[i].id = 0;
272 		}
273 	}
274 
275 	if (m_program)
276 	{
277 		glw::GLint textureSampler = gl.getUniformLocation(m_program, "texture_sampler");
278 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
279 		gl.useProgram(m_program);
280 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
281 		gl.uniform1i(textureSampler, 0);
282 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i call failed.");
283 	}
284 	else
285 		TCU_FAIL("Failed to prepare program");
286 }
287 
288 /** @brief Function prepares texture object with test's data.
289  *
290  *  @note The function may throw if unexpected error has occured.
291  */
prepareTexture()292 void TextureCubeMapArrayETC2Support::prepareTexture()
293 {
294 	/* Shortcut for GL functionality */
295 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
296 
297 	gl.activeTexture(GL_TEXTURE0);
298 	GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture call failed.");
299 
300 	/* Texture creation and binding. */
301 	gl.genTextures(1, &m_texture);
302 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures call failed.");
303 
304 	const glw::GLuint target = GL_TEXTURE_CUBE_MAP_ARRAY;
305 	gl.bindTexture(target, m_texture);
306 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture call failed.");
307 
308 	/* Uploading texture. */
309 	gl.compressedTexImage3D(target, 0, GL_COMPRESSED_RGB8_ETC2, RENDER_WIDTH, RENDER_HEIGHT, 6, 0,
310 							s_compressed_RGB_texture_data_size, s_compressed_RGB_texture_data);
311 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage3D call failed.");
312 
313 	gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
314 	gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
315 	gl.texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
316 	gl.texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
317 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri call failed.");
318 }
319 
320 /** @brief Function draws a quad.
321  *
322  *  @note The function may throw if unexpected error has occured.
323  */
draw()324 void TextureCubeMapArrayETC2Support::draw()
325 {
326 	/* Shortcut for GL functionality. */
327 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
328 
329 	gl.viewport(0, 0, RENDER_WIDTH, RENDER_HEIGHT);
330 
331 	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
332 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
333 }
334 
335 /** @brief Check if drawn image is same as reference.
336  */
isRenderedImageValid()337 bool TextureCubeMapArrayETC2Support::isRenderedImageValid()
338 {
339 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
340 
341 	/* Construct reference image. */
342 	const tcu::TextureFormat	textureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
343 	tcu::ConstPixelBufferAccess referenceImg(textureFormat, RENDER_WIDTH, RENDER_HEIGHT, 1, s_RGB_texture_data);
344 
345 	/* Read GL image. */
346 	GLubyte				   empty_data[RENDER_WIDTH * RENDER_HEIGHT * 4];
347 	tcu::PixelBufferAccess renderedImg(textureFormat, RENDER_WIDTH, RENDER_HEIGHT, 1, empty_data);
348 	glu::readPixels(m_context.getRenderContext(), 0, 0, renderedImg);
349 	GLU_EXPECT_NO_ERROR(gl.getError(), "glu::readPixels call failed.");
350 
351 	/* Compare images using a big thresholdbecause as compression brings inaccuracy. */
352 	const float compareThreshold = 0.05f;
353 	return tcu::fuzzyCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result", referenceImg, renderedImg,
354 							 compareThreshold, tcu::COMPARE_LOG_RESULT);
355 }
356 
357 /** @brief Release all GL objects.
358  */
clean()359 void TextureCubeMapArrayETC2Support::clean()
360 {
361 	/* Shortcut for GL functionality. */
362 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
363 
364 	if (m_fbo)
365 	{
366 		gl.deleteFramebuffers(1, &m_fbo);
367 		m_fbo = 0;
368 	}
369 
370 	if (m_rbo)
371 	{
372 		gl.deleteRenderbuffers(1, &m_rbo);
373 		m_rbo = 0;
374 	}
375 
376 	if (m_vao)
377 	{
378 		gl.deleteVertexArrays(1, &m_vao);
379 		m_vao = 0;
380 	}
381 
382 	if (m_texture)
383 	{
384 		gl.deleteTextures(1, &m_texture);
385 		m_texture = 0;
386 	}
387 
388 	if (m_program)
389 	{
390 		gl.useProgram(0);
391 		gl.deleteProgram(m_program);
392 		m_program = 0;
393 	}
394 }
395 
396 /* Vertex shader source code. */
397 const glw::GLchar TextureCubeMapArrayETC2Support::s_vertex_shader[] =
398 	"\n"
399 	"out highp vec4 texCoord;\n"
400 	"void main()\n"
401 	"{\n"
402 	"    switch(gl_VertexID)\n"
403 	"    {\n"
404 	"        case 0:\n"
405 	"            gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
406 	"            break;\n"
407 	"        case 1:\n"
408 	"            gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
409 	"            break;\n"
410 	"        case 2:\n"
411 	"            gl_Position = vec4(-1.0,-1.0, 0.0, 1.0);\n"
412 	"            break;\n"
413 	"        case 3:\n"
414 	"            gl_Position = vec4( 1.0,-1.0, 0.0, 1.0);\n"
415 	"            break;\n"
416 	"    }\n"
417 	"    texCoord = vec4(gl_Position.xy, 1.0, 0.0);"
418 	"}\n";
419 
420 /* Fragment shader source program. */
421 const glw::GLchar TextureCubeMapArrayETC2Support::s_fragment_shader[] =
422 	"\n"
423 	"uniform highp samplerCubeArray texture_sampler;\n"
424 	"in highp vec4 texCoord;"
425 	"out highp vec4 color;\n"
426 	"void main()\n"
427 	"{\n"
428 	"    color = texture(texture_sampler, texCoord);\n"
429 	"}\n";
430 
431 /* Texture data, 8x8 RGBA. */
432 const glw::GLubyte TextureCubeMapArrayETC2Support::s_RGB_texture_data[] = {
433 	0, 224,   0, 255, 0, 224,  32, 255, 0, 224,  64, 255, 0, 224,  96, 255,
434 	0, 224, 128, 255, 0, 224, 160, 255, 0, 224, 192, 255, 0, 224, 224, 255,
435 	0, 192,   0, 255, 0, 192,  32, 255, 0, 192,  64, 255, 0, 192,  96, 255,
436 	0, 192, 128, 255, 0, 192, 160, 255, 0, 192, 192, 255, 0, 192, 224, 255,
437 
438 	0, 160,   0, 255, 0, 160,  32, 255, 0, 160,  64, 255, 0, 160,  96, 255,
439 	0, 160, 128, 255, 0, 160, 160, 255, 0, 160, 192, 255, 0, 160, 224, 255,
440 	0, 128,   0, 255, 0, 128,  32, 255, 0, 128,  64, 255, 0, 128,  96, 255,
441 	0, 128, 128, 255, 0, 128, 160, 255, 0, 128, 192, 255, 0, 128, 224, 255,
442 
443 	0,  96,   0, 255, 0,  96,  32, 255, 0,  96,  64, 255, 0,  96,  96, 255,
444 	0,  96, 128, 255, 0,  96, 160, 255, 0,  96, 192, 255, 0,  96, 224, 255,
445 	0,  64,   0, 255, 0,  64,  32, 255, 0,  64,  64, 255, 0,  64,  96, 255,
446 	0,  64, 128, 255, 0,  64, 160, 255, 0,  64, 192, 255, 0,  64, 224, 255,
447 
448 	0,  32,   0, 255, 0,  32,  32, 255, 0,  32,  64, 255, 0,  32,  96, 255,
449 	0,  32, 128, 255, 0,  32, 160, 255, 0,  32, 192, 255, 0,  32, 224, 255,
450 	0,   0,   0, 255, 0,   0,  32, 255, 0,   0,  64, 255, 0,   0,  96, 255,
451 	0,   0, 128, 255, 0,   0, 160, 255, 0,   0, 192, 255, 0,   0, 224, 255,
452 };
453 
454 const glw::GLsizei TextureCubeMapArrayETC2Support::s_RGB_texture_data_size =
455 	sizeof(TextureCubeMapArrayETC2Support::s_RGB_texture_data);
456 
457 /* Compressed texture data 8x8x6 RGB - all layers are the same. */
458 const glw::GLubyte TextureCubeMapArrayETC2Support::s_compressed_RGB_texture_data[] = {
459 	/* Layer 0 */
460 	0x0, 0x0, 0x4, 0x2, 0x1, 0x0, 0x6f, 0xc0, 0x0, 0x1, 0x4, 0x2, 0x1, 0xf8, 0x6f, 0xe0, 0x1, 0x0, 0x4, 0x2, 0x80, 0xf8,
461 	0x5f, 0xc0, 0x1, 0x0, 0xfb, 0x82, 0x81, 0xf8, 0x5f, 0xe0,
462 
463 	/* Layer 1 */
464 	0x0, 0x0, 0x4, 0x2, 0x1, 0x0, 0x6f, 0xc0, 0x0, 0x1, 0x4, 0x2, 0x1, 0xf8, 0x6f, 0xe0, 0x1, 0x0, 0x4, 0x2, 0x80, 0xf8,
465 	0x5f, 0xc0, 0x1, 0x0, 0xfb, 0x82, 0x81, 0xf8, 0x5f, 0xe0,
466 
467 	/* Layer 2 */
468 	0x0, 0x0, 0x4, 0x2, 0x1, 0x0, 0x6f, 0xc0, 0x0, 0x1, 0x4, 0x2, 0x1, 0xf8, 0x6f, 0xe0, 0x1, 0x0, 0x4, 0x2, 0x80, 0xf8,
469 	0x5f, 0xc0, 0x1, 0x0, 0xfb, 0x82, 0x81, 0xf8, 0x5f, 0xe0,
470 
471 	/* Layer 3 */
472 	0x0, 0x0, 0x4, 0x2, 0x1, 0x0, 0x6f, 0xc0, 0x0, 0x1, 0x4, 0x2, 0x1, 0xf8, 0x6f, 0xe0, 0x1, 0x0, 0x4, 0x2, 0x80, 0xf8,
473 	0x5f, 0xc0, 0x1, 0x0, 0xfb, 0x82, 0x81, 0xf8, 0x5f, 0xe0,
474 
475 	/* Layer 4 */
476 	0x0, 0x0, 0x4, 0x2, 0x1, 0x0, 0x6f, 0xc0, 0x0, 0x1, 0x4, 0x2, 0x1, 0xf8, 0x6f, 0xe0, 0x1, 0x0, 0x4, 0x2, 0x80, 0xf8,
477 	0x5f, 0xc0, 0x1, 0x0, 0xfb, 0x82, 0x81, 0xf8, 0x5f, 0xe0,
478 
479 	/* Layer 5 */
480 	0x0, 0x0, 0x4, 0x2, 0x1, 0x0, 0x6f, 0xc0, 0x0, 0x1, 0x4, 0x2, 0x1, 0xf8, 0x6f, 0xe0, 0x1, 0x0, 0x4, 0x2, 0x80, 0xf8,
481 	0x5f, 0xc0, 0x1, 0x0, 0xfb, 0x82, 0x81, 0xf8, 0x5f, 0xe0,
482 };
483 
484 /* Compressed texture width. */
485 const glw::GLsizei TextureCubeMapArrayETC2Support::s_compressed_RGB_texture_data_size =
486 	sizeof(TextureCubeMapArrayETC2Support::s_compressed_RGB_texture_data);
487 
488 } // namespace glcts
489