Add RENDERBUFFER_VALID bit to R8, RG8 definition am: 1d7c8df82e
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / gl / gl4cTextureViewTests.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 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
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23
24 /**
25  * \file  gl4cTextureViewTests.cpp
26  * \brief Implements conformance tests for "texture view" functionality.
27  */ /*-------------------------------------------------------------------*/
28
29 #include "gl4cTextureViewTests.hpp"
30 #include "deFloat16.h"
31 #include "deMath.h"
32 #include "gluContextInfo.hpp"
33 #include "glwFunctions.hpp"
34 #include "tcuFloat.hpp"
35 #include "tcuTestLog.hpp"
36 #include <algorithm>
37
38 /* Type definitions needed to handle GL_R11F_G11F_B10F internal format */
39 typedef tcu::Float<deUint32, 5, 5, 15, 0> Float10;
40 typedef tcu::Float<deUint32, 5, 6, 15, 0> Float11;
41
42 namespace gl4cts
43 {
44 using namespace TextureView;
45
46 /** Stores internalformat->view class associations */
47 const int internalformat_view_compatibility_array[] = {
48         /*      [internalformat]                       [view class]        */
49         GL_RGBA32F, VIEW_CLASS_128_BITS, GL_RGBA32UI, VIEW_CLASS_128_BITS, GL_RGBA32I, VIEW_CLASS_128_BITS, GL_RGB32F,
50         VIEW_CLASS_96_BITS, GL_RGB32UI, VIEW_CLASS_96_BITS, GL_RGB32I, VIEW_CLASS_96_BITS, GL_RGBA16F, VIEW_CLASS_64_BITS,
51         GL_RG32F, VIEW_CLASS_64_BITS, GL_RGBA16UI, VIEW_CLASS_64_BITS, GL_RG32UI, VIEW_CLASS_64_BITS, GL_RGBA16I,
52         VIEW_CLASS_64_BITS, GL_RG32I, VIEW_CLASS_64_BITS, GL_RGBA16, VIEW_CLASS_64_BITS, GL_RGBA16_SNORM,
53         VIEW_CLASS_64_BITS, GL_RGB16, VIEW_CLASS_48_BITS, GL_RGB16_SNORM, VIEW_CLASS_48_BITS, GL_RGB16F, VIEW_CLASS_48_BITS,
54         GL_RGB16UI, VIEW_CLASS_48_BITS, GL_RGB16I, VIEW_CLASS_48_BITS, GL_RG16F, VIEW_CLASS_32_BITS, GL_R11F_G11F_B10F,
55         VIEW_CLASS_32_BITS, GL_R32F, VIEW_CLASS_32_BITS, GL_RGB10_A2UI, VIEW_CLASS_32_BITS, GL_RGBA8UI, VIEW_CLASS_32_BITS,
56         GL_RG16UI, VIEW_CLASS_32_BITS, GL_R32UI, VIEW_CLASS_32_BITS, GL_RGBA8I, VIEW_CLASS_32_BITS, GL_RG16I,
57         VIEW_CLASS_32_BITS, GL_R32I, VIEW_CLASS_32_BITS, GL_RGB10_A2, VIEW_CLASS_32_BITS, GL_RGBA8, VIEW_CLASS_32_BITS,
58         GL_RG16, VIEW_CLASS_32_BITS, GL_RGBA8_SNORM, VIEW_CLASS_32_BITS, GL_RG16_SNORM, VIEW_CLASS_32_BITS, GL_SRGB8_ALPHA8,
59         VIEW_CLASS_32_BITS, GL_RGB9_E5, VIEW_CLASS_32_BITS, GL_RGB8, VIEW_CLASS_24_BITS, GL_RGB8_SNORM, VIEW_CLASS_24_BITS,
60         GL_SRGB8, VIEW_CLASS_24_BITS, GL_RGB8UI, VIEW_CLASS_24_BITS, GL_RGB8I, VIEW_CLASS_24_BITS, GL_R16F,
61         VIEW_CLASS_16_BITS, GL_RG8UI, VIEW_CLASS_16_BITS, GL_R16UI, VIEW_CLASS_16_BITS, GL_RG8I, VIEW_CLASS_16_BITS,
62         GL_R16I, VIEW_CLASS_16_BITS, GL_RG8, VIEW_CLASS_16_BITS, GL_R16, VIEW_CLASS_16_BITS, GL_RG8_SNORM,
63         VIEW_CLASS_16_BITS, GL_R16_SNORM, VIEW_CLASS_16_BITS, GL_R8UI, VIEW_CLASS_8_BITS, GL_R8I, VIEW_CLASS_8_BITS, GL_R8,
64         VIEW_CLASS_8_BITS, GL_R8_SNORM, VIEW_CLASS_8_BITS,
65
66         /* Compressed texture formats. */
67         GL_COMPRESSED_RED_RGTC1, VIEW_CLASS_RGTC1_RED, GL_COMPRESSED_SIGNED_RED_RGTC1, VIEW_CLASS_RGTC1_RED,
68         GL_COMPRESSED_RG_RGTC2, VIEW_CLASS_RGTC2_RG, GL_COMPRESSED_SIGNED_RG_RGTC2, VIEW_CLASS_RGTC2_RG,
69         GL_COMPRESSED_RGBA_BPTC_UNORM, VIEW_CLASS_BPTC_UNORM, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, VIEW_CLASS_BPTC_UNORM,
70         GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, VIEW_CLASS_BPTC_FLOAT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT,
71         VIEW_CLASS_BPTC_FLOAT
72 };
73
74 const int n_internalformat_view_compatibility_array_entries =
75         sizeof(internalformat_view_compatibility_array) / sizeof(internalformat_view_compatibility_array[0]);
76
77 /** Stores all internalformats valid in OpenGL 4.x. Information whether particular internalformat
78  *  can be considered supported can be retrieved by calling TextureViewTests::isInternalformatSupported()
79  *  function.
80  */
81 const glw::GLenum valid_gl_internalformats[] = {
82         /* Section 8.5.1 */
83         GL_RGBA32F,                /* >= GL 4.0 */
84         GL_RGBA32I,                /* >= GL 4.0 */
85         GL_RGBA32UI,       /* >= GL 4.0 */
86         GL_RGBA16,                 /* >= GL 4.0 */
87         GL_RGBA16F,                /* >= GL 4.0 */
88         GL_RGBA16I,                /* >= GL 4.0 */
89         GL_RGBA16UI,       /* >= GL 4.0 */
90         GL_RGBA8,                  /* >= GL 4.0 */
91         GL_RGBA8I,                 /* >= GL 4.0 */
92         GL_RGBA8UI,                /* >= GL 4.0 */
93         GL_SRGB8_ALPHA8,   /* >= GL 4.0 */
94         GL_RGB10_A2,       /* >= GL 4.0 */
95         GL_RGB10_A2UI,   /* >= GL 4.0 */
96         GL_RGB5_A1,                /* >= GL 4.0 */
97         GL_RGBA4,                  /* >= GL 4.0 */
98         GL_R11F_G11F_B10F, /* >= GL 4.0 */
99         GL_RGB565,                 /* >= GL 4.2 */
100         GL_RG32F,                  /* >= GL 4.0 */
101         GL_RG32I,                  /* >= GL 4.0 */
102         GL_RG32UI,                 /* >= GL 4.0 */
103         GL_RG16,                   /* >= GL 4.0 */
104         GL_RG16F,                  /* >= GL 4.0 */
105         GL_RG16I,                  /* >= GL 4.0 */
106         GL_RG16UI,                 /* >= GL 4.0 */
107         GL_RG8,                    /* >= GL 4.0 */
108         GL_RG8I,                   /* >= GL 4.0 */
109         GL_RG8UI,                  /* >= GL 4.0 */
110         GL_R32F,                   /* >= GL 4.0 */
111         GL_R32I,                   /* >= GL 4.0 */
112         GL_R32UI,                  /* >= GL 4.0 */
113         GL_R16F,                   /* >= GL 4.0 */
114         GL_R16I,                   /* >= GL 4.0 */
115         GL_R16UI,                  /* >= GL 4.0 */
116         GL_R16,                    /* >= GL 4.0 */
117         GL_R8,                     /* >= GL 4.0 */
118         GL_R8I,                    /* >= GL 4.0 */
119         GL_R8UI,                   /* >= GL 4.0 */
120         GL_RGBA16_SNORM,   /* >= GL 4.0 */
121         GL_RGBA8_SNORM, /* >= GL 4.0 */
122         GL_RGB32F,                 /* >= GL 4.0 */
123         GL_RGB32I,                 /* >= GL 4.0 */
124         GL_RGB32UI,                /* >= GL 4.0 */
125         GL_RGB16_SNORM, /* >= GL 4.0 */
126         GL_RGB16F,                 /* >= GL 4.0 */
127         GL_RGB16I,                 /* >= GL 4.0 */
128         GL_RGB16UI,                /* >= GL 4.0 */
129         GL_RGB16,                  /* >= GL 4.0 */
130         GL_RGB8_SNORM,   /* >= GL 4.0 */
131         GL_RGB8,                   /* >= GL 4.0 */
132         GL_RGB8I,                  /* >= GL 4.0 */
133         GL_RGB8UI,                 /* >= GL 4.0 */
134         GL_SRGB8,                  /* >= GL 4.0 */
135         GL_RGB9_E5,                /* >= GL 4.0 */
136         GL_RG16_SNORM,   /* >= GL 4.0 */
137         GL_RG8_SNORM,     /* >= GL 4.0 */
138         GL_R16_SNORM,     /* >= GL 4.0 */
139         GL_R8_SNORM,       /* >= GL 4.0 */
140
141         GL_DEPTH_COMPONENT32F, /* >= GL 4.0 */
142         GL_DEPTH_COMPONENT24,  /* >= GL 4.0 */
143         GL_DEPTH_COMPONENT16,  /* >= GL 4.0 */
144
145         GL_DEPTH32F_STENCIL8, /* >= GL 4.0 */
146         GL_DEPTH24_STENCIL8,  /* >= GL 4.0 */
147
148         /* Table 8.14: generic compressed internalformats have been removed */
149         GL_COMPRESSED_RED_RGTC1,                                          /* >= GL 4.0 */
150         GL_COMPRESSED_SIGNED_RED_RGTC1,                           /* >= GL 4.0 */
151         GL_COMPRESSED_RG_RGTC2,                                           /* >= GL 4.0 */
152         GL_COMPRESSED_SIGNED_RG_RGTC2,                            /* >= GL 4.0 */
153         GL_COMPRESSED_RGBA_BPTC_UNORM,                            /* >= GL 4.2 */
154         GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM,              /* >= GL 4.2 */
155         GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT,              /* >= GL 4.2 */
156         GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT,            /* >= GL 4.2 */
157         GL_COMPRESSED_RGB8_ETC2,                                          /* >= GL 4.3 */
158         GL_COMPRESSED_SRGB8_ETC2,                                         /* >= GL 4.3 */
159         GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  /* >= GL 4.3 */
160         GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, /* >= GL 4.3 */
161         GL_COMPRESSED_RGBA8_ETC2_EAC,                             /* >= GL 4.3 */
162         GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,              /* >= GL 4.3 */
163         GL_COMPRESSED_R11_EAC,                                            /* >= GL 4.3 */
164         GL_COMPRESSED_SIGNED_R11_EAC,                             /* >= GL 4.3 */
165         GL_COMPRESSED_RG11_EAC,                                           /* >= GL 4.3 */
166         GL_COMPRESSED_SIGNED_RG11_EAC,                            /* >= GL 4.3 */
167 };
168
169 const int n_valid_gl_internalformats = sizeof(valid_gl_internalformats) / sizeof(valid_gl_internalformats[0]);
170
171 /** An array of texture targets that is used by a number of TextureViewUtilities methods. */
172 static glw::GLenum valid_texture_targets[] = { GL_TEXTURE_1D,
173                                                                                            GL_TEXTURE_1D_ARRAY,
174                                                                                            GL_TEXTURE_2D,
175                                                                                            GL_TEXTURE_2D_ARRAY,
176                                                                                            GL_TEXTURE_2D_MULTISAMPLE,
177                                                                                            GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
178                                                                                            GL_TEXTURE_3D,
179                                                                                            GL_TEXTURE_BUFFER,
180                                                                                            GL_TEXTURE_CUBE_MAP,
181                                                                                            GL_TEXTURE_CUBE_MAP_ARRAY,
182                                                                                            GL_TEXTURE_RECTANGLE };
183 const unsigned int n_valid_texture_targets = sizeof(valid_texture_targets) / sizeof(valid_texture_targets[0]);
184
185 /** Retrieves amount of components defined by user-specified internalformat.
186  *
187  *  This function throws TestError exception if @param internalformat is not recognized.
188  *
189  *  @param internalformat Internalformat to use for the query.
190  *
191  *  @return Requested value.
192  **/
193 unsigned int TextureViewUtilities::getAmountOfComponentsForInternalformat(const glw::GLenum internalformat)
194 {
195         unsigned int result = 0;
196
197         switch (internalformat)
198         {
199         case GL_COMPRESSED_RGBA_BPTC_UNORM:
200         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
201         case GL_RGB10_A2:
202         case GL_RGB10_A2UI:
203         case GL_RGB5_A1:
204         case GL_RGBA16F:
205         case GL_RGBA16I:
206         case GL_RGBA16UI:
207         case GL_RGBA16:
208         case GL_RGBA16_SNORM:
209         case GL_RGBA32F:
210         case GL_RGBA32I:
211         case GL_RGBA32UI:
212         case GL_RGBA4:
213         case GL_RGBA8I:
214         case GL_RGBA8UI:
215         case GL_RGBA8:
216         case GL_RGBA8_SNORM:
217         case GL_SRGB8_ALPHA8:
218         {
219                 result = 4;
220
221                 break;
222         }
223
224         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
225         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
226         case GL_R11F_G11F_B10F:
227         case GL_RGB16_SNORM:
228         case GL_RGB16F:
229         case GL_RGB16I:
230         case GL_RGB16UI:
231         case GL_RGB16:
232         case GL_RGB32F:
233         case GL_RGB32I:
234         case GL_RGB32UI:
235         case GL_RGB565:
236         case GL_RGB8:
237         case GL_RGB8_SNORM:
238         case GL_RGB8I:
239         case GL_RGB8UI:
240         case GL_RGB9_E5:
241         case GL_SRGB8:
242         {
243                 result = 3;
244
245                 break;
246         }
247
248         case GL_COMPRESSED_RG_RGTC2:
249         case GL_COMPRESSED_SIGNED_RG_RGTC2:
250         case GL_RG16:
251         case GL_RG16F:
252         case GL_RG16I:
253         case GL_RG16UI:
254         case GL_RG16_SNORM:
255         case GL_RG32F:
256         case GL_RG32I:
257         case GL_RG32UI:
258         case GL_RG8:
259         case GL_RG8_SNORM:
260         case GL_RG8I:
261         case GL_RG8UI:
262         {
263                 result = 2;
264
265                 break;
266         }
267
268         case GL_COMPRESSED_RED_RGTC1:
269         case GL_COMPRESSED_SIGNED_RED_RGTC1:
270         case GL_DEPTH_COMPONENT16:
271         case GL_DEPTH_COMPONENT24:
272         case GL_DEPTH32F_STENCIL8: /* only one piece of information can be retrieved at a time */
273         case GL_DEPTH24_STENCIL8:  /* only one piece of information can be retrieved at a time */
274         case GL_R16:
275         case GL_R16_SNORM:
276         case GL_R16F:
277         case GL_R16I:
278         case GL_R16UI:
279         case GL_R32F:
280         case GL_R32I:
281         case GL_R32UI:
282         case GL_R8_SNORM:
283         case GL_R8:
284         case GL_R8I:
285         case GL_R8UI:
286         {
287                 result = 1;
288
289                 break;
290         }
291
292         default:
293         {
294                 TCU_FAIL("Unrecognized internalformat");
295         }
296         } /* switch (interalformat) */
297
298         return result;
299 }
300
301 /** Retrieves block size used by user-specified compressed internalformat.
302  *
303  *  Throws TestError exception if @param internalformat is not recognized.
304  *
305  *  @param internalformat Compressed internalformat to use for the query.
306  *
307  *  @return Requested information (in bytes).
308  **/
309 unsigned int TextureViewUtilities::getBlockSizeForCompressedInternalformat(const glw::GLenum internalformat)
310 {
311         unsigned int result = 0;
312
313         switch (internalformat)
314         {
315         case GL_COMPRESSED_RED_RGTC1:
316         case GL_COMPRESSED_SIGNED_RED_RGTC1:
317         {
318                 result = 8;
319
320                 break;
321         }
322
323         case GL_COMPRESSED_RG_RGTC2:
324         case GL_COMPRESSED_SIGNED_RG_RGTC2:
325         case GL_COMPRESSED_RGBA_BPTC_UNORM:
326         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
327         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
328         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
329         {
330                 result = 16;
331
332                 break;
333         }
334
335         default:
336         {
337                 TCU_FAIL("Unrecognized internalformat");
338         }
339         } /* switch (internalformat) */
340
341         return result;
342 }
343
344 /** Retrieves amount of bits used for R/G/B/A components by user-specified
345  *  *non-compressed* internalformat.
346  *
347  *  Throws TestError exception if @param internalformat is not recognized.
348  *
349  *  @param internalformat Internalformat to use for the query. Must not describe
350  *                        compressed internalformat.
351  *  @param out_rgba_size  Must be spacious enough to hold 4 ints. Deref will be
352  *                        used to store requested information for R/G/B/A channels.
353  *                        Must not be NULL.
354  **/
355 void TextureViewUtilities::getComponentSizeForInternalformat(const glw::GLenum internalformat,
356                                                                                                                          unsigned int*   out_rgba_size)
357 {
358         /* Note: Compressed textures are not supported by this function */
359
360         /* Reset all the values before we continue. */
361         memset(out_rgba_size, 0, 4 /* rgba */ * sizeof(unsigned int));
362
363         /* Depending on the user-specified internalformat, update relevant arguments */
364         switch (internalformat)
365         {
366         case GL_RGBA32F:
367         case GL_RGBA32I:
368         case GL_RGBA32UI:
369         {
370                 out_rgba_size[0] = 32;
371                 out_rgba_size[1] = 32;
372                 out_rgba_size[2] = 32;
373                 out_rgba_size[3] = 32;
374
375                 break;
376         }
377
378         case GL_RGBA16F:
379         case GL_RGBA16I:
380         case GL_RGBA16UI:
381         case GL_RGBA16:
382         case GL_RGBA16_SNORM:
383         {
384                 out_rgba_size[0] = 16;
385                 out_rgba_size[1] = 16;
386                 out_rgba_size[2] = 16;
387                 out_rgba_size[3] = 16;
388
389                 break;
390         }
391
392         case GL_RGBA8I:
393         case GL_RGBA8UI:
394         case GL_RGBA8:
395         case GL_RGBA8_SNORM:
396         case GL_SRGB8_ALPHA8:
397         {
398                 out_rgba_size[0] = 8;
399                 out_rgba_size[1] = 8;
400                 out_rgba_size[2] = 8;
401                 out_rgba_size[3] = 8;
402
403                 break;
404         }
405
406         case GL_RGB10_A2:
407         case GL_RGB10_A2UI:
408         {
409                 out_rgba_size[0] = 10;
410                 out_rgba_size[1] = 10;
411                 out_rgba_size[2] = 10;
412                 out_rgba_size[3] = 2;
413
414                 break;
415         }
416
417         case GL_RGB5_A1:
418         {
419                 out_rgba_size[0] = 5;
420                 out_rgba_size[1] = 5;
421                 out_rgba_size[2] = 5;
422                 out_rgba_size[3] = 1;
423
424                 break;
425         }
426
427         case GL_RGBA4:
428         {
429                 out_rgba_size[0] = 4;
430                 out_rgba_size[1] = 4;
431                 out_rgba_size[2] = 4;
432                 out_rgba_size[3] = 4;
433
434                 break;
435         }
436
437         case GL_RGB9_E5:
438         {
439                 out_rgba_size[0] = 9;
440                 out_rgba_size[1] = 9;
441                 out_rgba_size[2] = 9;
442                 out_rgba_size[3] = 5;
443
444                 break;
445         }
446
447         case GL_R11F_G11F_B10F:
448         {
449                 out_rgba_size[0] = 11;
450                 out_rgba_size[1] = 11;
451                 out_rgba_size[2] = 10;
452
453                 break;
454         }
455
456         case GL_RGB565:
457         {
458                 out_rgba_size[0] = 5;
459                 out_rgba_size[1] = 6;
460                 out_rgba_size[2] = 5;
461
462                 break;
463         }
464
465         case GL_RGB32F:
466         case GL_RGB32I:
467         case GL_RGB32UI:
468         {
469                 out_rgba_size[0] = 32;
470                 out_rgba_size[1] = 32;
471                 out_rgba_size[2] = 32;
472
473                 break;
474         }
475
476         case GL_RGB16_SNORM:
477         case GL_RGB16F:
478         case GL_RGB16I:
479         case GL_RGB16UI:
480         case GL_RGB16:
481         {
482                 out_rgba_size[0] = 16;
483                 out_rgba_size[1] = 16;
484                 out_rgba_size[2] = 16;
485
486                 break;
487         }
488
489         case GL_RGB8_SNORM:
490         case GL_RGB8:
491         case GL_RGB8I:
492         case GL_RGB8UI:
493         case GL_SRGB8:
494         {
495                 out_rgba_size[0] = 8;
496                 out_rgba_size[1] = 8;
497                 out_rgba_size[2] = 8;
498
499                 break;
500         }
501
502         case GL_RG32F:
503         case GL_RG32I:
504         case GL_RG32UI:
505         {
506                 out_rgba_size[0] = 32;
507                 out_rgba_size[1] = 32;
508
509                 break;
510         }
511
512         case GL_RG16:
513         case GL_RG16F:
514         case GL_RG16I:
515         case GL_RG16UI:
516         case GL_RG16_SNORM:
517         {
518                 out_rgba_size[0] = 16;
519                 out_rgba_size[1] = 16;
520
521                 break;
522         }
523
524         case GL_RG8:
525         case GL_RG8I:
526         case GL_RG8UI:
527         case GL_RG8_SNORM:
528         {
529                 out_rgba_size[0] = 8;
530                 out_rgba_size[1] = 8;
531
532                 break;
533         }
534
535         case GL_R32F:
536         case GL_R32I:
537         case GL_R32UI:
538         {
539                 out_rgba_size[0] = 32;
540
541                 break;
542         }
543
544         case GL_R16F:
545         case GL_R16I:
546         case GL_R16UI:
547         case GL_R16:
548         case GL_R16_SNORM:
549         case GL_DEPTH_COMPONENT16:
550         {
551                 out_rgba_size[0] = 16;
552
553                 break;
554         }
555
556         case GL_R8:
557         case GL_R8I:
558         case GL_R8UI:
559         case GL_R8_SNORM:
560         {
561                 out_rgba_size[0] = 8;
562
563                 break;
564         }
565
566         case GL_DEPTH_COMPONENT24:
567         {
568                 out_rgba_size[0] = 24;
569
570                 break;
571         }
572
573         case GL_DEPTH32F_STENCIL8:
574         {
575                 out_rgba_size[0] = 32;
576                 out_rgba_size[1] = 8;
577
578                 break;
579         }
580
581         case GL_DEPTH24_STENCIL8:
582         {
583                 out_rgba_size[0] = 24;
584                 out_rgba_size[1] = 8;
585
586                 break;
587         }
588
589         default:
590         {
591                 TCU_FAIL("Unrecognized internalformat");
592         }
593         } /* switch (interalformat) */
594 }
595
596 /** Tells how many bits per components should be used to define input data with
597  *  user-specified type.
598  *
599  *  Throws TestError exception if @param type is not recognized.
600  *
601  *  @param type          Type to use for the query.
602  *  @param out_rgba_size Deref will be used to store requested information. Must
603  *                       not be NULL. Must be capacious enough to hold 4 ints.
604  *
605  **/
606 void TextureViewUtilities::getComponentSizeForType(const glw::GLenum type, unsigned int* out_rgba_size)
607 {
608         memset(out_rgba_size, 0, sizeof(unsigned int) * 4 /* rgba */);
609
610         switch (type)
611         {
612         case GL_BYTE:
613         case GL_UNSIGNED_BYTE:
614         {
615                 out_rgba_size[0] = 8;
616                 out_rgba_size[1] = 8;
617                 out_rgba_size[2] = 8;
618                 out_rgba_size[3] = 8;
619
620                 break;
621         }
622
623         case GL_FLOAT:
624         case GL_UNSIGNED_INT:
625         case GL_INT:
626         {
627                 out_rgba_size[0] = 32;
628                 out_rgba_size[1] = 32;
629                 out_rgba_size[2] = 32;
630                 out_rgba_size[3] = 32;
631
632                 break;
633         }
634
635         case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
636         {
637                 out_rgba_size[0] = 8;
638                 out_rgba_size[1] = 24;
639                 out_rgba_size[2] = 32;
640                 out_rgba_size[3] = 0;
641
642                 break;
643         }
644
645         case GL_HALF_FLOAT:
646         case GL_UNSIGNED_SHORT:
647         case GL_SHORT:
648         {
649                 out_rgba_size[0] = 16;
650                 out_rgba_size[1] = 16;
651                 out_rgba_size[2] = 16;
652                 out_rgba_size[3] = 16;
653
654                 break;
655         }
656
657         case GL_UNSIGNED_INT_10_10_10_2:
658         {
659                 out_rgba_size[0] = 10;
660                 out_rgba_size[1] = 10;
661                 out_rgba_size[2] = 10;
662                 out_rgba_size[3] = 2;
663
664                 break;
665         }
666
667         case GL_UNSIGNED_INT_10F_11F_11F_REV:
668         {
669                 out_rgba_size[0] = 11;
670                 out_rgba_size[1] = 11;
671                 out_rgba_size[2] = 10;
672
673                 break;
674         }
675
676         case GL_UNSIGNED_INT_24_8:
677         {
678                 out_rgba_size[0] = 24;
679                 out_rgba_size[1] = 8;
680                 out_rgba_size[2] = 0;
681                 out_rgba_size[3] = 0;
682
683                 break;
684         }
685
686         case GL_UNSIGNED_INT_2_10_10_10_REV:
687         {
688                 out_rgba_size[0] = 10;
689                 out_rgba_size[1] = 10;
690                 out_rgba_size[2] = 10;
691                 out_rgba_size[3] = 2;
692
693                 break;
694         }
695
696         case GL_UNSIGNED_INT_5_9_9_9_REV:
697         {
698                 out_rgba_size[0] = 9;
699                 out_rgba_size[1] = 9;
700                 out_rgba_size[2] = 9;
701                 out_rgba_size[3] = 5;
702
703                 break;
704         }
705
706         default:
707         {
708                 TCU_FAIL("Unrecognized type");
709         }
710         } /* switch (type) */
711 }
712
713 /** Returns strings naming GL error codes.
714  *
715  *  @param error_code GL error code.
716  *
717  *  @return Requested strings or "[?]" if @param error_code was not
718  *          recognized.
719  **/
720 const char* TextureViewUtilities::getErrorCodeString(const glw::GLint error_code)
721 {
722         switch (error_code)
723         {
724         case GL_INVALID_ENUM:
725                 return "GL_INVALID_ENUM";
726         case GL_INVALID_FRAMEBUFFER_OPERATION:
727                 return "GL_INVALID_FRAMEBUFFER_OPERATION";
728         case GL_INVALID_OPERATION:
729                 return "GL_INVALID_OPERATION";
730         case GL_INVALID_VALUE:
731                 return "GL_INVALID_VALUE";
732         case GL_NO_ERROR:
733                 return "GL_NO_ERROR";
734         case GL_OUT_OF_MEMORY:
735                 return "GL_OUT_OF_MEMORY";
736         case GL_STACK_OVERFLOW:
737                 return "GL_STACK_OVERFLOW";
738         case GL_STACK_UNDERFLOW:
739                 return "GL_STACK_UNDERFLOW";
740         default:
741                 return "[?]";
742         }
743 }
744
745 /** Tells what the format of user-specified internalformat is (eg. whether it's a FP,
746  *  unorm, snorm, etc.). Note: this is NOT the GL-speak format.
747  *
748  *  Supports both compressed and non-compressed internalformats.
749  *  Throws TestError exception if @param internalformat is not recognized.
750  *
751  *  @param internalformat Internalformat to use for the query.
752  *
753  *  @return Requested information.
754  *
755  **/
756 _format TextureViewUtilities::getFormatOfInternalformat(const glw::GLenum internalformat)
757 {
758         _format result = FORMAT_UNDEFINED;
759
760         switch (internalformat)
761         {
762         case GL_COMPRESSED_RG_RGTC2:
763         case GL_COMPRESSED_RGBA_BPTC_UNORM:
764         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
765         case GL_COMPRESSED_RED_RGTC1:
766         case GL_RGBA16:
767         case GL_RGBA4:
768         case GL_RGBA8:
769         case GL_RGB10_A2:
770         case GL_RGB16:
771         case GL_RGB5_A1:
772         case GL_RGB565:
773         case GL_RGB8:
774         case GL_RG16:
775         case GL_RG8:
776         case GL_R16:
777         case GL_R8:
778         case GL_SRGB8:
779         case GL_SRGB8_ALPHA8:
780         {
781                 result = FORMAT_UNORM;
782
783                 break;
784         }
785
786         case GL_COMPRESSED_SIGNED_RED_RGTC1:
787         case GL_COMPRESSED_SIGNED_RG_RGTC2:
788         case GL_RGBA16_SNORM:
789         case GL_RGBA8_SNORM:
790         case GL_RGB16_SNORM:
791         case GL_RGB8_SNORM:
792         case GL_RG16_SNORM:
793         case GL_RG8_SNORM:
794         case GL_R16_SNORM:
795         case GL_R8_SNORM:
796         {
797                 result = FORMAT_SNORM;
798
799                 break;
800         }
801
802         case GL_RGB10_A2UI:
803         case GL_RGBA16UI:
804         case GL_RGBA32UI:
805         case GL_RGBA8UI:
806         case GL_RGB16UI:
807         case GL_RGB32UI:
808         case GL_RGB8UI:
809         case GL_RG16UI:
810         case GL_RG32UI:
811         case GL_RG8UI:
812         case GL_R16UI:
813         case GL_R32UI:
814         case GL_R8UI:
815         {
816                 result = FORMAT_UNSIGNED_INTEGER;
817
818                 break;
819         }
820
821         case GL_RGB9_E5:
822         {
823                 result = FORMAT_RGBE;
824
825                 break;
826         }
827
828         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
829         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
830         case GL_DEPTH_COMPONENT16:
831         case GL_DEPTH_COMPONENT24:
832         case GL_DEPTH_COMPONENT32F:
833         case GL_R11F_G11F_B10F:
834         case GL_RGBA16F:
835         case GL_RGBA32F:
836         case GL_RGB16F:
837         case GL_RGB32F:
838         case GL_RG16F:
839         case GL_RG32F:
840         case GL_R16F:
841         case GL_R32F:
842         {
843                 result = FORMAT_FLOAT;
844
845                 break;
846         }
847
848         case GL_RGBA16I:
849         case GL_RGBA32I:
850         case GL_RGBA8I:
851         case GL_RGB16I:
852         case GL_RGB32I:
853         case GL_RGB8I:
854         case GL_RG16I:
855         case GL_RG32I:
856         case GL_RG8I:
857         case GL_R16I:
858         case GL_R32I:
859         case GL_R8I:
860         {
861                 result = FORMAT_SIGNED_INTEGER;
862
863                 break;
864         }
865
866         default:
867         {
868                 TCU_FAIL("Unrecognized internalformat");
869         }
870         } /* switch (interalformat) */
871
872         return result;
873 }
874
875 /** Returns GL format that is compatible with user-specified internalformat.
876  *
877  *  Throws TestError exception if @param internalformat is not recognized.
878  *
879  *  @param internalformat Internalformat to use for the query.
880  *
881  *  @return Requested information.
882  **/
883 glw::GLenum TextureViewUtilities::getGLFormatOfInternalformat(const glw::GLenum internalformat)
884 {
885         glw::GLenum result = FORMAT_UNDEFINED;
886
887         switch (internalformat)
888         {
889         case GL_COMPRESSED_RGBA_BPTC_UNORM:
890         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
891         case GL_COMPRESSED_RGBA8_ETC2_EAC:
892         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
893         case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
894         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
895         {
896                 result = GL_COMPRESSED_RGBA;
897
898                 break;
899         }
900
901         case GL_RGB10_A2:
902         case GL_RGB5_A1:
903         case GL_RGBA16:
904         case GL_RGBA16F:
905         case GL_RGBA16_SNORM:
906         case GL_RGBA32F:
907         case GL_RGBA4:
908         case GL_RGBA8:
909         case GL_RGBA8_SNORM:
910         case GL_SRGB8_ALPHA8:
911         {
912                 result = GL_RGBA;
913
914                 break;
915         }
916
917         case GL_RGB10_A2UI:
918         case GL_RGBA16I:
919         case GL_RGBA16UI:
920         case GL_RGBA32I:
921         case GL_RGBA32UI:
922         case GL_RGBA8I:
923         case GL_RGBA8UI:
924         {
925                 result = GL_RGBA_INTEGER;
926
927                 break;
928         }
929
930         case GL_COMPRESSED_RGB8_ETC2:
931         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
932         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
933         case GL_COMPRESSED_SRGB8_ETC2:
934         {
935                 result = GL_COMPRESSED_RGB;
936
937                 break;
938         }
939
940         case GL_R11F_G11F_B10F:
941         case GL_RGB16:
942         case GL_RGB16_SNORM:
943         case GL_RGB16F:
944         case GL_RGB32F:
945         case GL_RGB565:
946         case GL_RGB8:
947         case GL_RGB8_SNORM:
948         case GL_RGB9_E5:
949         case GL_SRGB8:
950         {
951                 result = GL_RGB;
952
953                 break;
954         }
955
956         case GL_RGB16I:
957         case GL_RGB16UI:
958         case GL_RGB32I:
959         case GL_RGB32UI:
960         case GL_RGB8I:
961         case GL_RGB8UI:
962         {
963                 result = GL_RGB_INTEGER;
964
965                 break;
966         }
967
968         case GL_COMPRESSED_RG_RGTC2:
969         case GL_COMPRESSED_RG11_EAC:
970         case GL_COMPRESSED_SIGNED_RG_RGTC2:
971         case GL_COMPRESSED_SIGNED_RG11_EAC:
972         {
973                 result = GL_COMPRESSED_RG;
974
975                 break;
976         }
977
978         case GL_RG16:
979         case GL_RG16_SNORM:
980         case GL_RG16F:
981         case GL_RG32F:
982         case GL_RG8:
983         case GL_RG8_SNORM:
984         {
985                 result = GL_RG;
986
987                 break;
988         }
989
990         case GL_RG16I:
991         case GL_RG16UI:
992         case GL_RG32I:
993         case GL_RG32UI:
994         case GL_RG8I:
995         case GL_RG8UI:
996         {
997                 result = GL_RG_INTEGER;
998
999                 break;
1000         }
1001
1002         case GL_COMPRESSED_R11_EAC:
1003         case GL_COMPRESSED_RED_RGTC1:
1004         case GL_COMPRESSED_SIGNED_R11_EAC:
1005         case GL_COMPRESSED_SIGNED_RED_RGTC1:
1006         {
1007                 result = GL_COMPRESSED_RED;
1008
1009                 break;
1010         }
1011
1012         case GL_R16:
1013         case GL_R16F:
1014         case GL_R16_SNORM:
1015         case GL_R32F:
1016         case GL_R8:
1017         case GL_R8_SNORM:
1018         {
1019                 result = GL_RED;
1020
1021                 break;
1022         }
1023
1024         case GL_R16I:
1025         case GL_R16UI:
1026         case GL_R32I:
1027         case GL_R32UI:
1028         case GL_R8I:
1029         case GL_R8UI:
1030         {
1031                 result = GL_RED_INTEGER;
1032
1033                 break;
1034         }
1035
1036         case GL_DEPTH_COMPONENT16:
1037         case GL_DEPTH_COMPONENT24:
1038         case GL_DEPTH_COMPONENT32F:
1039         {
1040                 result = GL_DEPTH_COMPONENT;
1041
1042                 break;
1043         }
1044
1045         case GL_DEPTH24_STENCIL8:
1046         case GL_DEPTH32F_STENCIL8:
1047         {
1048                 result = GL_DEPTH_STENCIL;
1049
1050                 break;
1051         }
1052
1053         default:
1054         {
1055                 TCU_FAIL("Unrecognized internalformat");
1056         }
1057         } /* switch (internalformat) */
1058
1059         return result;
1060 }
1061
1062 /** Returns a string that corresponds to a GLSL type that can act as input to user-specified
1063  *  sampler type, and which can hold user-specified amount of components.
1064  *
1065  *  Throws TestError exception if either of the arguments was found invalid.
1066  *
1067  *  @param sampler_type Type of the sampler to use for the query.
1068  *  @param n_components Amount of components to use for the query.
1069  *
1070  *  @return Requested string.
1071  **/
1072 const char* TextureViewUtilities::getGLSLDataTypeForSamplerType(const _sampler_type sampler_type,
1073                                                                                                                                 const unsigned int  n_components)
1074 {
1075         const char* result = "";
1076
1077         switch (sampler_type)
1078         {
1079         case SAMPLER_TYPE_FLOAT:
1080         {
1081                 switch (n_components)
1082                 {
1083                 case 1:
1084                         result = "float";
1085                         break;
1086                 case 2:
1087                         result = "vec2";
1088                         break;
1089                 case 3:
1090                         result = "vec3";
1091                         break;
1092                 case 4:
1093                         result = "vec4";
1094                         break;
1095
1096                 default:
1097                 {
1098                         TCU_FAIL("Unsupported number of components");
1099                 }
1100                 } /* switch (n_components) */
1101
1102                 break;
1103         }
1104
1105         case SAMPLER_TYPE_SIGNED_INTEGER:
1106         {
1107                 switch (n_components)
1108                 {
1109                 case 1:
1110                         result = "int";
1111                         break;
1112                 case 2:
1113                         result = "ivec2";
1114                         break;
1115                 case 3:
1116                         result = "ivec3";
1117                         break;
1118                 case 4:
1119                         result = "ivec4";
1120                         break;
1121
1122                 default:
1123                 {
1124                         TCU_FAIL("Unsupported number of components");
1125                 }
1126                 } /* switch (n_components) */
1127
1128                 break;
1129         }
1130
1131         case SAMPLER_TYPE_UNSIGNED_INTEGER:
1132         {
1133                 switch (n_components)
1134                 {
1135                 case 1:
1136                         result = "uint";
1137                         break;
1138                 case 2:
1139                         result = "uvec2";
1140                         break;
1141                 case 3:
1142                         result = "uvec3";
1143                         break;
1144                 case 4:
1145                         result = "uvec4";
1146                         break;
1147
1148                 default:
1149                 {
1150                         TCU_FAIL("Unsupported number of components");
1151                 }
1152                 } /* switch (n_components) */
1153
1154                 break;
1155         }
1156
1157         default:
1158         {
1159                 TCU_FAIL("Unrecognized sampler type");
1160         }
1161         } /* switch (sampler_type) */
1162
1163         return result;
1164 }
1165
1166 /** Retrieves a string defining a sampler type in GLSL which corresponds to user-specified internal
1167  *  sampler type.
1168  *
1169  *  Throws TestError exception if @param sampler_type was not recognized.
1170  *
1171  *  @param sampler_type Internal sampler type to use for the query.
1172  *
1173  *  @return Requested string.
1174  **/
1175 const char* TextureViewUtilities::getGLSLTypeForSamplerType(const _sampler_type sampler_type)
1176 {
1177         const char* result = "";
1178
1179         switch (sampler_type)
1180         {
1181         case SAMPLER_TYPE_FLOAT:
1182                 result = "sampler2D";
1183                 break;
1184         case SAMPLER_TYPE_SIGNED_INTEGER:
1185                 result = "isampler2D";
1186                 break;
1187         case SAMPLER_TYPE_UNSIGNED_INTEGER:
1188                 result = "usampler2D";
1189                 break;
1190
1191         default:
1192         {
1193                 TCU_FAIL("Unrecognized sampler type");
1194         }
1195         } /* switch (sampler_type) */
1196
1197         return result;
1198 }
1199
1200 /** Returns a vector of texture+view internalformat combinations that are known to be incompatible.
1201  *
1202  *  @return Requested information.
1203  **/
1204 TextureViewUtilities::_incompatible_internalformat_pairs TextureViewUtilities::
1205         getIllegalTextureAndViewInternalformatCombinations()
1206 {
1207         TextureViewUtilities::_incompatible_internalformat_pairs result;
1208
1209         /* Iterate in two loops over the set of supported internalformats */
1210         for (int n_texture_internalformat = 0;
1211                  n_texture_internalformat <
1212                  (n_internalformat_view_compatibility_array_entries / 2); /* the array stores two values per entry */
1213                  ++n_texture_internalformat)
1214         {
1215                 glw::GLenum src_internalformat = internalformat_view_compatibility_array[(n_texture_internalformat * 2) + 0];
1216                 _view_class src_view_class =
1217                         (_view_class)internalformat_view_compatibility_array[(n_texture_internalformat * 2) + 1];
1218
1219                 for (int n_view_internalformat = n_texture_internalformat + 1;
1220                          n_view_internalformat < (n_internalformat_view_compatibility_array_entries >> 1); ++n_view_internalformat)
1221                 {
1222                         glw::GLenum view_internalformat = internalformat_view_compatibility_array[(n_view_internalformat * 2) + 0];
1223                         _view_class view_view_class =
1224                                 (_view_class)internalformat_view_compatibility_array[(n_view_internalformat * 2) + 1];
1225
1226                         if (src_view_class != view_view_class)
1227                         {
1228                                 result.push_back(_internalformat_pair(src_internalformat, view_internalformat));
1229                         }
1230                 } /* for (all internalformats we can use for the texture view) */
1231         }        /* for (all internalformats we can use for the parent texture) */
1232
1233         return result;
1234 }
1235
1236 /** Returns a vector of texture+view target texture combinations that are known to be incompatible.
1237  *
1238  *  @return Requested information.
1239  **/
1240 TextureViewUtilities::_incompatible_texture_target_pairs TextureViewUtilities::
1241         getIllegalTextureAndViewTargetCombinations()
1242 {
1243         _incompatible_texture_target_pairs result;
1244
1245         /* Iterate through all combinations of texture targets and store those that are
1246          * reported as invalid
1247          */
1248         for (unsigned int n_parent_texture_target = 0; n_parent_texture_target < n_valid_texture_targets;
1249                  ++n_parent_texture_target)
1250         {
1251                 glw::GLenum parent_texture_target = valid_texture_targets[n_parent_texture_target];
1252
1253                 for (unsigned int n_view_texture_target = 0; n_view_texture_target < n_valid_texture_targets;
1254                          ++n_view_texture_target)
1255                 {
1256                         glw::GLenum view_texture_target = valid_texture_targets[n_view_texture_target];
1257
1258                         if (!isLegalTextureTargetForTextureView(parent_texture_target, view_texture_target))
1259                         {
1260                                 result.push_back(_internalformat_pair(parent_texture_target, view_texture_target));
1261                         }
1262                 } /* for (all texture targets considered for views) */
1263         }        /* for (all texture targets considered for parent texture) */
1264
1265         return result;
1266 }
1267
1268 /** Returns internalformats associated with user-specified view class.
1269  *
1270  *  @param view_class View class to use for the query.
1271  *
1272  *  @return Requested information.
1273  **/
1274 TextureViewUtilities::_internalformats TextureViewUtilities::getInternalformatsFromViewClass(_view_class view_class)
1275 {
1276         _internalformats result;
1277
1278         /* Iterate over the data array and push those internalformats that match the requested view class */
1279         const unsigned int n_array_elements = n_internalformat_view_compatibility_array_entries;
1280
1281         for (unsigned int n_array_pair = 0; n_array_pair < (n_array_elements >> 1); ++n_array_pair)
1282         {
1283                 const glw::GLenum internalformat = internalformat_view_compatibility_array[n_array_pair * 2 + 0];
1284                 const _view_class current_view_class =
1285                         (_view_class)internalformat_view_compatibility_array[n_array_pair * 2 + 1];
1286
1287                 if (current_view_class == view_class)
1288                 {
1289                         result.push_back(internalformat);
1290                 }
1291         } /* for (all pairs in the data array) */
1292
1293         return result;
1294 }
1295
1296 /** Returns a string defining user-specified internalformat.
1297  *
1298  *  Throws a TestError exception if @param internalformat was not recognized.
1299  *
1300  *  @param internalformat Internalformat to use for the query.
1301  *
1302  *  @return Requested string.
1303  **/
1304 const char* TextureViewUtilities::getInternalformatString(const glw::GLenum internalformat)
1305 {
1306         const char* result = "[?]";
1307
1308         switch (internalformat)
1309         {
1310         case GL_RGBA32F:
1311                 result = "GL_RGBA32F";
1312                 break;
1313         case GL_RGBA32I:
1314                 result = "GL_RGBA32I";
1315                 break;
1316         case GL_RGBA32UI:
1317                 result = "GL_RGBA32UI";
1318                 break;
1319         case GL_RGBA16:
1320                 result = "GL_RGBA16";
1321                 break;
1322         case GL_RGBA16F:
1323                 result = "GL_RGBA16F";
1324                 break;
1325         case GL_RGBA16I:
1326                 result = "GL_RGBA16I";
1327                 break;
1328         case GL_RGBA16UI:
1329                 result = "GL_RGBA16UI";
1330                 break;
1331         case GL_RGBA8:
1332                 result = "GL_RGBA8";
1333                 break;
1334         case GL_RGBA8I:
1335                 result = "GL_RGBA8I";
1336                 break;
1337         case GL_RGBA8UI:
1338                 result = "GL_RGBA8UI";
1339                 break;
1340         case GL_SRGB8_ALPHA8:
1341                 result = "GL_SRGB8_ALPHA8";
1342                 break;
1343         case GL_RGB10_A2:
1344                 result = "GL_RGB10_A2";
1345                 break;
1346         case GL_RGB10_A2UI:
1347                 result = "GL_RGB10_A2UI";
1348                 break;
1349         case GL_RGB5_A1:
1350                 result = "GL_RGB5_A1";
1351                 break;
1352         case GL_RGBA4:
1353                 result = "GL_RGBA4";
1354                 break;
1355         case GL_R11F_G11F_B10F:
1356                 result = "GL_R11F_G11F_B10F";
1357                 break;
1358         case GL_RGB565:
1359                 result = "GL_RGB565";
1360                 break;
1361         case GL_RG32F:
1362                 result = "GL_RG32F";
1363                 break;
1364         case GL_RG32I:
1365                 result = "GL_RG32I";
1366                 break;
1367         case GL_RG32UI:
1368                 result = "GL_RG32UI";
1369                 break;
1370         case GL_RG16:
1371                 result = "GL_RG16";
1372                 break;
1373         case GL_RG16F:
1374                 result = "GL_RG16F";
1375                 break;
1376         case GL_RG16I:
1377                 result = "GL_RG16I";
1378                 break;
1379         case GL_RG16UI:
1380                 result = "GL_RG16UI";
1381                 break;
1382         case GL_RG8:
1383                 result = "GL_RG8";
1384                 break;
1385         case GL_RG8I:
1386                 result = "GL_RG8I";
1387                 break;
1388         case GL_RG8UI:
1389                 result = "GL_RG8UI";
1390                 break;
1391         case GL_R32F:
1392                 result = "GL_R32F";
1393                 break;
1394         case GL_R32I:
1395                 result = "GL_R32I";
1396                 break;
1397         case GL_R32UI:
1398                 result = "GL_R32UI";
1399                 break;
1400         case GL_R16F:
1401                 result = "GL_R16F";
1402                 break;
1403         case GL_R16I:
1404                 result = "GL_R16I";
1405                 break;
1406         case GL_R16UI:
1407                 result = "GL_R16UI";
1408                 break;
1409         case GL_R16:
1410                 result = "GL_R16";
1411                 break;
1412         case GL_R8:
1413                 result = "GL_R8";
1414                 break;
1415         case GL_R8I:
1416                 result = "GL_R8I";
1417                 break;
1418         case GL_R8UI:
1419                 result = "GL_R8UI";
1420                 break;
1421         case GL_RGBA16_SNORM:
1422                 result = "GL_RGBA16_SNORM";
1423                 break;
1424         case GL_RGBA8_SNORM:
1425                 result = "GL_RGBA8_SNORM";
1426                 break;
1427         case GL_RGB32F:
1428                 result = "GL_RGB32F";
1429                 break;
1430         case GL_RGB32I:
1431                 result = "GL_RGB32I";
1432                 break;
1433         case GL_RGB32UI:
1434                 result = "GL_RGB32UI";
1435                 break;
1436         case GL_RGB16_SNORM:
1437                 result = "GL_RGB16_SNORM";
1438                 break;
1439         case GL_RGB16F:
1440                 result = "GL_RGB16F";
1441                 break;
1442         case GL_RGB16I:
1443                 result = "GL_RGB16I";
1444                 break;
1445         case GL_RGB16UI:
1446                 result = "GL_RGB16UI";
1447                 break;
1448         case GL_RGB16:
1449                 result = "GL_RGB16";
1450                 break;
1451         case GL_RGB8_SNORM:
1452                 result = "GL_RGB8_SNORM";
1453                 break;
1454         case GL_RGB8:
1455                 result = "GL_RGB8";
1456                 break;
1457         case GL_RGB8I:
1458                 result = "GL_RGB8I";
1459                 break;
1460         case GL_RGB8UI:
1461                 result = "GL_RGB8UI";
1462                 break;
1463         case GL_SRGB8:
1464                 result = "GL_SRGB8";
1465                 break;
1466         case GL_RGB9_E5:
1467                 result = "GL_RGB9_E5";
1468                 break;
1469         case GL_RG16_SNORM:
1470                 result = "GL_RG16_SNORM";
1471                 break;
1472         case GL_RG8_SNORM:
1473                 result = "GL_RG8_SNORM";
1474                 break;
1475         case GL_R16_SNORM:
1476                 result = "GL_R16_SNORM";
1477                 break;
1478         case GL_R8_SNORM:
1479                 result = "GL_R8_SNORM";
1480                 break;
1481         case GL_DEPTH_COMPONENT32F:
1482                 result = "GL_DEPTH_COMPONENT32F";
1483                 break;
1484         case GL_DEPTH_COMPONENT24:
1485                 result = "GL_DEPTH_COMPONENT24";
1486                 break;
1487         case GL_DEPTH_COMPONENT16:
1488                 result = "GL_DEPTH_COMPONENT16";
1489                 break;
1490         case GL_DEPTH32F_STENCIL8:
1491                 result = "GL_DEPTH32F_STENCIL8";
1492                 break;
1493         case GL_DEPTH24_STENCIL8:
1494                 result = "GL_DEPTH24_STENCIL8";
1495                 break;
1496         case GL_COMPRESSED_RED_RGTC1:
1497                 result = "GL_COMPRESSED_RED_RGTC1";
1498                 break;
1499         case GL_COMPRESSED_SIGNED_RED_RGTC1:
1500                 result = "GL_COMPRESSED_SIGNED_RED_RGTC1";
1501                 break;
1502         case GL_COMPRESSED_RG_RGTC2:
1503                 result = "GL_COMPRESSED_RG_RGTC2";
1504                 break;
1505         case GL_COMPRESSED_SIGNED_RG_RGTC2:
1506                 result = "GL_COMPRESSED_SIGNED_RG_RGTC2";
1507                 break;
1508         case GL_COMPRESSED_RGBA_BPTC_UNORM:
1509                 result = "GL_COMPRESSED_RGBA_BPTC_UNORM";
1510                 break;
1511         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
1512                 result = "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM";
1513                 break;
1514         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
1515                 result = "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT";
1516                 break;
1517         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
1518                 result = "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT";
1519                 break;
1520         case GL_COMPRESSED_RGB8_ETC2:
1521                 result = "GL_COMPRESSED_RGB8_ETC2";
1522                 break;
1523         case GL_COMPRESSED_SRGB8_ETC2:
1524                 result = "GL_COMPRESSED_SRGB8_ETC2";
1525                 break;
1526         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1527                 result = "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2";
1528                 break;
1529         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1530                 result = "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2";
1531                 break;
1532         case GL_COMPRESSED_RGBA8_ETC2_EAC:
1533                 result = "GL_COMPRESSED_RGBA8_ETC2_EAC";
1534                 break;
1535         case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
1536                 result = "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC";
1537                 break;
1538         case GL_COMPRESSED_R11_EAC:
1539                 result = "GL_COMPRESSED_R11_EAC";
1540                 break;
1541         case GL_COMPRESSED_SIGNED_R11_EAC:
1542                 result = "GL_COMPRESSED_SIGNED_R11_EAC";
1543                 break;
1544         case GL_COMPRESSED_RG11_EAC:
1545                 result = "GL_COMPRESSED_RG11_EAC";
1546                 break;
1547         case GL_COMPRESSED_SIGNED_RG11_EAC:
1548                 result = "GL_COMPRESSED_SIGNED_RG11_EAC";
1549                 break;
1550
1551         default:
1552                 TCU_FAIL("Unrecognized internalformat");
1553         }
1554
1555         return result;
1556 }
1557
1558 /** Returns all texture+view internalformat pairs that are valid in light of GL_ARB_texture_view specification.
1559  *
1560  *  @return As described.
1561  **/
1562 TextureViewUtilities::_compatible_internalformat_pairs TextureViewUtilities::
1563         getLegalTextureAndViewInternalformatCombinations()
1564 {
1565         _compatible_internalformat_pairs result;
1566
1567         /* Iterate over all view classes */
1568         for (int current_view_class_it = static_cast<int>(VIEW_CLASS_FIRST);
1569                  current_view_class_it != static_cast<int>(VIEW_CLASS_COUNT); current_view_class_it++)
1570         {
1571                 _view_class              current_view_class                     = static_cast<_view_class>(current_view_class_it);
1572                 _internalformats view_class_internalformats = getInternalformatsFromViewClass(current_view_class);
1573
1574                 /* Store all combinations in the result vector */
1575                 for (_internalformats_const_iterator left_iterator = view_class_internalformats.begin();
1576                          left_iterator != view_class_internalformats.end(); left_iterator++)
1577                 {
1578                         for (_internalformats_const_iterator right_iterator = view_class_internalformats.begin();
1579                                  right_iterator != view_class_internalformats.end(); ++right_iterator)
1580                         {
1581                                 result.push_back(_internalformat_pair(*left_iterator, *right_iterator));
1582                         } /* for (all internalformats to be used as right-side values) */
1583                 }        /* for (all internalformats to be used as left-side values) */
1584         }                 /* for (all view classes) */
1585
1586         return result;
1587 }
1588
1589 /** Returns all valid texture+view texture targets pairs.
1590  *
1591  *  @return As per description.
1592  **/
1593 TextureViewUtilities::_compatible_texture_target_pairs TextureViewUtilities::getLegalTextureAndViewTargetCombinations()
1594 {
1595         _compatible_texture_target_pairs result;
1596
1597         /* Iterate over all texture targets valid for a glTextureView() call. Consider each one of them as
1598          * original texture target.
1599          */
1600         for (unsigned int n_original_texture_target = 0; n_original_texture_target < n_valid_texture_targets;
1601                  ++n_original_texture_target)
1602         {
1603                 const glw::GLenum original_texture_target = valid_texture_targets[n_original_texture_target];
1604
1605                 /* Iterate again, but this time consider each texture target as a valid new target */
1606                 for (unsigned int n_compatible_texture_target = 0; n_compatible_texture_target < n_valid_texture_targets;
1607                          ++n_compatible_texture_target)
1608                 {
1609                         const glw::GLenum view_texture_target = valid_texture_targets[n_compatible_texture_target];
1610
1611                         if (TextureViewUtilities::isLegalTextureTargetForTextureView(original_texture_target, view_texture_target))
1612                         {
1613                                 result.push_back(_texture_target_pair(original_texture_target, view_texture_target));
1614                         }
1615                 } /* for (all texture targets that are potentially compatible) */
1616         }        /* for (all original texture targets) */
1617
1618         return result;
1619 }
1620
1621 /** Returns major & minor version for user-specified CTS rendering context type.
1622  *
1623  *  @param context_type      CTS rendering context type.
1624  *  @param out_major_version Deref will be used to store major version. Must not be NULL.
1625  *  @param out_minor_version Deref will be used to store minor version. Must not be NULL.
1626  *
1627  **/
1628 void TextureViewUtilities::getMajorMinorVersionFromContextVersion(const glu::ContextType& context_type,
1629                                                                                                                                   glw::GLint*                     out_major_version,
1630                                                                                                                                   glw::GLint*                     out_minor_version)
1631 {
1632         if (context_type.getAPI() == glu::ApiType::core(4, 0))
1633         {
1634                 *out_major_version = 4;
1635                 *out_minor_version = 0;
1636         }
1637         else if (context_type.getAPI() == glu::ApiType::core(4, 1))
1638         {
1639                 *out_major_version = 4;
1640                 *out_minor_version = 1;
1641         }
1642         else if (context_type.getAPI() == glu::ApiType::core(4, 2))
1643         {
1644                 *out_major_version = 4;
1645                 *out_minor_version = 2;
1646         }
1647         else if (context_type.getAPI() == glu::ApiType::core(4, 3))
1648         {
1649                 *out_major_version = 4;
1650                 *out_minor_version = 3;
1651         }
1652         else if (context_type.getAPI() == glu::ApiType::core(4, 4))
1653         {
1654                 *out_major_version = 4;
1655                 *out_minor_version = 4;
1656         }
1657         else if (context_type.getAPI() == glu::ApiType::core(4, 5))
1658         {
1659                 *out_major_version = 4;
1660                 *out_minor_version = 5;
1661         }
1662         else
1663         {
1664                 TCU_FAIL("Unrecognized rendering context version");
1665         }
1666 }
1667
1668 /** Tells which sampler can be used to sample a texture defined with user-specified
1669  *  internalformat.
1670  *
1671  *  Supports both compressed and non-compressed internalformats.
1672  *  Throws TestError exception if @param internalformat was not recognized.
1673  *
1674  *  @param internalformat Internalformat to use for the query.
1675  *
1676  *  @return Requested information.
1677  **/
1678 _sampler_type TextureViewUtilities::getSamplerTypeForInternalformat(const glw::GLenum internalformat)
1679 {
1680         _sampler_type result = SAMPLER_TYPE_UNDEFINED;
1681
1682         /* Compressed internalformats not supported at the moment */
1683
1684         switch (internalformat)
1685         {
1686         case GL_COMPRESSED_RED_RGTC1:
1687         case GL_COMPRESSED_SIGNED_RED_RGTC1:
1688         case GL_COMPRESSED_RG_RGTC2:
1689         case GL_COMPRESSED_SIGNED_RG_RGTC2:
1690         case GL_COMPRESSED_RGBA_BPTC_UNORM:
1691         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
1692         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
1693         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
1694         case GL_DEPTH_COMPONENT16:
1695         case GL_DEPTH_COMPONENT24:
1696         case GL_DEPTH_COMPONENT32F:
1697         case GL_RGBA16:
1698         case GL_RGBA16_SNORM:
1699         case GL_RGBA16F:
1700         case GL_RGBA32F:
1701         case GL_RGBA4:
1702         case GL_RGBA8:
1703         case GL_RGBA8_SNORM:
1704         case GL_RGB10_A2:
1705         case GL_RGB16:
1706         case GL_RGB16_SNORM:
1707         case GL_RGB16F:
1708         case GL_RGB32F:
1709         case GL_RGB5_A1:
1710         case GL_RGB565:
1711         case GL_RGB8:
1712         case GL_RGB8_SNORM:
1713         case GL_RGB9_E5:
1714         case GL_RG16:
1715         case GL_RG16_SNORM:
1716         case GL_RG16F:
1717         case GL_RG32F:
1718         case GL_RG8:
1719         case GL_RG8_SNORM:
1720         case GL_R11F_G11F_B10F:
1721         case GL_R16:
1722         case GL_R16F:
1723         case GL_R16_SNORM:
1724         case GL_R32F:
1725         case GL_R8:
1726         case GL_R8_SNORM:
1727         case GL_SRGB8_ALPHA8:
1728         case GL_SRGB8:
1729         {
1730                 result = SAMPLER_TYPE_FLOAT;
1731
1732                 break;
1733         }
1734
1735         case GL_RGB10_A2UI:
1736         case GL_RGBA32UI:
1737         case GL_RGBA16UI:
1738         case GL_RGBA8UI:
1739         case GL_RGB16UI:
1740         case GL_RGB32UI:
1741         case GL_RGB8UI:
1742         case GL_RG16UI:
1743         case GL_RG32UI:
1744         case GL_RG8UI:
1745         case GL_R16UI:
1746         case GL_R32UI:
1747         case GL_R8UI:
1748         {
1749                 result = SAMPLER_TYPE_UNSIGNED_INTEGER;
1750
1751                 break;
1752         }
1753
1754         case GL_RGBA16I:
1755         case GL_RGBA32I:
1756         case GL_RGBA8I:
1757         case GL_RGB16I:
1758         case GL_RGB32I:
1759         case GL_RGB8I:
1760         case GL_RG16I:
1761         case GL_RG32I:
1762         case GL_RG8I:
1763         case GL_R16I:
1764         case GL_R32I:
1765         case GL_R8I:
1766         {
1767                 result = SAMPLER_TYPE_SIGNED_INTEGER;
1768
1769                 break;
1770         }
1771
1772         default:
1773         {
1774                 TCU_FAIL("Unrecognized internalformat");
1775         }
1776         } /* switch (interalformat) */
1777
1778         return result;
1779 }
1780
1781 /** Tells how many bytes are required to define a texture mip-map using
1782  *  user-specified internalformat and type, assuming user-defined mip-map
1783  *  resolution. Compressed internalformats are NOT supported.
1784  *
1785  *  Throws TestError exception if @param internalformat or @param type are
1786  *  found invalid.
1787  *
1788  *  @param internalformat Internalformat to use for the query.
1789  *  @param type           Type to use for the query.
1790  *  @param width          Mip-map width to use for the query.
1791  *  @param height         Mip-map height to use for the query.
1792  *
1793  *  @return Requested information.
1794  **/
1795 unsigned int TextureViewUtilities::getTextureDataSize(const glw::GLenum internalformat, const glw::GLenum type,
1796                                                                                                           const unsigned int width, const unsigned int height)
1797 {
1798         unsigned int internalformat_rgba_size[4] = { 0 };
1799         unsigned int type_rgba_size[4]                   = { 0 };
1800         unsigned int texel_size                                  = 0;
1801
1802         TextureViewUtilities::getComponentSizeForInternalformat(internalformat, internalformat_rgba_size);
1803         TextureViewUtilities::getComponentSizeForType(type, type_rgba_size);
1804
1805         if (internalformat_rgba_size[0] == 0)
1806         {
1807                 type_rgba_size[0] = 0;
1808         }
1809
1810         if (internalformat_rgba_size[1] == 0)
1811         {
1812                 type_rgba_size[1] = 0;
1813         }
1814
1815         if (internalformat_rgba_size[2] == 0)
1816         {
1817                 type_rgba_size[2] = 0;
1818         }
1819
1820         if (internalformat_rgba_size[3] == 0)
1821         {
1822                 type_rgba_size[3] = 0;
1823         }
1824
1825         texel_size = type_rgba_size[0] + type_rgba_size[1] + type_rgba_size[2] + type_rgba_size[3];
1826
1827         /* Current implementation assumes we do not need to use bit resolution when
1828          * preparing texel data. Make extra sure we're not wrong. */
1829         DE_ASSERT((texel_size % 8) == 0);
1830
1831         texel_size /= 8; /* bits per byte */
1832
1833         return texel_size * width * height;
1834 }
1835
1836 /** Returns a string corresponding to a GL enum describing a texture target.
1837  *
1838  *  @return As per description or "[?]" if the enum was not recognized.
1839  **/
1840 const char* TextureViewUtilities::getTextureTargetString(const glw::GLenum texture_target)
1841 {
1842         const char* result = "[?]";
1843
1844         switch (texture_target)
1845         {
1846         case GL_TEXTURE_1D:
1847                 result = "GL_TEXTURE_1D";
1848                 break;
1849         case GL_TEXTURE_1D_ARRAY:
1850                 result = "GL_TEXTURE_1D_ARRAY";
1851                 break;
1852         case GL_TEXTURE_2D:
1853                 result = "GL_TEXTURE_2D";
1854                 break;
1855         case GL_TEXTURE_2D_ARRAY:
1856                 result = "GL_TEXTURE_2D_ARRAY";
1857                 break;
1858         case GL_TEXTURE_2D_MULTISAMPLE:
1859                 result = "GL_TEXTURE_2D_MULTISAMPLE";
1860                 break;
1861         case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1862                 result = "GL_TEXTURE_2D_MULTISAMPLE_ARRAY";
1863                 break;
1864         case GL_TEXTURE_3D:
1865                 result = "GL_TEXTURE_3D";
1866                 break;
1867         case GL_TEXTURE_BUFFER:
1868                 result = "GL_TEXTURE_BUFFER";
1869                 break;
1870         case GL_TEXTURE_CUBE_MAP:
1871                 result = "GL_TEXTURE_CUBE_MAP";
1872                 break;
1873         case GL_TEXTURE_CUBE_MAP_ARRAY:
1874                 result = "GL_TEXTURE_CUBE_MAP_ARRAY";
1875                 break;
1876         case GL_TEXTURE_RECTANGLE:
1877                 result = "GL_TEXTURE_RECTANGLE";
1878                 break;
1879         }
1880
1881         return result;
1882 }
1883
1884 /** Returns GL type that can be used to define a texture mip-map defined
1885  *  with an internalformat of @param internalformat.
1886  *
1887  *  Throws TestError exception if @param internalformat was found to be invalid.
1888  *
1889  *  @param internalformat Internalformat to use for the query.
1890  *
1891  *  @return Requested information.
1892  **/
1893 glw::GLenum TextureViewUtilities::getTypeCompatibleWithInternalformat(const glw::GLenum internalformat)
1894 {
1895         glw::GLenum result = GL_NONE;
1896
1897         /* Compressed internalformats not supported at the moment */
1898
1899         switch (internalformat)
1900         {
1901         case GL_RGBA8_SNORM:
1902         case GL_RGB8_SNORM:
1903         case GL_RG8_SNORM:
1904         case GL_R8_SNORM:
1905         case GL_RGBA8I:
1906         case GL_RGB8I:
1907         case GL_RG8I:
1908         case GL_R8I:
1909         {
1910                 result = GL_BYTE;
1911
1912                 break;
1913         }
1914
1915         case GL_DEPTH24_STENCIL8:
1916         {
1917                 result = GL_UNSIGNED_INT_24_8;
1918
1919                 break;
1920         }
1921
1922         case GL_DEPTH32F_STENCIL8:
1923         {
1924                 result = GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
1925
1926                 break;
1927         }
1928
1929         case GL_RGBA16F:
1930         case GL_RGB16F:
1931         case GL_RG16F:
1932         case GL_R16F:
1933         {
1934                 result = GL_HALF_FLOAT;
1935
1936                 break;
1937         }
1938
1939         case GL_DEPTH_COMPONENT32F:
1940         case GL_RGBA32F:
1941         case GL_RGB32F:
1942         case GL_RG32F:
1943         case GL_R11F_G11F_B10F:
1944         case GL_R32F:
1945         {
1946                 result = GL_FLOAT;
1947
1948                 break;
1949         }
1950
1951         case GL_RGBA16_SNORM:
1952         case GL_RGB16_SNORM:
1953         case GL_RG16_SNORM:
1954         case GL_R16_SNORM:
1955         {
1956                 result = GL_SHORT;
1957
1958                 break;
1959         }
1960
1961         case GL_RGBA4:
1962         case GL_RGBA8:
1963         case GL_RGB10_A2:
1964         case GL_RGB5_A1:
1965         case GL_RGB565:
1966         case GL_RGB8:
1967         case GL_RGB9_E5:
1968         case GL_RG8:
1969         case GL_R8:
1970         case GL_SRGB8_ALPHA8:
1971         case GL_SRGB8:
1972         case GL_RGBA8UI:
1973         case GL_RGB8UI:
1974         case GL_RG8UI:
1975         case GL_R8UI:
1976         {
1977                 result = GL_UNSIGNED_BYTE;
1978
1979                 break;
1980         }
1981
1982         case GL_R16I:
1983         case GL_RGBA16I:
1984         case GL_RGB16I:
1985         case GL_RG16I:
1986         {
1987                 result = GL_SHORT;
1988
1989                 break;
1990         }
1991
1992         case GL_DEPTH_COMPONENT16:
1993         case GL_RGBA16:
1994         case GL_RGB16:
1995         case GL_RG16:
1996         case GL_R16:
1997         case GL_RGBA16UI:
1998         case GL_RGB16UI:
1999         case GL_RG16UI:
2000         case GL_R16UI:
2001         {
2002                 result = GL_UNSIGNED_SHORT;
2003
2004                 break;
2005         }
2006
2007         case GL_RGBA32I:
2008         case GL_RGB32I:
2009         case GL_RG32I:
2010         case GL_R32I:
2011         {
2012                 result = GL_INT;
2013
2014                 break;
2015         }
2016
2017         case GL_DEPTH_COMPONENT24:
2018         case GL_RGBA32UI:
2019         case GL_RGB32UI:
2020         case GL_RG32UI:
2021         case GL_R32UI:
2022         {
2023                 result = GL_UNSIGNED_INT;
2024
2025                 break;
2026         }
2027
2028         case GL_RGB10_A2UI:
2029         {
2030                 result = GL_UNSIGNED_INT_2_10_10_10_REV;
2031
2032                 break;
2033         }
2034
2035         default:
2036         {
2037                 TCU_FAIL("Unrecognized internalformat");
2038         }
2039         } /* switch (interalformat) */
2040
2041         return result;
2042 }
2043
2044 /** Tells what view class is the user-specified internalformat associated with.
2045  *
2046  *  Implements Table 8.21 from OpenGL Specification 4.3
2047  *
2048  *  @param internalformat Internalformat to use for the query.
2049  *
2050  *  @return Requested information or VIEW_CLASS_UNDEFINED if @param internalformat
2051  *          has not been recognized.
2052  **/
2053 _view_class TextureViewUtilities::getViewClassForInternalformat(const glw::GLenum internalformat)
2054 {
2055         _view_class result = VIEW_CLASS_UNDEFINED;
2056
2057         /* Note that n_internalformat_view_compatibility_array_entries needs to be divided by 2
2058          * because the value refers to a total number of entries in the array, not to the number
2059          * of pairs that can be read.
2060          */
2061         for (int n_entry = 0; n_entry < (n_internalformat_view_compatibility_array_entries >> 1); n_entry++)
2062         {
2063                 glw::GLenum array_internalformat = internalformat_view_compatibility_array[(n_entry * 2) + 0];
2064                 _view_class view_class                   = (_view_class)internalformat_view_compatibility_array[(n_entry * 2) + 1];
2065
2066                 if (array_internalformat == internalformat)
2067                 {
2068                         result = view_class;
2069
2070                         break;
2071                 }
2072         } /* for (all pairs in data array) */
2073
2074         return result;
2075 }
2076
2077 /** Initializes texture storage for either an immutable or mutable texture object,
2078  *  depending on configuration of the test run the storage is to be initialized for.
2079  *
2080  *  @param gl                          GL entry-points to use for storage initialization.
2081  *  @param init_mutable_to             true if a mutable texture storage should be initialized,
2082  *                                     false to initialize immutable texture storage.
2083  *  @param texture_target              Texture target to be used.
2084  *  @param texture_depth               Depth to be used for texture storage. Only used
2085  *                                     for texture targets that use the depth information.
2086  *  @param texture_height              Height to be used for texture storage. Only used
2087  *                                     for texture targets that use the height information.
2088  *  @param texture_width               Width to be used for texture storage.
2089  *  @param texture_internalformat      Internalformat to be used for texture storage.
2090  *  @param texture_format              Format to be used for texture storage.
2091  *  @param texture_type                Type to be used for texture storage.
2092  *  @param n_levels_needed             Amount of mip-map levels that should be used for texture storage.
2093  *                                     Only used for texture targets that support mip-maps.
2094  *  @param n_cubemaps_needed           Amount of cube-maps to be used for initialization of cube map
2095  *                                     array texture storage. Only used if @param texture_internalformat
2096  *                                     is set to GL_TEXTURE_CUBE_MAP_ARRAY.
2097  *  @param bo_id                       ID of a buffer object to be used for initialization of
2098  *                                     buffer texture storage. Only used if @param texture_internalformat
2099  *                                     is set to GL_TEXTURE_BUFFEER.
2100  *
2101  **/
2102 void TextureViewUtilities::initTextureStorage(const glw::Functions& gl, bool init_mutable_to,
2103                                                                                           glw::GLenum texture_target, glw::GLint texture_depth,
2104                                                                                           glw::GLint texture_height, glw::GLint texture_width,
2105                                                                                           glw::GLenum texture_internalformat, glw::GLenum texture_format,
2106                                                                                           glw::GLenum texture_type, unsigned int n_levels_needed,
2107                                                                                           unsigned int n_cubemaps_needed, glw::GLint bo_id)
2108 {
2109         const glw::GLenum cubemap_texture_targets[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
2110                                                                                                         GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
2111                                                                                                         GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
2112         const unsigned int n_cubemap_texture_targets = sizeof(cubemap_texture_targets) / sizeof(cubemap_texture_targets[0]);
2113
2114         /* If we're going to be initializing a multisample texture object,
2115          * determine how many samples can be used for GL_RGBA8 internalformat,
2116          * given texture target that is of our interest */
2117         glw::GLint gl_max_color_texture_samples_value = 0;
2118
2119         gl.getIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &gl_max_color_texture_samples_value);
2120         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_COLOR_TEXTURE_SAMPLES");
2121
2122         if (texture_target == GL_TEXTURE_BUFFER)
2123         {
2124                 gl.texBuffer(GL_TEXTURE_BUFFER, texture_internalformat, bo_id);
2125
2126                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexBuffer() call failed for GL_TEXTURE_BUFFER target");
2127         }
2128         else if (init_mutable_to)
2129         {
2130                 for (unsigned int n_level = 0; n_level < n_levels_needed; ++n_level)
2131                 {
2132                         /* If level != 0 and we're trying to initialize a texture target which
2133                          * only accepts a single level, leave now
2134                          */
2135                         if (n_level != 0 &&
2136                                 (texture_target == GL_TEXTURE_RECTANGLE || texture_target == GL_TEXTURE_2D_MULTISAMPLE ||
2137                                  texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY || texture_target == GL_TEXTURE_BUFFER))
2138                         {
2139                                 break;
2140                         }
2141
2142                         /* Initialize mutable texture storage */
2143                         switch (texture_target)
2144                         {
2145                         case GL_TEXTURE_1D:
2146                         {
2147                                 gl.texImage1D(texture_target, n_level, texture_internalformat, texture_width >> n_level, 0, /* border */
2148                                                           texture_format, texture_type, DE_NULL);                                                                               /* pixels */
2149
2150                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage1D() call failed for GL_TEXTURE_1D texture target");
2151
2152                                 break;
2153                         }
2154
2155                         case GL_TEXTURE_1D_ARRAY:
2156                         case GL_TEXTURE_2D:
2157                         case GL_TEXTURE_RECTANGLE:
2158                         {
2159                                 gl.texImage2D(texture_target, n_level, texture_internalformat, texture_width >> n_level,
2160                                                           texture_height >> n_level, 0,                   /* border */
2161                                                           texture_format, texture_type, DE_NULL); /* pixels */
2162
2163                                 GLU_EXPECT_NO_ERROR(gl.getError(),
2164                                                                         (texture_target == GL_TEXTURE_1D_ARRAY) ?
2165                                                                                 "glTexImage2D() call failed for GL_TEXTURE_1D_ARRAY texture target" :
2166                                                                                 (texture_target == GL_TEXTURE_2D) ?
2167                                                                                 "glTexImage2D() call failed for GL_TEXTURE_2D texture target" :
2168                                                                                 "glTexImage2D() call failed for GL_TEXTURE_RECTANGLE texture target");
2169
2170                                 break;
2171                         }
2172
2173                         case GL_TEXTURE_2D_ARRAY:
2174                         case GL_TEXTURE_3D:
2175                         {
2176                                 gl.texImage3D(texture_target, n_level, texture_internalformat, texture_width >> n_level,
2177                                                           texture_height >> n_level, texture_depth >> n_level, 0, /* border */
2178                                                           texture_format, texture_type, DE_NULL);                                 /* pixels */
2179
2180                                 GLU_EXPECT_NO_ERROR(gl.getError(),
2181                                                                         (texture_target == GL_TEXTURE_2D_ARRAY) ?
2182                                                                                 "glTexImage3D() call failed for GL_TEXTURE_2D_ARRAY texture target" :
2183                                                                                 "glTexImage3D() call failed for GL_TEXTURE_3D texture target");
2184
2185                                 break;
2186                         }
2187
2188                         case GL_TEXTURE_2D_MULTISAMPLE:
2189                         {
2190                                 gl.texImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, gl_max_color_texture_samples_value,
2191                                                                                  texture_internalformat, texture_width >> n_level, texture_height >> n_level,
2192                                                                                  GL_TRUE); /* fixedsamplelocations */
2193
2194                                 GLU_EXPECT_NO_ERROR(
2195                                         gl.getError(),
2196                                         "glTexImage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target");
2197
2198                                 break;
2199                         }
2200
2201                         case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2202                         {
2203                                 gl.texImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, gl_max_color_texture_samples_value,
2204                                                                                  texture_internalformat, texture_width >> n_level, texture_height >> n_level,
2205                                                                                  texture_depth >> n_level, GL_TRUE); /* fixedsamplelocations */
2206
2207                                 GLU_EXPECT_NO_ERROR(
2208                                         gl.getError(),
2209                                         "glTexImage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY texture target");
2210
2211                                 break;
2212                         }
2213
2214                         case GL_TEXTURE_CUBE_MAP:
2215                         {
2216                                 for (unsigned int n_cubemap_texture_target = 0; n_cubemap_texture_target < n_cubemap_texture_targets;
2217                                          ++n_cubemap_texture_target)
2218                                 {
2219                                         glw::GLenum cubemap_texture_target = cubemap_texture_targets[n_cubemap_texture_target];
2220
2221                                         gl.texImage2D(cubemap_texture_target, n_level, texture_internalformat, texture_width >> n_level,
2222                                                                   texture_height >> n_level, 0,                   /* border */
2223                                                                   texture_format, texture_type, DE_NULL); /* pixels */
2224
2225                                         GLU_EXPECT_NO_ERROR(gl.getError(),
2226                                                                                 "glTexImage2D() call failed for one of the cube-map texture targets");
2227
2228                                         break;
2229                                 } /* for (all cube-map texture targets) */
2230
2231                                 break;
2232                         }
2233
2234                         case GL_TEXTURE_CUBE_MAP_ARRAY:
2235                         {
2236                                 gl.texImage3D(texture_target, n_level, texture_internalformat, texture_width >> n_level,
2237                                                           texture_height >> n_level, 6 /* layer-faces */ * n_cubemaps_needed, 0, /* border */
2238                                                           texture_format, texture_type, DE_NULL);                                                                /* pixels */
2239
2240                                 GLU_EXPECT_NO_ERROR(gl.getError(),
2241                                                                         "glTexImage3D() call failed for GL_TEXTURE_CUBE_MAP_ARRAY texture target");
2242
2243                                 break;
2244                         }
2245
2246                         default:
2247                         {
2248                                 TCU_FAIL("Unrecognized texture target");
2249                         }
2250                         } /* switch (texture_target) */
2251                 }        /* for (all levels) */
2252         }                 /* if (texture_type == TEST_TEXTURE_TYPE_MUTABLE_TEXTURE_OBJECT) */
2253         else
2254         {
2255                 /* Initialize immutable texture storage */
2256                 switch (texture_target)
2257                 {
2258                 case GL_TEXTURE_1D:
2259                 {
2260                         gl.texStorage1D(texture_target, n_levels_needed, texture_internalformat, texture_width);
2261
2262                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage1D() call failed for GL_TEXTURE_1D texture target");
2263
2264                         break;
2265                 }
2266
2267                 case GL_TEXTURE_1D_ARRAY:
2268                 case GL_TEXTURE_2D:
2269                 case GL_TEXTURE_CUBE_MAP:
2270                 case GL_TEXTURE_RECTANGLE:
2271                 {
2272                         const unsigned n_levels = (texture_target == GL_TEXTURE_RECTANGLE) ? 1 : n_levels_needed;
2273
2274                         gl.texStorage2D(texture_target, n_levels, texture_internalformat, texture_width, texture_height);
2275
2276                         GLU_EXPECT_NO_ERROR(gl.getError(),
2277                                                                 (texture_target == GL_TEXTURE_1D_ARRAY) ?
2278                                                                         "glTexStorage2D() call failed for GL_TEXTURE_1D_ARRAY texture target" :
2279                                                                         (texture_target == GL_TEXTURE_2D) ?
2280                                                                         "glTexStorage2D() call failed for GL_TEXTURE_2D texture target" :
2281                                                                         (texture_target == GL_TEXTURE_CUBE_MAP) ?
2282                                                                         "glTexStorage2D() call failed for GL_TEXTURE_CUBE_MAP texture target" :
2283                                                                         "glTexStorage2D() call failed for GL_TEXTURE_RECTANGLE texture target");
2284
2285                         break;
2286                 }
2287
2288                 case GL_TEXTURE_2D_ARRAY:
2289                 case GL_TEXTURE_3D:
2290                 {
2291                         gl.texStorage3D(texture_target, n_levels_needed, texture_internalformat, texture_width, texture_height,
2292                                                         texture_depth);
2293
2294                         GLU_EXPECT_NO_ERROR(gl.getError(),
2295                                                                 (texture_target == GL_TEXTURE_2D_ARRAY) ?
2296                                                                         "glTexStorage3D() call failed for GL_TEXTURE_2D_ARRAY texture target" :
2297                                                                         "glTexStorage3D() call failed for GL_TEXTURE_3D texture target");
2298
2299                         break;
2300                 }
2301
2302                 case GL_TEXTURE_2D_MULTISAMPLE:
2303                 {
2304                         gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, gl_max_color_texture_samples_value,
2305                                                                            texture_internalformat, texture_width, texture_height,
2306                                                                            GL_TRUE); /* fixedsamplelocations */
2307
2308                         GLU_EXPECT_NO_ERROR(gl.getError(),
2309                                                                 "glTexStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target");
2310
2311                         break;
2312                 }
2313
2314                 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2315                 {
2316                         gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, gl_max_color_texture_samples_value,
2317                                                                            texture_internalformat, texture_width, texture_height, texture_depth,
2318                                                                            GL_TRUE); /* fixedsamplelocations */
2319
2320                         GLU_EXPECT_NO_ERROR(
2321                                 gl.getError(),
2322                                 "glTexStorage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY texture target");
2323
2324                         break;
2325                 }
2326
2327                 case GL_TEXTURE_CUBE_MAP_ARRAY:
2328                 {
2329                         const unsigned int actual_texture_depth = 6 /* layer-faces */ * n_cubemaps_needed;
2330
2331                         gl.texStorage3D(texture_target, n_levels_needed, texture_internalformat, texture_width, texture_height,
2332                                                         actual_texture_depth);
2333
2334                         GLU_EXPECT_NO_ERROR(gl.getError(),
2335                                                                 "glTexStorage3D() call failed for GL_TEXTURE_CUBE_MAP_ARRAY texture target");
2336
2337                         break;
2338                 }
2339
2340                 default:
2341                 {
2342                         TCU_FAIL("Unrecognized texture target");
2343                 }
2344                 } /* switch (texture_target) */
2345         }
2346 }
2347
2348 /** Tells whether a parent texture object, storage of which uses @param original_internalformat
2349  *  internalformat, can be used to generate a texture view using @param view_internalformat
2350  *  internalformat.
2351  *
2352  *  @param original_internalformat Internalformat used for parent texture object storage.
2353  *  @param view_internalformat     Internalformat to be used for view texture object storage.
2354  *
2355  *  @return true if the internalformats are compatible, false otherwise.
2356  **/
2357 bool TextureViewUtilities::isInternalformatCompatibleForTextureView(glw::GLenum original_internalformat,
2358                                                                                                                                         glw::GLenum view_internalformat)
2359 {
2360         const _view_class original_internalformat_view_class = getViewClassForInternalformat(original_internalformat);
2361         const _view_class view_internalformat_view_class         = getViewClassForInternalformat(view_internalformat);
2362
2363         return (original_internalformat_view_class == view_internalformat_view_class);
2364 }
2365
2366 /** Tells whether user-specified internalformat is compressed.
2367  *
2368  *  @param internalformat Internalformat to use for the query.
2369  *
2370  *  @return true if @param internalformat is a known compressed internalformat,
2371  *          false otherwise.
2372  **/
2373 bool TextureViewUtilities::isInternalformatCompressed(const glw::GLenum internalformat)
2374 {
2375         bool result = false;
2376
2377         switch (internalformat)
2378         {
2379         case GL_COMPRESSED_RED_RGTC1:
2380         case GL_COMPRESSED_SIGNED_RED_RGTC1:
2381         case GL_COMPRESSED_RG_RGTC2:
2382         case GL_COMPRESSED_SIGNED_RG_RGTC2:
2383         case GL_COMPRESSED_RGBA_BPTC_UNORM:
2384         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
2385         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
2386         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
2387         case GL_COMPRESSED_RGB8_ETC2:
2388         case GL_COMPRESSED_SRGB8_ETC2:
2389         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
2390         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
2391         case GL_COMPRESSED_RGBA8_ETC2_EAC:
2392         case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
2393         case GL_COMPRESSED_R11_EAC:
2394         case GL_COMPRESSED_SIGNED_R11_EAC:
2395         case GL_COMPRESSED_RG11_EAC:
2396         case GL_COMPRESSED_SIGNED_RG11_EAC:
2397         {
2398                 result = true;
2399
2400                 break;
2401         }
2402         } /* switch (internalformat) */
2403
2404         return result;
2405 }
2406
2407 /** Tells whether user-specified internalformat operates in sRGB color space.
2408  *
2409  *  @param internalformat Internalformat to use for the query.
2410  *
2411  *  @return true if @param internalformat is a known sRGB internalformat,
2412  *          false otherwise.
2413  **/
2414 bool TextureViewUtilities::isInternalformatSRGB(const glw::GLenum internalformat)
2415 {
2416         return (internalformat == GL_SRGB8 || internalformat == GL_SRGB8_ALPHA8 ||
2417                         internalformat == GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM);
2418 }
2419
2420 /** Tells whether user-specified internalformat is supported by OpenGL of a given version.
2421  *
2422  *  @param internalformat Internalformat to use for the query.
2423  *  @param major_version  Major version of the rendering context.
2424  *  @param minor_version  Minor version of the rendering context.
2425  *
2426  *  @return true if the internalformat is supported, false otherwise.
2427  **/
2428 bool TextureViewUtilities::isInternalformatSupported(glw::GLenum internalformat, const glw::GLint major_version,
2429                                                                                                          const glw::GLint minor_version)
2430 {
2431         (void)major_version;
2432         /* NOTE: This function, as it stands right now, does not consider OpenGL contexts
2433          *       lesser than 4.
2434          **/
2435         glw::GLint minimum_minor_version = 0;
2436
2437         DE_ASSERT(major_version >= 4);
2438
2439         switch (internalformat)
2440         {
2441         /* >= OpenGL 4.0 */
2442         case GL_RGBA32F:
2443         case GL_RGBA32I:
2444         case GL_RGBA32UI:
2445         case GL_RGBA16:
2446         case GL_RGBA16F:
2447         case GL_RGBA16I:
2448         case GL_RGBA16UI:
2449         case GL_RGBA8:
2450         case GL_RGBA8I:
2451         case GL_RGBA8UI:
2452         case GL_SRGB8_ALPHA8:
2453         case GL_RGB10_A2:
2454         case GL_RGB10_A2UI:
2455         case GL_RGB5_A1:
2456         case GL_RGBA4:
2457         case GL_R11F_G11F_B10F:
2458         case GL_RG32F:
2459         case GL_RG32I:
2460         case GL_RG32UI:
2461         case GL_RG16:
2462         case GL_RG16F:
2463         case GL_RG16I:
2464         case GL_RG16UI:
2465         case GL_RG8:
2466         case GL_RG8I:
2467         case GL_RG8UI:
2468         case GL_R32F:
2469         case GL_R32I:
2470         case GL_R32UI:
2471         case GL_R16F:
2472         case GL_R16I:
2473         case GL_R16UI:
2474         case GL_R16:
2475         case GL_R8:
2476         case GL_R8I:
2477         case GL_R8UI:
2478         case GL_RGBA16_SNORM:
2479         case GL_RGBA8_SNORM:
2480         case GL_RGB32F:
2481         case GL_RGB32I:
2482         case GL_RGB32UI:
2483         case GL_RGB16_SNORM:
2484         case GL_RGB16F:
2485         case GL_RGB16I:
2486         case GL_RGB16UI:
2487         case GL_RGB16:
2488         case GL_RGB8_SNORM:
2489         case GL_RGB8:
2490         case GL_RGB8I:
2491         case GL_RGB8UI:
2492         case GL_SRGB8:
2493         case GL_RGB9_E5:
2494         case GL_RG16_SNORM:
2495         case GL_RG8_SNORM:
2496         case GL_R16_SNORM:
2497         case GL_R8_SNORM:
2498         case GL_DEPTH_COMPONENT32F:
2499         case GL_DEPTH_COMPONENT24:
2500         case GL_DEPTH_COMPONENT16:
2501         case GL_DEPTH32F_STENCIL8:
2502         case GL_DEPTH24_STENCIL8:
2503         case GL_COMPRESSED_RED_RGTC1:
2504         case GL_COMPRESSED_SIGNED_RED_RGTC1:
2505         case GL_COMPRESSED_RG_RGTC2:
2506         case GL_COMPRESSED_SIGNED_RG_RGTC2:
2507         {
2508                 /* Already covered by default value of minimum_minor_version */
2509
2510                 break;
2511         }
2512
2513         /* >= OpenGL 4.2 */
2514         case GL_RGB565:
2515         case GL_COMPRESSED_RGBA_BPTC_UNORM:
2516         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
2517         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
2518         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
2519         {
2520                 minimum_minor_version = 2;
2521
2522                 break;
2523         }
2524
2525         /* >= OpenGL 4.3 */
2526         case GL_COMPRESSED_RGB8_ETC2:
2527         case GL_COMPRESSED_SRGB8_ETC2:
2528         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
2529         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
2530         case GL_COMPRESSED_RGBA8_ETC2_EAC:
2531         case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
2532         case GL_COMPRESSED_R11_EAC:
2533         case GL_COMPRESSED_SIGNED_R11_EAC:
2534         case GL_COMPRESSED_RG11_EAC:
2535         case GL_COMPRESSED_SIGNED_RG11_EAC:
2536         {
2537                 minimum_minor_version = 3;
2538
2539                 break;
2540         }
2541
2542         default:
2543                 TCU_FAIL("Unrecognized internalformat");
2544         }
2545
2546         return (minor_version >= minimum_minor_version);
2547 }
2548
2549 /** Tells whether a parent texture object using @param original_texture_target texture target
2550  *  can be used to generate a texture view of @param view_texture_target texture target.
2551  *
2552  *  @param original_texture_target Texture target used by parent texture;
2553  *  @param view_texture_target     Texture target to be used for view texture;
2554  *
2555  *  @return true if the texture targets are compatible, false otherwise.
2556  **/
2557 bool TextureViewUtilities::isLegalTextureTargetForTextureView(glw::GLenum original_texture_target,
2558                                                                                                                           glw::GLenum view_texture_target)
2559 {
2560         bool result = false;
2561
2562         switch (original_texture_target)
2563         {
2564         case GL_TEXTURE_1D:
2565         {
2566                 result = (view_texture_target == GL_TEXTURE_1D || view_texture_target == GL_TEXTURE_1D_ARRAY);
2567
2568                 break;
2569         }
2570
2571         case GL_TEXTURE_2D:
2572         {
2573                 result = (view_texture_target == GL_TEXTURE_2D || view_texture_target == GL_TEXTURE_2D_ARRAY);
2574
2575                 break;
2576         }
2577
2578         case GL_TEXTURE_3D:
2579         {
2580                 result = (view_texture_target == GL_TEXTURE_3D);
2581
2582                 break;
2583         }
2584
2585         case GL_TEXTURE_CUBE_MAP:
2586         {
2587                 result = (view_texture_target == GL_TEXTURE_CUBE_MAP || view_texture_target == GL_TEXTURE_2D ||
2588                                   view_texture_target == GL_TEXTURE_2D_ARRAY || view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
2589
2590                 break;
2591         }
2592
2593         case GL_TEXTURE_RECTANGLE:
2594         {
2595                 result = (view_texture_target == GL_TEXTURE_RECTANGLE);
2596
2597                 break;
2598         }
2599
2600         case GL_TEXTURE_BUFFER:
2601         {
2602                 /* No targets supported */
2603
2604                 break;
2605         }
2606
2607         case GL_TEXTURE_1D_ARRAY:
2608         {
2609                 result = (view_texture_target == GL_TEXTURE_1D_ARRAY || view_texture_target == GL_TEXTURE_1D);
2610
2611                 break;
2612         }
2613
2614         case GL_TEXTURE_2D_ARRAY:
2615         {
2616                 result = (view_texture_target == GL_TEXTURE_2D_ARRAY || view_texture_target == GL_TEXTURE_2D ||
2617                                   view_texture_target == GL_TEXTURE_CUBE_MAP || view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
2618
2619                 break;
2620         }
2621
2622         case GL_TEXTURE_CUBE_MAP_ARRAY:
2623         {
2624                 result = (view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY || view_texture_target == GL_TEXTURE_2D_ARRAY ||
2625                                   view_texture_target == GL_TEXTURE_2D || view_texture_target == GL_TEXTURE_CUBE_MAP);
2626
2627                 break;
2628         }
2629
2630         case GL_TEXTURE_2D_MULTISAMPLE:
2631         {
2632                 result = (view_texture_target == GL_TEXTURE_2D_MULTISAMPLE ||
2633                                   view_texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
2634
2635                 break;
2636         }
2637
2638         case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2639         {
2640                 result = (view_texture_target == GL_TEXTURE_2D_MULTISAMPLE ||
2641                                   view_texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
2642
2643                 break;
2644         }
2645         } /* switch (original_texture_target) */
2646
2647         return result;
2648 }
2649
2650 /** Constructor.
2651  *
2652  *  @param context Rendering context.
2653  **/
2654 TextureViewTestGetTexParameter::TextureViewTestGetTexParameter(deqp::Context& context)
2655         : TestCase(context, "gettexparameter", "Verifies glGetTexParameterfv() and glGetTexParameteriv() "
2656                                                                                    "work as specified")
2657 {
2658         /* Left blank on purpose */
2659 }
2660
2661 /** De-initializes all GL objects created for the test. */
2662 void TextureViewTestGetTexParameter::deinit()
2663 {
2664         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2665
2666         /* Deinitialize all test runs */
2667         for (_test_runs_iterator it = m_test_runs.begin(); it != m_test_runs.end(); ++it)
2668         {
2669                 _test_run& test_run = *it;
2670
2671                 if (test_run.parent_texture_object_id != 0)
2672                 {
2673                         gl.deleteTextures(1, &test_run.parent_texture_object_id);
2674
2675                         test_run.parent_texture_object_id = 0;
2676                 }
2677
2678                 if (test_run.texture_view_object_created_from_immutable_to_id != 0)
2679                 {
2680                         gl.deleteTextures(1, &test_run.texture_view_object_created_from_immutable_to_id);
2681
2682                         test_run.texture_view_object_created_from_immutable_to_id = 0;
2683                 }
2684
2685                 if (test_run.texture_view_object_created_from_view_to_id != 0)
2686                 {
2687                         gl.deleteTextures(1, &test_run.texture_view_object_created_from_view_to_id);
2688
2689                         test_run.texture_view_object_created_from_view_to_id = 0;
2690                 }
2691         }
2692         m_test_runs.clear();
2693 }
2694
2695 /** Initializes test run descriptors used by the test. This also includes
2696  *  all GL objects used by all the iterations.
2697  **/
2698 void TextureViewTestGetTexParameter::initTestRuns()
2699 {
2700         const glw::Functions& gl                                = m_context.getRenderContext().getFunctions();
2701         const int                         n_cubemaps_needed = 4; /* only used for GL_TEXTURE_CUBE_MAP_ARRAY */
2702         const int                         texture_depth         = 16;
2703         const int                         texture_height        = 32;
2704         const int                         texture_width         = 64;
2705
2706         const glw::GLenum texture_targets[] = {
2707                 GL_TEXTURE_1D,           GL_TEXTURE_1D_ARRAY,           GL_TEXTURE_2D,
2708                 GL_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
2709                 GL_TEXTURE_3D,           GL_TEXTURE_CUBE_MAP,           GL_TEXTURE_CUBE_MAP_ARRAY,
2710                 GL_TEXTURE_RECTANGLE
2711         };
2712         const _test_texture_type texture_types[] = { TEST_TEXTURE_TYPE_NO_STORAGE_ALLOCATED,
2713                                                                                                  TEST_TEXTURE_TYPE_IMMUTABLE_TEXTURE_OBJECT,
2714                                                                                                  TEST_TEXTURE_TYPE_MUTABLE_TEXTURE_OBJECT,
2715                                                                                                  TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_IMMUTABLE_TEXTURE_OBJECT,
2716                                                                                                  TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_TEXTURE_VIEW };
2717         const unsigned int n_texture_targets = sizeof(texture_targets) / sizeof(texture_targets[0]);
2718         const unsigned int n_texture_types   = sizeof(texture_types) / sizeof(texture_types[0]);
2719
2720         /* Iterate through all texture types supported by the test */
2721         for (unsigned int n_texture_type = 0; n_texture_type < n_texture_types; ++n_texture_type)
2722         {
2723                 const _test_texture_type texture_type = texture_types[n_texture_type];
2724
2725                 /* Iterate through all texture targets supported by the test */
2726                 for (unsigned int n_texture_target = 0; n_texture_target < n_texture_targets; ++n_texture_target)
2727                 {
2728                         _test_run                 new_test_run;
2729                         const glw::GLenum texture_target = texture_targets[n_texture_target];
2730
2731                         /* Texture buffers are neither immutable nor mutable. In order to avoid testing
2732                          * them in both cases, let's assume they are immutable objects */
2733                         if (texture_target == GL_TEXTURE_BUFFER && texture_type == TEST_TEXTURE_TYPE_MUTABLE_TEXTURE_OBJECT)
2734                         {
2735                                 continue;
2736                         }
2737
2738                         /* Set up test run properties. Since we're only testing a single
2739                          * configuration, we can set these to predefined values..
2740                          */
2741                         const int  n_levels_needed               = 6;
2742                         glw::GLint n_min_layer                   = 1;
2743                         glw::GLint n_num_layers                  = 2;
2744                         glw::GLint n_min_level                   = 2;
2745                         glw::GLint n_num_levels                  = 3;
2746                         int                parent_texture_depth  = texture_depth;
2747                         int                parent_texture_height = texture_height;
2748                         int                parent_texture_width  = texture_width;
2749
2750                         new_test_run.texture_target = texture_target;
2751                         new_test_run.texture_type   = texture_type;
2752
2753                         /* Take note of target-specific restrictions */
2754                         if (texture_target == GL_TEXTURE_CUBE_MAP || texture_target == GL_TEXTURE_CUBE_MAP_ARRAY)
2755                         {
2756                                 n_num_layers = 6 /* layer-faces */ * 2; /* as per spec */
2757
2758                                 /* Make sure that cube face width matches its height */
2759                                 parent_texture_height = 64;
2760                                 parent_texture_width  = 64;
2761
2762                                 /* Also change the depth so that there's at least a few layers
2763                                  * we can use in the test for GL_TEXTURE_CUBE_MAP_ARRAY case
2764                                  */
2765                                 parent_texture_depth = 64;
2766                         }
2767
2768                         if (texture_target == GL_TEXTURE_CUBE_MAP)
2769                         {
2770                                 /* Texture views created from a cube map texture should always
2771                                  * use a minimum layer of zero
2772                                  */
2773                                 n_min_layer  = 0;
2774                                 n_num_layers = 6;
2775                         }
2776
2777                         if (texture_target == GL_TEXTURE_CUBE_MAP_ARRAY)
2778                         {
2779                                 /* Slightly modify the values we'll use for <minlayer>
2780                                  * and <numlayers> arguments passed to glTextureView() calls
2781                                  * so that we can test the "view from view from texture" case
2782                                  */
2783                                 n_min_layer = 0;
2784                         }
2785
2786                         if (texture_target == GL_TEXTURE_1D || texture_target == GL_TEXTURE_2D ||
2787                                 texture_target == GL_TEXTURE_2D_MULTISAMPLE || texture_target == GL_TEXTURE_3D ||
2788                                 texture_target == GL_TEXTURE_RECTANGLE)
2789                         {
2790                                 /* All these texture targets are single-layer only. glTextureView()
2791                                  * also requires <numlayers> argument to be set to 1 for them, so
2792                                  * take this into account.
2793                                  **/
2794                                 n_min_layer  = 0;
2795                                 n_num_layers = 1;
2796                         }
2797
2798                         if (texture_target == GL_TEXTURE_2D_MULTISAMPLE || texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY ||
2799                                 texture_target == GL_TEXTURE_RECTANGLE)
2800                         {
2801                                 /* All these texture targets do not support mip-maps */
2802                                 n_min_level = 0;
2803                         }
2804
2805                         /* Initialize parent texture object */
2806                         gl.genTextures(1, &new_test_run.parent_texture_object_id);
2807                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
2808
2809                         gl.bindTexture(texture_target, new_test_run.parent_texture_object_id);
2810                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
2811
2812                         if (texture_type != TEST_TEXTURE_TYPE_NO_STORAGE_ALLOCATED)
2813                         {
2814                                 TextureViewUtilities::initTextureStorage(gl, (texture_type == TEST_TEXTURE_TYPE_MUTABLE_TEXTURE_OBJECT),
2815                                                                                                                  texture_target, parent_texture_depth, parent_texture_height,
2816                                                                                                                  parent_texture_width, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE,
2817                                                                                                                  n_levels_needed, n_cubemaps_needed, 0); /* bo_id */
2818                         }
2819
2820                         /* Update expected view-specific property values to include interactions
2821                          * with immutable textures. */
2822                         if (texture_type == TEST_TEXTURE_TYPE_IMMUTABLE_TEXTURE_OBJECT ||
2823                                 texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_IMMUTABLE_TEXTURE_OBJECT ||
2824                                 texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_TEXTURE_VIEW)
2825                         {
2826                                 /* Set expected GL_TEXTURE_IMMUTABLE_LEVELS property value to the number
2827                                  * of levels we'll be using for the immutable texture storage. For selected
2828                                  * texture targets that do no take <levels> argument, we'll change this
2829                                  * value on a case-by-case basis.
2830                                  */
2831                                 new_test_run.expected_n_immutable_levels = n_levels_needed;
2832
2833                                 /* Set expected GL_TEXTURE_VIEW_NUM_LAYERS property value to 1, as per GL spec.
2834                                  * This value will be modified for selected texture targets */
2835                                 new_test_run.expected_n_num_layers = 1;
2836
2837                                 /* Configured expected GL_TEXTURE_VIEW_NUM_LEVELS value as per GL spec */
2838                                 new_test_run.expected_n_num_levels = n_levels_needed;
2839
2840                                 /* Initialize immutable texture storage */
2841                                 switch (texture_target)
2842                                 {
2843                                 case GL_TEXTURE_1D_ARRAY:
2844                                 {
2845                                         /* Update expected GL_TEXTURE_VIEW_NUM_LAYERS property value as per GL specification */
2846                                         new_test_run.expected_n_num_layers = texture_height;
2847
2848                                         break;
2849                                 }
2850
2851                                 case GL_TEXTURE_CUBE_MAP:
2852                                 {
2853                                         /* Update expected GL_TEXTURE_VIEW_NUM_LAYERS property value as per GL specification */
2854                                         new_test_run.expected_n_num_layers = 6;
2855
2856                                         break;
2857                                 }
2858
2859                                 case GL_TEXTURE_RECTANGLE:
2860                                 {
2861                                         new_test_run.expected_n_immutable_levels = 1;
2862                                         new_test_run.expected_n_num_levels               = 1;
2863
2864                                         break;
2865                                 }
2866
2867                                 case GL_TEXTURE_2D_ARRAY:
2868                                 {
2869                                         /* Update expected GL_TEXTURE_VIEW_NUM_LAYERS property value as per GL specification */
2870                                         new_test_run.expected_n_num_layers = texture_depth;
2871
2872                                         break;
2873                                 }
2874
2875                                 case GL_TEXTURE_2D_MULTISAMPLE:
2876                                 {
2877                                         /* 2D multisample texture are not mip-mapped, so update
2878                                          * expected GL_TEXTURE_IMMUTABLE_LEVELS and GL_TEXTURE_VIEW_NUM_LEVELS
2879                                          * value accordingly */
2880                                         new_test_run.expected_n_immutable_levels = 1;
2881                                         new_test_run.expected_n_num_levels               = 1;
2882
2883                                         break;
2884                                 }
2885
2886                                 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2887                                 {
2888                                         /* 2D multisample array textures are not mip-mapped, so update
2889                                          * expected GL_TEXTURE_IMMUTABLE_LEVELS and GL_TEXTURE_VIEW_NUM_LEVELS
2890                                          * values accordingly */
2891                                         new_test_run.expected_n_immutable_levels = 1;
2892                                         new_test_run.expected_n_num_levels               = 1;
2893
2894                                         /* Update expected GL_TEXTURE_VIEW_NUM_LAYERS property value as per GL specification */
2895                                         new_test_run.expected_n_num_layers = texture_depth;
2896
2897                                         break;
2898                                 }
2899
2900                                 case GL_TEXTURE_CUBE_MAP_ARRAY:
2901                                 {
2902                                         const unsigned int actual_texture_depth = 6 /* layer-faces */ * n_cubemaps_needed;
2903
2904                                         /* Update expected GL_TEXTURE_VIEW_NUM_LAYERS property value as per GL specification */
2905                                         new_test_run.expected_n_num_layers = actual_texture_depth;
2906
2907                                         break;
2908                                 }
2909                                 } /* switch (texture_target) */
2910                         }
2911
2912                         /* Initialize the view(s) */
2913                         if (texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_IMMUTABLE_TEXTURE_OBJECT ||
2914                                 texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_TEXTURE_VIEW)
2915                         {
2916                                 const unsigned int n_iterations =
2917                                         (texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_TEXTURE_VIEW) ? 2 : 1;
2918
2919                                 for (unsigned int n_iteration = 0; n_iteration < n_iterations; ++n_iteration)
2920                                 {
2921                                         glw::GLuint* parent_id_ptr = (n_iteration == 0) ?
2922                                                                                                          &new_test_run.parent_texture_object_id :
2923                                                                                                          &new_test_run.texture_view_object_created_from_immutable_to_id;
2924                                         glw::GLuint* view_id_ptr = (n_iteration == 0) ?
2925                                                                                                    &new_test_run.texture_view_object_created_from_immutable_to_id :
2926                                                                                                    &new_test_run.texture_view_object_created_from_view_to_id;
2927
2928                                         gl.genTextures(1, view_id_ptr);
2929                                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
2930
2931                                         gl.textureView(*view_id_ptr, new_test_run.texture_target, *parent_id_ptr,
2932                                                                    GL_RGBA8, /* use the parent texture object's internalformat */
2933                                                                    n_min_level, n_num_levels, n_min_layer, n_num_layers);
2934                                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed");
2935
2936                                         /* Query parent object's properties */
2937                                         glw::GLint parent_min_level                      = -1;
2938                                         glw::GLint parent_min_layer                      = -1;
2939                                         glw::GLint parent_num_layers             = -1;
2940                                         glw::GLint parent_num_levels             = -1;
2941                                         glw::GLint parent_n_immutable_levels = -1;
2942
2943                                         gl.bindTexture(texture_target, *parent_id_ptr);
2944                                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
2945
2946                                         gl.getTexParameteriv(texture_target, GL_TEXTURE_IMMUTABLE_LEVELS, &parent_n_immutable_levels);
2947                                         GLU_EXPECT_NO_ERROR(
2948                                                 gl.getError(),
2949                                                 "glGetTexParameteriv() failed for GL_TEXTURE_IMMUTABLE_LEVELS pname queried for parent object");
2950
2951                                         gl.getTexParameteriv(texture_target, GL_TEXTURE_VIEW_MIN_LAYER, &parent_min_layer);
2952                                         GLU_EXPECT_NO_ERROR(
2953                                                 gl.getError(),
2954                                                 "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_MIN_LAYER pname queried for parent object");
2955
2956                                         gl.getTexParameteriv(texture_target, GL_TEXTURE_VIEW_MIN_LEVEL, &parent_min_level);
2957                                         GLU_EXPECT_NO_ERROR(
2958                                                 gl.getError(),
2959                                                 "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_MIN_LEVEL pname queried for parent object");
2960
2961                                         gl.getTexParameteriv(texture_target, GL_TEXTURE_VIEW_NUM_LAYERS, &parent_num_layers);
2962                                         GLU_EXPECT_NO_ERROR(
2963                                                 gl.getError(),
2964                                                 "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_NUM_LAYERS pname queried for parent object");
2965
2966                                         gl.getTexParameteriv(texture_target, GL_TEXTURE_VIEW_NUM_LEVELS, &parent_num_levels);
2967                                         GLU_EXPECT_NO_ERROR(
2968                                                 gl.getError(),
2969                                                 "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_NUM_LEVELS pname queried for parent object");
2970
2971                                         /* Update test run-specific expected values as per GL_ARB_texture_view extension specification */
2972                                         /*
2973                                          * - TEXTURE_IMMUTABLE_LEVELS is set to the value of TEXTURE_IMMUTABLE_LEVELS
2974                                          *   from the original texture.
2975                                          */
2976                                         new_test_run.expected_n_immutable_levels = parent_n_immutable_levels;
2977
2978                                         /*
2979                                          * - TEXTURE_VIEW_MIN_LEVEL is set to <minlevel> plus the value of
2980                                          *   TEXTURE_VIEW_MIN_LEVEL from the original texture.
2981                                          */
2982                                         new_test_run.expected_n_min_level = n_min_level + parent_min_level;
2983
2984                                         /*
2985                                          * - TEXTURE_VIEW_MIN_LAYER is set to <minlayer> plus the value of
2986                                          *   TEXTURE_VIEW_MIN_LAYER from the original texture.
2987                                          */
2988                                         new_test_run.expected_n_min_layer = n_min_layer + parent_min_layer;
2989
2990                                         /*
2991                                          * - TEXTURE_VIEW_NUM_LAYERS is set to the lesser of <numlayers> and the
2992                                          *   value of TEXTURE_VIEW_NUM_LAYERS from the original texture minus
2993                                          *   <minlayer>.
2994                                          *
2995                                          */
2996                                         if ((parent_num_layers - n_min_layer) < n_num_layers)
2997                                         {
2998                                                 new_test_run.expected_n_num_layers = parent_num_layers - n_min_layer;
2999                                         }
3000                                         else
3001                                         {
3002                                                 new_test_run.expected_n_num_layers = n_num_layers;
3003                                         }
3004
3005                                         /*
3006                                          * - TEXTURE_VIEW_NUM_LEVELS is set to the lesser of <numlevels> and the
3007                                          *   value of TEXTURE_VIEW_NUM_LEVELS from the original texture minus
3008                                          *   <minlevels>.
3009                                          *
3010                                          */
3011                                         if ((parent_num_levels - n_min_level) < n_num_levels)
3012                                         {
3013                                                 new_test_run.expected_n_num_levels = parent_num_levels - n_min_level;
3014                                         }
3015                                         else
3016                                         {
3017                                                 new_test_run.expected_n_num_levels = n_num_levels;
3018                                         }
3019                                 } /* for (all iterations) */
3020                         }        /* if (texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_IMMUTABLE_TEXTURE_OBJECT ||
3021                          texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_TEXTURE_VIEW) */
3022
3023                         /* Store the descriptor */
3024                         m_test_runs.push_back(new_test_run);
3025                 } /* for (all texture targets) */
3026         }        /* for (all texture types) */
3027 }
3028
3029 /** Executes test iteration.
3030  *
3031  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3032  */
3033 tcu::TestNode::IterateResult TextureViewTestGetTexParameter::iterate()
3034 {
3035         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3036
3037         /* Make sure GL_ARB_texture_view is reported as supported before carrying on
3038          * with actual execution */
3039         const std::vector<std::string>& extensions = m_context.getContextInfo().getExtensions();
3040
3041         if (std::find(extensions.begin(), extensions.end(), "GL_ARB_texture_view") == extensions.end())
3042         {
3043                 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported");
3044         }
3045
3046         /* Initialize all objects necessary to execute the test */
3047         initTestRuns();
3048
3049         /* Iterate through all test runs and issue the queries */
3050         for (_test_runs_const_iterator test_run_iterator = m_test_runs.begin(); test_run_iterator != m_test_runs.end();
3051                  test_run_iterator++)
3052         {
3053                 glw::GLfloat     query_texture_immutable_levels_value_float = -1.0f;
3054                 glw::GLint               query_texture_immutable_levels_value_int   = -1;
3055                 glw::GLfloat     query_texture_view_min_layer_value_float   = -1.0f;
3056                 glw::GLint               query_texture_view_min_layer_value_int         = -1;
3057                 glw::GLfloat     query_texture_view_min_level_value_float   = -1.0f;
3058                 glw::GLint               query_texture_view_min_level_value_int         = -1;
3059                 glw::GLfloat     query_texture_view_num_layers_value_float  = -1.0f;
3060                 glw::GLint               query_texture_view_num_layers_value_int        = -1;
3061                 glw::GLfloat     query_texture_view_num_levels_value_float  = -1.0f;
3062                 glw::GLint               query_texture_view_num_levels_value_int        = -1;
3063                 const _test_run& test_run                                                                       = *test_run_iterator;
3064                 glw::GLint               texture_object_id                                                      = 0;
3065
3066                 switch (test_run.texture_type)
3067                 {
3068                 case TEST_TEXTURE_TYPE_IMMUTABLE_TEXTURE_OBJECT:
3069                         texture_object_id = test_run.parent_texture_object_id;
3070                         break;
3071                 case TEST_TEXTURE_TYPE_MUTABLE_TEXTURE_OBJECT:
3072                         texture_object_id = test_run.parent_texture_object_id;
3073                         break;
3074                 case TEST_TEXTURE_TYPE_NO_STORAGE_ALLOCATED:
3075                         texture_object_id = test_run.parent_texture_object_id;
3076                         break;
3077                 case TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_IMMUTABLE_TEXTURE_OBJECT:
3078                         texture_object_id = test_run.texture_view_object_created_from_immutable_to_id;
3079                         break;
3080                 case TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_TEXTURE_VIEW:
3081                         texture_object_id = test_run.texture_view_object_created_from_view_to_id;
3082                         break;
3083
3084                 default:
3085                 {
3086                         TCU_FAIL("Unrecognized texture type");
3087                 }
3088                 }
3089
3090                 /* Bind the texture object of our interest to the target */
3091                 gl.bindTexture(test_run.texture_target, texture_object_id);
3092                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3093
3094                 /* Run all the queries */
3095                 gl.getTexParameterfv(test_run.texture_target, GL_TEXTURE_IMMUTABLE_LEVELS,
3096                                                          &query_texture_immutable_levels_value_float);
3097                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameterfv() failed for GL_TEXTURE_IMMUTABLE_LEVELS pname");
3098
3099                 gl.getTexParameteriv(test_run.texture_target, GL_TEXTURE_IMMUTABLE_LEVELS,
3100                                                          &query_texture_immutable_levels_value_int);
3101                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexPrameteriv() failed for GL_TEXTURE_IMMUTABLE_LEVELS pname");
3102
3103                 gl.getTexParameterfv(test_run.texture_target, GL_TEXTURE_VIEW_MIN_LAYER,
3104                                                          &query_texture_view_min_layer_value_float);
3105                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameterfv() failed for GL_TEXTURE_VIEW_MIN_LAYER pname");
3106
3107                 gl.getTexParameteriv(test_run.texture_target, GL_TEXTURE_VIEW_MIN_LAYER,
3108                                                          &query_texture_view_min_layer_value_int);
3109                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_MIN_LAYER pname");
3110
3111                 gl.getTexParameterfv(test_run.texture_target, GL_TEXTURE_VIEW_MIN_LEVEL,
3112                                                          &query_texture_view_min_level_value_float);
3113                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameterfv() failed for GL_TEXTURE_VIEW_MIN_LEVEL pname");
3114
3115                 gl.getTexParameteriv(test_run.texture_target, GL_TEXTURE_VIEW_MIN_LEVEL,
3116                                                          &query_texture_view_min_level_value_int);
3117                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_MIN_LEVEL pname");
3118
3119                 gl.getTexParameterfv(test_run.texture_target, GL_TEXTURE_VIEW_NUM_LAYERS,
3120                                                          &query_texture_view_num_layers_value_float);
3121                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameterfv() failed for GL_TEXTURE_VIEW_NUM_LAYERS pname");
3122
3123                 gl.getTexParameteriv(test_run.texture_target, GL_TEXTURE_VIEW_NUM_LAYERS,
3124                                                          &query_texture_view_num_layers_value_int);
3125                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_NUM_LAYERS pname");
3126
3127                 gl.getTexParameterfv(test_run.texture_target, GL_TEXTURE_VIEW_NUM_LEVELS,
3128                                                          &query_texture_view_num_levels_value_float);
3129                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameterfv() failed for GL_TEXTURE_VIEW_NUM_LEVELS pname");
3130
3131                 gl.getTexParameteriv(test_run.texture_target, GL_TEXTURE_VIEW_NUM_LEVELS,
3132                                                          &query_texture_view_num_levels_value_int);
3133                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_NUM_LEVELS pname");
3134
3135                 /* Verify the results */
3136                 const float epsilon = 1e-5f;
3137
3138                 if (de::abs(query_texture_immutable_levels_value_float - (float)test_run.expected_n_immutable_levels) > epsilon)
3139                 {
3140                         m_testCtx.getLog() << tcu::TestLog::Message
3141                                                            << "Invalid floating-point value reported for GL_TEXTURE_IMMUTABLE_LEVELS pname "
3142                                                            << "(expected: " << test_run.expected_n_immutable_levels
3143                                                            << " found: " << query_texture_immutable_levels_value_float << ")."
3144                                                            << tcu::TestLog::EndMessage;
3145
3146                         TCU_FAIL("Invalid FP value reported for GL_TEXTURE_IMMUTABLE_LEVELS pname");
3147                 }
3148
3149                 if (query_texture_immutable_levels_value_int != test_run.expected_n_immutable_levels)
3150                 {
3151                         m_testCtx.getLog() << tcu::TestLog::Message
3152                                                            << "Invalid integer value reported for GL_TEXTURE_IMMUTABLE_LEVELS pname "
3153                                                            << "(expected: " << test_run.expected_n_immutable_levels
3154                                                            << " found: " << query_texture_immutable_levels_value_int << ")."
3155                                                            << tcu::TestLog::EndMessage;
3156
3157                         TCU_FAIL("Invalid FP value reported for GL_TEXTURE_IMMUTABLE_LEVELS pname");
3158                 }
3159
3160                 if (de::abs(query_texture_view_min_layer_value_float - (float)test_run.expected_n_min_layer) > epsilon)
3161                 {
3162                         m_testCtx.getLog() << tcu::TestLog::Message
3163                                                            << "Invalid floating-point value reported for GL_TEXTURE_VIEW_MIN_LAYER pname "
3164                                                            << "(expected: " << test_run.expected_n_min_layer
3165                                                            << " found: " << query_texture_view_min_layer_value_float << ")."
3166                                                            << tcu::TestLog::EndMessage;
3167
3168                         TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_MIN_LAYER pname");
3169                 }
3170
3171                 if (query_texture_view_min_layer_value_int != test_run.expected_n_min_layer)
3172                 {
3173                         m_testCtx.getLog() << tcu::TestLog::Message
3174                                                            << "Invalid integer value reported for GL_TEXTURE_VIEW_MIN_LAYER pname "
3175                                                            << "(expected: " << test_run.expected_n_min_layer
3176                                                            << " found: " << query_texture_view_min_layer_value_int << ")."
3177                                                            << tcu::TestLog::EndMessage;
3178
3179                         TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_MIN_LAYER pname");
3180                 }
3181
3182                 if (de::abs(query_texture_view_min_level_value_float - (float)test_run.expected_n_min_level) > epsilon)
3183                 {
3184                         m_testCtx.getLog() << tcu::TestLog::Message
3185                                                            << "Invalid floating-point value reported for GL_TEXTURE_VIEW_MIN_LEVEL pname "
3186                                                            << "(expected: " << test_run.expected_n_min_level
3187                                                            << " found: " << query_texture_view_min_level_value_float << ")."
3188                                                            << tcu::TestLog::EndMessage;
3189
3190                         TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_MIN_LEVEL pname");
3191                 }
3192
3193                 if (query_texture_view_min_level_value_int != test_run.expected_n_min_level)
3194                 {
3195                         m_testCtx.getLog() << tcu::TestLog::Message
3196                                                            << "Invalid integer value reported for GL_TEXTURE_VIEW_MIN_LEVEL pname "
3197                                                            << "(expected: " << test_run.expected_n_min_level
3198                                                            << " found: " << query_texture_view_min_level_value_int << ")."
3199                                                            << tcu::TestLog::EndMessage;
3200
3201                         TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_MIN_LEVEL pname");
3202                 }
3203
3204                 if (de::abs(query_texture_view_num_layers_value_float - (float)test_run.expected_n_num_layers) > epsilon)
3205                 {
3206                         m_testCtx.getLog() << tcu::TestLog::Message
3207                                                            << "Invalid floating-point value reported for GL_TEXTURE_VIEW_NUM_LAYERS pname "
3208                                                            << "(expected: " << test_run.expected_n_num_layers
3209                                                            << " found: " << query_texture_view_num_layers_value_float << ")."
3210                                                            << tcu::TestLog::EndMessage;
3211
3212                         TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_NUM_LAYERS pname");
3213                 }
3214
3215                 if (query_texture_view_num_layers_value_int != test_run.expected_n_num_layers)
3216                 {
3217                         m_testCtx.getLog() << tcu::TestLog::Message
3218                                                            << "Invalid integer value reported for GL_TEXTURE_VIEW_NUM_LAYERS pname "
3219                                                            << "(expected: " << test_run.expected_n_num_layers
3220                                                            << " found: " << query_texture_view_num_layers_value_int << ")."
3221                                                            << tcu::TestLog::EndMessage;
3222
3223                         TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_NUM_LAYERS pname");
3224                 }
3225
3226                 if (de::abs(query_texture_view_num_levels_value_float - (float)test_run.expected_n_num_levels) > epsilon)
3227                 {
3228                         m_testCtx.getLog() << tcu::TestLog::Message
3229                                                            << "Invalid floating-point value reported for GL_TEXTURE_VIEW_NUM_LEVELS pname "
3230                                                            << "(expected: " << test_run.expected_n_num_levels
3231                                                            << " found: " << query_texture_view_num_levels_value_float << ")."
3232                                                            << tcu::TestLog::EndMessage;
3233
3234                         TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_NUM_LEVELS pname");
3235                 }
3236
3237                 if (query_texture_view_num_levels_value_int != test_run.expected_n_num_levels)
3238                 {
3239                         m_testCtx.getLog() << tcu::TestLog::Message
3240                                                            << "Invalid integer value reported for GL_TEXTURE_VIEW_NUM_LEVELS pname "
3241                                                            << "(expected: " << test_run.expected_n_num_levels
3242                                                            << " found: " << query_texture_view_num_levels_value_int << ")."
3243                                                            << tcu::TestLog::EndMessage;
3244
3245                         TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_NUM_LEVELS pname");
3246                 }
3247         } /* for (all test runs) */
3248
3249         /* Test case passed */
3250         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3251
3252         return STOP;
3253 }
3254
3255 /** Constructor.
3256  *
3257  *  @param context Rendering context
3258  **/
3259 TextureViewTestErrors::TextureViewTestErrors(deqp::Context& context)
3260         : TestCase(context, "errors", "test_description")
3261         , m_bo_id(0)
3262         , m_reference_immutable_to_1d_id(0)
3263         , m_reference_immutable_to_2d_id(0)
3264         , m_reference_immutable_to_2d_array_id(0)
3265         , m_reference_immutable_to_2d_array_32_by_33_id(0)
3266         , m_reference_immutable_to_2d_multisample_id(0)
3267         , m_reference_immutable_to_3d_id(0)
3268         , m_reference_immutable_to_cube_map_id(0)
3269         , m_reference_immutable_to_cube_map_array_id(0)
3270         , m_reference_immutable_to_rectangle_id(0)
3271         , m_reference_mutable_to_2d_id(0)
3272         , m_test_modified_to_id_1(0)
3273         , m_test_modified_to_id_2(0)
3274         , m_test_modified_to_id_3(0)
3275         , m_view_bound_to_id(0)
3276         , m_view_never_bound_to_id(0)
3277 {
3278         /* Left blank on purpose */
3279 }
3280
3281 /** Deinitializes all GL objects that may have been generated for the test. */
3282 void TextureViewTestErrors::deinit()
3283 {
3284         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3285
3286         if (m_bo_id != 0)
3287         {
3288                 gl.deleteBuffers(1, &m_bo_id);
3289
3290                 m_bo_id = 0;
3291         }
3292
3293         if (m_reference_immutable_to_1d_id != 0)
3294         {
3295                 gl.deleteTextures(1, &m_reference_immutable_to_1d_id);
3296
3297                 m_reference_immutable_to_1d_id = 0;
3298         }
3299
3300         if (m_reference_immutable_to_2d_id != 0)
3301         {
3302                 gl.deleteTextures(1, &m_reference_immutable_to_2d_id);
3303
3304                 m_reference_immutable_to_2d_id = 0;
3305         }
3306
3307         if (m_reference_immutable_to_2d_array_id != 0)
3308         {
3309                 gl.deleteTextures(1, &m_reference_immutable_to_2d_array_id);
3310
3311                 m_reference_immutable_to_2d_array_id = 0;
3312         }
3313
3314         if (m_reference_immutable_to_2d_array_32_by_33_id != 0)
3315         {
3316                 gl.deleteTextures(1, &m_reference_immutable_to_2d_array_32_by_33_id);
3317
3318                 m_reference_immutable_to_2d_array_32_by_33_id = 0;
3319         }
3320
3321         if (m_reference_immutable_to_2d_multisample_id != 0)
3322         {
3323                 gl.deleteTextures(1, &m_reference_immutable_to_2d_multisample_id);
3324
3325                 m_reference_immutable_to_2d_multisample_id = 0;
3326         }
3327
3328         if (m_reference_immutable_to_3d_id != 0)
3329         {
3330                 gl.deleteTextures(1, &m_reference_immutable_to_3d_id);
3331
3332                 m_reference_immutable_to_3d_id = 0;
3333         }
3334
3335         if (m_reference_immutable_to_cube_map_id != 0)
3336         {
3337                 gl.deleteTextures(1, &m_reference_immutable_to_cube_map_id);
3338
3339                 m_reference_immutable_to_cube_map_id = 0;
3340         }
3341
3342         if (m_reference_immutable_to_cube_map_array_id != 0)
3343         {
3344                 gl.deleteTextures(1, &m_reference_immutable_to_cube_map_array_id);
3345
3346                 m_reference_immutable_to_cube_map_array_id = 0;
3347         }
3348
3349         if (m_reference_immutable_to_rectangle_id != 0)
3350         {
3351                 gl.deleteTextures(1, &m_reference_immutable_to_rectangle_id);
3352
3353                 m_reference_immutable_to_rectangle_id = 0;
3354         }
3355
3356         if (m_reference_mutable_to_2d_id != 0)
3357         {
3358                 gl.deleteTextures(1, &m_reference_mutable_to_2d_id);
3359
3360                 m_reference_mutable_to_2d_id = 0;
3361         }
3362
3363         if (m_test_modified_to_id_1 != 0)
3364         {
3365                 gl.deleteTextures(1, &m_test_modified_to_id_1);
3366
3367                 m_test_modified_to_id_1 = 0;
3368         }
3369
3370         if (m_test_modified_to_id_2 != 0)
3371         {
3372                 gl.deleteTextures(1, &m_test_modified_to_id_2);
3373
3374                 m_test_modified_to_id_2 = 0;
3375         }
3376
3377         if (m_test_modified_to_id_3 != 0)
3378         {
3379                 gl.deleteTextures(1, &m_test_modified_to_id_3);
3380
3381                 m_test_modified_to_id_3 = 0;
3382         }
3383
3384         if (m_view_bound_to_id != 0)
3385         {
3386                 gl.deleteTextures(1, &m_view_bound_to_id);
3387
3388                 m_view_bound_to_id = 0;
3389         }
3390
3391         if (m_view_never_bound_to_id != 0)
3392         {
3393                 gl.deleteTextures(1, &m_view_never_bound_to_id);
3394
3395                 m_view_never_bound_to_id = 0;
3396         }
3397 }
3398
3399 /** Executes test iteration.
3400  *
3401  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3402  */
3403 tcu::TestNode::IterateResult TextureViewTestErrors::iterate()
3404 {
3405         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3406
3407         /* Make sure GL_ARB_texture_view is reported as supported before carrying on
3408          * with actual execution */
3409         const std::vector<std::string>& extensions = m_context.getContextInfo().getExtensions();
3410
3411         if (std::find(extensions.begin(), extensions.end(), "GL_ARB_texture_view") == extensions.end())
3412         {
3413                 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported");
3414         }
3415
3416         /* Create a buffer object that we'll need to use to define storage of
3417          * buffer textures */
3418         gl.genBuffers(1, &m_bo_id);
3419         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
3420
3421         gl.bindBuffer(GL_TEXTURE_BUFFER, m_bo_id);
3422         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
3423
3424         gl.bufferData(GL_TEXTURE_BUFFER, 123, /* arbitrary size */
3425                                   DE_NULL,                                /* data */
3426                                   GL_STATIC_DRAW);
3427         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
3428
3429         /* Create reference texture objects */
3430         const glw::GLint  reference_bo_id                         = m_bo_id;
3431         const glw::GLint  reference_to_depth              = 2;
3432         const glw::GLenum reference_to_format             = GL_RGBA;
3433         const glw::GLint  reference_to_height             = 64;
3434         const glw::GLenum reference_to_internalformat = GL_RGBA32F;
3435         const glw::GLint  reference_n_cubemaps            = 1;
3436         const glw::GLint  reference_n_levels              = 1;
3437         const glw::GLenum reference_to_type                       = GL_FLOAT;
3438         const glw::GLint  reference_to_width              = 64;
3439
3440         gl.genTextures(1, &m_reference_immutable_to_1d_id);
3441         gl.genTextures(1, &m_reference_immutable_to_2d_id);
3442         gl.genTextures(1, &m_reference_immutable_to_2d_array_id);
3443         gl.genTextures(1, &m_reference_immutable_to_2d_array_32_by_33_id);
3444         gl.genTextures(1, &m_reference_immutable_to_2d_multisample_id);
3445         gl.genTextures(1, &m_reference_immutable_to_3d_id);
3446         gl.genTextures(1, &m_reference_immutable_to_cube_map_id);
3447         gl.genTextures(1, &m_reference_immutable_to_cube_map_array_id);
3448         gl.genTextures(1, &m_reference_immutable_to_rectangle_id);
3449         gl.genTextures(1, &m_reference_mutable_to_2d_id);
3450         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
3451
3452         /* Retrieve GL_SAMPLES value - we'll need it to initialize multisample storage */
3453         glw::GLint gl_max_samples_value = 0;
3454
3455         gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, reference_to_internalformat, GL_SAMPLES,
3456                                                    1 /* bufSize - first result */, &gl_max_samples_value);
3457         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed for GL_SAMPLES pname");
3458
3459         /* Set up texture storage for single-dimensional texture object */
3460         gl.bindTexture(GL_TEXTURE_1D, m_reference_immutable_to_1d_id);
3461         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3462
3463         gl.texStorage1D(GL_TEXTURE_1D, reference_n_levels, reference_to_internalformat, reference_to_width);
3464         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage1D() call failed");
3465
3466         /* Set up immutable texture storage for two-dimensional texture object */
3467         gl.bindTexture(GL_TEXTURE_2D, m_reference_immutable_to_2d_id);
3468         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3469
3470         gl.texStorage2D(GL_TEXTURE_2D, reference_n_levels, reference_to_internalformat, reference_to_width,
3471                                         reference_to_height);
3472         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
3473
3474         /* Set up immutable texture storage for two-dimensional array texture object */
3475         gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_reference_immutable_to_2d_array_id);
3476         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3477
3478         gl.texStorage3D(GL_TEXTURE_2D_ARRAY, reference_n_levels, reference_to_internalformat, reference_to_width,
3479                                         reference_to_height, reference_to_depth);
3480         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed");
3481
3482         /* Set up immutable texture storage for two-dimensional array texture object, base
3483          * level of which uses a resolution of 32x33. We'll need it to check case r) */
3484         gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_reference_immutable_to_2d_array_32_by_33_id);
3485         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3486
3487         gl.texStorage3D(GL_TEXTURE_2D_ARRAY, reference_n_levels, reference_to_internalformat, 32, /* width */
3488                                         33,                                                                                                                                               /* height */
3489                                         6); /* depth - 6 layers so that a cube-map/cube-map array view can be created from this texture */
3490         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed");
3491
3492         /* Set up immutable texture storage for two-dimensional multisample texture object */
3493         gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_reference_immutable_to_2d_multisample_id);
3494         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3495
3496         gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, gl_max_samples_value, reference_to_internalformat,
3497                                                            reference_to_width, reference_to_height, GL_TRUE); /* fixedsamplelocations */
3498         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed");
3499
3500         /* Set up immutable texture storage for three-dimensional texture object */
3501         gl.bindTexture(GL_TEXTURE_3D, m_reference_immutable_to_3d_id);
3502         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3503
3504         gl.texStorage3D(GL_TEXTURE_3D, reference_n_levels, reference_to_internalformat, reference_to_width,
3505                                         reference_to_height, reference_to_depth);
3506         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed");
3507
3508         /* Set up immutable texture storage for cube-map texture object */
3509         gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_reference_immutable_to_cube_map_id);
3510         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3511
3512         gl.texStorage2D(GL_TEXTURE_CUBE_MAP, reference_n_levels, reference_to_internalformat, reference_to_width,
3513                                         reference_to_height);
3514         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
3515
3516         /* Set up immutable texture storage for cube-map array texture object */
3517         gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_reference_immutable_to_cube_map_array_id);
3518         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3519
3520         gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, reference_n_levels, reference_to_internalformat, reference_to_width,
3521                                         reference_to_height, 6 /* layer-faces */ * reference_to_depth);
3522         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
3523
3524         /* Set up immutable texture storage for rectangular texture object */
3525         gl.bindTexture(GL_TEXTURE_RECTANGLE, m_reference_immutable_to_rectangle_id);
3526         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3527
3528         gl.texStorage2D(GL_TEXTURE_RECTANGLE, reference_n_levels, reference_to_internalformat, reference_to_width,
3529                                         reference_to_height);
3530         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
3531
3532         /* Set up mutable texture storage for two-dimensional texture object */
3533         gl.bindTexture(GL_TEXTURE_2D, m_reference_mutable_to_2d_id);
3534         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3535
3536         for (glw::GLint n_level = 0; n_level < reference_n_levels; ++n_level)
3537         {
3538                 gl.texImage2D(GL_TEXTURE_2D, n_level, reference_to_internalformat, reference_to_width << n_level,
3539                                           reference_to_height << n_level, 0,                            /* border */
3540                                           reference_to_format, reference_to_type, DE_NULL); /* pixels */
3541
3542                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() call failed");
3543         }
3544
3545         /* Create texture objects we'll be attempting to define as texture views */
3546         gl.genTextures(1, &m_view_bound_to_id);
3547         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
3548
3549         gl.genTextures(1, &m_view_never_bound_to_id);
3550         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
3551
3552         gl.bindTexture(GL_TEXTURE_2D, m_view_bound_to_id);
3553         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3554
3555         /* a) GL_INVALID_VALUE should be generated if <texture> is 0. */
3556         glw::GLint error_code = GL_NO_ERROR;
3557
3558         gl.textureView(0,                                                                                                                                                         /* texture */
3559                                    GL_TEXTURE_2D, m_reference_immutable_to_2d_id, reference_to_internalformat, 0, /* minlevel */
3560                                    reference_n_levels, 0,                                                                                                                 /* minlayer */
3561                                    1);                                                                                                                                                    /* numlayers */
3562
3563         error_code = gl.getError();
3564         if (error_code != GL_INVALID_VALUE)
3565         {
3566                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3567                                                    << "]"
3568                                                           " error generated when passing <texture> argument of 0"
3569                                                           " to a glTextureView(), whereas GL_INVALID_VALUE was "
3570                                                           "expected."
3571                                                    << tcu::TestLog::EndMessage;
3572
3573                 TCU_FAIL("GL_INVALID_VALUE not generated when passing 0 as <texture> argument to a "
3574                                  "glTextureView() call.");
3575         }
3576
3577         /* b) GL_INVALID_OPERATION should be generated if <texture> is not
3578          *    a valid name returned by glGenTextures().
3579          */
3580         const glw::GLint invalid_to_id = 0xFFFFFFFF;
3581
3582         gl.textureView(invalid_to_id, GL_TEXTURE_2D, m_reference_immutable_to_2d_id, reference_to_internalformat,
3583                                    0,                                     /* minlevel */
3584                                    reference_n_levels, 0, /* minlayer */
3585                                    1);                                    /* numlayers */
3586
3587         error_code = gl.getError();
3588         if (error_code != GL_INVALID_OPERATION)
3589         {
3590                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3591                                                    << "]"
3592                                                           " error generated when passing <texture> argument of"
3593                                                           " value that does not correspond to a valid texture "
3594                                                           "object ID, whereas GL_INVALID_OPERATION was expected."
3595                                                    << tcu::TestLog::EndMessage;
3596
3597                 TCU_FAIL("GL_INVALID_OPERATION not generated when passing 0xFFFFFFFF as <texture> "
3598                                  "argument to a glTextureView() call.");
3599         }
3600
3601         /* c) GL_INVALID_OPERATION should be generated if <texture> has
3602          *    already been bound and given a target.
3603          */
3604         gl.textureView(m_view_bound_to_id, GL_TEXTURE_2D, m_reference_immutable_to_2d_id, reference_to_internalformat,
3605                                    0,                                     /* minlevel */
3606                                    reference_n_levels, 0, /* minlayer */
3607                                    1);                                    /* numlayers */
3608
3609         error_code = gl.getError();
3610         if (error_code != GL_INVALID_OPERATION)
3611         {
3612                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3613                                                    << "]"
3614                                                           " error generated when passing <texture> argument "
3615                                                           " that refers to an ID of a texture object that has "
3616                                                           "already been bound to a texture target, whereas "
3617                                                           "GL_INVALID_OPERATION was expected."
3618                                                    << tcu::TestLog::EndMessage;
3619
3620                 TCU_FAIL("GL_INVALID_OPERATION not generated when passing <texture> set"
3621                                  " to an ID of a texture object, that has already been bound to"
3622                                  " a texture target, to a glTextureView() call.");
3623         }
3624
3625         /* d) GL_INVALID_VALUE should be generated if <origtexture> is not
3626          *    the name of a texture object.
3627          */
3628         gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_2D, invalid_to_id, reference_to_internalformat,
3629                                    0,                                     /* minlevel */
3630                                    reference_n_levels, 0, /* minlayer */
3631                                    1);                                    /* numlayers */
3632
3633         error_code = gl.getError();
3634         if (error_code != GL_INVALID_VALUE)
3635         {
3636                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3637                                                    << "]"
3638                                                           " error generated when passing <origtexture> argument "
3639                                                           " of value 0xFFFFFFFF, whereas GL_INVALID_VALUE was "
3640                                                           "expected."
3641                                                    << tcu::TestLog::EndMessage;
3642
3643                 TCU_FAIL("GL_INVALID_VALUE not generated when passing an invalid ID of a texture "
3644                                  "object to <origtexture> argument.");
3645         }
3646
3647         /* e) GL_INVALID_OPERATION error should be generated if <origtexture>
3648          *    is a mutable texture object.
3649          */
3650         gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_2D, m_reference_mutable_to_2d_id, reference_to_internalformat,
3651                                    0,                                     /* minlevel */
3652                                    reference_n_levels, 0, /* minlayer */
3653                                    1);                                    /* numlayers */
3654
3655         error_code = gl.getError();
3656         if (error_code != GL_INVALID_OPERATION)
3657         {
3658                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3659                                                    << "]"
3660                                                           " error generated when passing <origtexture> argument "
3661                                                           " set to refer to a mutable texture object, whereas "
3662                                                           "GL_INVALID_OPERATION was expected."
3663                                                    << tcu::TestLog::EndMessage;
3664
3665                 TCU_FAIL("GL_INVALID_OPERATION not generated when passing an ID of a mutable "
3666                                  "texture object through <origtexture> argument.");
3667         }
3668
3669         /* f) GL_INVALID_OPERATION error should be generated whenever the
3670          *    application tries to generate a texture view for a target
3671          *    that is incompatible with original texture's target. (as per
3672          *    table 8.20 from OpenGL 4.3 specification)
3673          *
3674          *   NOTE: All invalid original+view texture target combinations
3675          *         should be checked.
3676          */
3677         TextureViewUtilities::_incompatible_texture_target_pairs incompatible_texture_target_pairs =
3678                 TextureViewUtilities::getIllegalTextureAndViewTargetCombinations();
3679
3680         for (TextureViewUtilities::_incompatible_texture_target_pairs_const_iterator pair_iterator =
3681                          incompatible_texture_target_pairs.begin();
3682                  pair_iterator != incompatible_texture_target_pairs.end(); pair_iterator++)
3683         {
3684                 TextureViewUtilities::_internalformat_pair texture_target_pair   = *pair_iterator;
3685                 glw::GLenum                                                                original_texture_target = texture_target_pair.first;
3686                 glw::GLenum                                                                view_texture_target   = texture_target_pair.second;
3687
3688                 /* Generate texture IDs */
3689                 gl.genTextures(1, &m_test_modified_to_id_1);
3690                 gl.genTextures(1, &m_test_modified_to_id_2);
3691                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
3692
3693                 /* Configure reference texture object storage */
3694                 gl.bindTexture(original_texture_target, m_test_modified_to_id_1);
3695                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3696
3697                 TextureViewUtilities::initTextureStorage(gl, true, /* create mutable parent texture */
3698                                                                                                  original_texture_target, reference_to_depth, reference_to_height,
3699                                                                                                  reference_to_width, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE,
3700                                                                                                  reference_n_levels, reference_n_cubemaps, reference_bo_id);
3701
3702                 /* Attempt to create the invalid view */
3703                 gl.textureView(m_test_modified_to_id_2,                                          /* texture */
3704                                            view_texture_target, m_test_modified_to_id_1, /* origtexture */
3705                                            reference_to_internalformat, 0,                               /* minlevel */
3706                                            reference_n_levels, 0,                                                /* minlayer */
3707                                            1);                                                                                   /* numlayers */
3708
3709                 error_code = gl.getError();
3710                 if (error_code != GL_INVALID_OPERATION)
3711                 {
3712                         m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3713                                                            << "]"
3714                                                                   " error generated when passing <origtexture> argument "
3715                                                                   " set to refer to a mutable texture object, whereas "
3716                                                                   "GL_INVALID_OPERATION was expected."
3717                                                            << tcu::TestLog::EndMessage;
3718
3719                         TCU_FAIL("GL_INVALID_OPERATION not generated when passing an ID of a mutable "
3720                                          "texture object through <origtexture> argument.");
3721                 }
3722
3723                 /* Release the texture IDs */
3724                 gl.deleteTextures(1, &m_test_modified_to_id_1);
3725                 m_test_modified_to_id_1 = 0;
3726
3727                 gl.deleteTextures(1, &m_test_modified_to_id_2);
3728                 m_test_modified_to_id_2 = 0;
3729
3730                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call(s) failed");
3731         } /* for (all incompatible texture target pairs) */
3732
3733         /* g) GL_INVALID_OPERATION error should be generated whenever the
3734          *    application tries to create a texture view, internal format
3735          *    of which can be found in table 8.21 of OpenGL 4.4
3736          *    specification, and the texture view's internal format is
3737          *    incompatible with parent object's internal format. Both
3738          *    textures and views should be used as parent objects for the
3739          *    purpose of the test.
3740          *
3741          * NOTE: All invalid texture view internal formats should be
3742          *       checked for all applicable original object's internal
3743          *       formats
3744          */
3745         glw::GLint context_major_version = 0;
3746         glw::GLint context_minor_version = 0;
3747
3748         TextureViewUtilities::getMajorMinorVersionFromContextVersion(m_context.getRenderContext().getType(),
3749                                                                                                                                  &context_major_version, &context_minor_version);
3750
3751         TextureViewUtilities::_incompatible_internalformat_pairs internalformat_pairs =
3752                 TextureViewUtilities::getIllegalTextureAndViewInternalformatCombinations();
3753
3754         for (TextureViewUtilities::_incompatible_internalformat_pairs::const_iterator pair_iterator =
3755                          internalformat_pairs.begin();
3756                  pair_iterator != internalformat_pairs.end(); pair_iterator++)
3757         {
3758                 glw::GLenum src_internalformat  = pair_iterator->first;
3759                 glw::GLenum view_internalformat = pair_iterator->second;
3760
3761                 /* Only run the test for internalformats supported by the tested OpenGL implementation */
3762                 if (!TextureViewUtilities::isInternalformatSupported(src_internalformat, context_major_version,
3763                                                                                                                          context_minor_version) ||
3764                         !TextureViewUtilities::isInternalformatSupported(view_internalformat, context_major_version,
3765                                                                                                                          context_minor_version))
3766                 {
3767                         /* Next iteration, please */
3768                         continue;
3769                 }
3770
3771                 /* Generate texture IDs */
3772                 gl.genTextures(1, &m_test_modified_to_id_1);
3773                 gl.genTextures(1, &m_test_modified_to_id_2);
3774                 gl.genTextures(1, &m_test_modified_to_id_3);
3775                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
3776
3777                 /* Configure reference texture object storage */
3778                 gl.bindTexture(GL_TEXTURE_2D, m_test_modified_to_id_1);
3779                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3780
3781                 TextureViewUtilities::initTextureStorage(
3782                         gl, false,                /* views require immutable parent texture objects */
3783                         GL_TEXTURE_2D, 0, /* texture_depth */
3784                         reference_to_height, reference_to_width, src_internalformat,
3785                         GL_NONE,                           /* texture_format - not needed for immutable texture objects */
3786                         GL_NONE,                           /* texture_type   - not needed for immutable texture objects */
3787                         reference_n_levels, 0, /* n_cubemaps_needed */
3788                         0);                                        /* bo_id */
3789
3790                 /* Attempt to create an invalid view */
3791                 gl.textureView(m_test_modified_to_id_2,                            /* texture */
3792                                            GL_TEXTURE_2D, m_test_modified_to_id_1, /* origtexture */
3793                                            view_internalformat, 0,                                 /* minlevel */
3794                                            reference_n_levels, 0,                                  /* minlayer */
3795                                            1);                                                                     /* numlayers */
3796
3797                 error_code = gl.getError();
3798                 if (error_code != GL_INVALID_OPERATION)
3799                 {
3800                         m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3801                                                            << "]"
3802                                                                   " error generated when requesting a view that uses "
3803                                                                   " an internalformat that is incompatible with parent "
3804                                                                   " texture object's, whereas GL_INVALID_OPERATION was "
3805                                                                   "expected."
3806                                                            << tcu::TestLog::EndMessage;
3807
3808                         TCU_FAIL("GL_INVALID_OPERATION not generated when requesting a texture view that "
3809                                          "uses an internalformat which is incompatible with parent texture's.");
3810                 }
3811
3812                 /* Create a valid view now */
3813                 gl.textureView(m_test_modified_to_id_2,                            /* texture */
3814                                            GL_TEXTURE_2D, m_test_modified_to_id_1, /* origtexture */
3815                                            src_internalformat, 0,                                  /* minlevel */
3816                                            reference_n_levels, 0,                                  /* minlayer */
3817                                            1);                                                                     /* numlayers */
3818
3819                 GLU_EXPECT_NO_ERROR(gl.getError(), "A valid glTextureView() call failed");
3820
3821                 /* Attempt to create an invalid view, using the view we've just created
3822                  * as a parent */
3823                 gl.textureView(m_test_modified_to_id_3,                            /* texture */
3824                                            GL_TEXTURE_2D, m_test_modified_to_id_2, /* origtexture */
3825                                            view_internalformat, 0,                                 /* minlevel */
3826                                            reference_n_levels, 0,                                  /* minlayer */
3827                                            1);                                                                     /* numlayers */
3828
3829                 error_code = gl.getError();
3830                 if (error_code != GL_INVALID_OPERATION)
3831                 {
3832                         m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3833                                                            << "]"
3834                                                                   " error generated when requesting a view that uses "
3835                                                                   " an internalformat that is incompatible with parent "
3836                                                                   " view's, whereas GL_INVALID_OPERATION was expected."
3837                                                            << tcu::TestLog::EndMessage;
3838
3839                         TCU_FAIL("GL_INVALID_OPERATION not generated when requesting a texture view that "
3840                                          "uses an internalformat which is incompatible with parent view's.");
3841                 }
3842
3843                 /* Release the texture IDs */
3844                 gl.deleteTextures(1, &m_test_modified_to_id_1);
3845                 m_test_modified_to_id_1 = 0;
3846
3847                 gl.deleteTextures(1, &m_test_modified_to_id_2);
3848                 m_test_modified_to_id_2 = 0;
3849
3850                 gl.deleteTextures(1, &m_test_modified_to_id_3);
3851                 m_test_modified_to_id_3 = 0;
3852
3853                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call(s) failed");
3854         } /* for (all incompatible texture+view internalformat pairs) */
3855
3856         /* h) GL_INVALID_OPERATION error should be generated whenever the
3857          *    application tries to create a texture view using an internal
3858          *    format that does not match the original texture's, and the
3859          *    original texture's internalformat cannot be found in table
3860          *    8.21 of OpenGL 4.3 specification.
3861          *
3862          *    NOTE: All required base, sized and compressed texture internal
3863          *          formats (as described in section 8.5.1 and table 8.14
3864          *          of OpenGL 4.3 specification) that cannot be found in
3865          *          table 8.21 should be considered for the purpose of this
3866          *          test.
3867          */
3868         for (int n_gl_internalformat = 0; n_gl_internalformat < n_valid_gl_internalformats; ++n_gl_internalformat)
3869         {
3870                 glw::GLenum parent_texture_internalformat = valid_gl_internalformats[n_gl_internalformat];
3871
3872                 /* Only run the test for internalformats supported by the tested OpenGL implementation */
3873                 if (!TextureViewUtilities::isInternalformatSupported(parent_texture_internalformat, context_major_version,
3874                                                                                                                          context_minor_version))
3875                 {
3876                         /* Iterate the loop */
3877                         continue;
3878                 }
3879
3880                 /* For the purpose of the test, only consider internalformats that
3881                  * are not associated with any view class */
3882                 if (TextureViewUtilities::getViewClassForInternalformat(parent_texture_internalformat) == VIEW_CLASS_UNDEFINED)
3883                 {
3884                         /* Initialize parent texture object */
3885                         gl.genTextures(1, &m_test_modified_to_id_1);
3886                         gl.genTextures(1, &m_test_modified_to_id_2);
3887                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
3888
3889                         /* Configure reference texture object storage */
3890                         gl.bindTexture(GL_TEXTURE_2D, m_test_modified_to_id_1);
3891                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3892
3893                         TextureViewUtilities::initTextureStorage(
3894                                 gl, false,                /* views require immutable parent texture objects */
3895                                 GL_TEXTURE_2D, 0, /* texture_depth */
3896                                 reference_to_height, reference_to_width, parent_texture_internalformat,
3897                                 GL_NONE,                           /* texture_format - not needed for immutable texture objects */
3898                                 GL_NONE,                           /* texture_type   - not needed for immutable texture objects */
3899                                 reference_n_levels, 0, /* n_cubemaps_needed */
3900                                 0);                                        /* bo_id */
3901
3902                         /* Attempt to create the invalid view */
3903                         gl.textureView(m_test_modified_to_id_2,                                                                                                   /* texture */
3904                                                    GL_TEXTURE_2D, m_test_modified_to_id_1,                                                                        /* origtexture */
3905                                                    (parent_texture_internalformat != GL_RGBA32F) ? GL_RGBA32F : GL_RGB32F, 0, /* minlevel */
3906                                                    reference_n_levels, 0,                                                                                                         /* minlayer */
3907                                                    1);                                                                                                                                            /* numlayers */
3908
3909                         error_code = gl.getError();
3910                         if (error_code != GL_INVALID_OPERATION)
3911                         {
3912                                 m_testCtx.getLog() << tcu::TestLog::Message << "["
3913                                                                    << TextureViewUtilities::getErrorCodeString(error_code)
3914                                                                    << "]"
3915                                                                           " error generated when requesting a view that uses "
3916                                                                           " an internalformat different than the one used by "
3917                                                                           "parent texture object: "
3918                                                                           "["
3919                                                                    << parent_texture_internalformat
3920                                                                    << "] "
3921                                                                           " and the parent texture's internalformat is not "
3922                                                                           "associated with any view class; GL_INVALID_OPERATION "
3923                                                                           "was expected"
3924                                                                    << tcu::TestLog::EndMessage;
3925
3926                                 TCU_FAIL("GL_INVALID_OPERATION not generated when requesting a texture view for "
3927                                                  "a parent texture, internalformat of which is not associated with any "
3928                                                  "view class, when the view's internalformat is different than the one "
3929                                                  "used for parent texture.");
3930                         }
3931
3932                         /* Release the texture IDs */
3933                         gl.deleteTextures(1, &m_test_modified_to_id_1);
3934                         m_test_modified_to_id_1 = 0;
3935
3936                         gl.deleteTextures(1, &m_test_modified_to_id_2);
3937                         m_test_modified_to_id_2 = 0;
3938
3939                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call(s) failed");
3940                 } /* if (parent texture internalformat is not associated with a view class) */
3941         }        /* for (all valid GL internalformats) */
3942
3943         /* i) GL_INVALID_VALUE error should be generated if <minlevel> is
3944          *    larger than the greatest level of <origtexture>.
3945          */
3946         gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_2D, m_reference_immutable_to_2d_id, reference_to_internalformat,
3947                                    reference_n_levels, /* minlevel */
3948                                    1,                              /* numlevels */
3949                                    0,                              /* minlayer */
3950                                    1);                             /* numlayers */
3951
3952         error_code = gl.getError();
3953         if (error_code != GL_INVALID_VALUE)
3954         {
3955                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3956                                                    << "]"
3957                                                           " error generated when passing <minlevel> argument "
3958                                                           " larger than the greatest level of <origtexture>, whereas "
3959                                                           "GL_INVALID_VALUE was expected."
3960                                                    << tcu::TestLog::EndMessage;
3961
3962                 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of <minlevel> "
3963                                  "larger than the greatest level defined for <origtexture>");
3964         }
3965
3966         /* j) GL_INVALID_VALUE error should be generated if <minlayer> is
3967          *    larger than the greatest layer of <origtexture>.
3968          */
3969         gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_2D_ARRAY, m_reference_immutable_to_2d_array_id,
3970                                    reference_to_internalformat, 0, /* minlevel */
3971                                    reference_n_levels,                     /* numlevels */
3972                                    reference_to_depth,                     /* minlayer */
3973                                    1);                                                     /* numlayers */
3974
3975         error_code = gl.getError();
3976         if (error_code != GL_INVALID_VALUE)
3977         {
3978                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3979                                                    << "]"
3980                                                           " error generated when passing <minlayer> argument "
3981                                                           " larger than the greatest layer of <origtexture>, whereas "
3982                                                           "GL_INVALID_VALUE was expected."
3983                                                    << tcu::TestLog::EndMessage;
3984
3985                 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of <minlayer> "
3986                                  "larger than the greatest layer defined for <origtexture>");
3987         }
3988
3989         /* k) GL_INVALID_VALUE error should be generated if <target> is
3990          *    GL_TEXTURE_CUBE_MAP and <numlayers> is not 6.
3991          */
3992         gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_CUBE_MAP, m_reference_immutable_to_cube_map_id,
3993                                    reference_to_internalformat, 0, /* minlevel */
3994                                    1,                                                      /* numlevels */
3995                                    0,                                                      /* minlayer */
3996                                    5);                                                     /* numlayers - invalid argument value */
3997
3998         error_code = gl.getError();
3999         if (error_code != GL_INVALID_VALUE)
4000         {
4001                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4002                                                    << "]"
4003                                                           " error generated when passing <numlayers> argument of value "
4004                                                           "5 instead of 6 for GL_TEXTURE_CUBE_MAP texture target, whereas "
4005                                                           "GL_INVALID_VALUE was expected."
4006                                                    << tcu::TestLog::EndMessage;
4007
4008                 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 5 to <minlayer>"
4009                                  "argument");
4010         }
4011
4012         /* l) GL_INVALID_VALUE error should be generated if <target> is
4013          *    GL_TEXTURE_CUBE_MAP_ARRAY and <numlayers> is not a multiple
4014          *    of 6.
4015          */
4016         gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_CUBE_MAP_ARRAY, m_reference_immutable_to_cube_map_array_id,
4017                                    reference_to_internalformat, 0, /* minlevel */
4018                                    1,                                                      /* numlevels */
4019                                    0,                                                      /* minlayer */
4020                                    1);                                                     /* numlayers - invalid argument value */
4021
4022         error_code = gl.getError();
4023         if (error_code != GL_INVALID_VALUE)
4024         {
4025                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4026                                                    << "]"
4027                                                           " error generated when passing <numlayers> argument of value "
4028                                                           "1 instead of a multiple of 6 for GL_TEXTURE_CUBE_MAP_ARRAY "
4029                                                           "texture target, whereas GL_INVALID_VALUE was expected."
4030                                                    << tcu::TestLog::EndMessage;
4031
4032                 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 1 to <minlayer>"
4033                                  "argument for a GL_TEXTURE_CUBE_MAP_ARRAY texture target");
4034         }
4035
4036         /* m) GL_INVALID_VALUE error should be generated if <target> is
4037          *    GL_TEXTURE_1D and <numlayers> is not 1;
4038          */
4039         gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_1D, m_reference_immutable_to_1d_id, reference_to_internalformat,
4040                                    0,  /* minlevel */
4041                                    1,  /* numlevels */
4042                                    0,  /* minlayer */
4043                                    2); /* numlayers - invalid argument value */
4044
4045         error_code = gl.getError();
4046         if (error_code != GL_INVALID_VALUE)
4047         {
4048                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4049                                                    << "]"
4050                                                           " error generated when passing <numlayers> argument of value "
4051                                                           "2 instead of 1 for GL_TEXTURE_1D texture target, whereas "
4052                                                           "GL_INVALID_VALUE was expected."
4053                                                    << tcu::TestLog::EndMessage;
4054
4055                 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 2 to <numlayers>"
4056                                  "argument for a GL_TEXTURE_1D texture target");
4057         }
4058
4059         /* n) GL_INVALID_VALUE error should be generated if <target> is
4060          *    GL_TEXTURE_2D and <numlayers> is not 1;
4061          */
4062         gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_2D, m_reference_immutable_to_2d_id, reference_to_internalformat,
4063                                    0,  /* minlevel */
4064                                    1,  /* numlevels */
4065                                    0,  /* minlayer */
4066                                    2); /* numlayers - invalid argument value */
4067
4068         error_code = gl.getError();
4069         if (error_code != GL_INVALID_VALUE)
4070         {
4071                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4072                                                    << "]"
4073                                                           " error generated when passing <numlayers> argument of value "
4074                                                           "2 instead of 1 for GL_TEXTURE_2D texture target, whereas "
4075                                                           "GL_INVALID_VALUE was expected."
4076                                                    << tcu::TestLog::EndMessage;
4077
4078                 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 2 to <numlayers>"
4079                                  "argument for a GL_TEXTURE_2D texture target");
4080         }
4081
4082         /* o) GL_INVALID_VALUE error should be generated if <target> is
4083          *    GL_TEXTURE_3D and <numlayers> is not 1;
4084          */
4085         gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_3D, m_reference_immutable_to_3d_id, reference_to_internalformat,
4086                                    0,  /* minlevel */
4087                                    1,  /* numlevels */
4088                                    0,  /* minlayer */
4089                                    2); /* numlayers - invalid argument value */
4090
4091         error_code = gl.getError();
4092         if (error_code != GL_INVALID_VALUE)
4093         {
4094                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4095                                                    << "]"
4096                                                           " error generated when passing <numlayers> argument of value "
4097                                                           "2 instead of 1 for GL_TEXTURE_3D texture target, whereas "
4098                                                           "GL_INVALID_VALUE was expected."
4099                                                    << tcu::TestLog::EndMessage;
4100
4101                 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 2 to <numlayers>"
4102                                  "argument for a GL_TEXTURE_3D texture target");
4103         }
4104
4105         /* p) GL_INVALID_VALUE error should be generated if <target> is
4106          *    GL_TEXTURE_RECTANGLE and <numlayers> is not 1;
4107          */
4108         gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_RECTANGLE, m_reference_immutable_to_rectangle_id,
4109                                    reference_to_internalformat, 0, /* minlevel */
4110                                    1,                                                      /* numlevels */
4111                                    0,                                                      /* minlayer */
4112                                    2);                                                     /* numlayers - invalid argument value */
4113
4114         error_code = gl.getError();
4115         if (error_code != GL_INVALID_VALUE)
4116         {
4117                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4118                                                    << "]"
4119                                                           " error generated when passing <numlayers> argument of value "
4120                                                           "2 instead of 1 for GL_TEXTURE_RECTANGLE texture target, whereas "
4121                                                           "GL_INVALID_VALUE was expected."
4122                                                    << tcu::TestLog::EndMessage;
4123
4124                 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 2 to <numlayers>"
4125                                  "argument for a GL_TEXTURE_RECTANGLE texture target");
4126         }
4127
4128         /* q) GL_INVALID_VALUE error should be generated if <target> is
4129          *    GL_TEXTURE_2D_MULTISAMPLE and <numlayers> is not 1;
4130          */
4131         gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_2D_MULTISAMPLE, m_reference_immutable_to_2d_multisample_id,
4132                                    reference_to_internalformat, 0, /* minlevel */
4133                                    1,                                                      /* numlevels */
4134                                    0,                                                      /* minlayer */
4135                                    2);                                                     /* numlayers - invalid argument value */
4136
4137         error_code = gl.getError();
4138         if (error_code != GL_INVALID_VALUE)
4139         {
4140                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4141                                                    << "]"
4142                                                           " error generated when passing <numlayers> argument of value "
4143                                                           "2 instead of 1 for GL_TEXTURE_2D_MULTISAMPLE texture target, whereas "
4144                                                           "GL_INVALID_VALUE was expected."
4145                                                    << tcu::TestLog::EndMessage;
4146
4147                 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 2 to <numlayers>"
4148                                  "argument for a GL_TEXTURE_2D_MULTISAMPLE texture target");
4149         }
4150
4151         /* r) GL_INVALID_OPERATION error should be generated if <target> is
4152          *    GL_TEXTURE_CUBE_MAP and original texture's width does not
4153          *    match original texture's height for all levels.
4154          */
4155         gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_CUBE_MAP, m_reference_immutable_to_2d_array_32_by_33_id,
4156                                    reference_to_internalformat, 0, /* minlevel */
4157                                    1,                                                      /* numlevels */
4158                                    0,                                                      /* minlayer */
4159                                    6);                                                     /* numlayers */
4160
4161         error_code = gl.getError();
4162         if (error_code != GL_INVALID_OPERATION)
4163         {
4164                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4165                                                    << "]"
4166                                                           " error generated when using an immutable 2D array texture of 32x33x6 "
4167                                                           "resolution to generate a GL_TEXTURE_CUBE_MAP view, whereas "
4168                                                           "GL_INVALID_OPERATION was expected."
4169                                                    << tcu::TestLog::EndMessage;
4170
4171                 TCU_FAIL("GL_INVALID_OPERATION not generated when using an immutable 2D array texture of "
4172                                  "32x33x6 resolution to generate a GL_TEXTURE_CUBE_MAP view");
4173         }
4174
4175         /* s) GL_INVALID_OPERATION error should be generated if <target> is
4176          *    GL_TEXTURE_CUBE_MAP_ARRAY and original texture's width does
4177          *    not match original texture's height for all levels.
4178          */
4179         gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_CUBE_MAP_ARRAY, m_reference_immutable_to_2d_array_32_by_33_id,
4180                                    reference_to_internalformat, 0, /* minlevel */
4181                                    1,                                                      /* numlevels */
4182                                    0,                                                      /* minlayer */
4183                                    6);                                                     /* numlayers */
4184
4185         error_code = gl.getError();
4186         if (error_code != GL_INVALID_OPERATION)
4187         {
4188                 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4189                                                    << "]"
4190                                                           " error generated when using an immutable 2D array texture of 32x33x6 "
4191                                                           "resolution to generate a GL_TEXTURE_CUBE_MAP_ARRAY view, whereas "
4192                                                           "GL_INVALID_OPERATION was expected."
4193                                                    << tcu::TestLog::EndMessage;
4194
4195                 TCU_FAIL("GL_INVALID_OPERATION not generated when using an immutable 2D array texture of "
4196                                  "32x33x6 resolution to generate a GL_TEXTURE_CUBE_MAP_ARRAY view");
4197         }
4198
4199         /* Test case passed */
4200         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4201
4202         return STOP;
4203 }
4204
4205 /** Constructor.
4206  *
4207  *  @param context Rendering context.
4208  **/
4209 TextureViewTestViewSampling::TextureViewTestViewSampling(deqp::Context& context)
4210         : TestCase(context, "view_sampling", "Verify that sampling data from texture views, that use internal "
4211                                                                                  "format which is compatible with the original texture's internal "
4212                                                                                  "format, works correctly.")
4213         , m_bo_id(0)
4214         , m_fs_id(0)
4215         , m_gs_id(0)
4216         , m_po_id(0)
4217         , m_po_lod_location(-1)
4218         , m_po_n_face_location(-1)
4219         , m_po_reference_colors_location(-1)
4220         , m_po_texture_location(-1)
4221         , m_po_z_float_location(-1)
4222         , m_po_z_int_location(-1)
4223         , m_tc_id(0)
4224         , m_te_id(0)
4225         , m_vs_id(0)
4226         , m_per_sample_filler_fs_id(0)
4227         , m_per_sample_filler_gs_id(0)
4228         , m_per_sample_filler_po_id(0)
4229         , m_per_sample_filler_po_layer_id_location(-1)
4230         , m_per_sample_filler_po_reference_colors_location(-1)
4231         , m_per_sample_filler_vs_id(0)
4232         , m_result_to_id(0)
4233         , m_to_id(0)
4234         , m_view_to_id(0)
4235         , m_fbo_id(0)
4236         , m_vao_id(0)
4237         , m_max_color_texture_samples_gl_value(0)
4238         , m_iteration_parent_texture_depth(0)
4239         , m_iteration_parent_texture_height(0)
4240         , m_iteration_parent_texture_n_levels(0)
4241         , m_iteration_parent_texture_n_samples(0)
4242         , m_iteration_parent_texture_target(GL_NONE)
4243         , m_iteration_parent_texture_width(0)
4244         , m_iteration_view_texture_minlayer(0)
4245         , m_iteration_view_texture_numlayers(0)
4246         , m_iteration_view_texture_minlevel(0)
4247         , m_iteration_view_texture_numlevels(0)
4248         , m_iteration_view_texture_target(GL_NONE)
4249         , m_reference_texture_depth(4)
4250         , m_reference_texture_height(4)
4251         , m_reference_texture_n_mipmaps(3)
4252         , m_reference_texture_width(4)
4253         , m_reference_color_storage(DE_NULL)
4254         , m_result_data(DE_NULL)
4255 {
4256         /* Left blank on purpose */
4257 }
4258
4259 /** De-initializes all GL objects created for the test. */
4260 void TextureViewTestViewSampling::deinit()
4261 {
4262         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4263
4264         deinitIterationSpecificProgramAndShaderObjects();
4265         deinitPerSampleFillerProgramAndShaderObjects();
4266         deinitTextureObjects();
4267
4268         /* Make sure any buffers we may have allocated during the execution do not leak */
4269         if (m_result_data != DE_NULL)
4270         {
4271                 delete[] m_result_data;
4272
4273                 m_result_data = DE_NULL;
4274         }
4275
4276         /* Deinitialize other objects that are not re-created every iteration */
4277         if (m_bo_id != 0)
4278         {
4279                 gl.deleteBuffers(1, &m_bo_id);
4280
4281                 m_bo_id = 0;
4282         }
4283
4284         if (m_fbo_id != 0)
4285         {
4286                 gl.deleteFramebuffers(1, &m_fbo_id);
4287
4288                 m_fbo_id = 0;
4289         }
4290
4291         if (m_reference_color_storage != DE_NULL)
4292         {
4293                 delete m_reference_color_storage;
4294
4295                 m_reference_color_storage = DE_NULL;
4296         }
4297
4298         if (m_vao_id != 0)
4299         {
4300                 gl.deleteVertexArrays(1, &m_vao_id);
4301
4302                 m_vao_id = 0;
4303         }
4304
4305         /* Restore default GL state the test may have modified */
4306         gl.patchParameteri(GL_PATCH_VERTICES, 3);
4307         gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
4308         gl.pixelStorei(GL_UNPACK_ALIGNMENT, 4);
4309 }
4310
4311 /** De-initializes program and shader objects created for each iteration. **/
4312 void TextureViewTestViewSampling::deinitIterationSpecificProgramAndShaderObjects()
4313 {
4314         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4315
4316         if (m_fs_id != 0)
4317         {
4318                 gl.deleteShader(m_fs_id);
4319
4320                 m_fs_id = 0;
4321         }
4322
4323         if (m_gs_id != 0)
4324         {
4325                 gl.deleteShader(m_gs_id);
4326
4327                 m_gs_id = 0;
4328         }
4329
4330         if (m_po_id != 0)
4331         {
4332                 gl.deleteProgram(m_po_id);
4333
4334                 m_po_id = 0;
4335         }
4336
4337         if (m_tc_id != 0)
4338         {
4339                 gl.deleteShader(m_tc_id);
4340
4341                 m_tc_id = 0;
4342         }
4343
4344         if (m_te_id != 0)
4345         {
4346                 gl.deleteShader(m_te_id);
4347
4348                 m_te_id = 0;
4349         }
4350
4351         if (m_vs_id != 0)
4352         {
4353                 gl.deleteShader(m_vs_id);
4354
4355                 m_vs_id = 0;
4356         }
4357 }
4358
4359 /** De-initializes shader and program objects providing the 'per-sample filling'
4360  *  functionality.
4361  **/
4362 void TextureViewTestViewSampling::deinitPerSampleFillerProgramAndShaderObjects()
4363 {
4364         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4365
4366         if (m_per_sample_filler_fs_id != 0)
4367         {
4368                 gl.deleteShader(m_per_sample_filler_fs_id);
4369
4370                 m_per_sample_filler_fs_id = 0;
4371         }
4372
4373         if (m_per_sample_filler_gs_id != 0)
4374         {
4375                 gl.deleteShader(m_per_sample_filler_gs_id);
4376
4377                 m_per_sample_filler_gs_id = 0;
4378         }
4379
4380         if (m_per_sample_filler_po_id != 0)
4381         {
4382                 gl.deleteProgram(m_per_sample_filler_po_id);
4383
4384                 m_per_sample_filler_po_id = 0;
4385         }
4386
4387         if (m_per_sample_filler_vs_id != 0)
4388         {
4389                 gl.deleteShader(m_per_sample_filler_vs_id);
4390
4391                 m_per_sample_filler_vs_id = 0;
4392         }
4393 }
4394
4395 /** De-initializes texture objects used by the test */
4396 void TextureViewTestViewSampling::deinitTextureObjects()
4397 {
4398         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4399
4400         if (m_result_to_id != 0)
4401         {
4402                 gl.deleteTextures(1, &m_result_to_id);
4403
4404                 m_result_to_id = 0;
4405         }
4406
4407         if (m_to_id != 0)
4408         {
4409                 gl.deleteTextures(1, &m_to_id);
4410
4411                 m_to_id = 0;
4412         }
4413
4414         if (m_view_to_id != 0)
4415         {
4416                 gl.deleteTextures(1, &m_view_to_id);
4417
4418                 m_view_to_id = 0;
4419         }
4420 }
4421
4422 /** Executes a single test iteration.
4423  *
4424  *  @return true if the iteration executed successfully, false otherwise.
4425  **/
4426 bool TextureViewTestViewSampling::executeTest()
4427 {
4428         const glw::Functions& gl         = m_context.getRenderContext().getFunctions();
4429         bool                              result = true;
4430
4431         /* Bind the view to zero texture unit */
4432         gl.activeTexture(GL_TEXTURE0);
4433         GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed.");
4434
4435         gl.bindTexture(m_iteration_view_texture_target, m_view_to_id);
4436         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
4437
4438         /* Bind the buffer object to zero TF binding point */
4439         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
4440         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
4441
4442         /* Activate the test program */
4443         gl.useProgram(m_po_id);
4444         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
4445
4446         /* Update draw framebuffer configuration so that the test's fragment shader draws
4447          * to the result texture */
4448         gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
4449         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
4450
4451         gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_result_to_id, 0); /* level */
4452         GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
4453
4454         /* Allocate enough space to hold reference color data for all sample s*/
4455         float* reference_color_data = new float[m_iteration_parent_texture_n_samples * sizeof(float) * 4 /* rgba */];
4456
4457         /* Iterate through the layer/face/mipmap hierarchy. For each iteration, we
4458          * potentially need to update relevant uniforms controlling the sampling process
4459          * the test program object performs.
4460          */
4461         bool is_view_cm_cma = (m_iteration_view_texture_target == GL_TEXTURE_CUBE_MAP ||
4462                                                    m_iteration_view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
4463
4464         for (unsigned int n_current_layer = m_iteration_view_texture_minlayer;
4465                  n_current_layer < (m_iteration_view_texture_minlayer + m_iteration_view_texture_numlayers) && result;
4466                  n_current_layer++)
4467         {
4468                 unsigned int n_texture_face  = 0;
4469                 unsigned int n_texture_layer = 0;
4470                 unsigned int n_view_face         = 0;
4471                 unsigned int n_view_layer       = 0;
4472
4473                 if (is_view_cm_cma)
4474                 {
4475                         n_texture_face  = n_current_layer % 6;                                                                           /* faces */
4476                         n_texture_layer = n_current_layer / 6;                                                                           /* faces */
4477                         n_view_face             = (n_current_layer - m_iteration_view_texture_minlayer) % 6; /* faces */
4478                         n_view_layer    = (n_current_layer - m_iteration_view_texture_minlayer) / 6; /* faces */
4479                 }
4480                 else
4481                 {
4482                         /* Only cube-map and cube-map array textures consist of faces. */
4483                         n_texture_face  = 0;
4484                         n_texture_layer = n_current_layer;
4485                         n_view_face             = 0;
4486                         n_view_layer    = n_current_layer;
4487                 }
4488
4489                 if (m_po_z_float_location != -1)
4490                 {
4491                         float z = 0.0f;
4492
4493                         if (((false == is_view_cm_cma) && (m_iteration_view_texture_numlayers > 1)) ||
4494                                 ((true == is_view_cm_cma) && (m_iteration_view_texture_numlayers > 6)))
4495                         {
4496                                 if (is_view_cm_cma)
4497                                 {
4498                                         z = float(n_view_layer) / float(m_iteration_view_texture_numlayers / 6 - 1);
4499                                 }
4500                                 else
4501                                 {
4502                                         if (m_iteration_view_texture_numlayers > 1)
4503                                         {
4504                                                 /* The program will be sampling a view so make sure that layer the shader accesses
4505                                                  * is relative to how our view was configured */
4506                                                 z = float(n_view_layer - m_iteration_view_texture_minlayer) /
4507                                                         float(m_iteration_view_texture_numlayers - 1);
4508                                         }
4509                                         else
4510                                         {
4511                                                 /* z should stay at 0 */
4512                                         }
4513                                 }
4514                         }
4515                         else
4516                         {
4517                                 /* z should stay at 0.0 */
4518                         }
4519
4520                         gl.uniform1f(m_po_z_float_location, z);
4521                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f() call failed.");
4522                 }
4523
4524                 if (m_po_z_int_location != -1)
4525                 {
4526                         DE_ASSERT(!is_view_cm_cma);
4527
4528                         gl.uniform1i(m_po_z_int_location, n_current_layer - m_iteration_view_texture_minlayer);
4529                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
4530                 }
4531
4532                 if (m_po_n_face_location != -1)
4533                 {
4534                         gl.uniform1i(m_po_n_face_location, n_view_face);
4535                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
4536                 }
4537
4538                 for (unsigned int n_mipmap = m_iteration_view_texture_minlevel;
4539                          n_mipmap < (m_iteration_view_texture_minlevel + m_iteration_view_texture_numlevels) && result; n_mipmap++)
4540                 {
4541                         if (m_po_lod_location != -1)
4542                         {
4543                                 /* The program will be sampling a view so make sure that LOD the shader accesses
4544                                  * is relative to how our view was configured.
4545                                  */
4546                                 gl.uniform1f(m_po_lod_location, (float)(n_mipmap - m_iteration_view_texture_minlevel));
4547                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
4548                         }
4549
4550                         /* Update local reference color data storage */
4551                         for (unsigned int n_sample = 0; n_sample < m_iteration_parent_texture_n_samples; ++n_sample)
4552                         {
4553                                 tcu::Vec4 reference_color = getReferenceColor(n_texture_layer, n_texture_face, n_mipmap, n_sample);
4554
4555                                 reference_color_data[4 /* rgba */ * n_sample + 0] = reference_color.x();
4556                                 reference_color_data[4 /* rgba */ * n_sample + 1] = reference_color.y();
4557                                 reference_color_data[4 /* rgba */ * n_sample + 2] = reference_color.z();
4558                                 reference_color_data[4 /* rgba */ * n_sample + 3] = reference_color.w();
4559                         }
4560
4561                         /* Upload it to GPU */
4562                         gl.uniform4fv(m_po_reference_colors_location, m_iteration_parent_texture_n_samples, reference_color_data);
4563                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() call failed.");
4564
4565                         /* Bind the texture view to sample from */
4566                         gl.bindTexture(m_iteration_view_texture_target, m_view_to_id);
4567                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
4568
4569                         /* Draw a single patch. Given the rendering pipeline we've defined in the
4570                          * test program object, this should give us a nice full-screen quad, as well
4571                          * as 6*4 ints XFBed out, describing whether the view was sampled correctly.
4572                          */
4573                         gl.beginTransformFeedback(GL_TRIANGLES);
4574                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
4575                         {
4576                                 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
4577                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
4578                         }
4579                         gl.endTransformFeedback();
4580                         GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
4581
4582                         /* In order to verify if the texel data was sampled correctly, we need to do two things:
4583                          *
4584                          * 1) Verify buffer object contents;
4585                          * 2) Make sure that all texels of current render-target are vec4(1).
4586                          *
4587                          */
4588                         const int* bo_storage_ptr = (const int*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4589
4590                         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
4591                         if (bo_storage_ptr == NULL)
4592                         {
4593                                 TCU_FAIL("glMapBuffer() call succeeded but the pointer returned is NULL");
4594                         }
4595
4596                         /* The rendering pipeline should have written 6 vertices * 4 ints to the BO.
4597                          * The integers are set to 1 if the sampled texels were found valid, 0 otherwise,
4598                          * and are arranged in the following order:
4599                          *
4600                          * 1) Result of sampling in vertex shader stage;
4601                          * 2) Result of sampling in tessellation control shader stage;
4602                          * 3) Result of sampling in tessellation evaluation shader stage;
4603                          * 4) Result of sampling in geometry shader stage;
4604                          */
4605                         for (unsigned int n_vertex = 0; n_vertex < 6 /* as per comment */ && result; ++n_vertex)
4606                         {
4607                                 const int* vertex_data_ptr = bo_storage_ptr + n_vertex * 4 /* as per comment */;
4608                                 int                vs_result       = vertex_data_ptr[0];
4609                                 int                tc_result       = vertex_data_ptr[1];
4610                                 int                te_result       = vertex_data_ptr[2];
4611                                 int                gs_result       = vertex_data_ptr[3];
4612
4613                                 if (vs_result != 1)
4614                                 {
4615                                         m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data was sampled in vertex shader stage."
4616                                                                            << tcu::TestLog::EndMessage;
4617
4618                                         result = false;
4619                                 }
4620
4621                                 if (tc_result != 1)
4622                                 {
4623                                         m_testCtx.getLog() << tcu::TestLog::Message
4624                                                                            << "Invalid data was sampled in tessellation control shader stage."
4625                                                                            << tcu::TestLog::EndMessage;
4626
4627                                         result = false;
4628                                 }
4629
4630                                 if (te_result != 1)
4631                                 {
4632                                         m_testCtx.getLog() << tcu::TestLog::Message
4633                                                                            << "Invalid data was sampled in tessellation evaluation shader stage."
4634                                                                            << tcu::TestLog::EndMessage;
4635
4636                                         result = false;
4637                                 }
4638
4639                                 if (gs_result != 1)
4640                                 {
4641                                         m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data was sampled in geometry shader stage."
4642                                                                            << tcu::TestLog::EndMessage;
4643
4644                                         result = false;
4645                                 }
4646                         } /* for (all vertices) */
4647
4648                         /* Unmap the BO */
4649                         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4650                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
4651
4652                         /* Read texels rendered by the fragment shader. The texture attached uses
4653                          * GL_RGBA8 internalformat.*/
4654                         m_result_data = new unsigned char[m_reference_texture_width * m_reference_texture_height * 4 /* RGBA */];
4655
4656                         gl.bindTexture(GL_TEXTURE_2D, m_result_to_id);
4657                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed for GL_TEXTURE_2D texture target.");
4658
4659                         gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RGBA, GL_UNSIGNED_BYTE, m_result_data);
4660                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexImage() call failed.");
4661
4662                         /* The test fails if any of the fragments is not equal to vec4(1) */
4663                         bool fs_result = true;
4664
4665                         for (unsigned int y = 0; y < m_reference_texture_height && fs_result; ++y)
4666                         {
4667                                 const unsigned char* row_ptr = m_result_data + m_reference_texture_width * y * 4 /* RGBA */;
4668
4669                                 for (unsigned int x = 0; x < m_reference_texture_width && fs_result; ++x)
4670                                 {
4671                                         const unsigned char* pixel_ptr = row_ptr + x * 4 /* RGBA */;
4672
4673                                         if (pixel_ptr[0] != 255 || pixel_ptr[1] != 255 || pixel_ptr[2] != 255 || pixel_ptr[3] != 255)
4674                                         {
4675                                                 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data was sampled at (" << x << ", " << y
4676                                                                                    << ") "
4677                                                                                           "in fragment shader stage."
4678                                                                                    << tcu::TestLog::EndMessage;
4679
4680                                                 fs_result = false;
4681                                         }
4682                                 } /* for (all columns) */
4683                         }        /* for (all rows) */
4684
4685                         if (!fs_result)
4686                         {
4687                                 result = false;
4688                         }
4689
4690                         /* Done - we can release the buffer at this point */
4691                         delete[] m_result_data;
4692                         m_result_data = DE_NULL;
4693                 } /* for (all mip-maps) */
4694         }        /* for (all texture layers) */
4695
4696         /* Release the reference color data buffer */
4697         delete[] reference_color_data;
4698         reference_color_data = DE_NULL;
4699
4700         /* All done */
4701         return result;
4702 }
4703
4704 /** Returns a different vec4 every time the function is called. Each component
4705  *  is assigned a normalized value within <0, 1> range.
4706  *
4707  *  @return As per description.
4708  **/
4709 tcu::Vec4 TextureViewTestViewSampling::getRandomReferenceColor()
4710 {
4711         static unsigned int seed = 195;
4712         tcu::Vec4                       result;
4713
4714         result = tcu::Vec4(float((seed) % 255) / 255.0f, float((seed << 3) % 255) / 255.0f,
4715                                            float((seed << 4) % 255) / 255.0f, float((seed << 5) % 255) / 255.0f);
4716
4717         seed += 17;
4718
4719         return result;
4720 }
4721
4722 /** Every test iteration is assigned a different set of so-called reference colors.
4723  *  Depending on the texture target, each reference color corresponds to an unique color
4724  *  used to build different layers/faces/mip-maps or even samples of tose.
4725  *
4726  *  Once the reference color storage is initialized, this function can be used to retrieve
4727  *  details of a color allocated a specific sample of a layer/face mip-map.
4728  *
4729  *  This function will cause an assertion failure if an invalid layer/face/mipmap/sample is
4730  *  requested, as well as if the reference color storage is not initialized at the time of the call.
4731  *
4732  *  @param n_layer  Layer index to use for the query. A value of 0 should be used for non-arrayed
4733  *                  texture targets.
4734  *  @param n_face   Face index to use for the query. A value of 0 should be used for non-CM texture
4735  *                  targets. Otherwise:
4736  *                  * 0 corresponds to +X;
4737  *                  * 1 corresponds to -X;
4738  *                  * 2 corresponds to +Y;
4739  *                  * 3 corresponds to -Y;
4740  *                  * 4 corresponds to +Z;
4741  *                  * 5 corresponds to -Z.
4742  *  @param n_mipmap Mip-map index to use for the query. A value of 0 should be used for non-mipmapped
4743  *                  texture targets.
4744  *  @param n_sample Sample index to use for the query. A value of 0 should be used for single-sampled
4745  *                  texture targets.
4746  *
4747  *  @return Requested color data.
4748  **/
4749 tcu::Vec4 TextureViewTestViewSampling::getReferenceColor(unsigned int n_layer, unsigned int n_face,
4750                                                                                                                  unsigned int n_mipmap, unsigned int n_sample)
4751 {
4752         tcu::Vec4 result;
4753
4754         DE_ASSERT(m_reference_color_storage != DE_NULL);
4755         if (m_reference_color_storage != DE_NULL)
4756         {
4757                 bool is_parent_texture_cm_cma = (m_iteration_parent_texture_target == GL_TEXTURE_CUBE_MAP ||
4758                                                                                  m_iteration_parent_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
4759                 bool is_view_texture_cm_cma = (m_iteration_view_texture_target == GL_TEXTURE_CUBE_MAP ||
4760                                                                            m_iteration_view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
4761
4762                 if (is_view_texture_cm_cma && !is_parent_texture_cm_cma)
4763                 {
4764                         /* Parent texture is not using faces. Compute layer index, as
4765                          * if the texture was actually a CM or a CMA */
4766                         unsigned int temp = n_layer * 6 /* layer-faces per layer */ + n_face;
4767
4768                         n_layer = temp;
4769                         n_face  = 0;
4770                 }
4771                 else if (!is_view_texture_cm_cma && is_parent_texture_cm_cma)
4772                 {
4773                         /* The other way around - assume the texture is a CM or CMA */
4774                         n_face  = n_layer % 6; /* faces per cube-map layer */
4775                         n_layer = n_layer / 6; /* faces per cube-map layer */
4776                 }
4777
4778                 DE_ASSERT(n_face < m_reference_color_storage->n_faces);
4779                 DE_ASSERT(n_layer < m_reference_color_storage->n_layers);
4780                 DE_ASSERT(n_mipmap < m_reference_color_storage->n_mipmaps);
4781                 DE_ASSERT(n_sample < m_reference_color_storage->n_samples);
4782
4783                 /* Hierarchy is:
4784                  *
4785                  * layers -> faces -> mipmaps -> samples */
4786                 const unsigned int index =
4787                         n_layer * (m_reference_color_storage->n_faces * m_reference_color_storage->n_mipmaps *
4788                                            m_reference_color_storage->n_samples) +
4789                         n_face * (m_reference_color_storage->n_mipmaps * m_reference_color_storage->n_samples) +
4790                         n_mipmap * (m_reference_color_storage->n_samples) + n_sample;
4791
4792                 result = m_reference_color_storage->data[index];
4793         }
4794
4795         return result;
4796 }
4797
4798 /* Retrieve max conformant sample count when GL_NV_internalformat_sample_query is supported */
4799 glw::GLint TextureViewTestViewSampling::getMaxConformantSampleCount(glw::GLenum target, glw::GLenum internalFormat)
4800 {
4801         (void)internalFormat;
4802         glw::GLint max_conformant_samples = 0;
4803
4804         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4805
4806         /* Return the max conformant sample count if extension is supported */
4807         if (m_context.getContextInfo().isExtensionSupported("GL_NV_internalformat_sample_query"))
4808         {
4809                 glw::GLint gl_sample_counts = 0;
4810                 gl.getInternalformativ(target, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &gl_sample_counts);
4811                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed for GL_NUM_SAMPLE_COUNTS pname");
4812
4813                 /* Check and return the first conformant sample count */
4814                 glw::GLint* gl_supported_samples = new glw::GLint[gl_sample_counts];
4815                 if (gl_supported_samples)
4816                 {
4817                         gl.getInternalformativ(target, GL_RGBA8, GL_SAMPLES, gl_sample_counts, gl_supported_samples);
4818
4819                         for (glw::GLint i = 0; i < gl_sample_counts; i++)
4820                         {
4821                                 glw::GLint isConformant = 0;
4822                                 gl.getInternalformatSampleivNV(target, GL_RGBA8, gl_supported_samples[i], GL_CONFORMANT_NV, 1,
4823                                                                                            &isConformant);
4824                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformatSampleivNV() call(s) failed");
4825
4826                                 if (isConformant && gl_supported_samples[i] > max_conformant_samples)
4827                                 {
4828                                         max_conformant_samples = gl_supported_samples[i];
4829                                 }
4830                         }
4831                         delete[] gl_supported_samples;
4832                 }
4833         }
4834         else
4835         {
4836                 /* Otherwise return GL_MAX_COLOR_TEXTURE_SAMPLES */
4837                 gl.getIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &max_conformant_samples);
4838                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_COLOR_TEXTURE_SAMPLES pname.");
4839         }
4840
4841         return max_conformant_samples;
4842 }
4843
4844 /** Initializes iteration-specific program object used to sample the texture data. */
4845 void TextureViewTestViewSampling::initIterationSpecificProgramObject()
4846 {
4847         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4848
4849         /* Release shader/program objects that may have been initialized in previous
4850          * iterations.
4851          */
4852         deinitIterationSpecificProgramAndShaderObjects();
4853
4854         /* Create program and shader objects */
4855         m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
4856         m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
4857         m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
4858         m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
4859         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
4860
4861         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
4862
4863         m_po_id = gl.createProgram();
4864         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
4865
4866         /* Prepare token replacement strings */
4867         std::stringstream n_samples_sstream;
4868         std::string               sampler_declarations_string;
4869         std::string               sample_fetch_string;
4870         std::string               sample_fetch_fs_string;
4871         std::size_t               token_location                         = std::string::npos;
4872         const char*               token_n_samples                        = "N_SAMPLES";
4873         const char*               token_sampler_declarations = "SAMPLER_DECLARATIONS";
4874         const char*               token_sample_fetch             = "SAMPLE_FETCH";
4875
4876         n_samples_sstream << m_iteration_parent_texture_n_samples;
4877
4878         switch (m_iteration_view_texture_target)
4879         {
4880         case GL_TEXTURE_1D:
4881         {
4882                 sampler_declarations_string = "uniform sampler1D texture;";
4883                 sample_fetch_string                     = "vec4 current_sample = textureLod(texture, 0.5,        lod);\n";
4884                 sample_fetch_fs_string          = "vec4 current_sample = textureLod(texture, gs_fs_uv.x, lod);\n";
4885
4886                 break;
4887         }
4888
4889         case GL_TEXTURE_1D_ARRAY:
4890         {
4891                 sampler_declarations_string = "uniform sampler1DArray texture;\n"
4892                                                                           "uniform float          z_float;\n";
4893
4894                 sample_fetch_string     = "vec4 current_sample = textureLod(texture, vec2(0.5, z_float), lod);\n";
4895                 sample_fetch_fs_string = "vec4 current_sample = textureLod(texture, vec2(gs_fs_uv.x, z_float), lod);\n";
4896
4897                 break;
4898         }
4899
4900         case GL_TEXTURE_2D:
4901         {
4902                 sampler_declarations_string = "uniform sampler2D texture;";
4903                 sample_fetch_string                     = "vec4 current_sample = textureLod(texture, vec2(0.5), lod);\n";
4904                 sample_fetch_fs_string          = "vec4 current_sample = textureLod(texture, gs_fs_uv, lod);\n";
4905
4906                 break;
4907         }
4908
4909         case GL_TEXTURE_2D_ARRAY:
4910         {
4911                 sampler_declarations_string = "uniform float          z_float;\n"
4912                                                                           "uniform sampler2DArray texture;";
4913
4914                 sample_fetch_string     = "vec4 current_sample = textureLod(texture, vec3(vec2(0.5), z_float), lod);\n";
4915                 sample_fetch_fs_string = "vec4 current_sample = textureLod(texture, vec3(gs_fs_uv, z_float), lod);\n";
4916
4917                 break;
4918         }
4919
4920         case GL_TEXTURE_2D_MULTISAMPLE:
4921         {
4922                 sampler_declarations_string = "uniform sampler2DMS texture;";
4923                 sample_fetch_string                     = "ivec2 texture_size   = textureSize(texture);\n"
4924                                                           "vec4  current_sample = texelFetch (texture,\n"
4925                                                           "                                   ivec2(texture_size.xy / ivec2(2)),\n"
4926                                                           "                                   n_sample);\n";
4927
4928                 sample_fetch_fs_string = "ivec2 texture_size   = textureSize(texture);\n"
4929                                                                  "vec4  current_sample = texelFetch (texture,\n"
4930                                                                  "                                   ivec2(gs_fs_uv * vec2(texture_size)),\n"
4931                                                                  "                                   n_sample);\n";
4932
4933                 break;
4934         }
4935
4936         case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
4937         {
4938                 sampler_declarations_string = "uniform sampler2DMSArray texture;"
4939                                                                           "uniform int              z_int;\n";
4940
4941                 sample_fetch_string = "ivec3 texture_size   = textureSize(texture);\n"
4942                                                           "vec4  current_sample = texelFetch (texture,\n"
4943                                                           "                                   ivec3(texture_size.xy / ivec2(2), z_int),\n"
4944                                                           "                                   n_sample);\n";
4945
4946                 sample_fetch_fs_string =
4947                         "ivec3 texture_size = textureSize(texture);\n"
4948                         "vec4  current_sample = texelFetch (texture,\n"
4949                         "                                   ivec3(ivec2(gs_fs_uv * vec2(texture_size).xy), z_int),\n"
4950                         "                                   n_sample);\n";
4951
4952                 break;
4953         }
4954
4955         case GL_TEXTURE_3D:
4956         {
4957                 sampler_declarations_string = "uniform sampler3D texture;"
4958                                                                           "uniform float     z_float;";
4959
4960                 sample_fetch_string     = "vec4 current_sample = textureLod(texture, vec3(vec2(0.5), z_float), lod);\n";
4961                 sample_fetch_fs_string = "vec4 current_sample = textureLod(texture, vec3(gs_fs_uv, z_float), lod);\n";
4962
4963                 break;
4964         }
4965
4966         case GL_TEXTURE_CUBE_MAP:
4967         {
4968                 sampler_declarations_string = "uniform samplerCube texture;\n"
4969                                                                           "uniform int         n_face;";
4970
4971                 sample_fetch_string = "vec4 current_sample;\n"
4972                                                           "\n"
4973                                                           "switch (n_face)\n"
4974                                                           "{\n"
4975                                                           // GL_TEXTURE_CUBE_MAP_POSITIVE_X
4976                                                           "    case 0: current_sample = textureLod(texture, vec3( 1,  0,  0), lod); break;\n"
4977                                                           // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
4978                                                           "    case 1: current_sample = textureLod(texture, vec3(-1,  0,  0), lod); break;\n"
4979                                                           // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
4980                                                           "    case 2: current_sample = textureLod(texture, vec3( 0,  1,  0), lod); break;\n"
4981                                                           // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
4982                                                           "    case 3: current_sample = textureLod(texture, vec3( 0, -1,  0), lod); break;\n"
4983                                                           // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
4984                                                           "    case 4: current_sample = textureLod(texture, vec3( 0,  0,  1), lod); break;\n"
4985                                                           // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
4986                                                           "    case 5: current_sample = textureLod(texture, vec3( 0,  0, -1), lod); break;\n"
4987                                                           "}\n";
4988
4989                 sample_fetch_fs_string =
4990                         "vec4 current_sample;\n"
4991                         "\n"
4992                         "switch (n_face)\n"
4993                         "{\n"
4994                         // GL_TEXTURE_CUBE_MAP_POSITIVE_X
4995                         "    case 0: current_sample = textureLod(texture, normalize(vec3( 1, gs_fs_uv.xy)), lod); break;\n"
4996                         // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
4997                         "    case 1: current_sample = textureLod(texture, normalize(vec3(-1, gs_fs_uv.xy)), lod); break;\n"
4998                         // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
4999                         "    case 2: current_sample = textureLod(texture, normalize(vec3( gs_fs_uv.x, 1,  gs_fs_uv.y)), lod); "
5000                         "break;\n"
5001                         // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
5002                         "    case 3: current_sample = textureLod(texture, normalize(vec3( gs_fs_uv.x, -1, gs_fs_uv.y)), lod); "
5003                         "break;\n"
5004                         // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
5005                         "    case 4: current_sample = textureLod(texture, normalize(vec3( gs_fs_uv.xy,  1)), lod); break;\n"
5006                         // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
5007                         "    case 5: current_sample = textureLod(texture, normalize(vec3( gs_fs_uv.xy, -1)), lod); break;\n"
5008                         "}\n";
5009                 break;
5010         }
5011
5012         case GL_TEXTURE_CUBE_MAP_ARRAY:
5013         {
5014                 sampler_declarations_string = "uniform samplerCubeArray texture;\n"
5015                                                                           "uniform int              n_face;\n"
5016                                                                           "uniform float            z_float;\n";
5017
5018                 sample_fetch_string =
5019                         "vec4 current_sample;\n"
5020                         "\n"
5021                         "switch (n_face)\n"
5022                         "{\n"
5023                         // GL_TEXTURE_CUBE_MAP_POSITIVE_X
5024                         "    case 0: current_sample = textureLod(texture, vec4( 1,  0,  0, z_float), lod); break;\n"
5025                         // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
5026                         "    case 1: current_sample = textureLod(texture, vec4(-1,  0,  0, z_float), lod); break;\n"
5027                         // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
5028                         "    case 2: current_sample = textureLod(texture, vec4( 0,  1,  0, z_float), lod); break;\n"
5029                         // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
5030                         "    case 3: current_sample = textureLod(texture, vec4( 0, -1,  0, z_float), lod); break;\n"
5031                         // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
5032                         "    case 4: current_sample = textureLod(texture, vec4( 0,  0,  1, z_float), lod); break;\n"
5033                         // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
5034                         "    case 5: current_sample = textureLod(texture, vec4( 0,  0, -1, z_float), lod); break;\n"
5035                         "}\n";
5036
5037                 sample_fetch_fs_string = "vec4 current_sample;\n"
5038                                                                  "\n"
5039                                                                  "switch (n_face)\n"
5040                                                                  "{\n"
5041                                                                  // GL_TEXTURE_CUBE_MAP_POSITIVE_X
5042                                                                  "    case 0: current_sample = textureLod(texture, vec4(normalize(vec3( 1, "
5043                                                                  "gs_fs_uv.xy)), z_float), lod); break;\n"
5044                                                                  // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
5045                                                                  "    case 1: current_sample = textureLod(texture, vec4(normalize(vec3(-1, "
5046                                                                  "gs_fs_uv.xy)), z_float), lod); break;\n"
5047                                                                  // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
5048                                                                  "    case 2: current_sample = textureLod(texture, vec4(normalize(vec3( gs_fs_uv.x, 1, "
5049                                                                  " gs_fs_uv.y)), z_float), lod); break;\n"
5050                                                                  // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
5051                                                                  "    case 3: current_sample = textureLod(texture, vec4(normalize(vec3( gs_fs_uv.x, "
5052                                                                  "-1,  gs_fs_uv.y)), z_float), lod); break;\n"
5053                                                                  // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
5054                                                                  "    case 4: current_sample = textureLod(texture, vec4(normalize(vec3( gs_fs_uv.xy, "
5055                                                                  "1)), z_float), lod); break;\n"
5056                                                                  // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
5057                                                                  "    case 5: current_sample = textureLod(texture, vec4(normalize(vec3( gs_fs_uv.xy, "
5058                                                                  "-1)), z_float), lod); break;\n"
5059                                                                  "}\n";
5060
5061                 break;
5062         }
5063
5064         case GL_TEXTURE_RECTANGLE:
5065         {
5066                 sampler_declarations_string = "uniform sampler2DRect texture;";
5067                 sample_fetch_string                     = "ivec2 texture_size   = textureSize(texture);\n"
5068                                                           "vec4  current_sample = texelFetch (texture, texture_size / ivec2(2));\n";
5069
5070                 sample_fetch_fs_string =
5071                         "ivec2 texture_size   = textureSize(texture);\n"
5072                         "vec4  current_sample = texelFetch (texture, ivec2(gs_fs_uv.xy * vec2(texture_size)));\n";
5073
5074                 break;
5075         }
5076
5077         default:
5078         {
5079                 TCU_FAIL("Unrecognized texture target");
5080         }
5081         } /* switch (m_iteration_view_texture_target) */
5082
5083         /* Set vertex shader's body */
5084         const char* vs_body = "#version 400\n"
5085                                                   "\n"
5086                                                   "uniform float lod;\n"
5087                                                   "uniform vec4 reference_colors[N_SAMPLES];\n"
5088                                                   "SAMPLER_DECLARATIONS\n"
5089                                                   "\n"
5090                                                   "out int vs_tc_vs_sampling_result;\n"
5091                                                   "\n"
5092                                                   "void main()\n"
5093                                                   "{\n"
5094                                                   "    const float epsilon = 1.0 / 255.0;\n"
5095                                                   "\n"
5096                                                   "    vs_tc_vs_sampling_result = 1;\n"
5097                                                   "\n"
5098                                                   "    for (int n_sample = 0; n_sample < N_SAMPLES; ++n_sample)\n"
5099                                                   "    {\n"
5100                                                   "        SAMPLE_FETCH;\n"
5101                                                   "\n"
5102                                                   "        if (abs(current_sample.x - reference_colors[n_sample].x) > epsilon ||\n"
5103                                                   "            abs(current_sample.y - reference_colors[n_sample].y) > epsilon ||\n"
5104                                                   "            abs(current_sample.z - reference_colors[n_sample].z) > epsilon ||\n"
5105                                                   "            abs(current_sample.w - reference_colors[n_sample].w) > epsilon)\n"
5106                                                   "        {\n"
5107                                                   "            vs_tc_vs_sampling_result = int(current_sample.x * 256.0);\n"
5108                                                   "\n"
5109                                                   "            break;\n"
5110                                                   "        }\n"
5111                                                   "    }\n"
5112                                                   "\n"
5113                                                   "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
5114                                                   "}\n";
5115         std::string vs_string = vs_body;
5116
5117         while ((token_location = vs_string.find(token_n_samples)) != std::string::npos)
5118         {
5119                 vs_string.replace(token_location, strlen(token_n_samples), n_samples_sstream.str());
5120         }
5121
5122         while ((token_location = vs_string.find(token_sampler_declarations)) != std::string::npos)
5123         {
5124                 vs_string.replace(token_location, strlen(token_sampler_declarations), sampler_declarations_string);
5125         }
5126
5127         while ((token_location = vs_string.find(token_sample_fetch)) != std::string::npos)
5128         {
5129                 vs_string.replace(token_location, strlen(token_sample_fetch), sample_fetch_string);
5130         }
5131
5132         /* Set tessellation control shader's body */
5133         const char* tc_body = "#version 400\n"
5134                                                   "\n"
5135                                                   "layout(vertices = 1) out;\n"
5136                                                   "\n"
5137                                                   "uniform float lod;\n"
5138                                                   "uniform vec4  reference_colors[N_SAMPLES];\n"
5139                                                   "SAMPLER_DECLARATIONS\n"
5140                                                   "\n"
5141                                                   "in  int vs_tc_vs_sampling_result[];\n"
5142                                                   "out int tc_te_vs_sampling_result[];\n"
5143                                                   "out int tc_te_tc_sampling_result[];\n"
5144                                                   "\n"
5145                                                   "void main()\n"
5146                                                   "{\n"
5147                                                   "    const float epsilon = 1.0 / 255.0;\n"
5148                                                   "\n"
5149                                                   "    tc_te_vs_sampling_result[gl_InvocationID] = vs_tc_vs_sampling_result[gl_InvocationID];\n"
5150                                                   "    tc_te_tc_sampling_result[gl_InvocationID] = 1;\n"
5151                                                   "\n"
5152                                                   "    for (int n_sample = 0; n_sample < N_SAMPLES; ++n_sample)\n"
5153                                                   "    {\n"
5154                                                   "        SAMPLE_FETCH\n"
5155                                                   "\n"
5156                                                   "        if (abs(current_sample.x - reference_colors[n_sample].x) > epsilon ||\n"
5157                                                   "            abs(current_sample.y - reference_colors[n_sample].y) > epsilon ||\n"
5158                                                   "            abs(current_sample.z - reference_colors[n_sample].z) > epsilon ||\n"
5159                                                   "            abs(current_sample.w - reference_colors[n_sample].w) > epsilon)\n"
5160                                                   "        {\n"
5161                                                   "            tc_te_tc_sampling_result[gl_InvocationID] = 0;\n"
5162                                                   "\n"
5163                                                   "            break;\n"
5164                                                   "        }\n"
5165                                                   "    }\n"
5166                                                   "\n"
5167                                                   "   gl_TessLevelInner[0] = 1.0;\n"
5168                                                   "   gl_TessLevelInner[1] = 1.0;\n"
5169                                                   "   gl_TessLevelOuter[0] = 1.0;\n"
5170                                                   "   gl_TessLevelOuter[1] = 1.0;\n"
5171                                                   "   gl_TessLevelOuter[2] = 1.0;\n"
5172                                                   "   gl_TessLevelOuter[3] = 1.0;\n"
5173                                                   "}\n";
5174
5175         std::string tc_string = tc_body;
5176
5177         while ((token_location = tc_string.find(token_n_samples)) != std::string::npos)
5178         {
5179                 tc_string.replace(token_location, strlen(token_n_samples), n_samples_sstream.str());
5180         }
5181
5182         while ((token_location = tc_string.find(token_sampler_declarations)) != std::string::npos)
5183         {
5184                 tc_string.replace(token_location, strlen(token_sampler_declarations), sampler_declarations_string);
5185         }
5186
5187         while ((token_location = tc_string.find(token_sample_fetch)) != std::string::npos)
5188         {
5189                 tc_string.replace(token_location, strlen(token_sample_fetch), sample_fetch_string);
5190         }
5191
5192         /* Set tessellation evaluation shader's body */
5193         const char* te_body = "#version 400\n"
5194                                                   "\n"
5195                                                   "layout(quads) in;\n"
5196                                                   "\n"
5197                                                   "in  int  tc_te_vs_sampling_result[];\n"
5198                                                   "in  int  tc_te_tc_sampling_result[];\n"
5199                                                   "out int  te_gs_vs_sampling_result;\n"
5200                                                   "out int  te_gs_tc_sampling_result;\n"
5201                                                   "out int  te_gs_te_sampling_result;\n"
5202                                                   "out vec2 te_gs_uv;\n"
5203                                                   "\n"
5204                                                   "uniform float lod;\n"
5205                                                   "uniform vec4  reference_colors[N_SAMPLES];\n"
5206                                                   "SAMPLER_DECLARATIONS\n"
5207                                                   "\n"
5208                                                   "void main()\n"
5209                                                   "{\n"
5210                                                   "    te_gs_vs_sampling_result = tc_te_vs_sampling_result[0];\n"
5211                                                   "    te_gs_tc_sampling_result = tc_te_tc_sampling_result[0];\n"
5212                                                   "    te_gs_te_sampling_result = 1;\n"
5213                                                   "\n"
5214                                                   /* gl_TessCoord spans from 0 to 1 for XY. To generate a screen-space quad,
5215                  * we need to project these components to <-1, 1>. */
5216                                                   "    gl_Position.xy = gl_TessCoord.xy * 2.0 - 1.0;\n"
5217                                                   "    gl_Position.zw = vec2(0, 1);\n"
5218                                                   "    te_gs_uv       = vec2(gl_TessCoord.x, 1.0 - gl_TessCoord.y);\n"
5219                                                   "\n"
5220                                                   "\n"
5221                                                   "    const float epsilon = 1.0 / 255.0;\n"
5222                                                   "\n"
5223                                                   "    for (int n_sample = 0; n_sample < N_SAMPLES; ++n_sample)\n"
5224                                                   "    {\n"
5225                                                   "        SAMPLE_FETCH\n"
5226                                                   "\n"
5227                                                   "        if (abs(current_sample.x - reference_colors[n_sample].x) > epsilon ||\n"
5228                                                   "            abs(current_sample.y - reference_colors[n_sample].y) > epsilon ||\n"
5229                                                   "            abs(current_sample.z - reference_colors[n_sample].z) > epsilon ||\n"
5230                                                   "            abs(current_sample.w - reference_colors[n_sample].w) > epsilon)\n"
5231                                                   "        {\n"
5232                                                   "            te_gs_te_sampling_result = 0;\n"
5233                                                   "\n"
5234                                                   "            break;\n"
5235                                                   "        }\n"
5236                                                   "    }\n"
5237                                                   "\n"
5238                                                   "}\n";
5239
5240         std::string te_string = te_body;
5241
5242         while ((token_location = te_string.find(token_n_samples)) != std::string::npos)
5243         {
5244                 te_string.replace(token_location, strlen(token_n_samples), n_samples_sstream.str());
5245         }
5246
5247         while ((token_location = te_string.find(token_sampler_declarations)) != std::string::npos)
5248         {
5249                 te_string.replace(token_location, strlen(token_sampler_declarations), sampler_declarations_string);
5250         }
5251
5252         while ((token_location = te_string.find(token_sample_fetch)) != std::string::npos)
5253         {
5254                 te_string.replace(token_location, strlen(token_sample_fetch), sample_fetch_string);
5255         }
5256
5257         /* Set geometry shader's body */
5258         const char* gs_body = "#version 400\n"
5259                                                   "\n"
5260                                                   "layout (triangles)                        in;\n"
5261                                                   "layout (triangle_strip, max_vertices = 3) out;\n"
5262                                                   "\n"
5263                                                   "in  int  te_gs_vs_sampling_result[];\n"
5264                                                   "in  int  te_gs_tc_sampling_result[];\n"
5265                                                   "in  int  te_gs_te_sampling_result[];\n"
5266                                                   "in  vec2 te_gs_uv                [];\n"
5267                                                   "out int  gs_fs_vs_sampling_result;\n"
5268                                                   "out int  gs_fs_tc_sampling_result;\n"
5269                                                   "out int  gs_fs_te_sampling_result;\n"
5270                                                   "out int  gs_fs_gs_sampling_result;\n"
5271                                                   "out vec2 gs_fs_uv;\n"
5272                                                   "\n"
5273                                                   "uniform float lod;\n"
5274                                                   "uniform vec4  reference_colors[N_SAMPLES];\n"
5275                                                   "SAMPLER_DECLARATIONS\n"
5276                                                   "\n"
5277                                                   "void main()\n"
5278                                                   "{\n"
5279                                                   "    const float epsilon            = 1.0 / 255.0;\n"
5280                                                   "    int         gs_sampling_result = 1;\n"
5281                                                   "    int         tc_sampling_result = te_gs_tc_sampling_result[0] & "
5282                                                   "te_gs_tc_sampling_result[1] & te_gs_tc_sampling_result[2];\n"
5283                                                   "    int         te_sampling_result = te_gs_te_sampling_result[0] & "
5284                                                   "te_gs_te_sampling_result[1] & te_gs_te_sampling_result[2];\n"
5285                                                   "    int         vs_sampling_result = te_gs_vs_sampling_result[0] & "
5286                                                   "te_gs_vs_sampling_result[1] & te_gs_vs_sampling_result[2];\n"
5287                                                   "\n"
5288                                                   "    for (int n_sample = 0; n_sample < N_SAMPLES; ++n_sample)\n"
5289                                                   "    {\n"
5290                                                   "        SAMPLE_FETCH;\n"
5291                                                   "\n"
5292                                                   "        if (abs(current_sample.x - reference_colors[n_sample].x) > epsilon ||\n"
5293                                                   "            abs(current_sample.y - reference_colors[n_sample].y) > epsilon ||\n"
5294                                                   "            abs(current_sample.z - reference_colors[n_sample].z) > epsilon ||\n"
5295                                                   "            abs(current_sample.w - reference_colors[n_sample].w) > epsilon)\n"
5296                                                   "        {\n"
5297                                                   "            gs_sampling_result = 0;\n"
5298                                                   "\n"
5299                                                   "            break;\n"
5300                                                   "        }\n"
5301                                                   "    }\n"
5302                                                   "\n"
5303                                                   "    gl_Position              = gl_in[0].gl_Position;\n"
5304                                                   "    gs_fs_uv                 = te_gs_uv[0];\n"
5305                                                   "    gs_fs_gs_sampling_result = gs_sampling_result;\n"
5306                                                   "    gs_fs_tc_sampling_result = tc_sampling_result;\n"
5307                                                   "    gs_fs_te_sampling_result = te_sampling_result;\n"
5308                                                   "    gs_fs_vs_sampling_result = vs_sampling_result;\n"
5309                                                   "    EmitVertex();\n"
5310                                                   "\n"
5311                                                   "    gl_Position              = gl_in[1].gl_Position;\n"
5312                                                   "    gs_fs_uv                 = te_gs_uv[1];\n"
5313                                                   "    gs_fs_gs_sampling_result = gs_sampling_result;\n"
5314                                                   "    gs_fs_tc_sampling_result = tc_sampling_result;\n"
5315                                                   "    gs_fs_te_sampling_result = te_sampling_result;\n"
5316                                                   "    gs_fs_vs_sampling_result = vs_sampling_result;\n"
5317                                                   "    EmitVertex();\n"
5318                                                   "\n"
5319                                                   "    gl_Position              = gl_in[2].gl_Position;\n"
5320                                                   "    gs_fs_uv                 = te_gs_uv[2];\n"
5321                                                   "    gs_fs_gs_sampling_result = gs_sampling_result;\n"
5322                                                   "    gs_fs_tc_sampling_result = tc_sampling_result;\n"
5323                                                   "    gs_fs_te_sampling_result = te_sampling_result;\n"
5324                                                   "    gs_fs_vs_sampling_result = vs_sampling_result;\n"
5325                                                   "    EmitVertex();\n"
5326                                                   "    EndPrimitive();\n"
5327                                                   "}\n";
5328
5329         std::string gs_string = gs_body;
5330
5331         while ((token_location = gs_string.find(token_n_samples)) != std::string::npos)
5332         {
5333                 gs_string.replace(token_location, strlen(token_n_samples), n_samples_sstream.str());
5334         }
5335
5336         while ((token_location = gs_string.find(token_sampler_declarations)) != std::string::npos)
5337         {
5338                 gs_string.replace(token_location, strlen(token_sampler_declarations), sampler_declarations_string);
5339         }
5340
5341         while ((token_location = gs_string.find(token_sample_fetch)) != std::string::npos)
5342         {
5343                 gs_string.replace(token_location, strlen(token_sample_fetch), sample_fetch_string);
5344         }
5345
5346         /* Set fragment shader's body */
5347         const char* fs_body = "#version 400\n"
5348                                                   "\n"
5349                                                   "in vec2 gs_fs_uv;\n"
5350                                                   "\n"
5351                                                   "uniform float lod;\n"
5352                                                   "uniform vec4  reference_colors[N_SAMPLES];\n"
5353                                                   "SAMPLER_DECLARATIONS\n"
5354                                                   "\n"
5355                                                   "out vec4 result;\n"
5356                                                   "\n"
5357                                                   "void main()\n"
5358                                                   "{\n"
5359                                                   "    const float epsilon = 1.0 / 255.0;\n"
5360                                                   "\n"
5361                                                   "    result = vec4(1.0);\n"
5362                                                   "\n"
5363                                                   "    for (int n_sample = 0; n_sample < N_SAMPLES; ++n_sample)\n"
5364                                                   "    {\n"
5365                                                   "        SAMPLE_FETCH\n"
5366                                                   "\n"
5367                                                   "        if (abs(current_sample.x - reference_colors[n_sample].x) > epsilon ||\n"
5368                                                   "            abs(current_sample.y - reference_colors[n_sample].y) > epsilon ||\n"
5369                                                   "            abs(current_sample.z - reference_colors[n_sample].z) > epsilon ||\n"
5370                                                   "            abs(current_sample.w - reference_colors[n_sample].w) > epsilon)\n"
5371                                                   "        {\n"
5372                                                   "            result = vec4(0.0);\n"
5373                                                   "\n"
5374                                                   "            break;\n"
5375                                                   "        }\n"
5376                                                   "    }\n"
5377                                                   "}\n";
5378
5379         std::string fs_string = fs_body;
5380
5381         while ((token_location = fs_string.find(token_n_samples)) != std::string::npos)
5382         {
5383                 fs_string.replace(token_location, strlen(token_n_samples), n_samples_sstream.str());
5384         }
5385
5386         while ((token_location = fs_string.find(token_sampler_declarations)) != std::string::npos)
5387         {
5388                 fs_string.replace(token_location, strlen(token_sampler_declarations), sampler_declarations_string);
5389         }
5390
5391         while ((token_location = fs_string.find(token_sample_fetch)) != std::string::npos)
5392         {
5393                 fs_string.replace(token_location, strlen(token_sample_fetch), sample_fetch_fs_string);
5394         }
5395
5396         /* Configure shader bodies */
5397         const char* fs_body_raw_ptr = fs_string.c_str();
5398         const char* gs_body_raw_ptr = gs_string.c_str();
5399         const char* tc_body_raw_ptr = tc_string.c_str();
5400         const char* te_body_raw_ptr = te_string.c_str();
5401         const char* vs_body_raw_ptr = vs_string.c_str();
5402
5403         gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, NULL /* length */);
5404         gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, NULL /* length */);
5405         gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, NULL /* length */);
5406         gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, NULL /* length */);
5407         gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, NULL /* length */);
5408         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
5409
5410         /* Compile the shaders */
5411         const glw::GLuint  so_ids[] = { m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
5412         const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
5413
5414         const glw::GLchar* shader_sources[] = { fs_body_raw_ptr, gs_body_raw_ptr, tc_body_raw_ptr, te_body_raw_ptr,
5415                                                                                         vs_body_raw_ptr };
5416
5417         for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
5418         {
5419                 glw::GLint compile_status = GL_FALSE;
5420                 glw::GLint so_id                  = so_ids[n_so_id];
5421
5422                 gl.compileShader(so_id);
5423                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
5424
5425                 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
5426                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
5427
5428                 if (compile_status != GL_TRUE)
5429                 {
5430                         char temp[1024];
5431
5432                         gl.getShaderInfoLog(so_id, 1024, NULL, temp);
5433
5434                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation error log:\n"
5435                                                                                                 << temp << "\nShader source:\n"
5436                                                                                                 << shader_sources[n_so_id] << tcu::TestLog::EndMessage;
5437
5438                         TCU_FAIL("Shader compilation failed");
5439                 }
5440
5441                 /* Attach the shaders to the program object */
5442                 gl.attachShader(m_po_id, so_id);
5443                 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed");
5444         } /* for (all shader objects) */
5445
5446         /* Set up XFB */
5447         const char* varying_names[] = { "gs_fs_vs_sampling_result", "gs_fs_tc_sampling_result", "gs_fs_te_sampling_result",
5448                                                                         "gs_fs_gs_sampling_result" };
5449         const unsigned int n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]);
5450
5451         gl.transformFeedbackVaryings(m_po_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
5452         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
5453
5454         /* Link the program object */
5455         glw::GLint link_status = GL_FALSE;
5456
5457         gl.linkProgram(m_po_id);
5458         GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
5459
5460         gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
5461         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
5462
5463         if (link_status != GL_TRUE)
5464         {
5465                 TCU_FAIL("Program linking failed.");
5466         }
5467
5468         /* Retrieve uniform locations. Depending on the iteration, a number of those will be
5469          * inactive.
5470          */
5471         m_po_lod_location                          = gl.getUniformLocation(m_po_id, "lod");
5472         m_po_n_face_location               = gl.getUniformLocation(m_po_id, "n_face");
5473         m_po_reference_colors_location = gl.getUniformLocation(m_po_id, "reference_colors");
5474         m_po_texture_location              = gl.getUniformLocation(m_po_id, "texture");
5475         m_po_z_float_location              = gl.getUniformLocation(m_po_id, "z_float");
5476         m_po_z_int_location                        = gl.getUniformLocation(m_po_id, "z_int");
5477
5478         if (m_po_reference_colors_location == -1)
5479         {
5480                 TCU_FAIL("reference_colors is considered an inactive uniform which is invalid.");
5481         }
5482 }
5483
5484 /** Initializes contents of a texture, from which the view texture will be created. **/
5485 void TextureViewTestViewSampling::initParentTextureContents()
5486 {
5487         static const glw::GLenum cm_texture_targets[] = {
5488                 /* NOTE: This order must match the order used for sampling CM/CMA texture targets. */
5489                 GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
5490                 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
5491         };
5492         static const unsigned int n_cm_texture_targets = sizeof(cm_texture_targets) / sizeof(cm_texture_targets[0]);
5493         const glw::Functions&    gl                                = m_context.getRenderContext().getFunctions();
5494
5495         /* Bind the parent texture */
5496         gl.bindTexture(m_iteration_parent_texture_target, m_to_id);
5497         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
5498
5499         /* If we're dealing with a single-sampled texture target, then we can clear the
5500          * contents of each layer/face/slice using FBO. This will unfortunately not work
5501          * for arrayed textures, layers or layer-faces of which cannot be attached to a draw
5502          * framebuffer.
5503          * If we need to update contents of a multisampled, potentially arrayed texture,
5504          * we'll need to use the filler program.
5505          **/
5506         bool is_arrayed_texture_target = (m_iteration_parent_texture_target == GL_TEXTURE_1D_ARRAY ||
5507                                                                           m_iteration_parent_texture_target == GL_TEXTURE_2D_ARRAY ||
5508                                                                           m_iteration_parent_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
5509         bool is_multisampled_texture_target = (m_iteration_parent_texture_target == GL_TEXTURE_2D_MULTISAMPLE ||
5510                                                                                    m_iteration_parent_texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
5511
5512         if (!is_arrayed_texture_target && !is_multisampled_texture_target)
5513         {
5514                 /* Good, no need to work with samples! */
5515                 DE_ASSERT(m_iteration_parent_texture_depth >= 1);
5516                 DE_ASSERT(m_iteration_parent_texture_n_levels >= 1);
5517
5518                 /* Cube-map texture target cannot be directly used for a glFramebufferTexture2D() call. Instead,
5519                  * we need to split it into 6 cube-map texture targets. */
5520                 unsigned int n_texture_targets                                     = 1;
5521                 glw::GLenum  texture_targets[n_cm_texture_targets] = {
5522                         m_iteration_parent_texture_target, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
5523                 };
5524
5525                 if (m_iteration_parent_texture_target == GL_TEXTURE_CUBE_MAP)
5526                 {
5527                         DE_STATIC_ASSERT(sizeof(texture_targets) == sizeof(cm_texture_targets));
5528                         memcpy(texture_targets, cm_texture_targets, sizeof(cm_texture_targets));
5529
5530                         n_texture_targets = n_cm_texture_targets;
5531                 }
5532
5533                 resetReferenceColorStorage(m_iteration_parent_texture_depth,    /* n_layers */
5534                                                                    n_texture_targets,                                   /* n_faces */
5535                                                                    m_iteration_parent_texture_n_levels, /* n_mipmaps */
5536                                                                    1);                                                                  /* n_samples */
5537
5538                 /* Iterate through all texture targets we need to update */
5539                 for (unsigned int n_texture_target = 0; n_texture_target < n_texture_targets; ++n_texture_target)
5540                 {
5541                         const glw::GLenum texture_target = texture_targets[n_texture_target];
5542
5543                         /* Iterate through all layers of the texture. */
5544                         for (unsigned int n_layer = 0; n_layer < m_iteration_parent_texture_depth; ++n_layer)
5545                         {
5546                                 /* ..and mip-maps, too. */
5547                                 const unsigned int n_mipmaps_for_layer = (texture_target == GL_TEXTURE_3D) ?
5548                                                                                                                          (m_iteration_parent_texture_n_levels - n_layer) :
5549                                                                                                                          (m_iteration_parent_texture_n_levels);
5550
5551                                 for (unsigned int n_mipmap = 0; n_mipmap < n_mipmaps_for_layer; ++n_mipmap)
5552                                 {
5553                                         /* Use appropriate glFramebufferTexture*() API, depending on the texture target of the
5554                                          * parent texture.
5555                                          */
5556                                         switch (texture_target)
5557                                         {
5558                                         case GL_TEXTURE_1D:
5559                                         {
5560                                                 gl.framebufferTexture1D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_1D, m_to_id,
5561                                                                                                 n_mipmap);
5562
5563                                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture1D() call failed.");
5564                                                 break;
5565                                         }
5566
5567                                         case GL_TEXTURE_2D:
5568                                         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5569                                         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5570                                         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5571                                         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5572                                         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5573                                         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5574                                         case GL_TEXTURE_RECTANGLE:
5575                                         {
5576                                                 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target, m_to_id,
5577                                                                                                 n_mipmap);
5578
5579                                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
5580                                                 break;
5581                                         }
5582
5583                                         case GL_TEXTURE_3D:
5584                                         {
5585                                                 gl.framebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, m_to_id,
5586                                                                                                 n_mipmap, n_layer);
5587
5588                                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture3D() call failed.");
5589                                                 break;
5590                                         }
5591
5592                                         default:
5593                                         {
5594                                                 TCU_FAIL("Unrecognized texture target");
5595                                         }
5596                                         } /* switch (m_iteration_parent_texture_target) */
5597
5598                                         /* Each layer/mipmap needs to be assigned an unique vec4. */
5599                                         tcu::Vec4 reference_color = getRandomReferenceColor();
5600
5601                                         setReferenceColor(n_layer, n_texture_target, /* n_face */
5602                                                                           n_mipmap, 0,                           /* n_sample */
5603                                                                           reference_color);
5604
5605                                         /* We should be OK to clear the mip-map at this point */
5606                                         gl.clearColor(reference_color.x(), reference_color.y(), reference_color.z(), reference_color.w());
5607                                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
5608
5609                                         gl.clear(GL_COLOR_BUFFER_BIT);
5610                                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
5611                                 } /* for (all mip-maps) */
5612                         }        /* for (all layers) */
5613                 }                 /* for (all texture targets) */
5614         }                         /* if (!is_arrayed_texture_target && !is_multisampled_texture_target) */
5615         else
5616         {
5617                 /* We need to handle an either multisampled or arrayed texture target or
5618                  * a combination of the two.
5619                  */
5620                 DE_ASSERT(m_iteration_parent_texture_target == GL_TEXTURE_1D_ARRAY ||
5621                                   m_iteration_parent_texture_target == GL_TEXTURE_2D_ARRAY ||
5622                                   m_iteration_parent_texture_target == GL_TEXTURE_2D_MULTISAMPLE ||
5623                                   m_iteration_parent_texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY ||
5624                                   m_iteration_parent_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
5625
5626                 DE_ASSERT(m_iteration_parent_texture_depth >= 1);
5627                 DE_ASSERT(m_iteration_parent_texture_n_levels >= 1);
5628
5629                 const unsigned int n_faces =
5630                         (m_iteration_parent_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY) ? 6 /* faces */ : 1;
5631
5632                 resetReferenceColorStorage(m_iteration_parent_texture_depth,                     /* n_layers */
5633                                                                    n_faces, m_iteration_parent_texture_n_levels, /* n_mipmaps */
5634                                                                    m_max_color_texture_samples_gl_value);                /* n_samples */
5635
5636                 /* Set up storage for reference colors the fragment shader should use
5637                  * when rendering to multisampled texture target */
5638                 float* reference_colors = new float[4 /* rgba */ * m_max_color_texture_samples_gl_value];
5639
5640                 /* Activate the filler program */
5641                 gl.useProgram(m_per_sample_filler_po_id);
5642                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
5643
5644                 /* Iterate through all layers of the texture. */
5645                 for (unsigned int n_layer = 0; n_layer < m_iteration_parent_texture_depth; ++n_layer)
5646                 {
5647                         /* ..faces.. */
5648                         for (unsigned int n_face = 0; n_face < n_faces; ++n_face)
5649                         {
5650                                 /* ..and mip-maps, too. */
5651                                 for (unsigned int n_mipmap = 0; n_mipmap < m_iteration_parent_texture_n_levels; ++n_mipmap)
5652                                 {
5653                                         /* For all texture targets considered excl. GL_TEXTURE_2D_MULTISAMPLE, we need
5654                                          * to use glFramebufferTextur() to bind all layers to the color atatchment. For
5655                                          * 2DMS textures, we can use plain glFramebufferTexture2D().
5656                                          */
5657                                         if (m_iteration_parent_texture_target != GL_TEXTURE_2D_MULTISAMPLE)
5658                                         {
5659                                                 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_id, n_mipmap);
5660
5661                                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTextureLayer() call failed.");
5662                                         }
5663                                         else
5664                                         {
5665                                                 /* Sanity check */
5666                                                 DE_ASSERT(m_iteration_parent_texture_depth == 1);
5667
5668                                                 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5669                                                                                                 m_iteration_parent_texture_target, m_to_id, n_mipmap);
5670
5671                                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
5672                                         }
5673
5674                                         /* Generate reference colors for all samples */
5675                                         const unsigned int n_samples =
5676                                                 (is_multisampled_texture_target) ? m_max_color_texture_samples_gl_value : 1;
5677
5678                                         for (unsigned int n_sample = 0; n_sample < n_samples; ++n_sample)
5679                                         {
5680                                                 tcu::Vec4 reference_color = getRandomReferenceColor();
5681
5682                                                 reference_colors[4 /* rgba */ * n_sample + 0] = reference_color.x();
5683                                                 reference_colors[4 /* rgba */ * n_sample + 1] = reference_color.y();
5684                                                 reference_colors[4 /* rgba */ * n_sample + 2] = reference_color.z();
5685                                                 reference_colors[4 /* rgba */ * n_sample + 3] = reference_color.w();
5686
5687                                                 setReferenceColor(n_layer, n_face, n_mipmap, n_sample, reference_color);
5688                                         } /* for (all samples) */
5689
5690                                         /* Upload the reference sample colors */
5691                                         gl.uniform4fv(m_per_sample_filler_po_reference_colors_location, n_samples, reference_colors);
5692                                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() call failed.");
5693
5694                                         /* Update the layer ID the program should render to */
5695                                         const unsigned int layer_id = n_face * 6 /* faces */ + n_layer;
5696
5697                                         gl.uniform1i(m_per_sample_filler_po_layer_id_location, layer_id);
5698                                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
5699
5700                                         /* Draw the full-screen quad. Geometry shader will draw the quad for us,
5701                                          * so all we need to do is to feed the rendering pipeline with a single
5702                                          * point.
5703                                          */
5704                                         gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
5705                                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
5706                                 } /* for (all mip-maps) */
5707                         }        /* for (all faces) */
5708                 }                 /* for (all layers) */
5709
5710                 delete[] reference_colors;
5711         }
5712 }
5713
5714 /** Initializes the 'per sample filler' program object, used to fill a multi-sample texture
5715  *  with colors varying on a per-sample basis.
5716  */
5717 void TextureViewTestViewSampling::initPerSampleFillerProgramObject()
5718 {
5719         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5720
5721         /* Sanity checks: GL_MAX_COLOR_TEXTURE_SAMPLES is not 0 */
5722         DE_ASSERT(m_max_color_texture_samples_gl_value != 0);
5723
5724         /* Generate program and shader objects */
5725         m_per_sample_filler_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
5726         m_per_sample_filler_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
5727         m_per_sample_filler_vs_id = gl.createShader(GL_VERTEX_SHADER);
5728         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
5729
5730         m_per_sample_filler_po_id = gl.createProgram();
5731         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
5732
5733         /* Configure fragment shader's body */
5734         static const char* fs_body = "#version 400\n"
5735                                                                  "\n"
5736                                                                  "uniform vec4 reference_colors[N_MAX_SAMPLES];\n"
5737                                                                  "\n"
5738                                                                  "out vec4 result;\n"
5739                                                                  "\n"
5740                                                                  "void main()\n"
5741                                                                  "{\n"
5742                                                                  "    result = reference_colors[gl_SampleID];\n"
5743                                                                  "}\n";
5744         std::string               fs_body_string                 = fs_body;
5745         const char*               fs_body_string_raw_ptr = DE_NULL;
5746         std::stringstream n_max_samples_sstream;
5747         const char*               n_max_samples_token = "N_MAX_SAMPLES";
5748         std::size_t               token_location          = std::string::npos;
5749
5750         n_max_samples_sstream << m_max_color_texture_samples_gl_value;
5751
5752         while ((token_location = fs_body_string.find(n_max_samples_token)) != std::string::npos)
5753         {
5754                 fs_body_string.replace(token_location, strlen(n_max_samples_token), n_max_samples_sstream.str());
5755         }
5756
5757         fs_body_string_raw_ptr = fs_body_string.c_str();
5758
5759         gl.shaderSource(m_per_sample_filler_fs_id, 1 /* count */, &fs_body_string_raw_ptr, DE_NULL /* length */);
5760         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
5761
5762         /* Configure geometry shader's body */
5763         static const char* gs_body = "#version 400\n"
5764                                                                  "\n"
5765                                                                  "layout(points)                           in;\n"
5766                                                                  "layout(triangle_strip, max_vertices = 4) out;\n"
5767                                                                  "\n"
5768                                                                  "uniform int layer_id;\n"
5769                                                                  "\n"
5770                                                                  "void main()\n"
5771                                                                  "{\n"
5772                                                                  "    gl_Layer    = layer_id;\n"
5773                                                                  "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
5774                                                                  "    EmitVertex();\n"
5775                                                                  "\n"
5776                                                                  "    gl_Layer    = layer_id;\n"
5777                                                                  "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
5778                                                                  "    EmitVertex();\n"
5779                                                                  "\n"
5780                                                                  "    gl_Layer    = layer_id;\n"
5781                                                                  "    gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
5782                                                                  "    EmitVertex();\n"
5783                                                                  "\n"
5784                                                                  "    gl_Layer    = layer_id;\n"
5785                                                                  "    gl_Position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
5786                                                                  "    EmitVertex();\n"
5787                                                                  "\n"
5788                                                                  "    EndPrimitive();\n"
5789                                                                  "\n"
5790                                                                  "}\n";
5791
5792         gl.shaderSource(m_per_sample_filler_gs_id, 1 /* count */, &gs_body, DE_NULL /* length */);
5793         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
5794
5795         /* Configure vertex shader */
5796         static const char* vs_body = "#version 400\n"
5797                                                                  "\n"
5798                                                                  "void main()\n"
5799                                                                  "{\n"
5800                                                                  "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
5801                                                                  "}\n";
5802
5803         gl.shaderSource(m_per_sample_filler_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
5804         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
5805
5806         /* Attach the shaders to the program object */
5807         gl.attachShader(m_per_sample_filler_po_id, m_per_sample_filler_fs_id);
5808         gl.attachShader(m_per_sample_filler_po_id, m_per_sample_filler_gs_id);
5809         gl.attachShader(m_per_sample_filler_po_id, m_per_sample_filler_vs_id);
5810         GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
5811
5812         /* Compile the shaders */
5813         const glw::GLuint  so_ids[] = { m_per_sample_filler_fs_id, m_per_sample_filler_gs_id, m_per_sample_filler_vs_id };
5814         const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
5815
5816         for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
5817         {
5818                 glw::GLint  compile_status = GL_FALSE;
5819                 glw::GLuint so_id                  = so_ids[n_so_id];
5820
5821                 gl.compileShader(so_id);
5822                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
5823
5824                 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
5825                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiV() call failed.");
5826
5827                 if (compile_status != GL_TRUE)
5828                 {
5829                         TCU_FAIL("Shader compilation failed.");
5830                 }
5831         } /* for (all shader objects) */
5832
5833         /* Link the program object */
5834         glw::GLint link_status = GL_FALSE;
5835
5836         gl.linkProgram(m_per_sample_filler_po_id);
5837         GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
5838
5839         gl.getProgramiv(m_per_sample_filler_po_id, GL_LINK_STATUS, &link_status);
5840         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
5841
5842         if (link_status != GL_TRUE)
5843         {
5844                 TCU_FAIL("Program linking failed.");
5845         }
5846
5847         /* Retrieve uniform locations */
5848         m_per_sample_filler_po_layer_id_location = gl.getUniformLocation(m_per_sample_filler_po_id, "layer_id");
5849         m_per_sample_filler_po_reference_colors_location =
5850                 gl.getUniformLocation(m_per_sample_filler_po_id, "reference_colors[0]");
5851
5852         if (m_per_sample_filler_po_layer_id_location == -1)
5853         {
5854                 TCU_FAIL("layer_id uniform is considered inactive which is invalid");
5855         }
5856
5857         if (m_per_sample_filler_po_reference_colors_location == -1)
5858         {
5859                 TCU_FAIL("reference_colors uniform is considered inactive which is invalid");
5860         }
5861 }
5862
5863 /** Initializes GL objects needed to run the test (excluding iteration-specific objects) */
5864 void TextureViewTestViewSampling::initTest()
5865 {
5866         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5867
5868         /* Generate and configure BO storage to hold result XFB data of a single
5869          * draw call.
5870          *
5871          * Each draw call outputs 6 vertices. For each vertex, 4 ints will be XFBed out. */
5872         gl.genBuffers(1, &m_bo_id);
5873         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
5874
5875         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
5876         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
5877
5878         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 /* draw calls */ * (4 * sizeof(int)), /* as per comment */
5879                                   DE_NULL, GL_STATIC_DRAW);
5880         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
5881
5882         /* Generate a FBO and bind it to both binding targets */
5883         gl.genFramebuffers(1, &m_fbo_id);
5884         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
5885
5886         gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
5887         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
5888
5889         /* Generate and bind a VAO */
5890         gl.genVertexArrays(1, &m_vao_id);
5891         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
5892
5893         gl.bindVertexArray(m_vao_id);
5894         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
5895
5896         /* Generate and configure a texture object we will use to verify view sampling works correctly
5897          * from within a fragment shader.
5898          */
5899         gl.genTextures(1, &m_result_to_id);
5900         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
5901
5902         gl.bindTexture(GL_TEXTURE_2D, m_result_to_id);
5903         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
5904
5905         gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_reference_texture_width, m_reference_texture_height);
5906         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
5907
5908         /* Determine implementation-specific GL_MAX_COLOR_TEXTURE_SAMPLES value */
5909         gl.getIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &m_max_color_texture_samples_gl_value);
5910         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_COLOR_TEXTURE_SAMPLES pname.");
5911
5912         /* Modify pixel storage settings so that we don't rely on the default aligment setting. */
5913         gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
5914         gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
5915         GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call(s) failed.");
5916
5917         /* Modify GL_PATCH_VERTICES setting so that a single patch consists of only a single vertex
5918          * (instead of the default 3) */
5919         gl.patchParameteri(GL_PATCH_VERTICES, 1);
5920         GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
5921 }
5922
5923 /** Initializes and sets up a texture object storage, but does not fill it
5924  *  with actual content. Implements separate code paths for handling parent
5925  *  & view textures.
5926  *
5927  *  @param is_view_texture     true if a view texture should be initialized,
5928  *                             false if te caller needs a parent texture. Note
5929  *                             that a parent texture must be initialized prior
5930  *                             to configuring a view texture.
5931  *  @param texture_target      Texture target to use for the parent texture.
5932  *  @param view_texture_target Texture target to use for the view texture.
5933  **/
5934 void TextureViewTestViewSampling::initTextureObject(bool is_view_texture, glw::GLenum texture_target,
5935                                                                                                         glw::GLenum view_texture_target)
5936 {
5937         const glw::Functions& gl                        = m_context.getRenderContext().getFunctions();
5938         unsigned int              texture_depth = 0;
5939         glw::GLuint*              to_id_ptr             = (is_view_texture) ? &m_view_to_id : &m_to_id;
5940
5941         /* Sanity check: make sure GL_TEXTURE_BUFFER texture target is not requested. This
5942          *               would be against the test specification.
5943          **/
5944         DE_ASSERT(texture_target != GL_TEXTURE_BUFFER);
5945         DE_ASSERT(view_texture_target != GL_TEXTURE_BUFFER);
5946
5947         /* If we're going to be creating a cube-map or cube-map array texture view in this iteration,
5948          * make sure the parent or view texture's depth is valid */
5949         if (view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY)
5950         {
5951                 texture_depth = 13; /* 1 + 2 * (6 faces) */
5952         }
5953         else if (view_texture_target == GL_TEXTURE_CUBE_MAP)
5954         {
5955                 texture_depth = 7; /* 1 + (6 faces) */
5956         }
5957         else
5958         {
5959                 texture_depth = m_reference_texture_depth;
5960         }
5961
5962         if (texture_target == GL_TEXTURE_CUBE_MAP_ARRAY)
5963         {
5964                 texture_depth = 6 /* faces */ * 3;
5965         }
5966
5967         /* Release the texture object, as we're using immutable texture objects and would
5968          * prefer the resources not to leak.
5969          */
5970         if (*to_id_ptr != 0)
5971         {
5972                 gl.deleteTextures(1, to_id_ptr);
5973
5974                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
5975         }
5976
5977         /* Generate a new texture object */
5978         gl.genTextures(1, to_id_ptr);
5979         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
5980
5981         if (is_view_texture)
5982         {
5983                 /* Determine values of arguments we'll pass to glTextureView() call */
5984                 unsigned int minlayer  = 0;
5985                 unsigned int minlevel  = 0;
5986                 unsigned int numlayers = 0;
5987                 unsigned int numlevels = 2;
5988
5989                 const bool is_texture_arrayed_texture_target =
5990                         (texture_target == GL_TEXTURE_1D_ARRAY || texture_target == GL_TEXTURE_2D_ARRAY ||
5991                          texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY || texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
5992                 const bool is_texture_cube_map_texture_target = (texture_target == GL_TEXTURE_CUBE_MAP);
5993                 const bool is_texture_multisample_texture_target =
5994                         (texture_target == GL_TEXTURE_2D_MULTISAMPLE || texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
5995                 const bool is_texture_rectangle_texture_target = (texture_target == GL_TEXTURE_RECTANGLE);
5996                 const bool is_view_arrayed_texture_target =
5997                         (view_texture_target == GL_TEXTURE_1D_ARRAY || view_texture_target == GL_TEXTURE_2D_ARRAY ||
5998                          view_texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY ||
5999                          view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
6000                 const bool is_view_cube_map_texture_target               = (view_texture_target == GL_TEXTURE_CUBE_MAP);
6001                 const bool is_view_cube_map_array_texture_target = (view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
6002
6003                 if (is_texture_multisample_texture_target || is_texture_rectangle_texture_target)
6004                 {
6005                         minlevel  = 0;
6006                         numlevels = 1;
6007                 }
6008                 else
6009                 {
6010                         minlevel = 1;
6011                 }
6012
6013                 if ((true == is_texture_arrayed_texture_target) ||
6014                         ((false == is_texture_cube_map_texture_target) && (true == is_view_cube_map_texture_target)) ||
6015                         ((false == is_texture_cube_map_texture_target) && (true == is_view_cube_map_array_texture_target)))
6016                 {
6017                         minlayer = 1;
6018                 }
6019                 else
6020                 {
6021                         minlayer = 0;
6022                 }
6023
6024                 if (!is_texture_cube_map_texture_target && is_view_cube_map_array_texture_target)
6025                 {
6026                         numlayers = 12;
6027                 }
6028                 else if (is_view_cube_map_texture_target || is_view_cube_map_array_texture_target)
6029                 {
6030                         numlayers = 6;
6031                 }
6032                 else if (is_view_arrayed_texture_target)
6033                 {
6034                         if (is_texture_arrayed_texture_target || is_texture_cube_map_texture_target)
6035                         {
6036                                 numlayers = 2;
6037                         }
6038                         else
6039                         {
6040                                 numlayers = 1;
6041                         }
6042                 }
6043                 else
6044                 {
6045                         numlayers = 1;
6046                 }
6047
6048                 /* Set up view texture */
6049                 gl.textureView(*to_id_ptr, view_texture_target, m_to_id, GL_RGBA8, minlevel, numlevels, minlayer, numlayers);
6050
6051                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed.");
6052
6053                 /* Store the argument values */
6054                 m_iteration_view_texture_minlayer  = minlayer;
6055                 m_iteration_view_texture_minlevel  = minlevel;
6056                 m_iteration_view_texture_numlayers = numlayers;
6057                 m_iteration_view_texture_numlevels = numlevels;
6058                 m_iteration_view_texture_target = view_texture_target;
6059
6060                 m_testCtx.getLog() << tcu::TestLog::Message << "Created a view for texture target "
6061                                                    << "[" << TextureViewUtilities::getTextureTargetString(view_texture_target) << "] "
6062                                                    << "from a parent texture target "
6063                                                    << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6064                                                    << "using arguments: "
6065                                                    << "minlayer:[" << minlayer << "] "
6066                                                    << "minlevel:[" << minlevel << "] "
6067                                                    << "numlayers:[" << numlayers << "] "
6068                                                    << "numlevels:[" << numlevels << "]." << tcu::TestLog::EndMessage;
6069
6070                 gl.bindTexture(view_texture_target, *to_id_ptr);
6071                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
6072         } /* if (is_view_texture) */
6073         else
6074         {
6075                 /* Reset iteration-specific view settings */
6076                 m_iteration_parent_texture_depth         = 1;
6077                 m_iteration_parent_texture_height       = 1;
6078                 m_iteration_parent_texture_n_levels  = 1;
6079                 m_iteration_parent_texture_n_samples = 1;
6080                 m_iteration_parent_texture_width         = 1;
6081
6082                 /* Initialize storage for the newly created texture object */
6083                 gl.bindTexture(texture_target, *to_id_ptr);
6084                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
6085
6086                 /* Use max conformant sample count for multisample texture targets */
6087                 if (texture_target == GL_TEXTURE_2D_MULTISAMPLE || texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
6088                 {
6089                         m_max_color_texture_samples_gl_value = getMaxConformantSampleCount(texture_target, GL_RGBA8);
6090                 }
6091                 else
6092                 {
6093                         /* Use GL_MAX_COLOR_TEXTURE_SAMPLES value for other targets */
6094                         gl.getIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &m_max_color_texture_samples_gl_value);
6095                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_COLOR_TEXTURE_SAMPLES pname.");
6096                 }
6097
6098                 switch (texture_target)
6099                 {
6100                 case GL_TEXTURE_1D:
6101                 {
6102                         gl.texStorage1D(texture_target, m_reference_texture_n_mipmaps, GL_RGBA8, m_reference_texture_width);
6103
6104                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage1D() call failed.");
6105
6106                         m_iteration_parent_texture_n_levels = m_reference_texture_n_mipmaps;
6107                         m_iteration_parent_texture_width        = m_reference_texture_width;
6108
6109                         m_testCtx.getLog() << tcu::TestLog::Message
6110                                                            << "Created an immutable parent texture object for texture target "
6111                                                            << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6112                                                            << "of "
6113                                                            << "levels:[" << m_reference_texture_n_mipmaps << "] "
6114                                                            << "width:[" << m_reference_texture_width << "]." << tcu::TestLog::EndMessage;
6115                         break;
6116                 }
6117
6118                 case GL_TEXTURE_1D_ARRAY:
6119                 {
6120                         gl.texStorage2D(texture_target, m_reference_texture_n_mipmaps, GL_RGBA8, m_reference_texture_width,
6121                                                         texture_depth);
6122
6123                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
6124
6125                         m_iteration_parent_texture_depth        = texture_depth;
6126                         m_iteration_parent_texture_n_levels = m_reference_texture_n_mipmaps;
6127                         m_iteration_parent_texture_width        = m_reference_texture_width;
6128
6129                         m_testCtx.getLog() << tcu::TestLog::Message
6130                                                            << "Created an immutable parent texture object for texture target "
6131                                                            << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6132                                                            << "of "
6133                                                            << "depth:[" << texture_depth << "] "
6134                                                            << "levels:[" << m_reference_texture_n_mipmaps << "] "
6135                                                            << "width:[" << m_reference_texture_width << "]." << tcu::TestLog::EndMessage;
6136
6137                         break;
6138                 }
6139
6140                 case GL_TEXTURE_CUBE_MAP:
6141                 case GL_TEXTURE_2D:
6142                 {
6143                         gl.texStorage2D(texture_target, m_reference_texture_n_mipmaps, GL_RGBA8, m_reference_texture_width,
6144                                                         m_reference_texture_height);
6145
6146                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
6147
6148                         m_iteration_parent_texture_height   = m_reference_texture_height;
6149                         m_iteration_parent_texture_n_levels = m_reference_texture_n_mipmaps;
6150                         m_iteration_parent_texture_width        = m_reference_texture_width;
6151
6152                         m_testCtx.getLog() << tcu::TestLog::Message
6153                                                            << "Created an immutable parent texture object for texture target "
6154                                                            << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6155                                                            << "of "
6156                                                            << "levels:[" << m_reference_texture_n_mipmaps << "] "
6157                                                            << "width:[" << m_reference_texture_width << "] "
6158                                                            << "height:[" << m_reference_texture_height << "]." << tcu::TestLog::EndMessage;
6159
6160                         break;
6161                 }
6162
6163                 case GL_TEXTURE_RECTANGLE:
6164                 {
6165                         gl.texStorage2D(texture_target, 1, /* rectangle textures do not use mip-maps */
6166                                                         GL_RGBA8, m_reference_texture_width, m_reference_texture_height);
6167
6168                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
6169
6170                         m_iteration_parent_texture_height = m_reference_texture_height;
6171                         m_iteration_parent_texture_width  = m_reference_texture_width;
6172
6173                         m_testCtx.getLog() << tcu::TestLog::Message
6174                                                            << "Created an immutable parent texture object for texture target "
6175                                                            << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6176                                                            << "of "
6177                                                            << "levels:1 "
6178                                                            << "width:[" << m_reference_texture_width << "] "
6179                                                            << "height:[" << m_reference_texture_height << "]." << tcu::TestLog::EndMessage;
6180
6181                         break;
6182                 }
6183
6184                 case GL_TEXTURE_2D_ARRAY:
6185                 {
6186                         gl.texStorage3D(texture_target, m_reference_texture_n_mipmaps, GL_RGBA8, m_reference_texture_width,
6187                                                         m_reference_texture_height, texture_depth);
6188
6189                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed.");
6190
6191                         m_iteration_parent_texture_depth        = texture_depth;
6192                         m_iteration_parent_texture_height   = m_reference_texture_height;
6193                         m_iteration_parent_texture_n_levels = m_reference_texture_n_mipmaps;
6194                         m_iteration_parent_texture_width        = m_reference_texture_width;
6195
6196                         m_testCtx.getLog() << tcu::TestLog::Message
6197                                                            << "Created an immutable parent texture object for texture target "
6198                                                            << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6199                                                            << "of "
6200                                                            << "depth:[" << texture_depth << "] "
6201                                                            << "levels:[" << m_reference_texture_n_mipmaps << "] "
6202                                                            << "width:[" << m_reference_texture_width << "] "
6203                                                            << "height:[" << m_reference_texture_height << "]." << tcu::TestLog::EndMessage;
6204
6205                         break;
6206                 }
6207
6208                 case GL_TEXTURE_2D_MULTISAMPLE:
6209                 {
6210                         gl.texStorage2DMultisample(texture_target, m_max_color_texture_samples_gl_value, GL_RGBA8,
6211                                                                            m_reference_texture_width, m_reference_texture_height,
6212                                                                            GL_TRUE); /* fixedsamplelocations */
6213
6214                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed.");
6215
6216                         m_iteration_parent_texture_height       = m_reference_texture_height;
6217                         m_iteration_parent_texture_n_samples = m_max_color_texture_samples_gl_value;
6218                         m_iteration_parent_texture_width         = m_reference_texture_width;
6219
6220                         m_testCtx.getLog() << tcu::TestLog::Message
6221                                                            << "Created an immutable parent texture object for texture target "
6222                                                            << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6223                                                            << "of "
6224                                                            << "samples:[" << m_max_color_texture_samples_gl_value << "] "
6225                                                            << "width:[" << m_reference_texture_width << "] "
6226                                                            << "height:[" << m_reference_texture_height << "]." << tcu::TestLog::EndMessage;
6227
6228                         break;
6229                 }
6230
6231                 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
6232                 {
6233                         gl.texStorage3DMultisample(texture_target, m_max_color_texture_samples_gl_value, GL_RGBA8,
6234                                                                            m_reference_texture_width, m_reference_texture_height, texture_depth,
6235                                                                            GL_TRUE); /* fixed sample locations */
6236
6237                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3DMultisample() call failed.");
6238
6239                         m_iteration_parent_texture_depth         = texture_depth;
6240                         m_iteration_parent_texture_height       = m_reference_texture_height;
6241                         m_iteration_parent_texture_n_samples = m_max_color_texture_samples_gl_value;
6242                         m_iteration_parent_texture_width         = m_reference_texture_width;
6243
6244                         m_testCtx.getLog() << tcu::TestLog::Message
6245                                                            << "Created an immutable parent texture object for texture target "
6246                                                            << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6247                                                            << "of "
6248                                                            << "samples:[" << m_max_color_texture_samples_gl_value << "] "
6249                                                            << "width:[" << m_reference_texture_width << "] "
6250                                                            << "height:[" << m_reference_texture_height << "] "
6251                                                            << "depth:[" << texture_depth << "]." << tcu::TestLog::EndMessage;
6252
6253                         break;
6254                 }
6255
6256                 case GL_TEXTURE_3D:
6257                 case GL_TEXTURE_CUBE_MAP_ARRAY:
6258                 {
6259                         gl.texStorage3D(texture_target, m_reference_texture_n_mipmaps, GL_RGBA8, m_reference_texture_width,
6260                                                         m_reference_texture_height, texture_depth);
6261
6262                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed.");
6263
6264                         m_iteration_parent_texture_depth        = texture_depth;
6265                         m_iteration_parent_texture_height   = m_reference_texture_height;
6266                         m_iteration_parent_texture_n_levels = m_reference_texture_n_mipmaps;
6267                         m_iteration_parent_texture_width        = m_reference_texture_width;
6268
6269                         m_testCtx.getLog() << tcu::TestLog::Message
6270                                                            << "Created an immutable parent texture object for texture target "
6271                                                            << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6272                                                            << "of "
6273                                                            << "levels:[" << m_reference_texture_n_mipmaps << "] "
6274                                                            << "width:[" << m_reference_texture_width << "] "
6275                                                            << "height:[" << m_reference_texture_height << "] "
6276                                                            << "depth:[" << texture_depth << "]." << tcu::TestLog::EndMessage;
6277
6278                         break;
6279                 }
6280
6281                 default:
6282                 {
6283                         TCU_FAIL("Unrecognized texture target.");
6284                 }
6285                 } /* switch (texture_target) */
6286
6287                 m_iteration_parent_texture_target = texture_target;
6288         }
6289
6290         /* Configure texture filtering */
6291         if (texture_target != GL_TEXTURE_2D_MULTISAMPLE && texture_target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY &&
6292                 texture_target != GL_TEXTURE_RECTANGLE)
6293         {
6294                 gl.texParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6295                 gl.texParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
6296
6297                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call(s) failed.");
6298         }
6299 }
6300
6301 /** Executes test iteration.
6302  *
6303  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
6304  */
6305 tcu::TestNode::IterateResult TextureViewTestViewSampling::iterate()
6306 {
6307         bool has_failed = false;
6308
6309         /* Make sure GL_ARB_texture_view is reported as supported before carrying on
6310          * with actual execution */
6311         const std::vector<std::string>& extensions = m_context.getContextInfo().getExtensions();
6312
6313         if (std::find(extensions.begin(), extensions.end(), "GL_ARB_texture_view") == extensions.end())
6314         {
6315                 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported");
6316         }
6317
6318         /* Initialize all objects required to run the test */
6319         initTest();
6320
6321         /* Initialize per-sample filler program */
6322         initPerSampleFillerProgramObject();
6323
6324         /* Iterate through all texture/view texture target combinations */
6325         TextureViewUtilities::_compatible_texture_target_pairs_const_iterator texture_target_iterator;
6326         TextureViewUtilities::_compatible_texture_target_pairs                            texture_target_pairs =
6327                 TextureViewUtilities::getLegalTextureAndViewTargetCombinations();
6328
6329         for (texture_target_iterator = texture_target_pairs.begin(); texture_target_iterator != texture_target_pairs.end();
6330                  ++texture_target_iterator)
6331         {
6332                 const glw::GLenum parent_texture_target = texture_target_iterator->first;
6333                 const glw::GLenum view_texture_target   = texture_target_iterator->second;
6334
6335                 /* Initialize parent texture */
6336                 initTextureObject(false /* is_view_texture */, parent_texture_target, view_texture_target);
6337
6338                 /* Initialize view */
6339                 initTextureObject(true /* is_view_texture */, parent_texture_target, view_texture_target);
6340
6341                 /* Initialize contents of the parent texture */
6342                 initParentTextureContents();
6343
6344                 /* Initialize iteration-specific test program object */
6345                 initIterationSpecificProgramObject();
6346
6347                 /* Run the actual test */
6348                 bool status = executeTest();
6349
6350                 if (!status)
6351                 {
6352                         has_failed = true;
6353
6354                         m_testCtx.getLog() << tcu::TestLog::Message << "Test case failed." << tcu::TestLog::EndMessage;
6355                 }
6356                 else
6357                 {
6358                         m_testCtx.getLog() << tcu::TestLog::Message << "Test case succeeded." << tcu::TestLog::EndMessage;
6359                 }
6360         }
6361
6362         if (!has_failed)
6363         {
6364                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6365         }
6366         else
6367         {
6368                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6369         }
6370
6371         return STOP;
6372 }
6373
6374 /** De-allocates existing reference color storage (if one already exists) and
6375  *  allocates a new one using user-provided properties.
6376  *
6377  *  @param n_layers  Amount of layers to consider. Use a value of 1 for non-arrayed
6378  *                   texture targets.
6379  *  @param n_faces   Amount of faces to consider. Use a value of 1 for non-CM
6380  *                   texture targets.
6381  *  @param n_mipmaps Amount of mip-maps to consider. Use a value of 1 for non-mipmapped
6382  *                   texture targets.
6383  *  @param n_samples Amount of samples to consider. Use a value of 1 for single-sampled
6384  *                   texture targets.
6385  **/
6386 void TextureViewTestViewSampling::resetReferenceColorStorage(unsigned int n_layers, unsigned int n_faces,
6387                                                                                                                          unsigned int n_mipmaps, unsigned int n_samples)
6388 {
6389         /* Sanity checks */
6390         DE_ASSERT(n_layers >= 1);
6391         DE_ASSERT(n_faces >= 1);
6392         DE_ASSERT(n_mipmaps >= 1);
6393         DE_ASSERT(n_samples >= 1);
6394
6395         /* Allocate the descriptor if it's the first time the test will be
6396          * attempting to access it */
6397         if (m_reference_color_storage == DE_NULL)
6398         {
6399                 m_reference_color_storage = new _reference_color_storage(n_faces, n_layers, n_mipmaps, n_samples);
6400         }
6401         else
6402         {
6403                 /* The descriptor's already there so we only need to update the properties */
6404                 m_reference_color_storage->n_faces   = n_faces;
6405                 m_reference_color_storage->n_layers  = n_layers;
6406                 m_reference_color_storage->n_mipmaps = n_mipmaps;
6407                 m_reference_color_storage->n_samples = n_samples;
6408         }
6409
6410         /* If there's any data descriptor found allocated at this point,
6411          * release it */
6412         if (m_reference_color_storage->data != DE_NULL)
6413         {
6414                 delete[] m_reference_color_storage->data;
6415
6416                 m_reference_color_storage->data = DE_NULL;
6417         }
6418
6419         m_reference_color_storage->data = new tcu::Vec4[n_layers * n_faces * n_mipmaps * n_samples];
6420 }
6421
6422 /** Assigns user-specified reference color to a specific sample of a layer/face's mip-map.
6423  *
6424  *  This function throws an assertion failure if the requested layer/face/mip-map/sample index
6425  *  is invalid.
6426  *
6427  *  @param n_layer  Layer index to use for the association. Use a value of 0 for non-arrayed texture
6428  *                  targets.
6429  *  @param n_face   Face index to use for the association. Use a value of 0 for non-CM texture targets.
6430  *  @param n_mipmap Mip-map index to use for the association. Use a value of 0 for non-mipmapped texture
6431  *                  targets.
6432  *  @param n_sample Sample index to use for the association. Use a value of 0 for single-sampled texture
6433  *                  targets.
6434  *  @param color    Color to associate with the specified sample.
6435  **/
6436 void TextureViewTestViewSampling::setReferenceColor(unsigned int n_layer, unsigned int n_face, unsigned int n_mipmap,
6437                                                                                                         unsigned int n_sample, tcu::Vec4 color)
6438 {
6439         DE_ASSERT(m_reference_color_storage != DE_NULL);
6440         if (m_reference_color_storage != DE_NULL)
6441         {
6442                 DE_ASSERT(n_face < m_reference_color_storage->n_faces);
6443                 DE_ASSERT(n_layer < m_reference_color_storage->n_layers);
6444                 DE_ASSERT(n_mipmap < m_reference_color_storage->n_mipmaps);
6445                 DE_ASSERT(n_sample < m_reference_color_storage->n_samples);
6446
6447                 /* Hierarchy is:
6448                  *
6449                  * layers -> faces -> mipmaps -> samples */
6450                 const unsigned int index =
6451                         n_layer * (m_reference_color_storage->n_faces * m_reference_color_storage->n_mipmaps *
6452                                            m_reference_color_storage->n_samples) +
6453                         n_face * (m_reference_color_storage->n_mipmaps * m_reference_color_storage->n_samples) +
6454                         n_mipmap * (m_reference_color_storage->n_samples) + n_sample;
6455
6456                 m_reference_color_storage->data[index] = color;
6457         }
6458 }
6459
6460 /** Constructor.
6461  *
6462  *  @param context Rendering context.
6463  **/
6464 TextureViewTestViewClasses::TextureViewTestViewClasses(deqp::Context& context)
6465         : TestCase(context, "view_classes", "Verifies view sampling works correctly. Tests all valid"
6466                                                                                 " texture/view internalformat combinations.")
6467         , m_bo_id(0)
6468         , m_po_id(0)
6469         , m_to_id(0)
6470         , m_to_temp_id(0)
6471         , m_vao_id(0)
6472         , m_view_to_id(0)
6473         , m_vs_id(0)
6474         , m_decompressed_mipmap_data(DE_NULL)
6475         , m_mipmap_data(DE_NULL)
6476         , m_bo_size(0)
6477         , m_has_test_failed(false)
6478         , m_texture_height(4)
6479         , m_texture_unit_for_parent_texture(GL_TEXTURE0)
6480         , m_texture_unit_for_view_texture(GL_TEXTURE1)
6481         , m_texture_width(4)
6482         , m_view_data_offset(0)
6483 {
6484         /* Left blank on purpose */
6485 }
6486
6487 /** Deinitializes all buffers and GL objects that may have been created
6488  *  during test execution. Also restores GL state that may have been modified.
6489  **/
6490 void TextureViewTestViewClasses::deinit()
6491 {
6492         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6493
6494         if (m_bo_id != 0)
6495         {
6496                 gl.deleteBuffers(1, &m_bo_id);
6497
6498                 m_bo_id = 0;
6499         }
6500
6501         if (m_decompressed_mipmap_data != DE_NULL)
6502         {
6503                 delete[] m_decompressed_mipmap_data;
6504
6505                 m_decompressed_mipmap_data = DE_NULL;
6506         }
6507
6508         if (m_mipmap_data != DE_NULL)
6509         {
6510                 delete[] m_mipmap_data;
6511
6512                 m_mipmap_data = DE_NULL;
6513         }
6514
6515         if (m_po_id != 0)
6516         {
6517                 gl.deleteProgram(m_po_id);
6518
6519                 m_po_id = 0;
6520         }
6521
6522         if (m_to_id != 0)
6523         {
6524                 gl.deleteTextures(1, &m_to_id);
6525
6526                 m_to_id = 0;
6527         }
6528
6529         if (m_to_temp_id != 0)
6530         {
6531                 gl.deleteTextures(1, &m_to_temp_id);
6532
6533                 m_to_temp_id = 0;
6534         }
6535
6536         if (m_vao_id != 0)
6537         {
6538                 gl.deleteVertexArrays(1, &m_vao_id);
6539
6540                 m_vao_id = 0;
6541         }
6542
6543         if (m_view_to_id != 0)
6544         {
6545                 gl.deleteTextures(1, &m_view_to_id);
6546
6547                 m_view_to_id = 0;
6548         }
6549
6550         if (m_vs_id != 0)
6551         {
6552                 gl.deleteShader(m_vs_id);
6553
6554                 m_vs_id = 0;
6555         }
6556
6557         /* Bring back the default pixel storage settings that the test may have modified. */
6558         gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
6559         gl.pixelStorei(GL_UNPACK_ALIGNMENT, 4);
6560
6561         /* Restore rasterization */
6562         gl.enable(GL_RASTERIZER_DISCARD);
6563 }
6564
6565 /** Reads user-specified amount of components and stores it in user-provided location,
6566  *  according to user-defined format (snorm, unorm, etc.) and component size.
6567  *
6568  *  This function assumes component sizes are aligned on by boundary (that is: size % 8
6569  *  equals 0 for all components). An assertion failure will occur if this requirement is
6570  *  not met.
6571  *  This function throws TestError exception if any of the requested component sizes
6572  *  or format is not supported.
6573  *
6574  *  @param data            Raw data buffer to read the data from.
6575  *  @param n_components    Amount of components to read.
6576  *  @param component_sizes 4 ints subsequently defining component size for R/G/B/A channels.
6577  *                         Must not be NULL.
6578  *  @param format          Format to be used for data retrieval. This defines data format of
6579  *                         the underlying components (for instance: for UNORMs we need to
6580  *                         divide the read ubyte/ushort/uint data by maximum value allowed for
6581  *                         the type minus one)
6582  *  @param result          Location to store the read components. Must not be NULL. Must be
6583  *                         large enough to hold requested amount of components of user-specified
6584  *                         component size.
6585  *
6586  **/
6587 void TextureViewTestViewClasses::getComponentDataForByteAlignedInternalformat(const unsigned char* data,
6588                                                                                                                                                           const unsigned int   n_components,
6589                                                                                                                                                           const unsigned int*  component_sizes,
6590                                                                                                                                                           const _format format, void* result)
6591 {
6592         float*            result_float = (float*)result;
6593         signed int*   result_sint  = (signed int*)result;
6594         unsigned int* result_uint  = (unsigned int*)result;
6595
6596         /* Sanity checks: we assume the components are aligned on byte boundary. */
6597         DE_ASSERT((component_sizes[0] % 8) == 0 && (component_sizes[1] % 8) == 0 && (component_sizes[2] % 8) == 0 &&
6598                           (component_sizes[3] % 8) == 0);
6599
6600         for (unsigned int n_component = 0; n_component < n_components;
6601                  data += (component_sizes[n_component] >> 3 /* 8 bits/byte */), ++n_component)
6602         {
6603                 switch (format)
6604                 {
6605                 case FORMAT_FLOAT:
6606                 {
6607                         switch (component_sizes[n_component])
6608                         {
6609                         case 16:
6610                                 result_float[n_component] = deFloat16To32(*(const deFloat16*)data);
6611                                 break;
6612                         case 32:
6613                                 result_float[n_component] = *(float*)data;
6614                                 break;
6615
6616                         default:
6617                                 TCU_FAIL("Unsupported component size");
6618                         }
6619
6620                         break;
6621                 }
6622
6623                 case FORMAT_SIGNED_INTEGER:
6624                 {
6625                         switch (component_sizes[n_component])
6626                         {
6627                         case 8:
6628                                 result_sint[n_component] = *(signed char*)data;
6629                                 break;
6630                         case 16:
6631                                 result_sint[n_component] = *(signed short*)data;
6632                                 break;
6633                         case 32:
6634                                 result_sint[n_component] = *(signed int*)data;
6635                                 break;
6636
6637                         default:
6638                                 TCU_FAIL("Unsupported component size");
6639                         }
6640
6641                         break;
6642                 }
6643
6644                 case FORMAT_SNORM:
6645                 {
6646                         switch (component_sizes[n_component])
6647                         {
6648                         case 8:
6649                                 result_float[n_component] = float(*(signed char*)data) / 127.0f;
6650                                 break;
6651                         case 16:
6652                                 result_float[n_component] = float(*(signed short*)data) / 32767.0f;
6653                                 break;
6654
6655                         default:
6656                                 TCU_FAIL("Unsupported component size");
6657                         }
6658
6659                         if (result_float[n_component] < -1.0f)
6660                         {
6661                                 result_float[n_component] = -1.0f;
6662                         }
6663
6664                         break;
6665                 }
6666
6667                 case FORMAT_UNORM:
6668                 {
6669                         switch (component_sizes[n_component])
6670                         {
6671                         case 8:
6672                                 result_float[n_component] = float(*((unsigned char*)data)) / 255.0f;
6673                                 break;
6674                         case 16:
6675                                 result_float[n_component] = float(*((unsigned short*)data)) / 65535.0f;
6676                                 break;
6677
6678                         default:
6679                                 TCU_FAIL("Unsupported component size");
6680                         }
6681
6682                         break;
6683                 }
6684
6685                 case FORMAT_UNSIGNED_INTEGER:
6686                 {
6687                         switch (component_sizes[n_component])
6688                         {
6689                         case 8:
6690                                 result_uint[n_component] = *(unsigned char*)data;
6691                                 break;
6692                         case 16:
6693                                 result_uint[n_component] = *(unsigned short*)data;
6694                                 break;
6695                         case 32:
6696                                 result_uint[n_component] = *(unsigned int*)data;
6697                                 break;
6698
6699                         default:
6700                                 TCU_FAIL("Unsupported component size");
6701                         }
6702
6703                         break;
6704                 }
6705
6706                 default:
6707                 {
6708                         TCU_FAIL("Unrecognized mip-map format");
6709                 }
6710                 } /* switch (view_format) */
6711         }        /* for (all components) */
6712 }
6713
6714 /** Initializes buffer object storage of sufficient size to hold data that will be
6715  *  XFBed out by the test's vertex shader, given user-specified parent texture &
6716  *  view's internalformats.
6717  *
6718  *  Throws TestError exceptions if GL calls fail.
6719  *
6720  *  @param texture_internalformat Internalformat used by the parent texture object,
6721  *                                from which the view will be created.
6722  *  @param view_internalformat    Internalformat that will be used by the texture view.
6723  **/
6724 void TextureViewTestViewClasses::initBufferObject(glw::GLenum texture_internalformat, glw::GLenum view_internalformat)
6725 {
6726         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6727
6728         /* Calculate how much size we will need to read the XFBed data. Each sampled data
6729          * will either end up stored in a vecX, ivecX or uvecX (where X stands for amount
6730          * of components supported by considered internalformat), so we can assume it will
6731          * take a sizeof(float) = sizeof(int) = sizeof(unsigned int)
6732          */
6733         const unsigned int parent_texture_n_components =
6734                 TextureViewUtilities::getAmountOfComponentsForInternalformat(texture_internalformat);
6735         const unsigned int view_texture_n_components =
6736                 TextureViewUtilities::getAmountOfComponentsForInternalformat(view_internalformat);
6737
6738         /* Configure buffer object storage.
6739          *
6740          * NOTE: We do not care about the data type of the stored data, since sizes of the
6741          *       types we're interested in (floats, ints and uints) match.
6742          */
6743         DE_ASSERT(sizeof(float) == sizeof(unsigned int) && sizeof(float) == sizeof(int));
6744
6745         m_bo_size =
6746                 static_cast<unsigned int>(parent_texture_n_components * sizeof(float) * m_texture_height * m_texture_width +
6747                                                                   view_texture_n_components * sizeof(float) * m_texture_height * m_texture_width);
6748
6749         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_size, DE_NULL, /* data */
6750                                   GL_STATIC_DRAW);
6751         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
6752
6753         /* For XFB, we'll be outputting data sampled from both the texture and the view.
6754          * Sampled texture data will go to the first half of the buffer, and the corresponding
6755          * view data will go to the one half.
6756          *
6757          * Store the offset, from which the view's data will start so that we can correctly
6758          * configure buffer object bindings in initProgramObject()
6759          **/
6760         m_view_data_offset =
6761                 static_cast<unsigned int>(parent_texture_n_components * sizeof(float) * m_texture_height * m_texture_width);
6762 }
6763
6764 /** Initializes a program object that should be used for the test, given
6765  *  user-specified texture and view internalformats.
6766  *
6767  *  @param texture_internalformat Internalformat used by the parent texture object,
6768  *                                from which the view will be created.
6769  *  @param view_internalformat    Internalformat that will be used by the texture view.
6770  **/
6771 void TextureViewTestViewClasses::initProgramObject(glw::GLenum texture_internalformat, glw::GLenum view_internalformat)
6772 {
6773         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6774
6775         /* Determine which samplers we should be using for sampling both textures */
6776         const unsigned int texture_n_components =
6777                 TextureViewUtilities::getAmountOfComponentsForInternalformat(texture_internalformat);
6778         const _sampler_type texture_sampler_type =
6779                 TextureViewUtilities::getSamplerTypeForInternalformat(texture_internalformat);
6780         const char* texture_sampler_data_type_glsl =
6781                 TextureViewUtilities::getGLSLDataTypeForSamplerType(texture_sampler_type, texture_n_components);
6782         const char* texture_sampler_glsl = TextureViewUtilities::getGLSLTypeForSamplerType(texture_sampler_type);
6783         const char* texture_swizzle_glsl =
6784                 (texture_n_components == 4) ? "xyzw" :
6785                                                                           (texture_n_components == 3) ? "xyz" : (texture_n_components == 2) ? "xy" : "x";
6786         const unsigned int view_n_components =
6787                 TextureViewUtilities::getAmountOfComponentsForInternalformat(view_internalformat);
6788         const _sampler_type view_sampler_type = TextureViewUtilities::getSamplerTypeForInternalformat(view_internalformat);
6789         const char*                     view_sampler_data_type_glsl =
6790                 TextureViewUtilities::getGLSLDataTypeForSamplerType(view_sampler_type, view_n_components);
6791         const char* view_sampler_glsl = TextureViewUtilities::getGLSLTypeForSamplerType(view_sampler_type);
6792         const char* view_swizzle_glsl =
6793                 (view_n_components == 4) ? "xyzw" : (view_n_components == 3) ? "xyz" : (view_n_components == 2) ? "xy" : "x";
6794
6795         /* Form vertex shader body */
6796         const char* token_texture_data_type = "TEXTURE_DATA_TYPE";
6797         const char* token_texture_sampler   = "TEXTURE_SAMPLER";
6798         const char* token_texture_swizzle   = "TEXTURE_SWIZZLE";
6799         const char* token_view_data_type        = "VIEW_DATA_TYPE";
6800         const char* token_view_sampler          = "VIEW_SAMPLER";
6801         const char* token_view_swizzle          = "VIEW_SWIZZLE";
6802         const char* vs_template_body            = "#version 400\n"
6803                                                                    "\n"
6804                                                                    "uniform TEXTURE_SAMPLER texture;\n"
6805                                                                    "uniform VIEW_SAMPLER    view;\n"
6806                                                                    "\n"
6807                                                                    "out TEXTURE_DATA_TYPE out_texture_data;\n"
6808                                                                    "out VIEW_DATA_TYPE    out_view_data;\n"
6809                                                                    "\n"
6810                                                                    "void main()\n"
6811                                                                    "{\n"
6812                                                                    "    ivec2 uv = ivec2(gl_VertexID % 4,\n"
6813                                                                    "                     gl_VertexID / 4);\n"
6814                                                                    "\n"
6815                                                                    "    out_texture_data = texelFetch(texture, uv, 0).TEXTURE_SWIZZLE;\n"
6816                                                                    "    out_view_data    = texelFetch(view,    uv, 0).VIEW_SWIZZLE;\n"
6817                                                                    "}\n";
6818
6819         std::size_t token_position = std::string::npos;
6820         std::string vs_body                = vs_template_body;
6821
6822         while ((token_position = vs_body.find(token_texture_data_type)) != std::string::npos)
6823         {
6824                 vs_body.replace(token_position, strlen(token_texture_data_type), texture_sampler_data_type_glsl);
6825         }
6826
6827         while ((token_position = vs_body.find(token_texture_sampler)) != std::string::npos)
6828         {
6829                 vs_body.replace(token_position, strlen(token_texture_sampler), texture_sampler_glsl);
6830         }
6831
6832         while ((token_position = vs_body.find(token_texture_swizzle)) != std::string::npos)
6833         {
6834                 vs_body.replace(token_position, strlen(token_texture_swizzle), texture_swizzle_glsl);
6835         }
6836
6837         while ((token_position = vs_body.find(token_view_data_type)) != std::string::npos)
6838         {
6839                 vs_body.replace(token_position, strlen(token_view_data_type), view_sampler_data_type_glsl);
6840         }
6841
6842         while ((token_position = vs_body.find(token_view_sampler)) != std::string::npos)
6843         {
6844                 vs_body.replace(token_position, strlen(token_view_sampler), view_sampler_glsl);
6845         }
6846
6847         while ((token_position = vs_body.find(token_view_swizzle)) != std::string::npos)
6848         {
6849                 vs_body.replace(token_position, strlen(token_view_swizzle), view_swizzle_glsl);
6850         }
6851
6852         /* Compile the shader */
6853         glw::GLint  compile_status  = GL_FALSE;
6854         const char* vs_body_raw_ptr = vs_body.c_str();
6855
6856         gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
6857         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6858
6859         gl.compileShader(m_vs_id);
6860         GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
6861
6862         gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
6863         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
6864
6865         if (compile_status != GL_TRUE)
6866         {
6867                 TCU_FAIL("Shader compilation failed");
6868         }
6869
6870         /* Configure test program object for XFB */
6871         const char*                varying_names[] = { "out_texture_data", "out_view_data" };
6872         const unsigned int n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]);
6873
6874         gl.transformFeedbackVaryings(m_po_id, n_varying_names, varying_names, GL_SEPARATE_ATTRIBS);
6875         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
6876
6877         /* Configure buffer object bindings for XFB */
6878         gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index for 'out_texture_data' */
6879                                            m_bo_id, 0,                                          /* offset */
6880                                            m_view_data_offset);                         /* size */
6881         gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 1, /* index for 'out_view_data' */
6882                                            m_bo_id, m_view_data_offset,         /* offset */
6883                                            m_bo_size - m_view_data_offset); /* size */
6884
6885         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() call(s) failed.");
6886
6887         /* Link the program object */
6888         glw::GLint link_status = GL_FALSE;
6889
6890         gl.linkProgram(m_po_id);
6891         GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
6892
6893         gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
6894         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
6895
6896         if (link_status != GL_TRUE)
6897         {
6898                 TCU_FAIL("Program linking failed.");
6899         }
6900
6901         /* Configure sampler uniforms */
6902         glw::GLint texture_uniform_location = gl.getUniformLocation(m_po_id, "texture");
6903         glw::GLint view_uniform_location        = gl.getUniformLocation(m_po_id, "view");
6904
6905         if (texture_uniform_location == -1)
6906         {
6907                 TCU_FAIL("'texture' uniform is considered inactive which is invalid");
6908         }
6909
6910         if (view_uniform_location == -1)
6911         {
6912                 TCU_FAIL("'view' uniform is considered inactive which is invalid");
6913         }
6914
6915         gl.useProgram(m_po_id);
6916         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
6917
6918         gl.uniform1i(texture_uniform_location, m_texture_unit_for_parent_texture - GL_TEXTURE0);
6919         gl.uniform1i(view_uniform_location, m_texture_unit_for_view_texture - GL_TEXTURE0);
6920         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call(s) failed.");
6921 }
6922
6923 /** Creates GL objects required to run the test, as well as modifies GL
6924  *  configuration (pixel pack/unpack settings, enables 'rasterizer discard' mode)
6925  *  in order for the test to run properly.
6926  **/
6927 void TextureViewTestViewClasses::initTest()
6928 {
6929         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6930
6931         /* Generate objects that will be used by all test iterations.
6932          *
6933          * Note that we're not generating texture objects here. This is owing to the fact
6934          * we'll be using immutable textures and it makes more sense to generate the objects
6935          * in initTexture() instead.
6936          **/
6937         gl.genBuffers(1, &m_bo_id);
6938         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
6939
6940         m_po_id = gl.createProgram();
6941         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
6942
6943         gl.genVertexArrays(1, &m_vao_id);
6944         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
6945
6946         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
6947         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
6948
6949         /* Attach the vertex shader to the program object */
6950         gl.attachShader(m_po_id, m_vs_id);
6951         GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
6952
6953         /* Configure general buffer object binding. Indiced bindings will be configured
6954          * in initProgramObject()
6955          */
6956         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
6957         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
6958
6959         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
6960         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
6961
6962         /* Bind the VAO */
6963         gl.bindVertexArray(m_vao_id);
6964         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
6965
6966         /* Modify pack & unpack alignment settings */
6967         gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
6968         gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
6969         GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call(s) failed.");
6970
6971         /* Disable rasterizatino */
6972         gl.enable(GL_RASTERIZER_DISCARD);
6973         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed.");
6974 }
6975
6976 /** Generates and initializes storage of either the parent texture object or the
6977  *  texture view, using user-specified internalformat.
6978  *
6979  *  @param should_init_parent_texture true to initialize parent texture object storage,
6980  *                                    false to configure texture view.
6981  *  @param internalformat             Internalformat to use for the process.
6982  *  @param viewformat                 Internalformat that will be used by "view" texture.
6983  *
6984  **/
6985 void TextureViewTestViewClasses::initTextureObject(bool should_init_parent_texture, glw::GLenum texture_internalformat,
6986                                                                                                    glw::GLenum view_internalformat)
6987 {
6988         glw::GLenum                       cached_view_internalformat = view_internalformat;
6989         const glw::Functions& gl                                                 = m_context.getRenderContext().getFunctions();
6990         glw::GLuint*              to_id_ptr                                      = (should_init_parent_texture) ? &m_to_id : &m_view_to_id;
6991
6992         /* If the object we're about to initialize has already been created, delete it first. */
6993         if (*to_id_ptr != 0)
6994         {
6995                 gl.deleteTextures(1, to_id_ptr);
6996                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
6997
6998                 *to_id_ptr = 0;
6999         }
7000
7001         /* Generate a new texture object */
7002         gl.genTextures(1, to_id_ptr);
7003
7004         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
7005
7006         /* Initialize the object */
7007         if (should_init_parent_texture)
7008         {
7009                 gl.bindTexture(GL_TEXTURE_2D, *to_id_ptr);
7010                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7011
7012                 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
7013                                                 texture_internalformat, m_texture_width, m_texture_height);
7014
7015                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
7016         }
7017         else
7018         {
7019                 gl.textureView(m_view_to_id, GL_TEXTURE_2D, m_to_id, view_internalformat, 0, /* minlevel */
7020                                            1,                                                                                                                    /* numlevels */
7021                                            0,                                                                                                                    /* minlayer */
7022                                            1);                                                                                                                   /* numlayers */
7023
7024                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed.");
7025
7026                 gl.bindTexture(GL_TEXTURE_2D, m_view_to_id);
7027                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7028         }
7029
7030         if (should_init_parent_texture)
7031         {
7032                 /* We need to fill the base mip-map with actual contents. Calculate how much
7033                  * data we will need to fill a 4x4 mip-map, given the requested internalformat.
7034                  */
7035                 bool is_internalformat_compressed = TextureViewUtilities::isInternalformatCompressed(texture_internalformat);
7036                 glw::GLenum internalformat_to_use = GL_NONE;
7037
7038                 if (is_internalformat_compressed)
7039                 {
7040                         /* In order to initialize texture objects defined with a compressed internalformat
7041                          * using raw decompressed data, we need to override caller-specified internalformat
7042                          * with an internalformat that will describe decompressed data. The data will then
7043                          * be converted by GL to the compressed internalformat that was used for the previous
7044                          * glTexStorage2D() call.
7045                          **/
7046                         _format format = TextureViewUtilities::getFormatOfInternalformat(texture_internalformat);
7047
7048                         if (format == FORMAT_FLOAT)
7049                         {
7050                                 internalformat_to_use = GL_RGBA32F;
7051                         }
7052                         else
7053                         {
7054                                 DE_ASSERT(format == FORMAT_UNORM || format == FORMAT_SNORM);
7055
7056                                 internalformat_to_use = GL_RGBA8;
7057                         }
7058
7059                         view_internalformat = internalformat_to_use;
7060                 }
7061                 else
7062                 {
7063                         internalformat_to_use = texture_internalformat;
7064                 }
7065
7066                 /* Allocate the buffer.
7067                  *
7068                  * NOTE: This buffer is used in verifyResults(). When no longer needed, it will either
7069                  *       be deallocated there or in deinit().
7070                  **/
7071                 glw::GLenum format_to_use   = TextureViewUtilities::getGLFormatOfInternalformat(internalformat_to_use);
7072                 glw::GLenum type_to_use         = TextureViewUtilities::getTypeCompatibleWithInternalformat(internalformat_to_use);
7073                 const glw::GLenum view_type = TextureViewUtilities::getTypeCompatibleWithInternalformat(view_internalformat);
7074
7075                 /* For some internalformats, we need to use a special data type in order to avoid
7076                  * implicit data conversion during glTexSubImage2D() call.
7077                  */
7078                 switch (texture_internalformat)
7079                 {
7080                 case GL_R11F_G11F_B10F:
7081                         type_to_use = GL_UNSIGNED_INT_10F_11F_11F_REV;
7082                         break;
7083                 case GL_RGB9_E5:
7084                         type_to_use = GL_UNSIGNED_INT_5_9_9_9_REV;
7085                         break;
7086                 case GL_RGB10_A2:
7087                         type_to_use = GL_UNSIGNED_INT_2_10_10_10_REV;
7088                         break;
7089
7090                         /* Fall-through for other internalformats! */
7091                 } /* switch (texture_internalformat) */
7092
7093                 /* Carry on */
7094                 const unsigned int mipmap_raw_size = TextureViewUtilities::getTextureDataSize(
7095                         internalformat_to_use, type_to_use, m_texture_width, m_texture_height);
7096
7097                 if (m_mipmap_data != NULL)
7098                 {
7099                         delete[] m_mipmap_data;
7100
7101                         m_mipmap_data = NULL;
7102                 }
7103
7104                 m_mipmap_data = new unsigned char[mipmap_raw_size];
7105
7106                 /* Prepare data for texture */
7107                 memset(m_mipmap_data, 0, mipmap_raw_size);
7108
7109                 switch (view_type)
7110                 {
7111                 case GL_BYTE:
7112                 {
7113                         glw::GLbyte*      buffer                         = (glw::GLbyte*)m_mipmap_data;
7114                         const glw::GLuint n_total_components = mipmap_raw_size / 1;
7115
7116                         for (glw::GLuint i = 0; i < n_total_components; ++i)
7117                         {
7118                                 buffer[i] = static_cast<glw::GLbyte>(i - 128);
7119                         }
7120
7121                         break;
7122                 }
7123
7124                 case GL_SHORT:
7125                 {
7126                         glw::GLshort*    buffer                  = (glw::GLshort*)m_mipmap_data;
7127                         const glw::GLuint n_total_components = mipmap_raw_size / 2;
7128
7129                         for (glw::GLuint i = 0; i < n_total_components; ++i)
7130                         {
7131                                 buffer[i] = static_cast<glw::GLshort>(i - 0xC000); // 0xC000 = (fp16) -2 makes this non de-norm
7132                         }
7133
7134                         break;
7135                 }
7136
7137                 case GL_INT:
7138                 {
7139                         glw::GLint*               buffer                         = (glw::GLint*)m_mipmap_data;
7140                         const glw::GLuint n_total_components = mipmap_raw_size / 4;
7141
7142                         for (glw::GLuint i = 0; i < n_total_components; ++i)
7143                         {
7144                                 buffer[i] = i - 128;
7145                         }
7146
7147                         break;
7148                 }
7149
7150                 case GL_UNSIGNED_BYTE:
7151                 {
7152                         glw::GLubyte*    buffer                  = (glw::GLubyte*)m_mipmap_data;
7153                         const glw::GLuint n_total_components = mipmap_raw_size / 1;
7154
7155                         for (glw::GLuint i = 0; i < n_total_components; ++i)
7156                         {
7157                                 buffer[i] = static_cast<glw::GLubyte>(i);
7158                         }
7159
7160                         break;
7161                 }
7162
7163                 case GL_UNSIGNED_SHORT:
7164                 {
7165                         glw::GLushort*  buffer                   = (glw::GLushort*)m_mipmap_data;
7166                         const glw::GLuint n_total_components = mipmap_raw_size / 2;
7167
7168                         for (glw::GLuint i = 0; i < n_total_components; ++i)
7169                         {
7170                                 buffer[i] = static_cast<glw::GLushort>(i);
7171                         }
7172
7173                         break;
7174                 }
7175
7176                 case GL_UNSIGNED_INT:
7177                 {
7178                         glw::GLuint*      buffer                         = (glw::GLuint*)m_mipmap_data;
7179                         const glw::GLuint n_total_components = mipmap_raw_size / 4;
7180
7181                         for (glw::GLuint i = 0; i < n_total_components; ++i)
7182                         {
7183                                 buffer[i] = i;
7184                         }
7185
7186                         break;
7187                 }
7188
7189                 case GL_UNSIGNED_INT_24_8:
7190                 {
7191                         glw::GLuint*      buffer                         = (glw::GLuint*)m_mipmap_data;
7192                         const glw::GLuint n_total_components = mipmap_raw_size / 4;
7193
7194                         for (glw::GLuint i = 0; i < n_total_components; ++i)
7195                         {
7196                                 buffer[i] = (i << 8) | (0xaa);
7197                         }
7198
7199                         break;
7200                 }
7201
7202                 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
7203                 {
7204                         glw::GLfloat*    float_buffer            = (glw::GLfloat*)m_mipmap_data;
7205                         const glw::GLuint n_total_components = mipmap_raw_size / 8;
7206                         glw::GLuint*      uint_buffer            = (glw::GLuint*)(m_mipmap_data + 4);
7207
7208                         for (glw::GLuint i = 0; i < n_total_components; ++i)
7209                         {
7210                                 float_buffer[i * 2] = (float)i - 128;
7211                                 uint_buffer[i * 2]  = (i << 8) | (0xaa);
7212                         }
7213
7214                         break;
7215                 }
7216
7217                 case GL_HALF_FLOAT:
7218                 {
7219                         tcu::Float16*    buffer                  = (tcu::Float16*)m_mipmap_data;
7220                         const glw::GLuint n_total_components = mipmap_raw_size / 2;
7221
7222                         for (glw::GLuint i = 0; i < n_total_components; ++i)
7223                         {
7224                                 float value = (float)i - 128;
7225
7226                                 buffer[i] = (tcu::Float16)value;
7227                         }
7228
7229                         break;
7230                 }
7231
7232                 case GL_FLOAT:
7233                 {
7234                         glw::GLfloat*    float_buffer            = (glw::GLfloat*)m_mipmap_data;
7235                         const glw::GLuint n_total_components = mipmap_raw_size / 4;
7236
7237                         float offset = (cached_view_internalformat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT) ? 0.0f : -128.0f;
7238                         for (glw::GLuint i = 0; i < n_total_components; ++i)
7239                         {
7240                                 float_buffer[i] = (float)i + offset;
7241                         }
7242
7243                         break;
7244                 }
7245
7246                 case GL_UNSIGNED_INT_2_10_10_10_REV:
7247                 {
7248                         glw::GLuint*      buffer                         = (glw::GLuint*)m_mipmap_data;
7249                         const glw::GLuint n_total_components = mipmap_raw_size / 4;
7250
7251                         for (glw::GLuint i = 0; i < n_total_components; ++i)
7252                         {
7253                                 buffer[i] = i | (i << 8) | (i << 16);
7254                         }
7255
7256                         break;
7257                 }
7258
7259                 default:
7260                 {
7261                         TCU_FAIL("Unrecognized texture view type");
7262                 }
7263                 } /* switch (view_type) */
7264
7265                 /* BPTC_FLOAT view class is a special case that needs an extra step. Signed and
7266                  * unsigned internal formats use different encodings, so instead of passing
7267                  * "regular" 32-bit floating-point data, we need to convert the values we initialized
7268                  * above to an actual BPTC representation. Since the encodings differ, we should
7269                  * compress these values using the internalformat that we will be later using for the
7270                  * texture view.
7271                  */
7272                 unsigned int imageSize_to_use                                   = 0;
7273                 bool             use_glCompressedTexSubImage2D_call = false;
7274
7275                 if ((cached_view_internalformat == GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT ||
7276                          cached_view_internalformat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT) &&
7277                         cached_view_internalformat != texture_internalformat)
7278                 {
7279                         /* Create a temporary texture object we'll use to compress the floating-point data. */
7280                         gl.genTextures(1, &m_to_temp_id);
7281                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
7282
7283                         gl.bindTexture(GL_TEXTURE_2D, m_to_temp_id);
7284                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7285
7286                         /* Initialize compressed storage */
7287                         gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
7288                                                         cached_view_internalformat, m_texture_width, m_texture_height);
7289                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
7290
7291                         /* Submit floating-point decompressed data */
7292                         gl.texSubImage2D(GL_TEXTURE_2D, 0, /* level */
7293                                                          0,                                /* xoffset */
7294                                                          0,                                /* yoffset */
7295                                                          m_texture_width, m_texture_height, GL_RGB, GL_FLOAT, m_mipmap_data);
7296                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
7297
7298                         /* Extract the compressed version */
7299                         gl.getCompressedTexImage(GL_TEXTURE_2D, 0, /* level */
7300                                                                          m_mipmap_data);
7301                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetCompressedTexImage() call failed.");
7302
7303                         /* Delete the temporary texture object */
7304                         gl.deleteTextures(1, &m_to_temp_id);
7305                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
7306
7307                         m_to_temp_id = 0;
7308
7309                         /* Revert to previous 2D texture binding */
7310                         gl.bindTexture(GL_TEXTURE_2D, m_to_id);
7311                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7312
7313                         /* Make sure upcoming glCompressedTexSubImage2D() call is made with sensible arguments */
7314                         imageSize_to_use = (unsigned int)ceil((float)m_texture_width / 4.0f) *
7315                                                            (unsigned int)ceil((float)m_texture_height / 4.0f) * 16; /* block size */
7316                         use_glCompressedTexSubImage2D_call = true;
7317                 }
7318
7319                 /* Fill the mip-map with data */
7320                 if (use_glCompressedTexSubImage2D_call)
7321                 {
7322                         gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, /* level */
7323                                                                            0,                            /* xoffset */
7324                                                                            0,                            /* yoffset */
7325                                                                            m_texture_width, m_texture_height, texture_internalformat, imageSize_to_use,
7326                                                                            m_mipmap_data);
7327                         GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexSubImage2D() call failed.");
7328                 }
7329                 else
7330                 {
7331                         gl.texSubImage2D(GL_TEXTURE_2D, 0, /* level */
7332                                                          0,                                /* xoffset */
7333                                                          0,                                /* yoffset */
7334                                                          m_texture_width, m_texture_height, format_to_use, type_to_use, m_mipmap_data);
7335
7336                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
7337                 }
7338         }
7339
7340         /* Make sure the texture object is complete */
7341         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7342         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7343         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7344         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
7345                                          GL_NEAREST); /* we're using texelFetch() so no mipmaps needed */
7346         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
7347         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
7348
7349         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call(s) failed.");
7350 }
7351
7352 /** Executes test iteration.
7353  *
7354  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7355  */
7356 tcu::TestNode::IterateResult TextureViewTestViewClasses::iterate()
7357 {
7358         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7359
7360         /* Only execute the test if GL_ARB_texture_view is supported */
7361         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_view"))
7362         {
7363                 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported, skipping.");
7364         }
7365
7366         /* Create all GL objects required to run the test */
7367         initTest();
7368
7369         /* Iterate through all valid "texture internalformat + view internalformat" combinations */
7370         TextureViewUtilities::_compatible_internalformat_pairs_const_iterator internalformat_combination_iterator;
7371         TextureViewUtilities::_compatible_internalformat_pairs                            internalformat_combinations =
7372                 TextureViewUtilities::getLegalTextureAndViewInternalformatCombinations();
7373
7374         for (internalformat_combination_iterator = internalformat_combinations.begin();
7375                  internalformat_combination_iterator != internalformat_combinations.end();
7376                  internalformat_combination_iterator++)
7377         {
7378                 TextureViewUtilities::_internalformat_pair internalformat_pair  = *internalformat_combination_iterator;
7379                 glw::GLenum                                                                texture_internalformat = internalformat_pair.first;
7380                 glw::GLenum                                                                view_internalformat  = internalformat_pair.second;
7381
7382                 /* Initialize parent texture object storage */
7383                 initTextureObject(true, /* should_init_parent_texture */
7384                                                   texture_internalformat, view_internalformat);
7385
7386                 /* Create the texture view */
7387                 initTextureObject(false, /* should_init_parent_texture */
7388                                                   texture_internalformat, view_internalformat);
7389
7390                 /* Initialize buffer object storage so that it's large enough to
7391                  * hold the result data.
7392                  **/
7393                 initBufferObject(texture_internalformat, view_internalformat);
7394
7395                 /* Create the program object we'll use for the test */
7396                 initProgramObject(texture_internalformat, view_internalformat);
7397
7398                 /* Configure texture bindings */
7399                 gl.activeTexture(m_texture_unit_for_parent_texture);
7400                 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed.");
7401
7402                 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
7403                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7404
7405                 gl.activeTexture(m_texture_unit_for_view_texture);
7406                 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed.");
7407
7408                 gl.bindTexture(GL_TEXTURE_2D, m_view_to_id);
7409                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7410
7411                 /* Run the test program */
7412                 gl.beginTransformFeedback(GL_POINTS);
7413                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
7414                 {
7415                         gl.drawArrays(GL_POINTS, 0 /* first */, m_texture_width * m_texture_height);
7416                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7417                 }
7418                 gl.endTransformFeedback();
7419                 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
7420
7421                 /* Retrieve the results */
7422                 const unsigned char* result_bo_data_ptr =
7423                         (const unsigned char*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7424                 const unsigned char* result_texture_data_ptr = result_bo_data_ptr;
7425                 const unsigned char* result_view_data_ptr       = result_bo_data_ptr + m_view_data_offset;
7426
7427                 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
7428
7429                 /* Verify the retrieved values are valid */
7430                 verifyResultData(texture_internalformat, view_internalformat, result_texture_data_ptr, result_view_data_ptr);
7431
7432                 /* Unmap the buffer object */
7433                 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7434                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
7435         } /* for (all internalformat combinations) */
7436
7437         if (m_has_test_failed)
7438         {
7439                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7440         }
7441         else
7442         {
7443                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7444         }
7445
7446         return STOP;
7447 }
7448
7449 /** Verifies the data XFBed out by the test's vertex shader is valid.
7450  *
7451  *  @param texture_internalformat Internalformat that was used to define storage
7452  *                                of the parent texture object.
7453  *  @param view_internalformat    Internalformat that was used to define texture
7454  *                                view.
7455  *  @param texture_data_ptr       Data, as XFBed out by the vertex shader, that was
7456  *                                built by texelFetch() calls operating on the parent
7457  *                                texture object.
7458  *  @param view_data_ptr          Data, as XFBed out by the vertex shader, that was
7459  *                                built by texelFetch() calls operating on the texture
7460  *                                view.
7461  *
7462  **/
7463 void TextureViewTestViewClasses::verifyResultData(glw::GLenum texture_internalformat, glw::GLenum view_internalformat,
7464                                                                                                   const unsigned char* texture_data_ptr,
7465                                                                                                   const unsigned char* view_data_ptr)
7466 {
7467         const char* texture_internalformat_string = TextureViewUtilities::getInternalformatString(texture_internalformat);
7468         const char* view_internalformat_string  = TextureViewUtilities::getInternalformatString(view_internalformat);
7469
7470         /* For quite a number of cases, we can do a plain memcmp() applied to sampled texture/view data.
7471          * If both buffers are a match, we're OK.
7472          */
7473         bool                             has_failed  = false;
7474         const unsigned char* mipmap_data = DE_NULL;
7475
7476         if (memcmp(texture_data_ptr, view_data_ptr, m_view_data_offset) != 0)
7477         {
7478                 /* Iterate over all texel components.
7479                  *
7480                  * The approach we're taking here works as follows:
7481                  *
7482                  * 1) Calculate what values should be sampled for each component using input mipmap
7483                  *    data.
7484                  * 2) Compare the reference values against the values returned when sampling the view.
7485                  *
7486                  * Note that in step 2) we're dealing with data that is returned by float/int/uint samplers,
7487                  * so we need to additionally process the data that we obtain by "casting" input data to
7488                  * the view's internalformat before we can perform the comparison.
7489                  *
7490                  * Finally, if the reference values are calculated for compressed data, we decompress it
7491                  * to GL_R8/GL_RG8/GL_RGB8/GL_RGBA8 internalformat first, depending on how many components
7492                  * the compressed internalformat supports.
7493                  **/
7494                 bool                              can_continue = true;
7495                 const glw::Functions& gl                   = m_context.getRenderContext().getFunctions();
7496
7497                 /* Determine a few important properties first */
7498                 const bool is_view_internalformat_compressed =
7499                         TextureViewUtilities::isInternalformatCompressed(view_internalformat);
7500                 unsigned int n_bits_per_view_texel = 0;
7501
7502                 const unsigned int n_view_components =
7503                         TextureViewUtilities::getAmountOfComponentsForInternalformat(view_internalformat);
7504                 _format texture_format = TextureViewUtilities::getFormatOfInternalformat(texture_internalformat);
7505
7506                 unsigned int view_component_sizes[4] = { 0 };
7507                 _format          view_format                     = TextureViewUtilities::getFormatOfInternalformat(view_internalformat);
7508
7509                 if (!is_view_internalformat_compressed)
7510                 {
7511                         TextureViewUtilities::getComponentSizeForInternalformat(view_internalformat, view_component_sizes);
7512
7513                         n_bits_per_view_texel =
7514                                 view_component_sizes[0] + view_component_sizes[1] + view_component_sizes[2] + view_component_sizes[3];
7515                 }
7516                 else
7517                 {
7518                         if (texture_internalformat == GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT ||
7519                                 texture_internalformat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT)
7520                         {
7521                                 /* Each component of decompressed data will be retrieved as a 32-bit FP */
7522                                 for (unsigned int n_component = 0; n_component < n_view_components; ++n_component)
7523                                 {
7524                                         view_component_sizes[n_component] = 32 /* bits per byte */;
7525                                 }
7526
7527                                 n_bits_per_view_texel = 32 /* bits per byte */ * n_view_components;
7528                         }
7529                         else
7530                         {
7531                                 /* Each component of decompressed data is stored as either signed or unsigned
7532                                  * byte. */
7533                                 for (unsigned int n_component = 0; n_component < n_view_components; ++n_component)
7534                                 {
7535                                         view_component_sizes[n_component] = 8 /* bits per byte */;
7536                                 }
7537
7538                                 n_bits_per_view_texel = 8 /* bits per byte */ * n_view_components;
7539                         }
7540                 }
7541
7542                 /* If we need to use compressed data as reference, we need to ask GL to decompress
7543                  * the mipmap data using view-specific internalformat.
7544                  */
7545                 mipmap_data = m_mipmap_data;
7546
7547                 if (is_view_internalformat_compressed)
7548                 {
7549                         /* Deallocate the buffer if necessary just in case */
7550                         if (m_decompressed_mipmap_data != DE_NULL)
7551                         {
7552                                 delete[] m_decompressed_mipmap_data;
7553
7554                                 m_decompressed_mipmap_data = DE_NULL;
7555                         }
7556
7557                         m_decompressed_mipmap_data =
7558                                 new unsigned char[m_texture_width * m_texture_height * (n_bits_per_view_texel >> 3)];
7559
7560                         glw::GLuint reference_tex_id = m_to_id;
7561                         if (texture_internalformat == GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT ||
7562                                 texture_internalformat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT)
7563                         {
7564                                 // Encodings of SIGNED and UNSIGNED BPTC compressed texture are not compatible
7565                                 // even though they are in the same view class. Since the "view" texture contains
7566                                 // the correct encoding for the results we use that as a reference instead of the
7567                                 // incompatible parent encoded.
7568                                 reference_tex_id = m_view_to_id;
7569                         }
7570                         gl.bindTexture(GL_TEXTURE_2D, reference_tex_id);
7571                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7572
7573                         gl.getTexImage(GL_TEXTURE_2D, 0, /* level */
7574                                                    (n_view_components == 4) ?
7575                                                            GL_RGBA :
7576                                                            (n_view_components == 3) ? GL_RGB : (n_view_components == 2) ? GL_RG : GL_RED,
7577                                                    (texture_format == FORMAT_SNORM) ?
7578                                                            GL_BYTE :
7579                                                            (texture_format == FORMAT_FLOAT) ? GL_FLOAT : GL_UNSIGNED_BYTE,
7580                                                    m_decompressed_mipmap_data);
7581
7582                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexImage() call failed.");
7583
7584                         mipmap_data = m_decompressed_mipmap_data;
7585                 }
7586
7587                 for (unsigned int n_texel = 0; n_texel < m_texture_height * m_texture_width && can_continue; ++n_texel)
7588                 {
7589                         /* NOTE: Vertex shader stores the sampled contents of a view texture as a
7590                          *       vec4/ivec4/uvec4. This means that each comonent in view_data_ptr
7591                          *       always takes sizeof(float) = sizeof(int) = sizeof(uint) bytes.
7592                          *
7593                          * NOTE: We cast input mip-map's data to view's internalformat, which is
7594                          *       why we're assuming each components takes n_bits_per_view_texel
7595                          *       bits instead of n_bits_per_mipmap_texel.
7596                          */
7597                         const unsigned char* mipmap_texel_data =
7598                                 mipmap_data + (n_bits_per_view_texel >> 3 /* 8 bits/byte */) * n_texel;
7599                         float             reference_components_float[4] = { 0 };
7600                         signed int      reference_components_int[4]   = { 0 };
7601                         unsigned int  reference_components_uint[4]  = { 0 };
7602                         float             view_components_float[4]              = { 0 };
7603                         signed int      view_components_int[4]          = { 0 };
7604                         unsigned int  view_components_uint[4]           = { 0 };
7605                         _sampler_type view_sampler_type =
7606                                 TextureViewUtilities::getSamplerTypeForInternalformat(view_internalformat);
7607                         const unsigned char* view_texel_data = view_data_ptr + sizeof(float) * n_view_components * n_texel;
7608
7609                         /* Retrieve data sampled from the view */
7610                         for (unsigned int n_component = 0; n_component < n_view_components;
7611                                  view_texel_data += sizeof(float), /* as per comment */
7612                                  ++n_component)
7613                         {
7614                                 switch (view_sampler_type)
7615                                 {
7616                                 case SAMPLER_TYPE_FLOAT:
7617                                 {
7618                                         view_components_float[n_component] = *((float*)view_texel_data);
7619
7620                                         break;
7621                                 }
7622
7623                                 case SAMPLER_TYPE_SIGNED_INTEGER:
7624                                 {
7625                                         view_components_int[n_component] = *((signed int*)view_texel_data);
7626
7627                                         break;
7628                                 }
7629
7630                                 case SAMPLER_TYPE_UNSIGNED_INTEGER:
7631                                 {
7632                                         view_components_uint[n_component] = *((unsigned int*)view_texel_data);
7633
7634                                         break;
7635                                 }
7636
7637                                 default:
7638                                 {
7639                                         TCU_FAIL("Unrecognized sampler type");
7640                                 }
7641                                 } /* switch (view_sampler_type) */
7642                         }        /* for (all components) */
7643
7644                         /* Compute reference data. Handle non-byte aligned internalformats manually. */
7645                         if (view_internalformat == GL_R11F_G11F_B10F)
7646                         {
7647                                 const unsigned int* reference_data  = (unsigned int*)mipmap_texel_data;
7648                                 const unsigned int  red_component   = (*reference_data) & ((1 << 11) - 1);
7649                                 const unsigned int  green_component = (*reference_data >> 11) & ((1 << 11) - 1);
7650                                 const unsigned int  blue_component  = (*reference_data >> 22) & ((1 << 10) - 1);
7651
7652                                 if (view_sampler_type == SAMPLER_TYPE_FLOAT)
7653                                 {
7654                                         reference_components_float[0] = Float11(red_component).asFloat();
7655                                         reference_components_float[1] = Float11(green_component).asFloat();
7656                                         reference_components_float[2] = Float10(blue_component).asFloat();
7657                                 }
7658                                 else
7659                                 {
7660                                         TCU_FAIL("Internal error: invalid sampler type requested");
7661                                 }
7662                         }
7663                         else if (view_internalformat == GL_RGB9_E5)
7664                         {
7665                                 /* Refactored version of tcuTexture.cpp::unpackRGB999E5() */
7666                                 const unsigned int* reference_data  = (unsigned int*)mipmap_texel_data;
7667                                 const unsigned int  exponent            = (*reference_data >> 27) & ((1 << 5) - 1);
7668                                 const unsigned int  red_component   = (*reference_data) & ((1 << 9) - 1);
7669                                 const unsigned int  green_component = (*reference_data >> 9) & ((1 << 9) - 1);
7670                                 const unsigned int  blue_component  = (*reference_data >> 18) & ((1 << 9) - 1);
7671
7672                                 float shared_exponent =
7673                                         deFloatPow(2.0f, (float)((int)exponent - 15 /* exponent bias */ - 9 /* mantissa */));
7674
7675                                 if (view_sampler_type == SAMPLER_TYPE_FLOAT)
7676                                 {
7677                                         reference_components_float[0] = float(red_component) * shared_exponent;
7678                                         reference_components_float[1] = float(green_component) * shared_exponent;
7679                                         reference_components_float[2] = float(blue_component) * shared_exponent;
7680                                 }
7681                                 else
7682                                 {
7683                                         TCU_FAIL("Internal error: invalid sampler type requested");
7684                                 }
7685                         }
7686                         else if (view_internalformat == GL_RGB10_A2)
7687                         {
7688                                 unsigned int*     reference_data = (unsigned int*)mipmap_texel_data;
7689                                 const unsigned int mask_rgb               = (1 << 10) - 1;
7690                                 const unsigned int mask_a                 = (1 << 2) - 1;
7691
7692                                 if (view_sampler_type == SAMPLER_TYPE_FLOAT)
7693                                 {
7694                                         reference_components_float[0] = float(((*reference_data)) & (mask_rgb)) / float(mask_rgb);
7695                                         reference_components_float[1] = float(((*reference_data) >> 10) & (mask_rgb)) / float(mask_rgb);
7696                                         reference_components_float[2] = float(((*reference_data) >> 20) & (mask_rgb)) / float(mask_rgb);
7697                                         reference_components_float[3] = float(((*reference_data) >> 30) & (mask_a)) / float(mask_a);
7698                                 }
7699                                 else
7700                                 {
7701                                         TCU_FAIL("Internal error: invalid sampler type requested");
7702                                 }
7703                         }
7704                         else if (view_internalformat == GL_RGB10_A2UI)
7705                         {
7706                                 unsigned int*     reference_data = (unsigned int*)mipmap_texel_data;
7707                                 const unsigned int mask_rgb               = (1 << 10) - 1;
7708                                 const unsigned int mask_a                 = (1 << 2) - 1;
7709
7710                                 if (view_sampler_type == SAMPLER_TYPE_UNSIGNED_INTEGER)
7711                                 {
7712                                         reference_components_uint[0] = ((*reference_data)) & (mask_rgb);
7713                                         reference_components_uint[1] = ((*reference_data) >> 10) & (mask_rgb);
7714                                         reference_components_uint[2] = ((*reference_data) >> 20) & (mask_rgb);
7715                                         reference_components_uint[3] = ((*reference_data) >> 30) & (mask_a);
7716                                 }
7717                                 else
7718                                 {
7719                                         TCU_FAIL("Internal error: invalid sampler type requested");
7720                                 }
7721                         }
7722                         else if (view_internalformat == GL_RG16F)
7723                         {
7724                                 unsigned short* reference_data = (unsigned short*)mipmap_texel_data;
7725
7726                                 if (view_sampler_type == SAMPLER_TYPE_FLOAT)
7727                                 {
7728                                         reference_components_float[0] = tcu::Float16(*(reference_data + 0)).asFloat();
7729                                         reference_components_float[1] = tcu::Float16(*(reference_data + 1)).asFloat();
7730                                 }
7731                                 else
7732                                 {
7733                                         TCU_FAIL("Internal error: invalid sampler type requested");
7734                                 }
7735                         }
7736                         else
7737                         {
7738                                 void* result_data = NULL;
7739
7740                                 switch (view_sampler_type)
7741                                 {
7742                                 case SAMPLER_TYPE_FLOAT:
7743                                         result_data = reference_components_float;
7744                                         break;
7745                                 case SAMPLER_TYPE_SIGNED_INTEGER:
7746                                         result_data = reference_components_int;
7747                                         break;
7748                                 case SAMPLER_TYPE_UNSIGNED_INTEGER:
7749                                         result_data = reference_components_uint;
7750                                         break;
7751
7752                                 default:
7753                                         TCU_FAIL("Unrecognized sampler type");
7754                                 }
7755
7756                                 getComponentDataForByteAlignedInternalformat(mipmap_texel_data, n_view_components, view_component_sizes,
7757                                                                                                                          view_format, result_data);
7758                         }
7759
7760                         for (unsigned int n_component = 0; n_component < n_view_components; ++n_component)
7761                         {
7762                                 /* If view texture operates on sRGB color space, we need to adjust our
7763                                  * reference value so that it is moved back into linear space.
7764                                  */
7765                                 if (TextureViewUtilities::isInternalformatSRGB(view_internalformat) &&
7766                                         !TextureViewUtilities::isInternalformatSRGB(texture_internalformat))
7767                                 {
7768                                         DE_ASSERT(view_sampler_type == SAMPLER_TYPE_FLOAT);
7769
7770                                         /* Convert as per (8.14) from GL4.4 spec. Exclude alpha channel. */
7771                                         if (n_component != 3)
7772                                         {
7773                                                 if (reference_components_float[n_component] <= 0.04045f)
7774                                                 {
7775                                                         reference_components_float[n_component] /= 12.92f;
7776                                                 }
7777                                                 else
7778                                                 {
7779                                                         reference_components_float[n_component] =
7780                                                                 deFloatPow((reference_components_float[n_component] + 0.055f) / 1.055f, 2.4f);
7781                                                 }
7782                                         } /* if (n_component != 3) */
7783                                 }        /* if (TextureViewUtilities::isInternalformatSRGB(view_internalformat) ) */
7784
7785                                 /* Compare the reference and view texture values */
7786                                 const float                epsilon_float = 1.0f / float((1 << (view_component_sizes[n_component] - 1)) - 1);
7787                                 const signed int   epsilon_int   = 1;
7788                                 const unsigned int epsilon_uint  = 1;
7789
7790                                 switch (view_sampler_type)
7791                                 {
7792                                 case SAMPLER_TYPE_FLOAT:
7793                                 {
7794                                         if (de::abs(reference_components_float[n_component] - view_components_float[n_component]) >
7795                                                 epsilon_float)
7796                                         {
7797                                                 has_failed = true;
7798                                         }
7799
7800                                         break;
7801                                 }
7802
7803                                 case SAMPLER_TYPE_SIGNED_INTEGER:
7804                                 {
7805                                         signed int larger_value  = 0;
7806                                         signed int smaller_value = 0;
7807
7808                                         if (reference_components_int[n_component] > view_components_int[n_component])
7809                                         {
7810                                                 larger_value  = reference_components_int[n_component];
7811                                                 smaller_value = view_components_int[n_component];
7812                                         }
7813                                         else
7814                                         {
7815                                                 smaller_value = reference_components_int[n_component];
7816                                                 larger_value  = view_components_int[n_component];
7817                                         }
7818
7819                                         if ((larger_value - smaller_value) > epsilon_int)
7820                                         {
7821                                                 has_failed = true;
7822                                         }
7823
7824                                         break;
7825                                 }
7826
7827                                 case SAMPLER_TYPE_UNSIGNED_INTEGER:
7828                                 {
7829                                         unsigned int larger_value  = 0;
7830                                         unsigned int smaller_value = 0;
7831
7832                                         if (reference_components_uint[n_component] > view_components_uint[n_component])
7833                                         {
7834                                                 larger_value  = reference_components_uint[n_component];
7835                                                 smaller_value = view_components_uint[n_component];
7836                                         }
7837                                         else
7838                                         {
7839                                                 smaller_value = reference_components_uint[n_component];
7840                                                 larger_value  = view_components_uint[n_component];
7841                                         }
7842
7843                                         if ((larger_value - smaller_value) > epsilon_uint)
7844                                         {
7845                                                 has_failed = true;
7846                                         }
7847
7848                                         break;
7849                                 }
7850
7851                                 default:
7852                                         TCU_FAIL("Unrecognized sampler type");
7853                                 } /* switch (view_sampler_type) */
7854
7855                                 if (has_failed)
7856                                 {
7857                                         can_continue = false;
7858
7859                                         switch (view_sampler_type)
7860                                         {
7861                                         case SAMPLER_TYPE_FLOAT:
7862                                         {
7863                                                 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data sampled from a texture view "
7864                                                                                                                                            "["
7865                                                                                    << view_internalformat_string << "]"
7866                                                                                                                                                         " created from a texture object"
7867                                                                                                                                                         "["
7868                                                                                    << texture_internalformat_string << "]"
7869                                                                                                                                                            " at texel "
7870                                                                                                                                                            "("
7871                                                                                    << (n_texel % m_texture_width) << ", " << (n_texel / m_texture_height)
7872                                                                                    << "): expected:(" << reference_components_float[0] << ", "
7873                                                                                    << reference_components_float[1] << ", " << reference_components_float[2]
7874                                                                                    << ", " << reference_components_float[3] << ") found:("
7875                                                                                    << view_components_float[0] << ", " << view_components_float[1] << ", "
7876                                                                                    << view_components_float[2] << ", " << view_components_float[3] << ")."
7877                                                                                    << tcu::TestLog::EndMessage;
7878
7879                                                 break;
7880                                         }
7881
7882                                         case SAMPLER_TYPE_SIGNED_INTEGER:
7883                                         {
7884                                                 m_testCtx.getLog()
7885                                                         << tcu::TestLog::Message << "Invalid data sampled from a signed integer texture view "
7886                                                                                                                 "["
7887                                                         << view_internalformat_string << "]"
7888                                                                                                                          " created from a texture object"
7889                                                                                                                          "["
7890                                                         << texture_internalformat_string << "]"
7891                                                                                                                                 " at texel "
7892                                                                                                                                 "("
7893                                                         << (n_texel % m_texture_width) << ", " << (n_texel / m_texture_height) << "): expected:("
7894                                                         << reference_components_int[0] << ", " << reference_components_int[1] << ", "
7895                                                         << reference_components_int[2] << ", " << reference_components_int[3] << ") found:("
7896                                                         << view_components_int[0] << ", " << view_components_int[1] << ", "
7897                                                         << view_components_int[2] << ", " << view_components_int[3] << ")."
7898                                                         << tcu::TestLog::EndMessage;
7899
7900                                                 break;
7901                                         }
7902
7903                                         case SAMPLER_TYPE_UNSIGNED_INTEGER:
7904                                         {
7905                                                 m_testCtx.getLog()
7906                                                         << tcu::TestLog::Message << "Invalid data sampled from an unsigned integer texture view "
7907                                                                                                                 "["
7908                                                         << view_internalformat_string << "]"
7909                                                                                                                          " created from a texture object"
7910                                                                                                                          "["
7911                                                         << texture_internalformat_string << "]"
7912                                                                                                                                 " at texel "
7913                                                                                                                                 "("
7914                                                         << (n_texel % m_texture_width) << ", " << (n_texel / m_texture_height) << "): expected:("
7915                                                         << reference_components_uint[0] << ", " << reference_components_uint[1] << ", "
7916                                                         << reference_components_uint[2] << ", " << reference_components_uint[3] << ") found:("
7917                                                         << view_components_uint[0] << ", " << view_components_uint[1] << ", "
7918                                                         << view_components_uint[2] << ", " << view_components_uint[3] << ")."
7919                                                         << tcu::TestLog::EndMessage;
7920
7921                                                 break;
7922                                         }
7923
7924                                         default:
7925                                                 TCU_FAIL("Unrecognized sampler type");
7926                                         } /* switch (view_sampler_type) */
7927
7928                                         break;
7929                                 } /* if (has_failed) */
7930                         }        /* for (all components) */
7931                 }                 /* for (all texels) */
7932         }                         /* if (memcmp(texture_data_ptr, view_data_ptr, m_view_data_offset) != 0) */
7933
7934         if (has_failed)
7935         {
7936                 /* Log detailed information about the failure */
7937                 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data read from a view of internalformat "
7938                                                    << "[" << view_internalformat_string << "]"
7939                                                    << " created from a texture of internalformat "
7940                                                    << "[" << texture_internalformat_string << "]"
7941                                                    << ". Byte streams follow:" << tcu::TestLog::EndMessage;
7942
7943                 /* Form texture and view data strings */
7944                 std::stringstream mipmap_data_sstream;
7945                 std::stringstream sampled_view_data_sstream;
7946
7947                 mipmap_data_sstream.fill('0');
7948                 sampled_view_data_sstream.fill('0');
7949
7950                 mipmap_data_sstream.width(2);
7951                 sampled_view_data_sstream.width(2);
7952
7953                 mipmap_data_sstream << "Mip-map data: [";
7954                 sampled_view_data_sstream << "Sampled view data: [";
7955
7956                 for (unsigned int n = 0; n < m_view_data_offset; ++n)
7957                 {
7958                         mipmap_data_sstream << "0x" << std::hex << (int)(mipmap_data[n]);
7959                         sampled_view_data_sstream << "0x" << std::hex << (int)(view_data_ptr[n]);
7960
7961                         if (n != (m_view_data_offset - 1))
7962                         {
7963                                 mipmap_data_sstream << "|";
7964                                 sampled_view_data_sstream << "|";
7965                         }
7966                         else
7967                         {
7968                                 mipmap_data_sstream << "]";
7969                                 sampled_view_data_sstream << "]";
7970                         }
7971                 }
7972
7973                 sampled_view_data_sstream << "\n";
7974                 mipmap_data_sstream << "\n";
7975
7976                 /* Log both strings */
7977                 m_testCtx.getLog() << tcu::TestLog::Message << mipmap_data_sstream.str() << sampled_view_data_sstream.str()
7978                                                    << tcu::TestLog::EndMessage;
7979
7980                 /* Do not fail the test at this point. Instead, raise a failure flag that will
7981                  * cause the test to fail once all iterations execute */
7982                 m_has_test_failed = true;
7983         }
7984         else
7985         {
7986                 m_testCtx.getLog() << tcu::TestLog::Message << "Correct data read from a view of internalformat "
7987                                                    << "[" << view_internalformat_string << "]"
7988                                                    << " created from a texture of internalformat "
7989                                                    << "[" << texture_internalformat_string << "]" << tcu::TestLog::EndMessage;
7990         }
7991 }
7992
7993 /** Constructor.
7994  *
7995  *  @param context Rendering context.
7996  *
7997  **/
7998 TextureViewTestCoherency::TextureViewTestCoherency(deqp::Context& context)
7999         : TestCase(context, "coherency", "Verifies view/parent texture coherency")
8000         , m_are_images_supported(false)
8001         , m_bo_id(0)
8002         , m_draw_fbo_id(0)
8003         , m_gradient_verification_po_id(0)
8004         , m_gradient_verification_po_sample_exact_uv_location(-1)
8005         , m_gradient_verification_po_lod_location(-1)
8006         , m_gradient_verification_po_texture_location(-1)
8007         , m_gradient_verification_vs_id(0)
8008         , m_gradient_image_write_image_size_location(-1)
8009         , m_gradient_image_write_po_id(0)
8010         , m_gradient_image_write_vs_id(0)
8011         , m_gradient_write_po_id(0)
8012         , m_gradient_write_fs_id(0)
8013         , m_gradient_write_vs_id(0)
8014         , m_read_fbo_id(0)
8015         , m_static_to_id(0)
8016         , m_to_id(0)
8017         , m_vao_id(0)
8018         , m_view_to_id(0)
8019         , m_verification_po_expected_color_location(-1)
8020         , m_verification_po_lod_location(-1)
8021         , m_verification_po_id(0)
8022         , m_verification_vs_id(0)
8023         , m_static_texture_height(1)
8024         , m_static_texture_width(1)
8025         , m_texture_height(64)
8026         , m_texture_n_components(4)
8027         , m_texture_n_levels(7)
8028         , m_texture_width(64)
8029 {
8030         /* Initialize static color that will be used for some of the cases */
8031         m_static_color_byte[0] = 100;
8032         m_static_color_byte[1] = 0;
8033         m_static_color_byte[2] = 255;
8034         m_static_color_byte[3] = 200;
8035
8036         m_static_color_float[0] = float(m_static_color_byte[0]) / 255.0f;
8037         m_static_color_float[1] = float(m_static_color_byte[1]) / 255.0f;
8038         m_static_color_float[2] = float(m_static_color_byte[2]) / 255.0f;
8039         m_static_color_float[3] = float(m_static_color_byte[3]) / 255.0f;
8040 }
8041
8042 /** Verifies that texture/view & view/texture coherency requirement is met
8043  *  when glTexSubImage2D() or glBlitFramebuffer() API calls are used to modify
8044  *  the contents of one of the mip-maps. The function does not use any memory
8045  *  barriers as these are not required for the objects to stay synchronised.
8046  *
8047  *  Throws TestError  exceptionif the GL implementation fails the check.
8048  *
8049  *  @param texture_type               Defines whether it should be parent texture or
8050  *                                    its view that the writing operation should be
8051  *                                    performed against. The reading operation will
8052  *                                    be issued against the sibling object.
8053  *  @param should_use_glTexSubImage2D true if glTexSubImage2D() should be used for the
8054  *                                    check, false to use glBlitFramebuffer().
8055  *
8056  **/
8057 void TextureViewTestCoherency::checkAPICallCoherency(_texture_type texture_type, bool should_use_glTexSubImage2D)
8058 {
8059         const glw::Functions& gl                          = m_context.getRenderContext().getFunctions();
8060         unsigned int              write_to_height = 0;
8061         unsigned int              write_to_width  = 0;
8062         glw::GLuint                       write_to_id    = 0;
8063
8064         getWritePropertiesForTextureType(texture_type, &write_to_id, &write_to_width, &write_to_height);
8065
8066         if (should_use_glTexSubImage2D)
8067         {
8068                 /* Update texture binding for texture unit 0, given the texture type the caller wants
8069                  * us to test. We'll need the binding set appropriately for the subsequent
8070                  * glTexSubImage2D() call.
8071                  */
8072                 gl.activeTexture(GL_TEXTURE0);
8073                 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed.");
8074
8075                 gl.bindTexture(GL_TEXTURE_2D, write_to_id);
8076                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
8077         }
8078         else
8079         {
8080                 /* To perform a blit operation, we need to configure draw & read FBO, taking
8081                  * the tested texture type into account. */
8082                 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_draw_fbo_id);
8083                 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
8084                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call(s) failed.");
8085
8086                 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, write_to_id, 1); /* level */
8087                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed for GL_DRAW_FRAMEBUFFER target.");
8088
8089                 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_static_to_id,
8090                                                                 0); /* level */
8091                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed for GL_READ_FRAMEBUFFER target.");
8092         }
8093
8094         /* Execute the API call */
8095         const unsigned int region_width  = (write_to_width >> 1);
8096         const unsigned int region_height = (write_to_height >> 1);
8097         const unsigned int region_x              = region_width - (region_width >> 1);
8098         const unsigned int region_y              = region_height - (region_height >> 1);
8099
8100         if (should_use_glTexSubImage2D)
8101         {
8102                 /* Call glTexSubImage2D() to replace a portion of the gradient with a static color */
8103                 {
8104                         unsigned char* static_color_data_ptr = getStaticColorTextureData(region_width, region_height);
8105
8106                         gl.texSubImage2D(GL_TEXTURE_2D, 1, /* level */
8107                                                          region_x, region_y, region_width, region_height, GL_RGBA, GL_UNSIGNED_BYTE,
8108                                                          static_color_data_ptr);
8109
8110                         /* Good to release static color data buffer at this point */
8111                         delete[] static_color_data_ptr;
8112
8113                         static_color_data_ptr = DE_NULL;
8114
8115                         /* Make sure the API call was successful */
8116                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
8117                 }
8118         }
8119         else
8120         {
8121                 gl.blitFramebuffer(0,                                           /* srcX0 */
8122                                                    0,                                           /* srcY0 */
8123                                                    m_static_texture_width,  /* srcX1 */
8124                                                    m_static_texture_height, /* srcY1 */
8125                                                    region_x, region_y, region_x + region_width, region_y + region_height, GL_COLOR_BUFFER_BIT,
8126                                                    GL_NEAREST);
8127                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBlitFramebuffer() call failed.");
8128         }
8129
8130         /* Bind the sibling object so that we can make sure the data read from the
8131          * region can be correctly read from a shader without a memory barrier.
8132          *
8133          * While we're here, also determine which LOD we should be sampling from in
8134          * the shader.
8135          **/
8136         unsigned int read_lod   = 0;
8137         glw::GLuint  read_to_id = 0;
8138
8139         getReadPropertiesForTextureType(texture_type, &read_to_id, &read_lod);
8140
8141         gl.bindTexture(GL_TEXTURE_2D, read_to_id);
8142         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
8143
8144         /* Update the test program uniforms before we carry on with actual
8145          * verification
8146          */
8147         gl.useProgram(m_verification_po_id);
8148         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8149
8150         DE_STATIC_ASSERT(sizeof(m_static_color_float) == sizeof(float) * 4);
8151
8152         gl.uniform4fv(m_verification_po_expected_color_location, 1, /* count */
8153                                   m_static_color_float);
8154         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() call failed.");
8155
8156         gl.uniform1i(m_verification_po_lod_location, read_lod);
8157         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
8158
8159         /* Make sure rasterization is disabled before we carry on */
8160         gl.enable(GL_RASTERIZER_DISCARD);
8161         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed.");
8162
8163         /* Go ahead with the rendering. Make sure to capture the varyings */
8164         gl.beginTransformFeedback(GL_POINTS);
8165         GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
8166         {
8167                 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
8168                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
8169         }
8170         gl.endTransformFeedback();
8171         GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
8172
8173         /* Map the buffer object so we can validate the sampling result */
8174         const glw::GLint* data_ptr = (const glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
8175
8176         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
8177         DE_ASSERT(data_ptr != NULL);
8178
8179         /* Verify the outcome of the sampling operation */
8180         if (*data_ptr != 1)
8181         {
8182                 TCU_FAIL("Invalid data was sampled in vertex shader");
8183         }
8184
8185         /* Unmap the buffer object */
8186         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
8187         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
8188
8189         data_ptr = DE_NULL;
8190
8191         /* Disable GL_RASTERIZER_DISCARD mode */
8192         gl.disable(GL_RASTERIZER_DISCARD);
8193         GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed.");
8194 }
8195
8196 /** Verifies texture/view & view/texture coherency is met when one of the objects
8197  *  is used as a render-target. The function writes to user-specified texture type,
8198  *  and then verifies the contents of the sibling object.
8199  *
8200  *  The function throws TestError exception if any of the checks fail.
8201  *
8202  *  @param texture_type      Tells which of the two objects should be written to.
8203  *  @param should_use_images true if images should be used for
8204  *  @param barrier_type      Type of the memory barrier that should be injected
8205  *                           after vertex shader stage with image writes is executed.
8206  *                           Must be BARRIER_TYPE_NONE if @param should_use_images
8207  *                           is set to false.
8208  *  @param verification_mean Determines whether the verification should be performed
8209  *                           using a program object, or by CPU with the data
8210  *                           extracted from the sibling object using a glGetTexImage()
8211  *                           call.
8212  *
8213  **/
8214 void TextureViewTestCoherency::checkProgramWriteCoherency(_texture_type texture_type, bool should_use_images,
8215                                                                                                                   _barrier_type          barrier_type,
8216                                                                                                                   _verification_mean verification_mean)
8217 {
8218         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8219
8220         if (!should_use_images)
8221         {
8222                 /* Sanity check: no barrier should be requested if images are not used */
8223                 DE_ASSERT(barrier_type == BARRIER_TYPE_NONE);
8224
8225                 /* Sanity check: glGetTexImage*() call should only be used for verification
8226                  *               when images are used */
8227                 DE_ASSERT(verification_mean == VERIFICATION_MEAN_PROGRAM);
8228         }
8229
8230         /* Determine GL id of an object we will be rendering the gradient to */
8231         glw::GLuint  write_to_id         = 0;
8232         unsigned int write_to_width  = 0;
8233         unsigned int write_to_height = 0;
8234
8235         getWritePropertiesForTextureType(texture_type, &write_to_id, &write_to_width, &write_to_height);
8236
8237         /* Configure the render targets */
8238         if (should_use_images)
8239         {
8240                 gl.bindImageTexture(0,                          /* unit */
8241                                                         write_to_id, 1, /* second level */
8242                                                         GL_FALSE,               /* layered */
8243                                                         0,                              /* layer */
8244                                                         GL_WRITE_ONLY, GL_RGBA8);
8245
8246                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture() call failed.");
8247         }
8248         else
8249         {
8250                 /* We first need to fill either the texture or its sibling view with
8251                  * gradient data. Set up draw framebuffer */
8252                 gl.bindFramebuffer(GL_FRAMEBUFFER, m_draw_fbo_id);
8253                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed for GL_FRAMEBUFFER target");
8254
8255                 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, write_to_id, 1); /* level */
8256                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
8257
8258                 /* Configure the viewport accordingly */
8259                 gl.viewport(0, /* x */
8260                                         0, /* y */
8261                                         write_to_width, write_to_height);
8262                 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
8263         }
8264
8265         /* The gradient needs to be rendered differently, depending on whether
8266          * we're asked to use images or not */
8267         if (should_use_images)
8268         {
8269                 gl.useProgram(m_gradient_image_write_po_id);
8270                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8271
8272                 gl.uniform2i(m_gradient_image_write_image_size_location, write_to_width, write_to_height);
8273                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform2i() call failed.");
8274
8275                 gl.enable(GL_RASTERIZER_DISCARD);
8276                 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed.");
8277                 {
8278                         gl.drawArrays(GL_POINTS, 0 /* first */, write_to_width * write_to_height);
8279                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
8280                 }
8281                 gl.disable(GL_RASTERIZER_DISCARD);
8282                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable(GL_RASTERIZER_DISCARD) call failed.");
8283
8284                 /* If the caller requested any barriers, issue them at this point */
8285                 switch (barrier_type)
8286                 {
8287                 case BARRIER_TYPE_TEXTURE_FETCH_BARRIER_BIT:
8288                 {
8289                         gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
8290
8291                         GLU_EXPECT_NO_ERROR(gl.getError(),
8292                                                                 "glMemoryBarrier() call failed for GL_TEXTURE_FETCH_BARRIER_BIT barrier");
8293
8294                         break;
8295                 }
8296
8297                 case BARRIER_TYPE_TEXTURE_UPDATE_BUFFER_BIT:
8298                 {
8299                         gl.memoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
8300
8301                         GLU_EXPECT_NO_ERROR(gl.getError(),
8302                                                                 "glMemoryBarrier() call failed for GL_TEXTURE_UPDATE_BARRIER_BIT barrier");
8303
8304                         break;
8305                 }
8306
8307                 default:
8308                 {
8309                         TCU_FAIL("Unrecognized barrier type");
8310                 }
8311                 } /* switch (barrier_type) */
8312         }        /* if (should_use_images) */
8313         else
8314         {
8315                 /* Render the gradient on a full-screen quad */
8316                 gl.useProgram(m_gradient_write_po_id);
8317                 GLU_EXPECT_NO_ERROR(gl.getError(), "gluseProgram() call failed.");
8318
8319                 gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
8320                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
8321         }
8322
8323         /* Determine which texture and which mip-map level we will need to sample
8324          * in order to verify whether the former operations have been completed
8325          * successfully.
8326          **/
8327         unsigned int read_lod   = 0;
8328         glw::GLuint  read_to_id = 0;
8329
8330         getReadPropertiesForTextureType(texture_type, &read_to_id, &read_lod);
8331
8332         /* Before we proceed with verification, update the texture binding so that
8333          * the verification program can sample from the right texture */
8334         gl.activeTexture(GL_TEXTURE0);
8335         GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed.");
8336
8337         gl.bindTexture(GL_TEXTURE_2D, read_to_id);
8338         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
8339
8340         if (verification_mean == VERIFICATION_MEAN_PROGRAM)
8341         {
8342                 /* Switch to a verification program. It uses a vertex shader to sample
8343                  * all texels of the texture so issue as many invocations as necessary. */
8344                 unsigned int n_invocations = write_to_width * write_to_height;
8345
8346                 gl.useProgram(m_gradient_verification_po_id);
8347                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8348
8349                 gl.uniform1i(m_gradient_verification_po_texture_location, 0);
8350                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
8351
8352                 gl.uniform1i(m_gradient_verification_po_sample_exact_uv_location, should_use_images);
8353                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
8354
8355                 gl.uniform1f(m_gradient_verification_po_lod_location, (float)read_lod);
8356                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f() call failed.");
8357
8358                 gl.enable(GL_RASTERIZER_DISCARD);
8359                 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed.");
8360
8361                 gl.beginTransformFeedback(GL_POINTS);
8362                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
8363                 {
8364                         gl.drawArrays(GL_POINTS, 0 /* first */, n_invocations);
8365                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
8366                 }
8367                 gl.endTransformFeedback();
8368                 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
8369
8370                 gl.disable(GL_RASTERIZER_DISCARD);
8371                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable(GL_RASTERIZER_DISCARD) call failed.");
8372
8373                 /* Map the result buffer object storage into process space */
8374                 const int* result_data_ptr = (const int*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
8375
8376                 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
8377
8378                 if (result_data_ptr == DE_NULL)
8379                 {
8380                         TCU_FAIL("glMapBuffer() did not generate an error but returned a NULL pointer");
8381                 }
8382
8383                 /* Verify the XFBed data */
8384                 for (unsigned int n_invocation = 0; n_invocation < n_invocations; ++n_invocation)
8385                 {
8386                         if (result_data_ptr[n_invocation] != 1)
8387                         {
8388                                 unsigned int invocation_x = n_invocation % write_to_width;
8389                                 unsigned int invocation_y = n_invocation / write_to_width;
8390
8391                                 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data was sampled at "
8392                                                                    << "(" << invocation_x << ", " << invocation_y << ") when sampling from "
8393                                                                    << ((texture_type == TEXTURE_TYPE_PARENT_TEXTURE) ? "a texture" : "a view")
8394                                                                    << tcu::TestLog::EndMessage;
8395
8396                                 /* Make sure the buffer is unmapped before throwing the exception */
8397                                 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
8398
8399                                 TCU_FAIL("Invalid data sampled");
8400                         }
8401                 } /* for (all invocations) */
8402
8403                 /* Unmap the buffer storage */
8404                 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
8405                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
8406         } /* if (verification_mean == VERIFICATION_MEAN_PROGRAM) */
8407         else
8408         {
8409                 DE_ASSERT(verification_mean == VERIFICATION_MEAN_GLGETTEXIMAGE);
8410
8411                 /* Allocate space for the data */
8412                 unsigned char* data_ptr = new unsigned char[write_to_width * write_to_height * m_texture_n_components];
8413
8414                 /* Retrieve the rendered data */
8415                 gl.getTexImage(GL_TEXTURE_2D, read_lod, GL_RGBA, GL_UNSIGNED_BYTE, data_ptr);
8416
8417                 if (gl.getError() != GL_NO_ERROR)
8418                 {
8419                         /* Release the buffer before we throw an exception */
8420                         delete[] data_ptr;
8421
8422                         TCU_FAIL("glGetTexImage() call failed.");
8423                 }
8424
8425                 /* Verify the data is correct */
8426                 const int epsilon                 = 1;
8427                 bool      is_data_correct = true;
8428
8429                 for (unsigned int y = 0; y < write_to_height; ++y)
8430                 {
8431                         const unsigned char* row_ptr = data_ptr + y * m_texture_n_components * write_to_width;
8432
8433                         for (unsigned int x = 0; x < write_to_width; ++x)
8434                         {
8435                                 const unsigned char* texel_ptr  = row_ptr + x * m_texture_n_components;
8436                                 const float                      end_rgba[]   = { 0.0f, 0.1f, 1.0f, 1.0f };
8437                                 const float                      lerp_factor  = float(x) / float(write_to_width);
8438                                 const float                      start_rgba[] = { 1.0f, 0.9f, 0.0f, 0.0f };
8439                                 const float expected_data_float[] = { start_rgba[0] * (1.0f - lerp_factor) + end_rgba[0] * lerp_factor,
8440                                                                                                           start_rgba[1] * (1.0f - lerp_factor) + end_rgba[1] * lerp_factor,
8441                                                                                                           start_rgba[2] * (1.0f - lerp_factor) + end_rgba[2] * lerp_factor,
8442                                                                                                           start_rgba[3] * (1.0f - lerp_factor) +
8443                                                                                                                   end_rgba[3] * lerp_factor };
8444                                 const unsigned char expected_data_ubyte[] = { (unsigned char)(expected_data_float[0] * 255.0f),
8445                                                                                                                           (unsigned char)(expected_data_float[1] * 255.0f),
8446                                                                                                                           (unsigned char)(expected_data_float[2] * 255.0f),
8447                                                                                                                           (unsigned char)(expected_data_float[3] * 255.0f) };
8448
8449                                 if (de::abs((int)texel_ptr[0] - (int)expected_data_ubyte[0]) > epsilon ||
8450                                         de::abs((int)texel_ptr[1] - (int)expected_data_ubyte[1]) > epsilon ||
8451                                         de::abs((int)texel_ptr[2] - (int)expected_data_ubyte[2]) > epsilon ||
8452                                         de::abs((int)texel_ptr[3] - (int)expected_data_ubyte[3]) > epsilon)
8453                                 {
8454                                         is_data_correct = false;
8455
8456                                         break;
8457                                 }
8458                         }
8459                 } /* for (all rows) */
8460
8461                 /* Good to release the data buffer at this point */
8462                 delete[] data_ptr;
8463
8464                 data_ptr = DE_NULL;
8465
8466                 /* Fail the test if any of the rendered texels were found invalid */
8467                 if (!is_data_correct)
8468                 {
8469                         TCU_FAIL("Invalid data sampled");
8470                 }
8471         }
8472 }
8473
8474 /** Deinitializes all GL objects that may have been created during
8475  *  test execution.
8476  **/
8477 void TextureViewTestCoherency::deinit()
8478 {
8479         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8480
8481         /* Release any GL objects the test may have created */
8482         if (m_bo_id != 0)
8483         {
8484                 gl.deleteBuffers(1, &m_bo_id);
8485
8486                 m_bo_id = 0;
8487         }
8488
8489         if (m_draw_fbo_id != 0)
8490         {
8491                 gl.deleteFramebuffers(1, &m_draw_fbo_id);
8492
8493                 m_draw_fbo_id = 0;
8494         }
8495
8496         if (m_gradient_image_write_po_id != 0)
8497         {
8498                 gl.deleteProgram(m_gradient_image_write_po_id);
8499
8500                 m_gradient_image_write_po_id = 0;
8501         }
8502
8503         if (m_gradient_image_write_vs_id != 0)
8504         {
8505                 gl.deleteShader(m_gradient_image_write_vs_id);
8506
8507                 m_gradient_image_write_vs_id = 0;
8508         }
8509
8510         if (m_gradient_verification_po_id != 0)
8511         {
8512                 gl.deleteProgram(m_gradient_verification_po_id);
8513
8514                 m_gradient_verification_po_id = 0;
8515         }
8516
8517         if (m_gradient_verification_vs_id != 0)
8518         {
8519                 gl.deleteShader(m_gradient_verification_vs_id);
8520
8521                 m_gradient_verification_vs_id = 0;
8522         }
8523
8524         if (m_gradient_write_fs_id != 0)
8525         {
8526                 gl.deleteShader(m_gradient_write_fs_id);
8527
8528                 m_gradient_write_fs_id = 0;
8529         }
8530
8531         if (m_gradient_write_po_id != 0)
8532         {
8533                 gl.deleteProgram(m_gradient_write_po_id);
8534
8535                 m_gradient_write_po_id = 0;
8536         }
8537
8538         if (m_gradient_write_vs_id != 0)
8539         {
8540                 gl.deleteShader(m_gradient_write_vs_id);
8541
8542                 m_gradient_write_vs_id = 0;
8543         }
8544
8545         if (m_read_fbo_id != 0)
8546         {
8547                 gl.deleteFramebuffers(1, &m_read_fbo_id);
8548
8549                 m_read_fbo_id = 0;
8550         }
8551
8552         if (m_static_to_id != 0)
8553         {
8554                 gl.deleteTextures(1, &m_static_to_id);
8555
8556                 m_static_to_id = 0;
8557         }
8558
8559         if (m_to_id != 0)
8560         {
8561                 gl.deleteTextures(1, &m_to_id);
8562
8563                 m_to_id = 0;
8564         }
8565
8566         if (m_vao_id != 0)
8567         {
8568                 gl.deleteVertexArrays(1, &m_vao_id);
8569
8570                 m_vao_id = 0;
8571         }
8572
8573         if (m_view_to_id != 0)
8574         {
8575                 gl.deleteTextures(1, &m_view_to_id);
8576
8577                 m_view_to_id = 0;
8578         }
8579
8580         if (m_verification_po_id != 0)
8581         {
8582                 gl.deleteProgram(m_verification_po_id);
8583
8584                 m_verification_po_id = 0;
8585         }
8586
8587         if (m_verification_vs_id != 0)
8588         {
8589                 gl.deleteShader(m_verification_vs_id);
8590
8591                 m_verification_vs_id = 0;
8592         }
8593
8594         /* Disable GL_RASTERIZER_DISCARD mode */
8595         gl.disable(GL_RASTERIZER_DISCARD);
8596 }
8597
8598 /** Allocates a sufficiently large buffer for RGBA8 data and fills it with
8599  *  a horizontal gradient (as described in the test specification)
8600  *
8601  *  It is user's responsibility to release the buffer when no longer needed.
8602  *
8603  *  @return Pointer to the buffer.
8604  **/
8605 unsigned char* TextureViewTestCoherency::getHorizontalGradientData() const
8606 {
8607         const float                end_rgba[]   = { 1.0f, 0.9f, 0.0f, 0.0f };
8608         unsigned char*   result         = new unsigned char[m_texture_width * m_texture_height * m_texture_n_components];
8609         const float                start_rgba[] = { 0.0f, 0.1f, 1.0f, 1.0f };
8610         const unsigned int texel_size   = m_texture_n_components;
8611
8612         for (unsigned int y = 0; y < m_texture_height; ++y)
8613         {
8614                 unsigned char* row_data_ptr = result + texel_size * m_texture_width * y;
8615
8616                 for (unsigned int x = 0; x < m_texture_width; ++x)
8617                 {
8618                         const float     lerp_factor     = float(x) / float(m_texture_width);
8619                         unsigned char* pixel_data_ptr = row_data_ptr + texel_size * x;
8620
8621                         for (unsigned int n_component = 0; n_component < 4 /* rgba */; ++n_component)
8622                         {
8623                                 pixel_data_ptr[n_component] = (unsigned char)((end_rgba[n_component] * lerp_factor +
8624                                                                                                                            start_rgba[n_component] * (1.0f - lerp_factor)) *
8625                                                                                                                           255.0f);
8626                         } /* for (all components) */
8627                 }        /* for (all columns) */
8628         }                 /* for (all rows) */
8629
8630         return result;
8631 }
8632
8633 /** Retrieves properties of a sibling object that should be read from during
8634  *  some of the checks.
8635  *
8636  *  @param texture_type Type of the texture object that should be used for reading.
8637  *  @param out_to_id    Deref will be used to store texture object ID of the object.
8638  *  @param out_read_lod Deref will be used to store LOD to be used for reading from
8639  *                      the object.
8640  *
8641  **/
8642 void TextureViewTestCoherency::getReadPropertiesForTextureType(_texture_type texture_type, glw::GLuint* out_to_id,
8643                                                                                                                            unsigned int* out_read_lod) const
8644 {
8645         switch (texture_type)
8646         {
8647         case TEXTURE_TYPE_PARENT_TEXTURE:
8648         {
8649                 *out_to_id = m_view_to_id;
8650
8651                 /* We've modified LOD1 of parent texture which corresponds
8652                  * to LOD 0 from the view's PoV
8653                  */
8654                 *out_read_lod = 0;
8655
8656                 break;
8657         }
8658
8659         case TEXTURE_TYPE_TEXTURE_VIEW:
8660         {
8661                 *out_to_id = m_to_id;
8662
8663                 /* We've modified LOD1 of the view texture which corresponds
8664                  * to LOD2 from parent texture's PoV.
8665                  */
8666                 *out_read_lod = 2;
8667
8668                 break;
8669         }
8670
8671         default:
8672         {
8673                 TCU_FAIL("Unrecognized read source");
8674         }
8675         } /* switch (texture_type) */
8676 }
8677
8678 /** Allocates a sufficiently large buffer to hold RGBA8 data of user-specified resolution
8679  *  and fills it with a static color (as described in the test specification)
8680  *
8681  *  It is caller's responsibility to release the returned buffer when it's no longer
8682  *  needed.
8683  *
8684  *  @param width  Width of the mip-map the buffer will be used as a data source for;
8685  *  @param height Height of the mip-map the buffer will be used as a data source for;
8686  *
8687  *  @return Pointer to the buffer.
8688  **/
8689 unsigned char* TextureViewTestCoherency::getStaticColorTextureData(unsigned int width, unsigned int height) const
8690 {
8691         /* Prepare the data buffer storing the data we want to replace the region of the
8692          * data source with.
8693          */
8694         unsigned char* result_ptr = new unsigned char[width * height * m_texture_n_components];
8695
8696         for (unsigned int y = 0; y < height; ++y)
8697         {
8698                 unsigned char* row_data_ptr = result_ptr + y * width * m_texture_n_components;
8699
8700                 for (unsigned int x = 0; x < width; ++x)
8701                 {
8702                         unsigned char* pixel_data_ptr = row_data_ptr + x * m_texture_n_components;
8703
8704                         memcpy(pixel_data_ptr, m_static_color_byte, sizeof(m_static_color_byte));
8705                 } /* for (all columns) */
8706         }        /* for (all rows) */
8707
8708         return result_ptr;
8709 }
8710
8711 /** Retrieves properties of a parent texture object that should be written to during
8712  *  some of the checks.
8713  *
8714  *  @param texture_type Type of the texture object that should be used for writing.
8715  *  @param out_to_id    Deref will be used to store texture object ID of the object. Must not be NULL.
8716  *  @param out_width    Deref will be used to store width of the mip-map the test will
8717  *                      be writing to; Must not be NULL.
8718  *  @param out_height   Deref will be used to store height of the mip-map the test will
8719  *                      be writing to. Must not be NULL.
8720  *
8721  **/
8722 void TextureViewTestCoherency::getWritePropertiesForTextureType(_texture_type texture_type, glw::GLuint* out_to_id,
8723                                                                                                                                 unsigned int* out_width, unsigned int* out_height) const
8724 {
8725         DE_ASSERT(out_to_id != DE_NULL);
8726         DE_ASSERT(out_width != DE_NULL);
8727         DE_ASSERT(out_height != DE_NULL);
8728
8729         /* All tests will be attempting to modify layer 1 of either the texture
8730          * or its sibling view. For views, the resolution is therefore going to
8731          * be 16x16 (because the base resolution is 32x32, as the view uses a mipmap
8732          * range of 1 to 2 inclusive); for parent texture, this will be 32x32 (as the base
8733          * mip-map is 64x64)
8734          */
8735         switch (texture_type)
8736         {
8737         case TEXTURE_TYPE_PARENT_TEXTURE:
8738         {
8739                 *out_to_id  = m_to_id;
8740                 *out_width  = m_texture_width >> 1;
8741                 *out_height = m_texture_height >> 1;
8742
8743                 break;
8744         }
8745
8746         case TEXTURE_TYPE_TEXTURE_VIEW:
8747         {
8748                 *out_to_id  = m_view_to_id;
8749                 *out_width  = m_texture_width >> 2;
8750                 *out_height = m_texture_height >> 2;
8751
8752                 break;
8753         }
8754
8755         default:
8756         {
8757                 TCU_FAIL("Unrecognized texture type");
8758         }
8759         } /* switch (texture_type) */
8760 }
8761
8762 /** Initializes buffer objects that will be used during the test.
8763  *
8764  *  Throws exceptions if the initialization fails at any point.
8765  **/
8766 void TextureViewTestCoherency::initBufferObjects()
8767 {
8768         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8769
8770         /* Generate and configure buffer object storage */
8771         gl.genBuffers(1, &m_bo_id);
8772         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
8773
8774         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
8775         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
8776
8777         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
8778         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
8779
8780         /* Case 1) needs the BO to hold just a single int.
8781          * Case 3) needs one int per result texel.
8782          *
8783          * Allocate enough space to handle all the cases.
8784          **/
8785         glw::GLint bo_size = static_cast<glw::GLint>((m_texture_height >> 1) * (m_texture_width >> 1) * sizeof(int));
8786
8787         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL, /* data */
8788                                   GL_STATIC_DRAW);
8789         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferdata() call failed.");
8790 }
8791
8792 /** Initializes framebuffer objects that will be used during the test.
8793  *
8794  *  Throws exceptions if the initialization fails at any point.
8795  **/
8796 void TextureViewTestCoherency::initFBO()
8797 {
8798         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8799
8800         /* Generate framebuffer object(s) */
8801         gl.genFramebuffers(1, &m_draw_fbo_id);
8802         gl.genFramebuffers(1, &m_read_fbo_id);
8803         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
8804 }
8805
8806 /** Initializes program objects that will be used during the test.
8807  *
8808  *  This method will throw exceptions if either compilation or linking of
8809  *  any of the processed shaders/programs fails.
8810  *
8811  **/
8812 void TextureViewTestCoherency::initPrograms()
8813 {
8814         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8815
8816         /* The test uses images in vertex shader stage. Make sure this is actually supported by
8817          * the implementation */
8818         m_are_images_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_image_load_store");
8819
8820         if (m_are_images_supported)
8821         {
8822                 glw::GLint gl_max_vertex_image_uniforms_value = 0;
8823
8824                 gl.getIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &gl_max_vertex_image_uniforms_value);
8825                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_VERTEX_IMAGE_UNIFORM pname");
8826
8827                 if (gl_max_vertex_image_uniforms_value < 1)
8828                 {
8829                         m_testCtx.getLog() << tcu::TestLog::Message
8830                                                            << "Image support will not be tested by view_parent_texture_coherency, as"
8831                                                                   "the implementation does not support image uniforms in vertex shader stage."
8832                                                            << tcu::TestLog::EndMessage;
8833
8834                         /* We cannot execute the test on this platform */
8835                         m_are_images_supported = false;
8836                 }
8837         } /* if (m_are_images_supported) */
8838
8839         /* Create program objects */
8840         if (m_are_images_supported)
8841         {
8842                 m_gradient_image_write_po_id = gl.createProgram();
8843         }
8844
8845         m_gradient_verification_po_id = gl.createProgram();
8846         m_gradient_write_po_id            = gl.createProgram();
8847         m_verification_po_id              = gl.createProgram();
8848         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
8849
8850         /* Create fragment shader objects */
8851         m_gradient_write_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
8852         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for GL_FRAGMENT_SHADER type");
8853
8854         /* Create vertex shader objects */
8855         if (m_are_images_supported)
8856         {
8857                 m_gradient_image_write_vs_id = gl.createShader(GL_VERTEX_SHADER);
8858         }
8859
8860         m_gradient_verification_vs_id = gl.createShader(GL_VERTEX_SHADER);
8861         m_gradient_write_vs_id            = gl.createShader(GL_VERTEX_SHADER);
8862         m_verification_vs_id              = gl.createShader(GL_VERTEX_SHADER);
8863         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed for GL_VERTEX_SHADER type.");
8864
8865         /* Set gradient verification program's fragment shader body */
8866         const char* gradient_verification_vs_body =
8867                 "#version 400\n"
8868                 "\n"
8869                 "out int result;\n"
8870                 "\n"
8871                 "uniform float     lod;\n"
8872                 "uniform bool      sample_exact_uv;\n"
8873                 "uniform sampler2D texture;\n"
8874                 "\n"
8875                 "void main()\n"
8876                 "{\n"
8877                 "    const float epsilon    = 1.0 / 255.0;\n"
8878                 "    const vec4  end_rgba   = vec4(0.0, 0.1, 1.0, 1.0);\n"
8879                 "    const vec4  start_rgba = vec4(1.0, 0.9, 0.0, 0.0);\n"
8880                 "\n"
8881                 "    ivec2 texture_size   = textureSize(texture, int(lod) );\n"
8882                 "    vec2  uv             = vec2(      float(gl_VertexID % texture_size.x) / float(texture_size.x),\n"
8883                 "                                1.0 - float(gl_VertexID / texture_size.x) / float(texture_size.y) );\n"
8884                 "    vec4  expected_color;\n"
8885                 "    vec4  texture_color  = textureLod(texture, uv, lod);\n"
8886                 "\n"
8887                 "    if (sample_exact_uv)\n"
8888                 "    {\n"
8889                 "        expected_color = mix(start_rgba, end_rgba, uv.x);\n"
8890                 "    }\n"
8891                 "    else\n"
8892                 "    {\n"
8893                 "        expected_color = mix(start_rgba, end_rgba, uv.x + 0.5/float(texture_size.x) );\n"
8894                 "    }\n"
8895                 "\n"
8896                 "\n"
8897                 "    if (abs(texture_color.x - expected_color.x) > epsilon ||\n"
8898                 "        abs(texture_color.y - expected_color.y) > epsilon ||\n"
8899                 "        abs(texture_color.z - expected_color.z) > epsilon ||\n"
8900                 "        abs(texture_color.w - expected_color.w) > epsilon)\n"
8901                 "    {\n"
8902                 "        result = int( texture_color.y * 255.0);\n"
8903                 "    }\n"
8904                 "    else\n"
8905                 "    {\n"
8906                 "        result = 1;\n"
8907                 "    }\n"
8908                 "}\n";
8909
8910         gl.shaderSource(m_gradient_verification_vs_id, 1 /* count */, &gradient_verification_vs_body, NULL /* length */);
8911         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8912
8913         /* Set gradient write (for images) program's vertex shader body */
8914         if (m_are_images_supported)
8915         {
8916                 const char* gradient_write_image_vs_body =
8917                         "#version 400\n"
8918                         "\n"
8919                         "#extension GL_ARB_shader_image_load_store : require\n"
8920                         "\n"
8921                         "layout(rgba8) uniform image2D image;\n"
8922                         "              uniform ivec2   image_size;\n"
8923                         "\n"
8924                         "void main()\n"
8925                         "{\n"
8926                         "    const  vec4 end_rgba   =  vec4(0.0, 0.1, 1.0, 1.0);\n"
8927                         "    const  vec4 start_rgba =  vec4(1.0, 0.9, 0.0, 0.0);\n"
8928                         "          ivec2 xy         = ivec2(gl_VertexID % image_size.x,              gl_VertexID / image_size.x);\n"
8929                         "           vec2 uv         =  vec2(float(xy.x) / float(image_size.x), 1.0 - float(xy.y) / "
8930                         "float(image_size.y) );\n"
8931                         "          vec4  result     = mix  (start_rgba, end_rgba, uv.x);\n"
8932                         "\n"
8933                         "    imageStore(image, xy, result);\n"
8934                         "}\n";
8935
8936                 gl.shaderSource(m_gradient_image_write_vs_id, 1 /* count */, &gradient_write_image_vs_body, NULL /* length */);
8937                 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8938         }
8939
8940         /* Set gradient write program's fragment shader body */
8941         const char* gradient_write_fs_body = "#version 400\n"
8942                                                                                  "\n"
8943                                                                                  "in vec2 uv;\n"
8944                                                                                  "\n"
8945                                                                                  "layout(location = 0) out vec4 result;\n"
8946                                                                                  "\n"
8947                                                                                  "void main()\n"
8948                                                                                  "{\n"
8949                                                                                  "    const vec4 end_rgba   = vec4(0.0, 0.1, 1.0, 1.0);\n"
8950                                                                                  "    const vec4 start_rgba = vec4(1.0, 0.9, 0.0, 0.0);\n"
8951                                                                                  "\n"
8952                                                                                  "    result = mix(start_rgba, end_rgba, uv.x);\n"
8953                                                                                  "}\n";
8954
8955         gl.shaderSource(m_gradient_write_fs_id, 1 /* count */, &gradient_write_fs_body, NULL /* length */);
8956         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8957
8958         /* Set gradient write program's vertex shader body */
8959         const char* gradient_write_vs_body =
8960                 "#version 400\n"
8961                 "\n"
8962                 "out vec2 uv;\n"
8963                 "\n"
8964                 "void main()\n"
8965                 "{\n"
8966                 "    switch (gl_VertexID)\n"
8967                 "    {\n"
8968                 "        case 0: gl_Position = vec4(-1.0, -1.0, 0.0, 1.0); uv = vec2(0.0, 1.0); break;\n"
8969                 "        case 1: gl_Position = vec4(-1.0,  1.0, 0.0, 1.0); uv = vec2(0.0, 0.0); break;\n"
8970                 "        case 2: gl_Position = vec4( 1.0, -1.0, 0.0, 1.0); uv = vec2(1.0, 1.0); break;\n"
8971                 "        case 3: gl_Position = vec4( 1.0,  1.0, 0.0, 1.0); uv = vec2(1.0, 0.0); break;\n"
8972                 "    }\n"
8973                 "}\n";
8974
8975         gl.shaderSource(m_gradient_write_vs_id, 1 /* count */, &gradient_write_vs_body, NULL /* length */);
8976         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8977
8978         /* Set verification program's vertex shader body */
8979         const char* verification_vs_body = "#version 400\n"
8980                                                                            "\n"
8981                                                                            "uniform vec4      expected_color;\n"
8982                                                                            "uniform int       lod;\n"
8983                                                                            "uniform sampler2D sampler;\n"
8984                                                                            "\n"
8985                                                                            "out int result;\n"
8986                                                                            "\n"
8987                                                                            "void main()\n"
8988                                                                            "{\n"
8989                                                                            "    const float epsilon = 1.0 / 256.0;\n"
8990                                                                            "\n"
8991                                                                            "    vec4 sampled_data = textureLod(sampler, vec2(0.5, 0.5), lod);\n"
8992                                                                            "\n"
8993                                                                            "    if (abs(sampled_data.x - expected_color.x) > epsilon ||\n"
8994                                                                            "        abs(sampled_data.y - expected_color.y) > epsilon ||\n"
8995                                                                            "        abs(sampled_data.z - expected_color.z) > epsilon ||\n"
8996                                                                            "        abs(sampled_data.w - expected_color.w) > epsilon)\n"
8997                                                                            "    {\n"
8998                                                                            "        result = 0;\n"
8999                                                                            "    }\n"
9000                                                                            "    else\n"
9001                                                                            "    {\n"
9002                                                                            "        result = 1;\n"
9003                                                                            "    }\n"
9004                                                                            "}\n";
9005
9006         gl.shaderSource(m_verification_vs_id, 1 /* count */, &verification_vs_body, NULL /* length */);
9007         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
9008
9009         /* Compile the shaders */
9010         const glw::GLuint so_ids[] = { m_gradient_image_write_vs_id, m_gradient_verification_vs_id, m_gradient_write_fs_id,
9011                                                                    m_gradient_write_vs_id, m_verification_vs_id };
9012         const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
9013
9014         for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
9015         {
9016                 glw::GLuint so_id = so_ids[n_so_id];
9017
9018                 if (so_id != 0)
9019                 {
9020                         gl.compileShader(so_id);
9021                         GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
9022
9023                         /* Verify the compilation ended successfully */
9024                         glw::GLint compile_status = GL_FALSE;
9025
9026                         gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
9027                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
9028
9029                         if (compile_status != GL_TRUE)
9030                         {
9031                                 TCU_FAIL("Shader compilation failed.");
9032                         }
9033                 }
9034         } /* for (all shader objects) */
9035
9036         /* Attach the shaders to relevant programs */
9037         if (m_are_images_supported)
9038         {
9039                 gl.attachShader(m_gradient_image_write_po_id, m_gradient_image_write_vs_id);
9040         }
9041
9042         gl.attachShader(m_gradient_verification_po_id, m_gradient_verification_vs_id);
9043         gl.attachShader(m_gradient_write_po_id, m_gradient_write_fs_id);
9044         gl.attachShader(m_gradient_write_po_id, m_gradient_write_vs_id);
9045         gl.attachShader(m_verification_po_id, m_verification_vs_id);
9046         GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
9047
9048         /* Set up XFB */
9049         const char*               verification_varying_name = "result";
9050         const glw::GLuint xfb_po_ids[]                          = {
9051                 m_gradient_verification_po_id, m_verification_po_id,
9052         };
9053         const unsigned int n_xfb_po_ids = sizeof(xfb_po_ids) / sizeof(xfb_po_ids[0]);
9054
9055         for (unsigned int n_xfb_po_id = 0; n_xfb_po_id < n_xfb_po_ids; ++n_xfb_po_id)
9056         {
9057                 glw::GLint po_id = xfb_po_ids[n_xfb_po_id];
9058
9059                 gl.transformFeedbackVaryings(po_id, 1 /* count */, &verification_varying_name, GL_INTERLEAVED_ATTRIBS);
9060                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
9061         }
9062
9063         /* Link the programs */
9064         const glw::GLuint po_ids[] = { m_gradient_image_write_po_id, m_gradient_verification_po_id, m_gradient_write_po_id,
9065                                                                    m_verification_po_id };
9066         const unsigned int n_po_ids = sizeof(po_ids) / sizeof(po_ids[0]);
9067
9068         for (unsigned int n_po_id = 0; n_po_id < n_po_ids; ++n_po_id)
9069         {
9070                 glw::GLuint po_id = po_ids[n_po_id];
9071
9072                 if (po_id != 0)
9073                 {
9074                         gl.linkProgram(po_id);
9075                         GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
9076
9077                         /* Make sure the linking was successful. */
9078                         glw::GLint link_status = GL_FALSE;
9079
9080                         gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
9081                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
9082
9083                         if (link_status != GL_TRUE)
9084                         {
9085                                 TCU_FAIL("Program linking failed.");
9086                         }
9087                 }
9088         } /* for (all program objects) */
9089
9090         /* Retrieve uniform locations for gradient write program (image case) */
9091         if (m_are_images_supported)
9092         {
9093                 m_gradient_image_write_image_size_location = gl.getUniformLocation(m_gradient_image_write_po_id, "image_size");
9094
9095                 if (m_gradient_image_write_image_size_location == -1)
9096                 {
9097                         TCU_FAIL("image_size is considered an inactive uniform which is invalid.");
9098                 }
9099         }
9100
9101         /* Retrieve uniform locations for gradient verification program */
9102         m_gradient_verification_po_sample_exact_uv_location =
9103                 gl.getUniformLocation(m_gradient_verification_po_id, "sample_exact_uv");
9104         m_gradient_verification_po_lod_location         = gl.getUniformLocation(m_gradient_verification_po_id, "lod");
9105         m_gradient_verification_po_texture_location = gl.getUniformLocation(m_gradient_verification_po_id, "texture");
9106
9107         if (m_gradient_verification_po_sample_exact_uv_location == -1)
9108         {
9109                 TCU_FAIL("sample_exact_uv is considered an inactive uniform which is invalid");
9110         }
9111
9112         if (m_gradient_verification_po_lod_location == -1)
9113         {
9114                 TCU_FAIL("lod is considered an inactive uniform which is invalid.");
9115         }
9116
9117         if (m_gradient_verification_po_texture_location == -1)
9118         {
9119                 TCU_FAIL("texture is considered an inactive uniform which is invalid.");
9120         }
9121
9122         /* Retrieve uniform locations for verification program */
9123         m_verification_po_expected_color_location = gl.getUniformLocation(m_verification_po_id, "expected_color");
9124         m_verification_po_lod_location                    = gl.getUniformLocation(m_verification_po_id, "lod");
9125
9126         if (m_verification_po_expected_color_location == -1)
9127         {
9128                 TCU_FAIL("expected_color is considered an inactive uniform which is invalid.");
9129         }
9130
9131         if (m_verification_po_lod_location == -1)
9132         {
9133                 TCU_FAIL("lod is considered an inactive uniform which is invalid.");
9134         }
9135 }
9136
9137 /** Initializes texture objects required to run the test.
9138  *
9139  *  Throws exceptions if the initialization fails at any point.
9140  **/
9141 void TextureViewTestCoherency::initTextures()
9142 {
9143         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9144
9145         /* Generate the texture objects */
9146         gl.genTextures(1, &m_static_to_id);
9147         gl.genTextures(1, &m_to_id);
9148         gl.genTextures(1, &m_view_to_id);
9149         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed.");
9150
9151         /* Set up parent texture object */
9152         gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9153         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9154
9155         gl.texStorage2D(GL_TEXTURE_2D, m_texture_n_levels, GL_RGBA8, m_texture_width, m_texture_height);
9156         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9157
9158         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9159         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9160         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9161         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
9162         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call(s) failed.");
9163
9164         /* Set up the texture views we'll be using for the test */
9165         gl.textureView(m_view_to_id, GL_TEXTURE_2D, m_to_id, GL_RGBA8, 1, /* minlevel */
9166                                    2,                                                                                             /* numlevels */
9167                                    0,                                                                                             /* minlayer */
9168                                    1);                                                                                            /* numlayers */
9169         GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed");
9170
9171         gl.bindTexture(GL_TEXTURE_2D, m_view_to_id);
9172         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9173         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9174         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9175         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
9176
9177         /* Set up storage for static color texture */
9178         gl.bindTexture(GL_TEXTURE_2D, m_static_to_id);
9179         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9180
9181         gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
9182                                         GL_RGBA8, m_static_texture_width, m_static_texture_height);
9183         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9184
9185         /* Fill the texture objects with actual contents */
9186         initTextureContents();
9187 }
9188
9189 /** Fills all relevant mip-maps of all previously initialized texture objects with
9190  *  contents.
9191  *
9192  *  Throws an exception if any of the issued GL API calls fail.
9193  **/
9194 void TextureViewTestCoherency::initTextureContents()
9195 {
9196         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9197
9198         /* Make sure parent texture object is bound before we start modifying
9199          * the mip-maps */
9200         gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9201         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9202
9203         /* Set up parent texture mip-maps */
9204         unsigned char* base_mipmap_data_ptr = getHorizontalGradientData();
9205
9206         gl.texSubImage2D(GL_TEXTURE_2D, 0, /* level */
9207                                          0,                                /* xoffset */
9208                                          0,                                /* yoffset */
9209                                          m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, base_mipmap_data_ptr);
9210
9211         delete[] base_mipmap_data_ptr;
9212         base_mipmap_data_ptr = NULL;
9213
9214         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
9215
9216         /* Generate all mip-maps */
9217         gl.generateMipmap(GL_TEXTURE_2D);
9218         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap() call failed.");
9219
9220         /* Set up static color texture contents. We only need to fill the base mip-map
9221          * since the texture's resolution is 1x1.
9222          */
9223         DE_ASSERT(m_static_texture_height == 1 && m_static_texture_width == 1);
9224
9225         unsigned char* static_texture_data_ptr = getStaticColorTextureData(m_static_texture_width, m_static_texture_height);
9226
9227         gl.bindTexture(GL_TEXTURE_2D, m_static_to_id);
9228         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9229
9230         gl.texSubImage2D(GL_TEXTURE_2D, 0, /* level */
9231                                          0,                                /* xoffset */
9232                                          0,                                /* yoffset */
9233                                          m_static_texture_width, m_static_texture_height, GL_RGBA, GL_UNSIGNED_BYTE,
9234                                          static_texture_data_ptr);
9235
9236         /* Good to release the buffer at this point */
9237         delete[] static_texture_data_ptr;
9238
9239         static_texture_data_ptr = DE_NULL;
9240
9241         /* Was the API call successful? */
9242         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
9243 }
9244
9245 /** Initializes a vertex array object used for the draw calls issued during the test. */
9246 void TextureViewTestCoherency::initVAO()
9247 {
9248         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9249
9250         /* Generate and bind a vertex array object */
9251         gl.genVertexArrays(1, &m_vao_id);
9252         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9253
9254         gl.bindVertexArray(m_vao_id);
9255         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9256 }
9257
9258 /** Executes test iteration.
9259  *
9260  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
9261  */
9262 tcu::TestNode::IterateResult TextureViewTestCoherency::iterate()
9263 {
9264         /* Do not execute the test if GL_ARB_texture_view is not supported */
9265         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_view"))
9266         {
9267                 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported.");
9268         }
9269
9270         /* Initialize all GL objects required to run the test */
9271         initBufferObjects();
9272         initPrograms();
9273         initTextures();
9274         initFBO();
9275         initVAO();
9276
9277         /* Iterate over the set of texture types we are to test */
9278         const _texture_type texture_types[] = { TEXTURE_TYPE_PARENT_TEXTURE, TEXTURE_TYPE_TEXTURE_VIEW };
9279         const unsigned int  n_texture_types = sizeof(texture_types) / sizeof(texture_types[0]);
9280
9281         for (unsigned int n_texture_type = 0; n_texture_type < n_texture_types; ++n_texture_type)
9282         {
9283                 _texture_type texture_type = texture_types[n_texture_type];
9284
9285                 /* Verify parent texture/view coherency when using glTexSubImage2D() */
9286                 checkAPICallCoherency(texture_type, true);
9287
9288                 /* Verify parent texture/view coherency when using glBlitFramebuffer() */
9289                 checkAPICallCoherency(texture_type, false);
9290
9291                 /* Verify parent texture/view coherency when modifying contents of one
9292                  * of the objects in a program, and then reading the sibling from another
9293                  * program.
9294                  */
9295                 checkProgramWriteCoherency(texture_type, false, /* should_use_images */
9296                                                                    BARRIER_TYPE_NONE, VERIFICATION_MEAN_PROGRAM);
9297
9298                 if (m_are_images_supported)
9299                 {
9300                         /* Verify a view bound to an image unit and written to using image uniforms
9301                          * in vertex shader stage can later be sampled correctly, assuming
9302                          * a GL_TEXTURE_FETCH_BARRIER_BIT barrier is inserted between the write
9303                          * operations and sampling from another program object.
9304                          */
9305                         checkProgramWriteCoherency(texture_type, true, /* should_use_images */
9306                                                                            BARRIER_TYPE_TEXTURE_FETCH_BARRIER_BIT, VERIFICATION_MEAN_PROGRAM);
9307
9308                         /* Verify a view bound to an image unit and written to using image uniforms
9309                          * in vertex shader stage can later be correctly retrieved using a glGetTexImage()
9310                          * call, assuming a GL_TEXTURE_UPDATE_BARRIER_BIT barrier is inserted between the
9311                          * two operations.
9312                          **/
9313                         checkProgramWriteCoherency(texture_type, true, /* should_use_images */
9314                                                                            BARRIER_TYPE_TEXTURE_UPDATE_BUFFER_BIT, VERIFICATION_MEAN_GLGETTEXIMAGE);
9315                 }
9316
9317                 /* Reinitialize all texture contents */
9318                 initTextureContents();
9319         } /* for (all read sources) */
9320
9321         /* Test case passed */
9322         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9323
9324         return STOP;
9325 }
9326
9327 /** Constructor.
9328  *
9329  *  @param context Rendering context.
9330  *
9331  **/
9332 TextureViewTestBaseAndMaxLevels::TextureViewTestBaseAndMaxLevels(deqp::Context& context)
9333         : TestCase(context, "base_and_max_levels", "test_description")
9334         , m_texture_height(256)
9335         , m_texture_n_components(4)
9336         , m_texture_n_levels(6)
9337         , m_texture_width(256)
9338         , m_view_height(128)
9339         , m_view_width(128)
9340         , m_layer_data_lod0(DE_NULL)
9341         , m_layer_data_lod1(DE_NULL)
9342         , m_fbo_id(0)
9343         , m_fs_id(0)
9344         , m_po_id(0)
9345         , m_po_lod_index_uniform_location(-1)
9346         , m_po_to_sampler_uniform_location(-1)
9347         , m_result_to_id(0)
9348         , m_to_id(0)
9349         , m_vao_id(0)
9350         , m_view_to_id(0)
9351         , m_vs_id(0)
9352 {
9353         /* Left blank on purpose */
9354 }
9355
9356 /* Deinitializes all GL objects that may have been created during test execution. */
9357 void TextureViewTestBaseAndMaxLevels::deinit()
9358 {
9359         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9360
9361         if (m_fbo_id != 0)
9362         {
9363                 gl.deleteFramebuffers(1, &m_fbo_id);
9364
9365                 m_fbo_id = 0;
9366         }
9367
9368         if (m_fs_id != 0)
9369         {
9370                 gl.deleteShader(m_fs_id);
9371
9372                 m_fs_id = 0;
9373         }
9374
9375         if (m_layer_data_lod0 != DE_NULL)
9376         {
9377                 delete[] m_layer_data_lod0;
9378
9379                 m_layer_data_lod0 = DE_NULL;
9380         }
9381
9382         if (m_layer_data_lod1 != DE_NULL)
9383         {
9384                 delete[] m_layer_data_lod1;
9385
9386                 m_layer_data_lod1 = DE_NULL;
9387         }
9388
9389         if (m_po_id != 0)
9390         {
9391                 gl.deleteProgram(m_po_id);
9392
9393                 m_po_id = 0;
9394         }
9395
9396         if (m_result_to_id != 0)
9397         {
9398                 gl.deleteTextures(1, &m_result_to_id);
9399
9400                 m_result_to_id = 0;
9401         }
9402
9403         if (m_to_id != 0)
9404         {
9405                 gl.deleteTextures(1, &m_to_id);
9406
9407                 m_to_id = 0;
9408         }
9409
9410         if (m_vao_id != 0)
9411         {
9412                 gl.deleteVertexArrays(1, &m_vao_id);
9413
9414                 m_vao_id = 0;
9415         }
9416
9417         if (m_view_to_id != 0)
9418         {
9419                 gl.deleteTextures(1, &m_view_to_id);
9420
9421                 m_view_to_id = 0;
9422         }
9423
9424         if (m_vs_id != 0)
9425         {
9426                 gl.deleteShader(m_vs_id);
9427
9428                 m_vs_id = 0;
9429         }
9430 }
9431
9432 /* Initializes and configures a program object used later by the test. */
9433 void TextureViewTestBaseAndMaxLevels::initProgram()
9434 {
9435         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9436
9437         /* Generate shader object IDs */
9438         m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
9439         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
9440
9441         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed");
9442
9443         /* Generate program object ID */
9444         m_po_id = gl.createProgram();
9445
9446         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed");
9447
9448         /* Set up vertex shader body */
9449         static const char* vs_body =
9450                 "#version 400\n"
9451                 "\n"
9452                 "out vec2 uv;\n"
9453                 "\n"
9454                 "void main()\n"
9455                 "{\n"
9456                 "    switch (gl_VertexID)\n"
9457                 "    {\n"
9458                 "        case 0: gl_Position = vec4(-1.0,  1.0, 0.0, 1.0); uv = vec2(0.0, 1.0); break;\n"
9459                 "        case 1: gl_Position = vec4(-1.0, -1.0, 0.0, 1.0); uv = vec2(0.0, 0.0); break;\n"
9460                 "        case 2: gl_Position = vec4( 1.0,  1.0, 0.0, 1.0); uv = vec2(1.0, 1.0); break;\n"
9461                 "        case 3: gl_Position = vec4( 1.0, -1.0, 0.0, 1.0); uv = vec2(1.0, 0.0); break;\n"
9462                 "    };\n"
9463                 "}\n";
9464
9465         gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
9466         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for vertex shader case");
9467
9468         /* Set up fragment shader body */
9469         static const char* fs_body = "#version 400\n"
9470                                                                  "\n"
9471                                                                  "in vec2 uv;\n"
9472                                                                  "\n"
9473                                                                  "uniform int       lod_index;\n"
9474                                                                  "uniform sampler2D to_sampler;\n"
9475                                                                  "\n"
9476                                                                  "out vec4 result;\n"
9477                                                                  "\n"
9478                                                                  "void main()\n"
9479                                                                  "{\n"
9480                                                                  "    result = textureLod(to_sampler, uv, float(lod_index) );\n"
9481                                                                  "}\n";
9482
9483         gl.shaderSource(m_fs_id, 1 /* count */, &fs_body, DE_NULL /* length */);
9484         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for fragment shader case");
9485
9486         /* Compile both shaders */
9487         const glw::GLuint  so_ids[] = { m_fs_id, m_vs_id };
9488         const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
9489
9490         for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
9491         {
9492                 glw::GLint so_id = so_ids[n_so_id];
9493
9494                 gl.compileShader(so_id);
9495                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
9496
9497                 /* Make sure the compilation has succeeded */
9498                 glw::GLint compile_status = GL_FALSE;
9499
9500                 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
9501                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
9502
9503                 if (compile_status != GL_TRUE)
9504                 {
9505                         m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed" << tcu::TestLog::EndMessage;
9506                 }
9507         } /* for (all shader objects) */
9508
9509         /* Attach the shaders to the program object */
9510         gl.attachShader(m_po_id, m_fs_id);
9511         gl.attachShader(m_po_id, m_vs_id);
9512         GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed");
9513
9514         /* Link the program object */
9515         gl.linkProgram(m_po_id);
9516         GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call faikled");
9517
9518         /* Verify the linking has succeeded */
9519         glw::GLint link_status = GL_FALSE;
9520
9521         gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
9522         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed for GL_LINK_STATUS pname");
9523
9524         if (link_status != GL_TRUE)
9525         {
9526                 TCU_FAIL("Program linking failed");
9527         }
9528
9529         /* Retrieve uniform locations */
9530         m_po_lod_index_uniform_location  = gl.getUniformLocation(m_po_id, "lod_index");
9531         m_po_to_sampler_uniform_location = gl.getUniformLocation(m_po_id, "to_sampler");
9532
9533         if (m_po_lod_index_uniform_location == -1)
9534         {
9535                 TCU_FAIL("lod_index is considered an inactive uniform");
9536         }
9537
9538         if (m_po_to_sampler_uniform_location == -1)
9539         {
9540                 TCU_FAIL("to_sampler is considered an inactive uniform");
9541         }
9542 }
9543
9544 /* Initializes all GL objects used by the test. */
9545 void TextureViewTestBaseAndMaxLevels::initTest()
9546 {
9547         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9548
9549         /* Initialize textures */
9550         initTextures();
9551
9552         /* Initialize framebuffer and configure its attachments */
9553         gl.genFramebuffers(1, &m_fbo_id);
9554         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed");
9555
9556         /* Build the program we'll need for the test */
9557         initProgram();
9558
9559         /* Generate a vertex array object to execute the draw calls */
9560         gl.genVertexArrays(1, &m_vao_id);
9561         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9562
9563         gl.bindVertexArray(m_vao_id);
9564         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9565
9566         /* Finally, allocate space for buffers that will be filled with rendered data */
9567         m_layer_data_lod0 = new unsigned char[m_texture_width * m_texture_height * m_texture_n_components];
9568         m_layer_data_lod1 = new unsigned char[(m_texture_width >> 1) * (m_texture_height >> 1) * m_texture_n_components];
9569
9570         if (m_layer_data_lod0 == DE_NULL || m_layer_data_lod1 == DE_NULL)
9571         {
9572                 TCU_FAIL("Out of memory");
9573         }
9574 }
9575
9576 /** Initializes texture objects used by the test. */
9577 void TextureViewTestBaseAndMaxLevels::initTextures()
9578 {
9579         /* Generate IDs first */
9580         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9581
9582         gl.genTextures(1, &m_result_to_id);
9583         gl.genTextures(1, &m_to_id);
9584         gl.genTextures(1, &m_view_to_id);
9585         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
9586
9587         /* Set up parent texture object's storage */
9588         gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9589         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
9590
9591         gl.texStorage2D(GL_TEXTURE_2D, m_texture_n_levels, GL_RGBA8, m_texture_width, m_texture_height);
9592         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
9593
9594         /* Configure GL_TEXTURE_BASE_LEVEL parameter of the texture object as per test spec */
9595         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
9596         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call failed for GL_TEXTURE_BASE_LEVEL pname");
9597
9598         /* Configure GL_TEXTURE_MAX_LEVEL parameter of the texture object as per test spec */
9599         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 4);
9600         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call failed for GL_TEXTURE_MAX_LEVEL pname");
9601
9602         /* Set up mip-maps */
9603         for (unsigned int n_mipmap = 0; n_mipmap < m_texture_n_levels; ++n_mipmap)
9604         {
9605                 const float start_rgba[] = { /* As per test specification */
9606                                                                          float(n_mipmap + 0) / 10.0f, float(n_mipmap + 1) / 10.0f,
9607                                                                          float(n_mipmap + 2) / 10.0f, float(n_mipmap + 3) / 10.0f
9608                 };
9609                 const float end_rgba[] = { float(10 - (n_mipmap + 0)) / 10.0f, float(10 - (n_mipmap + 1)) / 10.0f,
9610                                                                    float(10 - (n_mipmap + 2)) / 10.0f, float(10 - (n_mipmap + 3)) / 10.0f };
9611
9612                 /* Allocate space for the layer data */
9613                 const unsigned int mipmap_height = m_texture_height >> n_mipmap;
9614                 const unsigned int mipmap_width  = m_texture_width >> n_mipmap;
9615                 unsigned char*   data                    = new unsigned char[mipmap_width * mipmap_height * m_texture_n_components];
9616
9617                 if (data == NULL)
9618                 {
9619                         TCU_FAIL("Out of memory");
9620                 }
9621
9622                 /* Fill the buffer with layer data */
9623                 const unsigned int pixel_size = 4 /* components */;
9624
9625                 for (unsigned int y = 0; y < mipmap_height; ++y)
9626                 {
9627                         unsigned char* row_data_ptr = data + mipmap_width * y * pixel_size;
9628
9629                         for (unsigned int x = 0; x < mipmap_width; ++x)
9630                         {
9631                                 const float     lerp_factor     = float(x) / float(mipmap_width);
9632                                 unsigned char* pixel_data_ptr = row_data_ptr + x * pixel_size;
9633
9634                                 for (unsigned int n_component = 0; n_component < m_texture_n_components; n_component++)
9635                                 {
9636                                         pixel_data_ptr[n_component] = (unsigned char)((start_rgba[n_component] * lerp_factor +
9637                                                                                                                                    end_rgba[n_component] * (1.0f - lerp_factor)) *
9638                                                                                                                                   255.0f);
9639                                 }
9640                         } /* for (all columns) */
9641                 }        /* for (all rows) */
9642
9643                 /* Upload the layer data */
9644                 gl.texSubImage2D(GL_TEXTURE_2D, n_mipmap, 0, /* xoffset */
9645                                                  0,                                                      /* yoffset */
9646                                                  mipmap_width, mipmap_height, GL_RGBA, GL_UNSIGNED_BYTE, data);
9647
9648                 /* Release the data buffer */
9649                 delete[] data;
9650
9651                 data = DE_NULL;
9652
9653                 /* Make sure the API call finished successfully */
9654                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed");
9655         } /* for (all mip-maps) */
9656
9657         /* Configure the texture view storage as per spec. */
9658         gl.textureView(m_view_to_id, GL_TEXTURE_2D, m_to_id, GL_RGBA8, 0, /* minlevel */
9659                                    5,                                                                                             /* numlevels */
9660                                    0,                                                                                             /* minlayer */
9661                                    1);                                                                                            /* numlayers */
9662         GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed");
9663
9664         /* Configure the texture view's GL_TEXTURE_BASE_LEVEL parameter */
9665         gl.bindTexture(GL_TEXTURE_2D, m_view_to_id);
9666         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
9667
9668         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
9669         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call failed for GL_TEXTURE_BASE_LEVEL pname");
9670
9671         /* Configure the texture view's GL_TEXTURE_MAX_LEVEL parameter */
9672         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
9673         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call failed for GL_TEXTURE_MAX_LEVEL pname");
9674
9675         /* Set up result texture storage */
9676         gl.bindTexture(GL_TEXTURE_2D, m_result_to_id);
9677         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
9678
9679         gl.texStorage2D(GL_TEXTURE_2D, 1, /* We will only attach the first level of the result texture to the FBO */
9680                                         GL_RGBA8, m_view_width, m_view_height);
9681         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
9682 }
9683
9684 /** Executes test iteration.
9685  *
9686  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
9687  */
9688 tcu::TestNode::IterateResult TextureViewTestBaseAndMaxLevels::iterate()
9689 {
9690         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9691
9692         /* Only execute if GL_ARB_texture_view extension is supported */
9693         const std::vector<std::string>& extensions = m_context.getContextInfo().getExtensions();
9694
9695         if (std::find(extensions.begin(), extensions.end(), "GL_ARB_texture_view") == extensions.end())
9696         {
9697                 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported");
9698         }
9699
9700         /* Initialize all GL objects necessary to run the test */
9701         initTest();
9702
9703         /* Activate test-wide program object */
9704         gl.useProgram(m_po_id);
9705         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9706
9707         /* Bind the data texture */
9708         gl.activeTexture(GL_TEXTURE0);
9709         GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed");
9710
9711         gl.bindTexture(GL_TEXTURE_2D, m_view_to_id);
9712         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9713
9714         /* We will now use the program to sample the view's LOD 0 and LOD 1 and store
9715          * it in two separate textures.
9716          **/
9717         for (unsigned int lod_level = 0; lod_level < 2; /* as per test spec */
9718                  ++lod_level)
9719         {
9720                 /* Set up FBO attachments */
9721                 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
9722                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed");
9723
9724                 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_result_to_id,
9725                                                                 0); /* level */
9726                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed");
9727
9728                 /* Update viewport configuration */
9729                 gl.viewport(0, /* x */
9730                                         0, /* y */
9731                                         m_view_width >> lod_level, m_view_height >> lod_level);
9732
9733                 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed");
9734
9735                 /* Configure program object uniforms before we continue */
9736                 gl.uniform1i(m_po_lod_index_uniform_location, lod_level);
9737                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
9738
9739                 /* Render a triangle strip. The program we're using will output a full-screen
9740                  * quad with the sampled data */
9741                 gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
9742                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9743
9744                 /* At the time of the draw call, we've modified the draw/read framebuffer binding
9745                  * so that everything we render ends up in result texture. It's time to read it */
9746                 glw::GLvoid* result_data_ptr = (lod_level == 0) ? m_layer_data_lod0 : m_layer_data_lod1;
9747
9748                 gl.readPixels(0, /* x */
9749                                           0, /* y */
9750                                           m_view_width >> lod_level, m_view_height >> lod_level, GL_RGBA, GL_UNSIGNED_BYTE,
9751                                           result_data_ptr);
9752
9753                 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
9754         } /* for (both LODs) */
9755
9756         /* Now that we have both pieces of data, we can proceed with actual verification */
9757         for (unsigned int lod_level = 0; lod_level < 2; ++lod_level)
9758         {
9759                 /* NOTE: This code is a modification of initialization routine
9760                  *       found in initTextures()
9761                  */
9762                 const unsigned char epsilon                        = 1;
9763                 const glw::GLvoid*  layer_data_ptr       = (lod_level == 0) ? m_layer_data_lod0 : m_layer_data_lod1;
9764                 const unsigned int  layer_height           = m_view_height >> lod_level;
9765                 const unsigned int  layer_width            = m_view_width >> lod_level;
9766                 const unsigned int  pixel_size             = 4 /* components */;
9767                 const unsigned int  view_minimum_level = 1; /* THS SHOULD BE 1 */
9768                 const float                     start_rgba[]       = {
9769                         /* As per test specification */
9770                         float(lod_level + view_minimum_level + 0) / 10.0f, float(lod_level + view_minimum_level + 1) / 10.0f,
9771                         float(lod_level + view_minimum_level + 2) / 10.0f, float(lod_level + view_minimum_level + 3) / 10.0f
9772                 };
9773                 const float end_rgba[] = { float(10 - (lod_level + view_minimum_level + 0)) / 10.0f,
9774                                                                    float(10 - (lod_level + view_minimum_level + 1)) / 10.0f,
9775                                                                    float(10 - (lod_level + view_minimum_level + 2)) / 10.0f,
9776                                                                    float(10 - (lod_level + view_minimum_level + 3)) / 10.0f };
9777
9778                 for (unsigned int y = 0; y < layer_height; ++y)
9779                 {
9780                         const unsigned char* row_data_ptr = (const unsigned char*)layer_data_ptr + layer_width * y * pixel_size;
9781
9782                         for (unsigned int x = 0; x < layer_width; ++x)
9783                         {
9784                                 const float                      lerp_factor    = float(x) / float(layer_width);
9785                                 const unsigned char* pixel_data_ptr = row_data_ptr + x * pixel_size;
9786
9787                                 const unsigned char expected_data[] = {
9788                                         (unsigned char)((start_rgba[0] * lerp_factor + end_rgba[0] * (1.0f - lerp_factor)) * 255.0f),
9789                                         (unsigned char)((start_rgba[1] * lerp_factor + end_rgba[1] * (1.0f - lerp_factor)) * 255.0f),
9790                                         (unsigned char)((start_rgba[2] * lerp_factor + end_rgba[2] * (1.0f - lerp_factor)) * 255.0f),
9791                                         (unsigned char)((start_rgba[3] * lerp_factor + end_rgba[3] * (1.0f - lerp_factor)) * 255.0f)
9792                                 };
9793
9794                                 if (de::abs(expected_data[0] - pixel_data_ptr[0]) > epsilon ||
9795                                         de::abs(expected_data[1] - pixel_data_ptr[1]) > epsilon ||
9796                                         de::abs(expected_data[2] - pixel_data_ptr[2]) > epsilon ||
9797                                         de::abs(expected_data[3] - pixel_data_ptr[3]) > epsilon)
9798                                 {
9799                                         m_testCtx.getLog() << tcu::TestLog::Message << "Found an invalid texel at (" << x << ", " << y
9800                                                                            << ");"
9801                                                                                   " expected value:"
9802                                                                                   "("
9803                                                                            << expected_data[0] << ", " << expected_data[1] << ", " << expected_data[2]
9804                                                                            << ", " << expected_data[3] << ")"
9805                                                                                                                                           ", found:"
9806                                                                                                                                           "("
9807                                                                            << pixel_data_ptr[0] << ", " << pixel_data_ptr[1] << ", " << pixel_data_ptr[2]
9808                                                                            << ", " << pixel_data_ptr[3] << ")" << tcu::TestLog::EndMessage;
9809
9810                                         TCU_FAIL("Rendered data does not match expected pixel data");
9811                                 } /* if (pixel mismatch found) */
9812                         }        /* for (all columns) */
9813                 }                 /* for (all rows) */
9814         }                         /* for (both LODs) */
9815
9816         /* Test case passed */
9817         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9818
9819         return STOP;
9820 }
9821
9822 /** Constructor.
9823  *
9824  *  @param context Rendering context.
9825  **/
9826 TextureViewTestReferenceCounting::TextureViewTestReferenceCounting(deqp::Context& context)
9827         : TestCase(context, "reference_counting",
9828                            "Makes sure that sampling from views, for which the parent texture object "
9829                            "has already been deleted, works correctly.")
9830         , m_bo_id(0)
9831         , m_parent_to_id(0)
9832         , m_po_id(0)
9833         , m_po_expected_texel_uniform_location(-1)
9834         , m_po_lod_uniform_location(-1)
9835         , m_vao_id(0)
9836         , m_view_to_id(0)
9837         , m_view_view_to_id(0)
9838         , m_vs_id(0)
9839         , m_texture_height(64)
9840         , m_texture_n_levels(7)
9841         , m_texture_width(64)
9842 {
9843         /* Configure a vector storing unique colors that should be used
9844          * for filling subsequent mip-maps of parent texture */
9845         m_mipmap_colors.push_back(_norm_vec4(123, 34, 56, 78));
9846         m_mipmap_colors.push_back(_norm_vec4(234, 45, 67, 89));
9847         m_mipmap_colors.push_back(_norm_vec4(34, 56, 78, 90));
9848         m_mipmap_colors.push_back(_norm_vec4(45, 67, 89, 1));
9849         m_mipmap_colors.push_back(_norm_vec4(56, 78, 90, 123));
9850         m_mipmap_colors.push_back(_norm_vec4(67, 89, 1, 234));
9851         m_mipmap_colors.push_back(_norm_vec4(78, 90, 12, 34));
9852
9853         DE_ASSERT(m_mipmap_colors.size() == m_texture_n_levels);
9854 }
9855
9856 /** Deinitializes all GL objects that may have been created during test
9857  *  execution.
9858  **/
9859 void TextureViewTestReferenceCounting::deinit()
9860 {
9861         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9862
9863         if (m_bo_id != 0)
9864         {
9865                 gl.deleteBuffers(1, &m_bo_id);
9866
9867                 m_bo_id = 0;
9868         }
9869
9870         if (m_parent_to_id != 0)
9871         {
9872                 gl.deleteTextures(1, &m_parent_to_id);
9873
9874                 m_parent_to_id = 0;
9875         }
9876
9877         if (m_po_id != 0)
9878         {
9879                 gl.deleteProgram(m_po_id);
9880
9881                 m_po_id = 0;
9882         }
9883
9884         if (m_vao_id != 0)
9885         {
9886                 gl.deleteVertexArrays(1, &m_vao_id);
9887
9888                 m_vao_id = 0;
9889         }
9890
9891         if (m_view_to_id != 0)
9892         {
9893                 gl.deleteTextures(1, &m_view_to_id);
9894
9895                 m_view_to_id = 0;
9896         }
9897
9898         if (m_view_view_to_id != 0)
9899         {
9900                 gl.deleteTextures(1, &m_view_view_to_id);
9901
9902                 m_view_view_to_id = 0;
9903         }
9904
9905         if (m_vs_id != 0)
9906         {
9907                 gl.deleteShader(m_vs_id);
9908
9909                 m_vs_id = 0;
9910         }
9911 }
9912
9913 /* Initializes a program object to be used during the test. */
9914 void TextureViewTestReferenceCounting::initProgram()
9915 {
9916         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9917
9918         /* Create program & shader object IDs */
9919         m_po_id = gl.createProgram();
9920         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed");
9921
9922         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
9923         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed");
9924
9925         /* Set vertex shader body */
9926         const char* vs_body = "#version 400\n"
9927                                                   "\n"
9928                                                   "uniform vec4      expected_texel;\n"
9929                                                   "uniform int       lod;\n"
9930                                                   "uniform sampler2D sampler;\n"
9931                                                   "\n"
9932                                                   "out int has_passed;\n"
9933                                                   "\n"
9934                                                   "void main()\n"
9935                                                   "{\n"
9936                                                   "          vec4  data    = textureLod(sampler, vec2(0.5, 0.5), lod);\n"
9937                                                   "    const float epsilon = 1.0 / 256.0;\n"
9938                                                   "\n"
9939                                                   "    if (abs(data.r - expected_texel.r) > epsilon ||\n"
9940                                                   "        abs(data.g - expected_texel.g) > epsilon ||\n"
9941                                                   "        abs(data.b - expected_texel.b) > epsilon ||\n"
9942                                                   "        abs(data.a - expected_texel.a) > epsilon)\n"
9943                                                   "    {\n"
9944                                                   "        has_passed = 0;\n"
9945                                                   "    }\n"
9946                                                   "    else\n"
9947                                                   "    {\n"
9948                                                   "        has_passed = 1;\n"
9949                                                   "    }\n"
9950                                                   "}\n";
9951
9952         gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, NULL /* length */);
9953         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
9954
9955         /* Configure XFB */
9956         const char* varying_name = "has_passed";
9957
9958         gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &varying_name, GL_INTERLEAVED_ATTRIBS);
9959         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed");
9960
9961         /* Attach the shader object to the program */
9962         gl.attachShader(m_po_id, m_vs_id);
9963         GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed");
9964
9965         /* Compile the shader */
9966         gl.compileShader(m_vs_id);
9967         GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
9968
9969         /* Make sure the compilation has succeeded */
9970         glw::GLint compile_status = GL_FALSE;
9971
9972         gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
9973         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
9974
9975         if (compile_status != GL_TRUE)
9976         {
9977                 m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed" << tcu::TestLog::EndMessage;
9978         }
9979
9980         /* Link the program object */
9981         gl.linkProgram(m_po_id);
9982         GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed");
9983
9984         /* Make sure the program object has linked successfully */
9985         glw::GLint link_status = GL_FALSE;
9986
9987         gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
9988         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
9989
9990         if (link_status != GL_TRUE)
9991         {
9992                 TCU_FAIL("Program linking failed");
9993         }
9994
9995         /* Retrieve uniform locations */
9996         m_po_expected_texel_uniform_location = gl.getUniformLocation(m_po_id, "expected_texel");
9997         m_po_lod_uniform_location                        = gl.getUniformLocation(m_po_id, "lod");
9998
9999         if (m_po_expected_texel_uniform_location == -1)
10000         {
10001                 TCU_FAIL("expected_texel is considered an inactive uniform which is invalid");
10002         }
10003
10004         if (m_po_lod_uniform_location == -1)
10005         {
10006                 TCU_FAIL("lod is considered an inactive uniform which is invalid");
10007         }
10008 }
10009
10010 /** Initializes all texture objects and all views used by the test. */
10011 void TextureViewTestReferenceCounting::initTextures()
10012 {
10013         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10014
10015         /* Generate texture IDs */
10016         gl.genTextures(1, &m_parent_to_id);
10017         gl.genTextures(1, &m_view_to_id);
10018         gl.genTextures(1, &m_view_view_to_id);
10019         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
10020
10021         /* Set up parent texture object A */
10022         gl.bindTexture(GL_TEXTURE_2D, m_parent_to_id);
10023         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
10024
10025         gl.texStorage2D(GL_TEXTURE_2D, m_texture_n_levels, GL_RGBA8, m_texture_width, m_texture_height);
10026         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
10027
10028         /* Set up view B */
10029         gl.textureView(m_view_to_id, GL_TEXTURE_2D, m_parent_to_id, GL_RGBA8, 0, /* minlevel */
10030                                    m_texture_n_levels, 0,                                                                        /* minlayer */
10031                                    1);                                                                                                           /* numlayers */
10032         GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed");
10033
10034         /* Set up view C */
10035         gl.textureView(m_view_view_to_id, GL_TEXTURE_2D, m_view_to_id, GL_RGBA8, 0, /* minlevel */
10036                                    m_texture_n_levels, 0,                                                                               /* minlayer */
10037                                    1);                                                                                                                  /* numlayers */
10038         GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed");
10039
10040         /* Fill parent texture mip-maps with different static colors */
10041         unsigned char* texel_data = new unsigned char[m_texture_width * m_texture_height * 4 /* components */];
10042
10043         for (unsigned int n_mipmap = 0; n_mipmap < m_mipmap_colors.size(); n_mipmap++)
10044         {
10045                 const _norm_vec4&  mipmap_color  = m_mipmap_colors[n_mipmap];
10046                 const unsigned int mipmap_height = m_texture_height >> n_mipmap;
10047                 const unsigned int mipmap_width  = m_texture_width >> n_mipmap;
10048
10049                 for (unsigned int n_texel = 0; n_texel < mipmap_height * mipmap_width; ++n_texel)
10050                 {
10051                         unsigned char* texel_data_ptr = texel_data + n_texel * sizeof(mipmap_color.rgba);
10052
10053                         memcpy(texel_data_ptr, mipmap_color.rgba, sizeof(mipmap_color.rgba));
10054                 } /* for (all relevant mip-map texels) */
10055
10056                 /* Upload new mip-map contents */
10057                 gl.texSubImage2D(GL_TEXTURE_2D, n_mipmap, 0, /* xoffset */
10058                                                  0,                                                      /* yoffset */
10059                                                  m_texture_width >> n_mipmap, m_texture_height >> n_mipmap, GL_RGBA, GL_UNSIGNED_BYTE,
10060                                                  texel_data);
10061
10062                 if (gl.getError() != GL_NO_ERROR)
10063                 {
10064                         delete[] texel_data;
10065                         texel_data = NULL;
10066
10067                         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed");
10068                 }
10069         } /* for (all mip-maps) */
10070
10071         delete[] texel_data;
10072         texel_data = NULL;
10073 }
10074
10075 /* Initialize all GL objects necessary to run the test */
10076 void TextureViewTestReferenceCounting::initTest()
10077 {
10078         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10079
10080         /* Initialize all texture objects */
10081         initTextures();
10082
10083         /* Initialize test program object */
10084         initProgram();
10085
10086         /* Initialize XFB */
10087         initXFB();
10088
10089         /* Generate and bind a vertex array object, since we'll be doing a number of
10090          * draw calls later in the test */
10091         gl.genVertexArrays(1, &m_vao_id);
10092         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
10093
10094         gl.bindVertexArray(m_vao_id);
10095         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
10096 }
10097
10098 /** Initializes a buffer object later used for Transform Feedback and binds
10099  *  it to both general and indexed Transform Feedback binding points.
10100  **/
10101 void TextureViewTestReferenceCounting::initXFB()
10102 {
10103         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10104
10105         /* Sanity checks */
10106         DE_ASSERT(m_po_id != 0);
10107
10108         /* Generate a buffer object we'll use for Transform Feedback */
10109         gl.genBuffers(1, &m_bo_id);
10110         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
10111
10112         /* Set up buffer object storage. We need it to be large enough to hold
10113          * sizeof(glw::GLint) per mipmap level */
10114         const glw::GLint bo_size = (glw::GLint)(sizeof(glw::GLint) * m_mipmap_colors.size());
10115
10116         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
10117         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
10118
10119         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
10120         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
10121
10122         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL, /* data */
10123                                   GL_STATIC_DRAW);
10124         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
10125 }
10126
10127 /** Executes test iteration.
10128  *
10129  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10130  */
10131 tcu::TestNode::IterateResult TextureViewTestReferenceCounting::iterate()
10132 {
10133         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10134
10135         /* Carry on only if GL_ARB_texture_view extension is supported */
10136         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_view"))
10137         {
10138                 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported");
10139         }
10140
10141         /* Initialize all GL objects used for the test */
10142         initTest();
10143
10144         /* Make sure texture unit 0 is currently active */
10145         gl.activeTexture(GL_TEXTURE0);
10146         GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed.");
10147
10148         /* Activate the test program object */
10149         gl.useProgram(m_po_id);
10150         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10151
10152         /* Run the test in three iterations:
10153          *
10154          * - Sample both the texture and all the views; once that's finished
10155          *   successfully, delete the parent texture.
10156          * - Sample both views; once that's finished successfully, delete
10157          *   the first of the views;
10158          * - Sample the only remaining view and make sure all mip-maps store
10159          *   valid colors.
10160          **/
10161         for (unsigned int n_iteration = 0; n_iteration < 3; /* iterations in total */
10162                  n_iteration++)
10163         {
10164                 glw::GLuint to_ids_to_sample[3] = { 0, 0, 0 };
10165
10166                 /* Configure IDs of textures we need to validate for current iteration */
10167                 switch (n_iteration)
10168                 {
10169                 case 0:
10170                 {
10171                         to_ids_to_sample[0] = m_parent_to_id;
10172                         to_ids_to_sample[1] = m_view_to_id;
10173                         to_ids_to_sample[2] = m_view_view_to_id;
10174
10175                         break;
10176                 }
10177
10178                 case 1:
10179                 {
10180                         to_ids_to_sample[0] = m_view_to_id;
10181                         to_ids_to_sample[1] = m_view_view_to_id;
10182
10183                         break;
10184                 }
10185
10186                 case 2:
10187                 {
10188                         to_ids_to_sample[0] = m_view_view_to_id;
10189
10190                         break;
10191                 }
10192
10193                 default:
10194                         TCU_FAIL("Invalid iteration index");
10195                 } /* switch (n_iteration) */
10196
10197                 /* Iterate through all texture objects of our concern */
10198                 for (unsigned int n_texture = 0; n_texture < sizeof(to_ids_to_sample) / sizeof(to_ids_to_sample[0]);
10199                          n_texture++)
10200                 {
10201                         glw::GLint to_id = to_ids_to_sample[n_texture];
10202
10203                         if (to_id == 0)
10204                         {
10205                                 /* No texture object to sample from. */
10206                                 continue;
10207                         }
10208
10209                         /* Bind the texture object of our interest to GL_TEXTURE_2D */
10210                         gl.bindTexture(GL_TEXTURE_2D, to_id);
10211                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
10212
10213                         /* Start XFB */
10214                         gl.beginTransformFeedback(GL_POINTS);
10215                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
10216
10217                         /* Iterate through all mip-maps of the texture we're currently sampling */
10218                         for (unsigned int n_mipmap = 0; n_mipmap < m_mipmap_colors.size(); ++n_mipmap)
10219                         {
10220                                 const _norm_vec4& expected_mipmap_color = m_mipmap_colors[n_mipmap];
10221
10222                                 /* Update uniforms first */
10223                                 gl.uniform4f(m_po_expected_texel_uniform_location, (float)(expected_mipmap_color.rgba[0]) / 255.0f,
10224                                                          (float)(expected_mipmap_color.rgba[1]) / 255.0f,
10225                                                          (float)(expected_mipmap_color.rgba[2]) / 255.0f,
10226                                                          (float)(expected_mipmap_color.rgba[3]) / 255.0f);
10227                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f() call failed.");
10228
10229                                 gl.uniform1i(m_po_lod_uniform_location, n_mipmap);
10230                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
10231
10232                                 /* Draw a single point. That'll feed the XFB buffer object with a single bool
10233                                  * indicating if the test passed for the mip-map, or not */
10234                                 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
10235                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
10236                         } /* for (all mip-maps) */
10237
10238                         /* We're done - close XFB */
10239                         gl.endTransformFeedback();
10240                         GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
10241
10242                         /* How did the sampling go? Map the buffer object containing the run
10243                          * results into process space.
10244                          */
10245                         const glw::GLint* run_results_ptr =
10246                                 (const glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
10247
10248                         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
10249
10250                         if (run_results_ptr == NULL)
10251                         {
10252                                 TCU_FAIL("Pointer to mapped buffer object storage is NULL.");
10253                         }
10254
10255                         /* Make sure all mip-maps were sampled successfully */
10256                         for (unsigned int n_mipmap = 0; n_mipmap < m_mipmap_colors.size(); ++n_mipmap)
10257                         {
10258                                 if (run_results_ptr[n_mipmap] != 1)
10259                                 {
10260                                         /* Make sure the TF BO is unmapped before we throw the exception */
10261                                         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10262
10263                                         m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data was sampled for mip-map level ["
10264                                                                            << n_mipmap << "] and iteration [" << n_iteration << "]"
10265                                                                            << tcu::TestLog::EndMessage;
10266
10267                                         TCU_FAIL("Mip-map sampling failed.");
10268                                 }
10269                         } /* for (all mip-maps) */
10270
10271                         /* Good to unmap the buffer object at this point */
10272                         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10273                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
10274                 } /* for (all initialized texture objects) */
10275
10276                 /* Now that we're done with the iteration, we should delete iteration-specific texture
10277                  * object.
10278                  */
10279                 switch (n_iteration)
10280                 {
10281                 case 0:
10282                 {
10283                         gl.deleteTextures(1, &m_parent_to_id);
10284                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
10285
10286                         m_parent_to_id = 0;
10287                         break;
10288                 }
10289
10290                 case 1:
10291                 {
10292                         gl.deleteTextures(1, &m_view_to_id);
10293                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
10294
10295                         m_view_to_id = 0;
10296                         break;
10297                 }
10298
10299                 case 2:
10300                 {
10301                         gl.deleteTextures(1, &m_view_view_to_id);
10302                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
10303
10304                         m_view_view_to_id = 0;
10305                         break;
10306                 }
10307
10308                 default:
10309                         TCU_FAIL("Invalid iteration index");
10310                 } /* switch (n_iteration) */
10311         }        /* for (all iterations) */
10312
10313         /* Test case passed */
10314         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10315
10316         return STOP;
10317 }
10318
10319 /** Constructor.
10320  *
10321  *  @param context Rendering context.
10322  **/
10323 TextureViewTests::TextureViewTests(deqp::Context& context)
10324         : TestCaseGroup(context, "texture_view", "Verifies \"texture view\" functionality")
10325 {
10326         /* Left blank on purpose */
10327 }
10328
10329 /** Initializes a texture_storage_multisample test group.
10330  *
10331  **/
10332 void TextureViewTests::init(void)
10333 {
10334         addChild(new TextureViewTestGetTexParameter(m_context));
10335         addChild(new TextureViewTestErrors(m_context));
10336         addChild(new TextureViewTestViewSampling(m_context));
10337         addChild(new TextureViewTestViewClasses(m_context));
10338         addChild(new TextureViewTestCoherency(m_context));
10339         addChild(new TextureViewTestBaseAndMaxLevels(m_context));
10340         addChild(new TextureViewTestReferenceCounting(m_context));
10341 }
10342
10343 } /* glcts namespace */