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