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)
53 , m_fbo(0)
54 , m_rbo(0)
55 , m_vao(0)
56 , m_texture(0)
57 , m_program(0)
58 {
59 }
60
61 /** Deinitializes test
62 *
63 **/
deinit(void)64 void TextureCubeMapArrayETC2Support::deinit(void)
65 {
66 glcts::TestCaseBase::deinit();
67 }
68
69 /** @brief Iterate Functional Test cases.
70 *
71 * @return Iteration result.
72 */
iterate(void)73 tcu::TestCase::IterateResult TextureCubeMapArrayETC2Support::iterate(void)
74 {
75 prepareFramebuffer();
76 prepareProgram();
77 prepareVertexArrayObject();
78 prepareTexture();
79 draw();
80
81 if (isRenderedImageValid())
82 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
83 else
84 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
85
86 clean();
87 return STOP;
88 }
89
90 /** @brief Bind default framebuffer object.
91 *
92 * @note The function may throw if unexpected error has occured.
93 */
prepareFramebuffer()94 void TextureCubeMapArrayETC2Support::prepareFramebuffer()
95 {
96 /* Shortcut for GL functionality */
97 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
98
99 gl.genRenderbuffers(1, &m_rbo);
100 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
101
102 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
103 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
104
105 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, RENDER_WIDTH, RENDER_HEIGHT);
106 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
107
108 gl.genFramebuffers(1, &m_fbo);
109 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
110
111 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
112 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
113
114 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
115 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
116 }
117
118 /** @brief Function generate and bind empty vertex array object.
119 *
120 * @note The function may throw if unexpected error has occured.
121 */
prepareVertexArrayObject()122 void TextureCubeMapArrayETC2Support::prepareVertexArrayObject()
123 {
124 /* Shortcut for GL functionality */
125 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
126
127 gl.genVertexArrays(1, &m_vao);
128 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
129
130 gl.bindVertexArray(m_vao);
131 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
132 }
133
134 /** @brief Function builds test's GLSL program.
135 * If succeded, the program will be set to be used.
136 *
137 * @note The function may throw if unexpected error has occured.
138 */
prepareProgram()139 void TextureCubeMapArrayETC2Support::prepareProgram()
140 {
141 /* Shortcut for GL functionality */
142 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
143
144 struct Shader
145 {
146 glw::GLchar const *const source;
147 glw::GLenum const type;
148 glw::GLuint id;
149 } shader[] = {{s_vertex_shader, GL_VERTEX_SHADER, 0}, {s_fragment_shader, GL_FRAGMENT_SHADER, 0}};
150
151 bool programPreparationFailed = false;
152 glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
153
154 /* Create program. */
155 m_program = gl.createProgram();
156 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
157
158 /* Shader compilation. */
159 for (glw::GLuint i = 0; i < shader_count; ++i)
160 {
161 if (DE_NULL != shader[i].source)
162 {
163 shader[i].id = gl.createShader(shader[i].type);
164
165 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
166
167 gl.attachShader(m_program, shader[i].id);
168
169 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
170
171 glu::ContextType contextType = m_context.getRenderContext().getType();
172 glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(contextType);
173 std::string shaderSource(glu::getGLSLVersionDeclaration(glslVersion));
174 shaderSource += shader[i].source;
175 const char *source = shaderSource.c_str();
176
177 gl.shaderSource(shader[i].id, 1, &source, NULL);
178
179 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
180
181 gl.compileShader(shader[i].id);
182
183 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
184
185 glw::GLint status = GL_FALSE;
186
187 gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
188 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
189
190 if (GL_FALSE == status)
191 {
192 glw::GLint log_size = 0;
193 gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
194 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
195
196 glw::GLchar *log_text = new glw::GLchar[log_size];
197
198 gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
199
200 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation error, log:\n"
201 << log_text << "\n"
202 << "Shader source code:\n"
203 << shaderSource << "\n"
204 << tcu::TestLog::EndMessage;
205
206 delete[] log_text;
207
208 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
209
210 programPreparationFailed = true;
211 break;
212 }
213 }
214 }
215
216 if (programPreparationFailed)
217 {
218 if (m_program)
219 {
220 gl.deleteProgram(m_program);
221 m_program = 0;
222 }
223 }
224 else
225 {
226 /* Link. */
227 gl.linkProgram(m_program);
228
229 GLU_EXPECT_NO_ERROR(gl.getError(), "glLlinkProgram call failed.");
230
231 glw::GLint status = GL_FALSE;
232
233 gl.getProgramiv(m_program, GL_LINK_STATUS, &status);
234
235 if (GL_TRUE == status)
236 {
237 for (glw::GLuint i = 0; i < shader_count; ++i)
238 {
239 if (shader[i].id)
240 {
241 gl.detachShader(m_program, shader[i].id);
242
243 GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
244 }
245 }
246 }
247 else
248 {
249 glw::GLint log_size = 0;
250
251 gl.getProgramiv(m_program, GL_INFO_LOG_LENGTH, &log_size);
252
253 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
254
255 glw::GLchar *log_text = new glw::GLchar[log_size];
256
257 gl.getProgramInfoLog(m_program, log_size, NULL, &log_text[0]);
258
259 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
260 << log_text << "\n"
261 << tcu::TestLog::EndMessage;
262
263 delete[] log_text;
264
265 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
266
267 programPreparationFailed = true;
268 }
269 }
270
271 for (glw::GLuint i = 0; i < shader_count; ++i)
272 {
273 if (0 != shader[i].id)
274 {
275 gl.deleteShader(shader[i].id);
276 shader[i].id = 0;
277 }
278 }
279
280 if (m_program)
281 {
282 glw::GLint textureSampler = gl.getUniformLocation(m_program, "texture_sampler");
283 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
284 gl.useProgram(m_program);
285 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
286 gl.uniform1i(textureSampler, 0);
287 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i call failed.");
288 }
289 else
290 TCU_FAIL("Failed to prepare program");
291 }
292
293 /** @brief Function prepares texture object with test's data.
294 *
295 * @note The function may throw if unexpected error has occured.
296 */
prepareTexture()297 void TextureCubeMapArrayETC2Support::prepareTexture()
298 {
299 /* Shortcut for GL functionality */
300 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
301
302 gl.activeTexture(GL_TEXTURE0);
303 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture call failed.");
304
305 /* Texture creation and binding. */
306 gl.genTextures(1, &m_texture);
307 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures call failed.");
308
309 const glw::GLuint target = GL_TEXTURE_CUBE_MAP_ARRAY;
310 gl.bindTexture(target, m_texture);
311 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture call failed.");
312
313 /* Uploading texture. */
314 gl.compressedTexImage3D(target, 0, GL_COMPRESSED_RGB8_ETC2, RENDER_WIDTH, RENDER_HEIGHT, 6, 0,
315 s_compressed_RGB_texture_data_size, s_compressed_RGB_texture_data);
316 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage3D call failed.");
317
318 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
319 gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
320 gl.texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
321 gl.texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
322 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri call failed.");
323 }
324
325 /** @brief Function draws a quad.
326 *
327 * @note The function may throw if unexpected error has occured.
328 */
draw()329 void TextureCubeMapArrayETC2Support::draw()
330 {
331 /* Shortcut for GL functionality. */
332 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
333
334 gl.viewport(0, 0, RENDER_WIDTH, RENDER_HEIGHT);
335
336 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
337 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
338 }
339
340 /** @brief Check if drawn image is same as reference.
341 */
isRenderedImageValid()342 bool TextureCubeMapArrayETC2Support::isRenderedImageValid()
343 {
344 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
345
346 /* Construct reference image. */
347 const tcu::TextureFormat textureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
348 tcu::ConstPixelBufferAccess referenceImg(textureFormat, RENDER_WIDTH, RENDER_HEIGHT, 1, s_RGB_texture_data);
349
350 /* Read GL image. */
351 GLubyte empty_data[RENDER_WIDTH * RENDER_HEIGHT * 4];
352 tcu::PixelBufferAccess renderedImg(textureFormat, RENDER_WIDTH, RENDER_HEIGHT, 1, empty_data);
353 glu::readPixels(m_context.getRenderContext(), 0, 0, renderedImg);
354 GLU_EXPECT_NO_ERROR(gl.getError(), "glu::readPixels call failed.");
355
356 /* Compare images using a big thresholdbecause as compression brings inaccuracy. */
357 const float compareThreshold = 0.05f;
358 return tcu::fuzzyCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result", referenceImg, renderedImg,
359 compareThreshold, tcu::COMPARE_LOG_RESULT);
360 }
361
362 /** @brief Release all GL objects.
363 */
clean()364 void TextureCubeMapArrayETC2Support::clean()
365 {
366 /* Shortcut for GL functionality. */
367 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
368
369 if (m_fbo)
370 {
371 gl.deleteFramebuffers(1, &m_fbo);
372 m_fbo = 0;
373 }
374
375 if (m_rbo)
376 {
377 gl.deleteRenderbuffers(1, &m_rbo);
378 m_rbo = 0;
379 }
380
381 if (m_vao)
382 {
383 gl.deleteVertexArrays(1, &m_vao);
384 m_vao = 0;
385 }
386
387 if (m_texture)
388 {
389 gl.deleteTextures(1, &m_texture);
390 m_texture = 0;
391 }
392
393 if (m_program)
394 {
395 gl.useProgram(0);
396 gl.deleteProgram(m_program);
397 m_program = 0;
398 }
399 }
400
401 /* Vertex shader source code. */
402 const glw::GLchar TextureCubeMapArrayETC2Support::s_vertex_shader[] =
403 "\n"
404 "out highp vec4 texCoord;\n"
405 "void main()\n"
406 "{\n"
407 " switch(gl_VertexID)\n"
408 " {\n"
409 " case 0:\n"
410 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
411 " break;\n"
412 " case 1:\n"
413 " gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
414 " break;\n"
415 " case 2:\n"
416 " gl_Position = vec4(-1.0,-1.0, 0.0, 1.0);\n"
417 " break;\n"
418 " case 3:\n"
419 " gl_Position = vec4( 1.0,-1.0, 0.0, 1.0);\n"
420 " break;\n"
421 " }\n"
422 " texCoord = vec4(gl_Position.xy, 1.0, 0.0);"
423 "}\n";
424
425 /* Fragment shader source program. */
426 const glw::GLchar TextureCubeMapArrayETC2Support::s_fragment_shader[] =
427 "\n"
428 "uniform highp samplerCubeArray texture_sampler;\n"
429 "in highp vec4 texCoord;"
430 "out highp vec4 color;\n"
431 "void main()\n"
432 "{\n"
433 " color = texture(texture_sampler, texCoord);\n"
434 "}\n";
435
436 /* Texture data, 8x8 RGBA. */
437 const glw::GLubyte TextureCubeMapArrayETC2Support::s_RGB_texture_data[] = {
438 0, 224, 0, 255, 0, 224, 32, 255, 0, 224, 64, 255, 0, 224, 96, 255, 0, 224, 128, 255, 0, 224,
439 160, 255, 0, 224, 192, 255, 0, 224, 224, 255, 0, 192, 0, 255, 0, 192, 32, 255, 0, 192, 64, 255,
440 0, 192, 96, 255, 0, 192, 128, 255, 0, 192, 160, 255, 0, 192, 192, 255, 0, 192, 224, 255,
441
442 0, 160, 0, 255, 0, 160, 32, 255, 0, 160, 64, 255, 0, 160, 96, 255, 0, 160, 128, 255, 0, 160,
443 160, 255, 0, 160, 192, 255, 0, 160, 224, 255, 0, 128, 0, 255, 0, 128, 32, 255, 0, 128, 64, 255,
444 0, 128, 96, 255, 0, 128, 128, 255, 0, 128, 160, 255, 0, 128, 192, 255, 0, 128, 224, 255,
445
446 0, 96, 0, 255, 0, 96, 32, 255, 0, 96, 64, 255, 0, 96, 96, 255, 0, 96, 128, 255, 0, 96,
447 160, 255, 0, 96, 192, 255, 0, 96, 224, 255, 0, 64, 0, 255, 0, 64, 32, 255, 0, 64, 64, 255,
448 0, 64, 96, 255, 0, 64, 128, 255, 0, 64, 160, 255, 0, 64, 192, 255, 0, 64, 224, 255,
449
450 0, 32, 0, 255, 0, 32, 32, 255, 0, 32, 64, 255, 0, 32, 96, 255, 0, 32, 128, 255, 0, 32,
451 160, 255, 0, 32, 192, 255, 0, 32, 224, 255, 0, 0, 0, 255, 0, 0, 32, 255, 0, 0, 64, 255,
452 0, 0, 96, 255, 0, 0, 128, 255, 0, 0, 160, 255, 0, 0, 192, 255, 0, 0, 224, 255,
453 };
454
455 const glw::GLsizei TextureCubeMapArrayETC2Support::s_RGB_texture_data_size =
456 sizeof(TextureCubeMapArrayETC2Support::s_RGB_texture_data);
457
458 /* Compressed texture data 8x8x6 RGB - all layers are the same. */
459 const glw::GLubyte TextureCubeMapArrayETC2Support::s_compressed_RGB_texture_data[] = {
460 /* Layer 0 */
461 0x0,
462 0x0,
463 0x4,
464 0x2,
465 0x1,
466 0x0,
467 0x6f,
468 0xc0,
469 0x0,
470 0x1,
471 0x4,
472 0x2,
473 0x1,
474 0xf8,
475 0x6f,
476 0xe0,
477 0x1,
478 0x0,
479 0x4,
480 0x2,
481 0x80,
482 0xf8,
483 0x5f,
484 0xc0,
485 0x1,
486 0x0,
487 0xfb,
488 0x82,
489 0x81,
490 0xf8,
491 0x5f,
492 0xe0,
493
494 /* Layer 1 */
495 0x0,
496 0x0,
497 0x4,
498 0x2,
499 0x1,
500 0x0,
501 0x6f,
502 0xc0,
503 0x0,
504 0x1,
505 0x4,
506 0x2,
507 0x1,
508 0xf8,
509 0x6f,
510 0xe0,
511 0x1,
512 0x0,
513 0x4,
514 0x2,
515 0x80,
516 0xf8,
517 0x5f,
518 0xc0,
519 0x1,
520 0x0,
521 0xfb,
522 0x82,
523 0x81,
524 0xf8,
525 0x5f,
526 0xe0,
527
528 /* Layer 2 */
529 0x0,
530 0x0,
531 0x4,
532 0x2,
533 0x1,
534 0x0,
535 0x6f,
536 0xc0,
537 0x0,
538 0x1,
539 0x4,
540 0x2,
541 0x1,
542 0xf8,
543 0x6f,
544 0xe0,
545 0x1,
546 0x0,
547 0x4,
548 0x2,
549 0x80,
550 0xf8,
551 0x5f,
552 0xc0,
553 0x1,
554 0x0,
555 0xfb,
556 0x82,
557 0x81,
558 0xf8,
559 0x5f,
560 0xe0,
561
562 /* Layer 3 */
563 0x0,
564 0x0,
565 0x4,
566 0x2,
567 0x1,
568 0x0,
569 0x6f,
570 0xc0,
571 0x0,
572 0x1,
573 0x4,
574 0x2,
575 0x1,
576 0xf8,
577 0x6f,
578 0xe0,
579 0x1,
580 0x0,
581 0x4,
582 0x2,
583 0x80,
584 0xf8,
585 0x5f,
586 0xc0,
587 0x1,
588 0x0,
589 0xfb,
590 0x82,
591 0x81,
592 0xf8,
593 0x5f,
594 0xe0,
595
596 /* Layer 4 */
597 0x0,
598 0x0,
599 0x4,
600 0x2,
601 0x1,
602 0x0,
603 0x6f,
604 0xc0,
605 0x0,
606 0x1,
607 0x4,
608 0x2,
609 0x1,
610 0xf8,
611 0x6f,
612 0xe0,
613 0x1,
614 0x0,
615 0x4,
616 0x2,
617 0x80,
618 0xf8,
619 0x5f,
620 0xc0,
621 0x1,
622 0x0,
623 0xfb,
624 0x82,
625 0x81,
626 0xf8,
627 0x5f,
628 0xe0,
629
630 /* Layer 5 */
631 0x0,
632 0x0,
633 0x4,
634 0x2,
635 0x1,
636 0x0,
637 0x6f,
638 0xc0,
639 0x0,
640 0x1,
641 0x4,
642 0x2,
643 0x1,
644 0xf8,
645 0x6f,
646 0xe0,
647 0x1,
648 0x0,
649 0x4,
650 0x2,
651 0x80,
652 0xf8,
653 0x5f,
654 0xc0,
655 0x1,
656 0x0,
657 0xfb,
658 0x82,
659 0x81,
660 0xf8,
661 0x5f,
662 0xe0,
663 };
664
665 /* Compressed texture width. */
666 const glw::GLsizei TextureCubeMapArrayETC2Support::s_compressed_RGB_texture_data_size =
667 sizeof(TextureCubeMapArrayETC2Support::s_compressed_RGB_texture_data);
668
669 } // namespace glcts
670