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