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