xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gl/gl4cCopyImageTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2015-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 gl4cCopyImageTests.cpp
21  * \brief Implements CopyImageSubData functional tests.
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "gl4cCopyImageTests.hpp"
25 
26 #include "gluDefs.hpp"
27 #include "gluStrUtil.hpp"
28 #include "glwEnums.hpp"
29 #include "glwFunctions.hpp"
30 #include "tcuFloat.hpp"
31 #include "tcuTestLog.hpp"
32 
33 #include <algorithm>
34 #include <iomanip>
35 #include <sstream>
36 
37 #include "deMath.h"
38 
39 /* There are far too much combinations specified for FunctionalTest.
40  *
41  * Following flags controls what is enabled. Set as 1 to enable
42  * all test case from given category, 0 otherwise.
43  *
44  * By default everything is disabled - which still gives 14560 test cases.
45  *
46  * ALL_FORMAT  - selects all internal formats, 61 x 61
47  * ALL_TARGETS - selects all valid targets, 10 x 10
48  * ALL_IMG_DIM - selects all image dimmensions, 9 x 9
49  * ALL_REG_DIM - selects all region dimmensions, 7 x 7
50  * ALL_REG_POS - selects all region positions, like left-top corner, 8 x 8
51  */
52 #define COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_FORMATS 0
53 #define COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_TARGETS 0
54 #define COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_IMG_DIM 0
55 #define COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_REG_DIM 0
56 #define COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_REG_POS 0
57 
58 /* The following flags controls if workarounds are enabled */
59 #define COPY_IMAGE_WRKARD_FORMATS 0
60 
61 using namespace glw;
62 
63 namespace gl4cts
64 {
65 namespace CopyImage
66 {
67 /** Various utilities used by all tests
68  *
69  **/
70 class Utils
71 {
72 public:
73     /* Routines */
74     static bool areFormatsCompatible(glw::GLenum src, glw::GLenum dst);
75 
76     static bool comparePixels(glw::GLenum left_internal_format, const glw::GLdouble &left_red,
77                               const glw::GLdouble &left_green, const glw::GLdouble &left_blue,
78                               const glw::GLdouble &left_alpha, glw::GLenum right_internal_format,
79                               const glw::GLdouble &right_red, const glw::GLdouble &right_green,
80                               const glw::GLdouble &right_blue, const glw::GLdouble &right_alpha);
81 
82     static bool comparePixels(glw::GLuint left_pixel_size, const glw::GLubyte *left_pixel_data,
83                               glw::GLuint right_pixel_size, const glw::GLubyte *right_pixel_data);
84 
85     static void deleteTexture(deqp::Context &context, glw::GLenum target, glw::GLuint name);
86 
87     static bool isTargetMultilayer(glw::GLenum target);
88     static bool isTargetMultilevel(glw::GLenum target);
89     static bool isTargetMultisampled(glw::GLenum target);
90 
91     static glw::GLuint generateTexture(deqp::Context &context, glw::GLenum target);
92 
93     static void maskPixelForFormat(glw::GLenum internal_format, glw::GLubyte *pixel);
94 
95     static glw::GLdouble getEpsilon(glw::GLenum internal_format);
96     static glw::GLuint getPixelSizeForFormat(glw::GLenum internal_format);
97     static glw::GLenum getFormat(glw::GLenum internal_format);
98     static glw::GLuint getNumberOfChannels(glw::GLenum internal_format);
99 
100     static std::string getPixelString(glw::GLenum internal_format, const glw::GLubyte *pixel);
101 
102     static glw::GLenum getType(glw::GLenum internal_format);
103     static void makeTextureComplete(deqp::Context &context, glw::GLenum target, glw::GLuint id, glw::GLint base_level,
104                                     glw::GLint max_level);
105 
106     static glw::GLuint prepareCompressedTex(deqp::Context &context, glw::GLenum target, glw::GLenum internal_format);
107 
108     static glw::GLuint prepareMultisampleTex(deqp::Context &context, glw::GLenum target, glw::GLsizei n_samples);
109 
110     static glw::GLuint prepareRenderBuffer(deqp::Context &context, glw::GLenum internal_format);
111 
112     static glw::GLuint prepareTex16x16x6(deqp::Context &context, glw::GLenum target, glw::GLenum internal_format,
113                                          glw::GLenum format, glw::GLenum type, glw::GLuint &out_buf_id);
114 
115     static void prepareTexture(deqp::Context &context, glw::GLuint name, glw::GLenum target,
116                                glw::GLenum internal_format, glw::GLenum format, glw::GLenum type, glw::GLuint level,
117                                glw::GLuint width, glw::GLuint height, glw::GLuint depth, const glw::GLvoid *pixels,
118                                glw::GLuint &out_buf_id);
119 
120     static glw::GLenum transProxyToRealTarget(glw::GLenum target);
121     static glw::GLenum transRealToBindTarget(glw::GLenum target);
122 
123     static void readChannel(glw::GLenum type, glw::GLuint channel, const glw::GLubyte *pixel, glw::GLdouble &out_value);
124 
125     static void writeChannel(glw::GLenum type, glw::GLuint channel, glw::GLdouble value, glw::GLubyte *pixel);
126 
127     static void packPixel(glw::GLenum internal_format, glw::GLenum type, glw::GLdouble red, glw::GLdouble green,
128                           glw::GLdouble blue, glw::GLdouble alpha, glw::GLubyte *out_pixel);
129 
130     static void unpackPixel(glw::GLenum format, glw::GLenum type, const glw::GLubyte *pixel, glw::GLdouble &out_red,
131                             glw::GLdouble &out_green, glw::GLdouble &out_blue, glw::GLdouble &out_alpha);
132 
133     static bool unpackAndComaprePixels(glw::GLenum left_format, glw::GLenum left_type, glw::GLenum left_internal_format,
134                                        const glw::GLubyte *left_pixel, glw::GLenum right_format, glw::GLenum right_type,
135                                        glw::GLenum right_internal_format, const glw::GLubyte *right_pixel);
136 
137     static inline bool roundComponent(glw::GLenum internal_format, glw::GLenum component, glw::GLdouble &value);
138 };
139 
140 /* Global constants */
141 static const GLenum s_internal_formats[] = {
142     /* R8 */
143     GL_R8,
144     GL_R8I,
145     GL_R8UI,
146     GL_R8_SNORM,
147 
148     /* R16 */
149     GL_R16,
150     GL_R16F,
151     GL_R16I,
152     GL_R16UI,
153     GL_R16_SNORM,
154 
155     /* R32 */
156     GL_R32F,
157     GL_R32I,
158     GL_R32UI,
159 
160     /* RG8 */
161     GL_RG8,
162     GL_RG8I,
163     GL_RG8UI,
164     GL_RG8_SNORM,
165 
166     /* RG16 */
167     GL_RG16,
168     GL_RG16F,
169     GL_RG16I,
170     GL_RG16UI,
171     GL_RG16_SNORM,
172 
173     /* RG32 */
174     GL_RG32F,
175     GL_RG32I,
176     GL_RG32UI,
177 
178     /* RGB8 */
179     GL_RGB8,
180     GL_RGB8I,
181     GL_RGB8UI,
182     GL_RGB8_SNORM,
183 
184     /* RGB16 */
185     GL_RGB16,
186     GL_RGB16F,
187     GL_RGB16I,
188     GL_RGB16UI,
189     GL_RGB16_SNORM,
190 
191     /* RGB32 */
192     GL_RGB32F,
193     GL_RGB32I,
194     GL_RGB32UI,
195 
196     /* RGBA8 */
197     GL_RGBA8,
198     GL_RGBA8I,
199     GL_RGBA8UI,
200     GL_RGBA8_SNORM,
201 
202     /* RGBA16 */
203     GL_RGBA16,
204     GL_RGBA16F,
205     GL_RGBA16I,
206     GL_RGBA16UI,
207     GL_RGBA16_SNORM,
208 
209     /* RGBA32 */
210     GL_RGBA32F,
211     GL_RGBA32I,
212     GL_RGBA32UI,
213 
214     /* 8 */
215     GL_R3_G3_B2,
216     GL_RGBA2,
217 
218     /* 12 */
219     GL_RGB4,
220 
221     /* 15 */
222     GL_RGB5,
223 
224     /* 16 */
225     GL_RGBA4,
226     GL_RGB5_A1,
227 
228     /* 30 */
229     GL_RGB10,
230 
231     /* 32 */
232     GL_RGB10_A2,
233     GL_RGB10_A2UI,
234     GL_R11F_G11F_B10F,
235     GL_RGB9_E5,
236 
237     /* 36 */
238     GL_RGB12,
239 
240     /* 48 */
241     GL_RGBA12,
242 };
243 
244 static const GLenum s_invalid_targets[] = {
245     GL_TEXTURE_BUFFER,
246     GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
247     GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
248     GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
249     GL_TEXTURE_CUBE_MAP_POSITIVE_X,
250     GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
251     GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
252     GL_PROXY_TEXTURE_1D,
253     GL_PROXY_TEXTURE_1D_ARRAY,
254     GL_PROXY_TEXTURE_2D,
255     GL_PROXY_TEXTURE_2D_ARRAY,
256     GL_PROXY_TEXTURE_2D_MULTISAMPLE,
257     GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY,
258     GL_PROXY_TEXTURE_3D,
259     GL_PROXY_TEXTURE_CUBE_MAP,
260     GL_PROXY_TEXTURE_CUBE_MAP_ARRAY,
261     GL_PROXY_TEXTURE_RECTANGLE,
262 };
263 
264 static const GLenum s_valid_targets[] = {
265     GL_RENDERBUFFER,
266     GL_TEXTURE_1D,
267     GL_TEXTURE_1D_ARRAY,
268     GL_TEXTURE_2D,
269     GL_TEXTURE_2D_ARRAY,
270     GL_TEXTURE_2D_MULTISAMPLE,
271     GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
272     GL_TEXTURE_3D,
273     GL_TEXTURE_CUBE_MAP,
274     GL_TEXTURE_CUBE_MAP_ARRAY,
275     GL_TEXTURE_RECTANGLE,
276 };
277 
278 static const GLuint s_n_internal_formats = sizeof(s_internal_formats) / sizeof(s_internal_formats[0]);
279 static const GLuint s_n_invalid_targets  = sizeof(s_invalid_targets) / sizeof(s_invalid_targets[0]);
280 static const GLuint s_n_valid_targets    = sizeof(s_valid_targets) / sizeof(s_valid_targets[0]);
281 
282 /**
283  * Pixel compatibility depends on pixel size. However value returned by getPixelSizeForFormat
284  * needs some refinements
285  *
286  * @param internal_format Internal format of image
287  *
288  * @return Size of pixel for compatibility checks
289  **/
getPixelSizeForCompatibilityVerification(GLenum internal_format)290 GLuint getPixelSizeForCompatibilityVerification(GLenum internal_format)
291 {
292     GLuint size = Utils::getPixelSizeForFormat(internal_format);
293 
294     switch (internal_format)
295     {
296     case GL_RGBA2:
297         size = 1;
298         break;
299     default:
300         break;
301     }
302 
303     return size;
304 }
305 
306 #if COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_FORMATS == 0
307 
308 /** Filters out formats that should not be tested by FunctionalTest
309  *
310  * @param format Internal format
311  *
312  * @return true if format should be tested, false otherwise
313  **/
filterFormats(GLenum format)314 bool filterFormats(GLenum format)
315 {
316     bool result = true;
317 
318     switch (format)
319     {
320     /* R8 */
321     case GL_R8I:
322     case GL_R8UI:
323     case GL_R8_SNORM:
324 
325     /* R16 */
326     case GL_R16:
327     case GL_R16F:
328     case GL_R16I:
329     case GL_R16UI:
330     case GL_R16_SNORM:
331 
332     /* R32 */
333     case GL_R32F:
334     case GL_R32I:
335     case GL_R32UI:
336 
337     /* RG8 */
338     case GL_RG8:
339     case GL_RG8I:
340     case GL_RG8UI:
341     case GL_RG8_SNORM:
342 
343     /* RG16 */
344     case GL_RG16:
345     case GL_RG16F:
346     case GL_RG16I:
347     case GL_RG16UI:
348     case GL_RG16_SNORM:
349 
350     /* RG32 */
351     case GL_RG32F:
352     case GL_RG32I:
353     case GL_RG32UI:
354 
355     /* RGB8 */
356     case GL_RGB8:
357     case GL_RGB8I:
358     case GL_RGB8UI:
359     case GL_RGB8_SNORM:
360 
361     /* RGB16 */
362     case GL_RGB16:
363     case GL_RGB16F:
364     case GL_RGB16I:
365     case GL_RGB16UI:
366     case GL_RGB16_SNORM:
367 
368     /* RGB32 */
369     case GL_RGB32I:
370     case GL_RGB32UI:
371 
372     /* RGBA8 */
373     case GL_RGBA8:
374     case GL_RGBA8I:
375     case GL_RGBA8UI:
376     case GL_RGBA8_SNORM:
377 
378     /* RGBA16 */
379     case GL_RGBA16:
380     case GL_RGBA16F:
381     case GL_RGBA16I:
382     case GL_RGBA16UI:
383     case GL_RGBA16_SNORM:
384 
385     /* RGBA32 */
386     case GL_RGBA32F:
387     case GL_RGBA32I:
388     case GL_RGBA32UI:
389         result = false;
390         break;
391 
392     default:
393         result = true;
394         break;
395     }
396 
397     return result;
398 }
399 
400 #endif /* COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_FORMATS */
401 
402 /** Checks if two internal_formats are compatible
403  *
404  * @param src Internal format of source image
405  * @param dst Internal format of destination image
406  *
407  * @return true for compatible formats, false otherwise
408  **/
areFormatsCompatible(glw::GLenum src,glw::GLenum dst)409 bool Utils::areFormatsCompatible(glw::GLenum src, glw::GLenum dst)
410 {
411     const GLuint dst_size = getPixelSizeForCompatibilityVerification(dst);
412     const GLuint src_size = getPixelSizeForCompatibilityVerification(src);
413 
414     if (dst_size != src_size)
415     {
416         return false;
417     }
418 
419 #if COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_FORMATS == 0
420 
421     if ((false == filterFormats(src)) || (false == filterFormats(dst)))
422     {
423         return false;
424     }
425 
426 #endif /* COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_FORMATS */
427 
428     if (src != dst)
429     {
430         if ((GL_R3_G3_B2 == dst) || (GL_R3_G3_B2 == src) || (GL_RGBA2 == dst) || (GL_RGBA2 == src) ||
431             (GL_RGBA4 == dst) || (GL_RGBA4 == src) || (GL_RGB5_A1 == dst) || (GL_RGB5_A1 == src) || (GL_RGB10 == dst) ||
432             (GL_RGB10 == src))
433         {
434             return false;
435         }
436     }
437 
438 #if COPY_IMAGE_WRKARD_FORMATS
439 
440     if ((GL_RGB10_A2 == src) && (GL_R11F_G11F_B10F == dst) || (GL_RGB10_A2 == src) && (GL_RGB9_E5 == dst) ||
441         (GL_RGB10_A2UI == src) && (GL_R11F_G11F_B10F == dst) || (GL_RGB10_A2UI == src) && (GL_RGB9_E5 == dst) ||
442         (GL_RGB9_E5 == src) && (GL_RGB10_A2 == dst) || (GL_RGB9_E5 == src) && (GL_RGB10_A2UI == dst) ||
443         (GL_R11F_G11F_B10F == src) && (GL_RGB10_A2 == dst) || (GL_R11F_G11F_B10F == src) && (GL_RGB10_A2UI == dst))
444     {
445         return false;
446     }
447 
448 #endif /* COPY_IMAGE_WRKARD_FORMATS */
449 
450     if (2 == dst_size)
451     {
452         if (src == dst)
453         {
454             return true;
455         }
456 
457         if (((GL_RGB4 == src) && (GL_RGB4 != dst)) || ((GL_RGB4 != src) && (GL_RGB4 == dst)) ||
458             ((GL_RGB5 == src) && (GL_RGB5 != dst)) || ((GL_RGB5 != src) && (GL_RGB5 == dst)))
459         {
460             return false;
461         }
462 
463         return true;
464     }
465 
466     if (4 == dst_size)
467     {
468         if (src == dst)
469         {
470             return true;
471         }
472 
473         return true;
474     }
475 
476     return true;
477 }
478 
479 /** Compare two pixels
480  *
481  * @param left_internal_format  Internal format of left image
482  * @param left_red              Red channel of left image
483  * @param left_green            Green channel of left image
484  * @param left_blue             Blue channel of left image
485  * @param left_alpha            Alpha channel of left image
486  * @param right_internal_format Internal format of right image
487  * @param right_red             Red channel of right image
488  * @param right_green           Green channel of right image
489  * @param right_blue            Blue channel of right image
490  * @param right_alpha           Alpha channel of right image
491  *
492  * @return true if pixels match, false otherwise
493  **/
comparePixels(GLenum left_internal_format,const GLdouble & left_red,const GLdouble & left_green,const GLdouble & left_blue,const GLdouble & left_alpha,GLenum right_internal_format,const GLdouble & right_red,const GLdouble & right_green,const GLdouble & right_blue,const GLdouble & right_alpha)494 bool Utils::comparePixels(GLenum left_internal_format, const GLdouble &left_red, const GLdouble &left_green,
495                           const GLdouble &left_blue, const GLdouble &left_alpha, GLenum right_internal_format,
496                           const GLdouble &right_red, const GLdouble &right_green, const GLdouble &right_blue,
497                           const GLdouble &right_alpha)
498 {
499     const GLuint left_n_channels  = getNumberOfChannels(left_internal_format);
500     const GLuint right_n_channels = getNumberOfChannels(right_internal_format);
501     const GLuint n_channels       = (left_n_channels >= right_n_channels) ? right_n_channels : left_n_channels;
502 
503     const GLdouble left_channels[4] = {left_red, left_green, left_blue, left_alpha};
504 
505     const GLdouble right_channels[4] = {right_red, right_green, right_blue, right_alpha};
506 
507     for (GLuint i = 0; i < n_channels; ++i)
508     {
509         const GLdouble left      = left_channels[i];
510         const GLdouble right     = right_channels[i];
511         const GLdouble left_eps  = getEpsilon(left_internal_format);
512         const GLdouble right_eps = getEpsilon(right_internal_format);
513         const GLdouble eps       = fabs(std::max(left_eps, right_eps));
514 
515         if (eps < fabs(left - right))
516         {
517             return false;
518         }
519     }
520 
521     return true;
522 }
523 
524 /** Compare two pixels with memcmp
525  *
526  * @param left_pixel_size  Size of left pixel
527  * @param left_pixel_data  Data of left pixel
528  * @param right_pixel_size Size of right pixel
529  * @param right_pixel_data Data of right pixel
530  *
531  * @return true if memory match, false otherwise
532  **/
comparePixels(GLuint left_pixel_size,const GLubyte * left_pixel_data,GLuint right_pixel_size,const GLubyte * right_pixel_data)533 bool Utils::comparePixels(GLuint left_pixel_size, const GLubyte *left_pixel_data, GLuint right_pixel_size,
534                           const GLubyte *right_pixel_data)
535 {
536     const GLuint pixel_size = (left_pixel_size >= right_pixel_size) ? left_pixel_size : right_pixel_size;
537 
538     return 0 == memcmp(left_pixel_data, right_pixel_data, pixel_size);
539 }
540 
541 /** Delete texture or renderbuffer
542  *
543  * @param context Test context
544  * @param target  Image target
545  * @param name    Name of image
546  **/
deleteTexture(deqp::Context & context,GLenum target,GLuint name)547 void Utils::deleteTexture(deqp::Context &context, GLenum target, GLuint name)
548 {
549     const Functions &gl = context.getRenderContext().getFunctions();
550 
551     if (GL_RENDERBUFFER == target)
552     {
553         gl.deleteRenderbuffers(1, &name);
554     }
555     else
556     {
557         gl.deleteTextures(1, &name);
558     }
559 }
560 
561 /** Get epsilon for given internal_format
562  *
563  * @param internal_format Internal format of image
564  *
565  * @return Epsilon value
566  **/
getEpsilon(GLenum internal_format)567 GLdouble Utils::getEpsilon(GLenum internal_format)
568 {
569     GLdouble epsilon;
570 
571     switch (internal_format)
572     {
573     case GL_R8:
574     case GL_R8_SNORM:
575     case GL_R16:
576     case GL_R16F:
577     case GL_R16_SNORM:
578     case GL_R32F:
579     case GL_R8I:
580     case GL_R8UI:
581     case GL_R16I:
582     case GL_R16UI:
583     case GL_R32I:
584     case GL_R32UI:
585     case GL_RG8:
586     case GL_RG8_SNORM:
587     case GL_RG16:
588     case GL_RG16F:
589     case GL_RG16_SNORM:
590     case GL_RG32F:
591     case GL_RG8I:
592     case GL_RG8UI:
593     case GL_RG16I:
594     case GL_RG16UI:
595     case GL_RG32I:
596     case GL_RG32UI:
597     case GL_R3_G3_B2:
598     case GL_RGB4:
599     case GL_RGB5:
600     case GL_RGB8:
601     case GL_RGB8_SNORM:
602     case GL_R11F_G11F_B10F:
603     case GL_RGB16:
604     case GL_RGB16F:
605     case GL_RGB16_SNORM:
606     case GL_RGB32F:
607     case GL_RGB8I:
608     case GL_RGB8UI:
609     case GL_RGB10:
610     case GL_RGB16I:
611     case GL_RGB16UI:
612     case GL_RGB32I:
613     case GL_RGB32UI:
614     case GL_RGB9_E5:
615     case GL_RGBA2:
616     case GL_RGBA4:
617     case GL_RGB5_A1:
618     case GL_RGBA8:
619     case GL_RGBA8_SNORM:
620     case GL_RGB10_A2:
621     case GL_RGBA16:
622     case GL_RGBA16F:
623     case GL_RGBA16_SNORM:
624     case GL_RGBA32F:
625     case GL_RGBA8I:
626     case GL_RGBA8UI:
627     case GL_RGB10_A2UI:
628     case GL_RGBA16I:
629     case GL_RGBA16UI:
630     case GL_RGBA32I:
631     case GL_RGBA32UI:
632         epsilon = 0.0;
633         break;
634     case GL_RGB12:
635     case GL_RGBA12:
636         epsilon = 0.00390625;
637         break;
638     default:
639         TCU_FAIL("Invalid enum");
640     }
641 
642     return epsilon;
643 }
644 
645 /** Get format for given internal format
646  *
647  * @param internal_format Internal format
648  *
649  * @return Format
650  **/
getFormat(GLenum internal_format)651 GLenum Utils::getFormat(GLenum internal_format)
652 {
653     GLenum format = 0;
654 
655     switch (internal_format)
656     {
657     /* R */
658     case GL_R8:
659     case GL_R8_SNORM:
660     case GL_R16:
661     case GL_R16F:
662     case GL_R16_SNORM:
663     case GL_R32F:
664         format = GL_RED;
665         break;
666 
667     case GL_R8I:
668     case GL_R8UI:
669     case GL_R16I:
670     case GL_R16UI:
671     case GL_R32I:
672     case GL_R32UI:
673         format = GL_RED_INTEGER;
674         break;
675 
676     /* RG */
677     case GL_RG8:
678     case GL_RG8_SNORM:
679     case GL_RG16:
680     case GL_RG16F:
681     case GL_RG16_SNORM:
682     case GL_RG32F:
683         format = GL_RG;
684         break;
685 
686     case GL_RG8I:
687     case GL_RG8UI:
688     case GL_RG16I:
689     case GL_RG16UI:
690     case GL_RG32I:
691     case GL_RG32UI:
692         format = GL_RG_INTEGER;
693         break;
694 
695     /* RGB */
696     case GL_R3_G3_B2:
697     case GL_RGB4:
698     case GL_RGB5:
699     case GL_RGB8:
700     case GL_RGB8_SNORM:
701     case GL_R11F_G11F_B10F:
702     case GL_RGB12:
703     case GL_RGB16:
704     case GL_RGB16F:
705     case GL_RGB16_SNORM:
706     case GL_RGB32F:
707     case GL_RGB9_E5:
708         format = GL_RGB;
709         break;
710 
711     case GL_RGB8I:
712     case GL_RGB8UI:
713     case GL_RGB16I:
714     case GL_RGB16UI:
715     case GL_RGB32I:
716     case GL_RGB32UI:
717         format = GL_RGB_INTEGER;
718         break;
719 
720     /* RGBA */
721     case GL_RGB10:
722     case GL_RGBA2:
723     case GL_RGBA4:
724     case GL_RGB5_A1:
725     case GL_RGBA8:
726     case GL_RGBA8_SNORM:
727     case GL_RGB10_A2:
728     case GL_RGBA12:
729     case GL_RGBA16:
730     case GL_RGBA16F:
731     case GL_RGBA16_SNORM:
732     case GL_RGBA32F:
733         format = GL_RGBA;
734         break;
735 
736     case GL_RGBA8I:
737     case GL_RGBA8UI:
738     case GL_RGB10_A2UI:
739     case GL_RGBA16I:
740     case GL_RGBA16UI:
741     case GL_RGBA32I:
742     case GL_RGBA32UI:
743         format = GL_RGBA_INTEGER;
744         break;
745 
746     default:
747         TCU_FAIL("Invalid enum");
748     }
749 
750     return format;
751 }
752 
753 /** Get number of channels for given internal_format
754  *
755  * @param internal_format Internal format
756  *
757  * @return Number of channels
758  **/
getNumberOfChannels(GLenum internal_format)759 GLuint Utils::getNumberOfChannels(GLenum internal_format)
760 {
761     GLuint result = 0;
762 
763     switch (internal_format)
764     {
765     case GL_R8:
766     case GL_R8_SNORM:
767     case GL_R16:
768     case GL_R16F:
769     case GL_R16_SNORM:
770     case GL_R32F:
771     case GL_R8I:
772     case GL_R8UI:
773     case GL_R16I:
774     case GL_R16UI:
775     case GL_R32I:
776     case GL_R32UI:
777         result = 1;
778         break;
779 
780     case GL_RG8:
781     case GL_RG8_SNORM:
782     case GL_RG16:
783     case GL_RG16F:
784     case GL_RG16_SNORM:
785     case GL_RG32F:
786     case GL_RG8I:
787     case GL_RG8UI:
788     case GL_RG16I:
789     case GL_RG16UI:
790     case GL_RG32I:
791     case GL_RG32UI:
792         result = 2;
793         break;
794 
795     case GL_R3_G3_B2:
796     case GL_RGB4:
797     case GL_RGB5:
798     case GL_RGB8:
799     case GL_RGB8_SNORM:
800     case GL_RGB10:
801     case GL_R11F_G11F_B10F:
802     case GL_RGB12:
803     case GL_RGB16:
804     case GL_RGB16F:
805     case GL_RGB16_SNORM:
806     case GL_RGB32F:
807     case GL_RGB9_E5:
808     case GL_RGB8I:
809     case GL_RGB8UI:
810     case GL_RGB16I:
811     case GL_RGB16UI:
812     case GL_RGB32I:
813     case GL_RGB32UI:
814         result = 3;
815         break;
816 
817     case GL_RGBA2:
818     case GL_RGBA4:
819     case GL_RGB5_A1:
820     case GL_RGBA8:
821     case GL_RGBA8_SNORM:
822     case GL_RGB10_A2:
823     case GL_RGBA12:
824     case GL_RGBA16:
825     case GL_RGBA16F:
826     case GL_RGBA16_SNORM:
827     case GL_RGBA32F:
828     case GL_RGBA8I:
829     case GL_RGBA8UI:
830     case GL_RGB10_A2UI:
831     case GL_RGBA16I:
832     case GL_RGBA16UI:
833     case GL_RGBA32I:
834     case GL_RGBA32UI:
835         result = 4;
836         break;
837 
838     default:
839         TCU_FAIL("Invalid enum");
840     }
841 
842     return result;
843 }
844 
845 /** Get type for given internal format
846  *
847  * @param internal_format Internal format
848  *
849  * @return Type
850  **/
getType(GLenum internal_format)851 GLenum Utils::getType(GLenum internal_format)
852 {
853     GLenum type = 0;
854 
855     switch (internal_format)
856     {
857     case GL_R8:
858     case GL_R8UI:
859     case GL_RG8:
860     case GL_RG8UI:
861     case GL_RGB8:
862     case GL_RGB8UI:
863     case GL_RGBA8:
864     case GL_RGBA8UI:
865         type = GL_UNSIGNED_BYTE;
866         break;
867 
868     case GL_R8_SNORM:
869     case GL_R8I:
870     case GL_RG8_SNORM:
871     case GL_RG8I:
872     case GL_RGB8_SNORM:
873     case GL_RGB8I:
874     case GL_RGBA8_SNORM:
875     case GL_RGBA8I:
876         type = GL_BYTE;
877         break;
878 
879     case GL_R3_G3_B2:
880         type = GL_UNSIGNED_BYTE_3_3_2;
881         break;
882 
883     case GL_RGB4:
884     case GL_RGB5:
885         type = GL_UNSIGNED_SHORT_5_6_5;
886         break;
887 
888     case GL_RGBA2:
889     case GL_RGBA4:
890         type = GL_UNSIGNED_SHORT_4_4_4_4;
891         break;
892 
893     case GL_RGB5_A1:
894         type = GL_UNSIGNED_SHORT_5_5_5_1;
895         break;
896 
897     case GL_RGB10:
898     case GL_RGB10_A2:
899     case GL_RGB10_A2UI:
900         type = GL_UNSIGNED_INT_2_10_10_10_REV;
901         break;
902 
903     case GL_R16F:
904     case GL_RG16F:
905     case GL_RGB16F:
906     case GL_RGBA16F:
907         type = GL_HALF_FLOAT;
908         break;
909 
910     case GL_R16:
911     case GL_R16UI:
912     case GL_RG16:
913     case GL_RG16UI:
914     case GL_RGB12:
915     case GL_RGB16:
916     case GL_RGB16UI:
917     case GL_RGBA12:
918     case GL_RGBA16:
919     case GL_RGBA16UI:
920         type = GL_UNSIGNED_SHORT;
921         break;
922 
923     case GL_R16_SNORM:
924     case GL_R16I:
925     case GL_RG16_SNORM:
926     case GL_RG16I:
927     case GL_RGB16_SNORM:
928     case GL_RGB16I:
929     case GL_RGBA16_SNORM:
930     case GL_RGBA16I:
931         type = GL_SHORT;
932         break;
933 
934     case GL_R32UI:
935     case GL_RG32UI:
936     case GL_RGB32UI:
937     case GL_RGBA32UI:
938         type = GL_UNSIGNED_INT;
939         break;
940 
941     case GL_RGB9_E5:
942         type = GL_UNSIGNED_INT_5_9_9_9_REV;
943         break;
944 
945     case GL_R32I:
946     case GL_RG32I:
947     case GL_RGB32I:
948     case GL_RGBA32I:
949         type = GL_INT;
950         break;
951 
952     case GL_R32F:
953     case GL_RG32F:
954     case GL_RGB32F:
955     case GL_RGBA32F:
956         type = GL_FLOAT;
957         break;
958 
959     case GL_R11F_G11F_B10F:
960         type = GL_UNSIGNED_INT_10F_11F_11F_REV;
961         break;
962 
963     default:
964         TCU_FAIL("Invalid enum");
965     }
966 
967     return type;
968 }
969 
970 /** Returns mask that should be applied to pixel value
971  *
972  * @param internal_format Internal format of texture
973  * @param pixel           Pixel data
974  *
975  * @return Mask
976  **/
maskPixelForFormat(GLenum internal_format,GLubyte * pixel)977 void Utils::maskPixelForFormat(GLenum internal_format, GLubyte *pixel)
978 {
979     switch (internal_format)
980     {
981     case GL_RGB10:
982         /* UINT_10_10_10_2 - ALPHA will be set to 3*/
983         pixel[0] |= 0x03;
984         break;
985 
986     default:
987         break;
988     }
989 }
990 
991 /** Get size of pixel for given internal format
992  *
993  * @param internal_format Internal format
994  *
995  * @return Number of bytes used by given format
996  **/
getPixelSizeForFormat(GLenum internal_format)997 GLuint Utils::getPixelSizeForFormat(GLenum internal_format)
998 {
999     GLuint size = 0;
1000 
1001     switch (internal_format)
1002     {
1003     /* 8 */
1004     case GL_R8:
1005     case GL_R8I:
1006     case GL_R8UI:
1007     case GL_R8_SNORM:
1008     case GL_R3_G3_B2:
1009         size = 1;
1010         break;
1011 
1012     /* 8 */
1013     case GL_RGBA2:
1014         size = 2;
1015         break;
1016 
1017     /* 12 */
1018     case GL_RGB4:
1019         size = 2;
1020         break;
1021 
1022     /* 15 */
1023     case GL_RGB5:
1024         size = 2;
1025         break;
1026 
1027     /* 16 */
1028     case GL_RG8:
1029     case GL_RG8I:
1030     case GL_RG8UI:
1031     case GL_RG8_SNORM:
1032     case GL_R16:
1033     case GL_R16F:
1034     case GL_R16I:
1035     case GL_R16UI:
1036     case GL_R16_SNORM:
1037     case GL_RGBA4:
1038     case GL_RGB5_A1:
1039         size = 2;
1040         break;
1041 
1042     /* 24 */
1043     case GL_RGB8:
1044     case GL_RGB8I:
1045     case GL_RGB8UI:
1046     case GL_RGB8_SNORM:
1047         size = 3;
1048         break;
1049 
1050     /* 30 */
1051     case GL_RGB10:
1052         size = 4;
1053         break;
1054 
1055     /* 32 */
1056     case GL_RGBA8:
1057     case GL_RGBA8I:
1058     case GL_RGBA8UI:
1059     case GL_RGBA8_SNORM:
1060     case GL_RG16:
1061     case GL_RG16F:
1062     case GL_RG16I:
1063     case GL_RG16UI:
1064     case GL_RG16_SNORM:
1065     case GL_R32F:
1066     case GL_R32I:
1067     case GL_R32UI:
1068     case GL_RGB10_A2:
1069     case GL_RGB10_A2UI:
1070     case GL_R11F_G11F_B10F:
1071     case GL_RGB9_E5:
1072         size = 4;
1073         break;
1074 
1075     /* 36 */
1076     case GL_RGB12:
1077         size = 6;
1078         break;
1079 
1080     /* 48 */
1081     case GL_RGB16:
1082     case GL_RGB16F:
1083     case GL_RGB16I:
1084     case GL_RGB16UI:
1085     case GL_RGB16_SNORM:
1086         size = 6;
1087         break;
1088 
1089     /* 64 */
1090     case GL_RGBA12:
1091     case GL_RGBA16:
1092     case GL_RGBA16F:
1093     case GL_RGBA16I:
1094     case GL_RGBA16UI:
1095     case GL_RGBA16_SNORM:
1096     case GL_RG32F:
1097     case GL_RG32I:
1098     case GL_RG32UI:
1099         size = 8;
1100         break;
1101 
1102     /* 96 */
1103     case GL_RGB32F:
1104     case GL_RGB32I:
1105     case GL_RGB32UI:
1106         size = 12;
1107         break;
1108 
1109     /* 128 */
1110     case GL_RGBA32F:
1111     case GL_RGBA32I:
1112     case GL_RGBA32UI:
1113         size = 16;
1114         break;
1115 
1116     default:
1117         TCU_FAIL("Invalid enum");
1118     }
1119 
1120     return size;
1121 }
1122 
1123 /** Prepare string that represents bytes of pixel
1124  *
1125  * @param internal_format Format
1126  * @param pixel           Pixel data
1127  *
1128  * @return String
1129  **/
getPixelString(GLenum internal_format,const GLubyte * pixel)1130 std::string Utils::getPixelString(GLenum internal_format, const GLubyte *pixel)
1131 {
1132     const GLuint pixel_size = Utils::getPixelSizeForFormat(internal_format);
1133     std::stringstream stream;
1134 
1135     stream << "0x";
1136 
1137     for (GLint i = pixel_size - 1; i >= 0; --i)
1138     {
1139         stream << std::setbase(16) << std::setw(2) << std::setfill('0') << (GLuint)pixel[i];
1140     }
1141 
1142     return stream.str();
1143 }
1144 
1145 /** Check if target supports multiple layers
1146  *
1147  * @param target Texture target
1148  *
1149  * @return true if target is multilayered
1150  **/
isTargetMultilayer(GLenum target)1151 bool Utils::isTargetMultilayer(GLenum target)
1152 {
1153     bool result = false;
1154 
1155     switch (target)
1156     {
1157     case GL_TEXTURE_1D_ARRAY:
1158     case GL_TEXTURE_2D_ARRAY:
1159     case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1160     case GL_TEXTURE_3D:
1161     case GL_TEXTURE_CUBE_MAP_ARRAY:
1162         result = true;
1163         break;
1164 
1165     default:
1166         break;
1167     }
1168 
1169     return result;
1170 }
1171 
1172 /** Check if target supports multiple level
1173  *
1174  * @param target Texture target
1175  *
1176  * @return true if target supports mipmaps
1177  **/
isTargetMultilevel(GLenum target)1178 bool Utils::isTargetMultilevel(GLenum target)
1179 {
1180     bool result = true;
1181 
1182     switch (target)
1183     {
1184     case GL_TEXTURE_2D_MULTISAMPLE:
1185     case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1186     case GL_TEXTURE_RECTANGLE:
1187     case GL_RENDERBUFFER:
1188         result = false;
1189         break;
1190     default:
1191         break;
1192     }
1193 
1194     return result;
1195 }
1196 
1197 /** Check if target is multisampled
1198  *
1199  * @param target Texture target
1200  *
1201  * @return true when for multisampled formats, false otherwise
1202  **/
isTargetMultisampled(GLenum target)1203 bool Utils::isTargetMultisampled(GLenum target)
1204 {
1205     bool result = false;
1206 
1207     switch (target)
1208     {
1209     case GL_TEXTURE_2D_MULTISAMPLE:
1210     case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1211         result = true;
1212         break;
1213     default:
1214         break;
1215     }
1216 
1217     return result;
1218 }
1219 
1220 /** Generate texture object
1221  *
1222  * @param context Test context
1223  * @param target  Target of texture
1224  *
1225  * @return Generated name
1226  **/
generateTexture(deqp::Context & context,GLenum target)1227 glw::GLuint Utils::generateTexture(deqp::Context &context, GLenum target)
1228 {
1229     const Functions &gl = context.getRenderContext().getFunctions();
1230     GLuint name         = 0;
1231 
1232     switch (target)
1233     {
1234     case GL_RENDERBUFFER:
1235         gl.genRenderbuffers(1, &name);
1236         GLU_EXPECT_NO_ERROR(gl.getError(), "GenRenderbuffers");
1237         break;
1238 
1239     default:
1240         gl.genTextures(1, &name);
1241         GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
1242         break;
1243     }
1244 
1245     return name;
1246 }
1247 
1248 /** Sets base and max level parameters of texture to make it complete
1249  *
1250  * @param context    Test context
1251  * @param target     GLenum representing target of texture that should be created
1252  * @param id         Id of texture
1253  * @param base_level Base level value, eg 0
1254  * @param max_level  Max level value, eg 0
1255  **/
makeTextureComplete(deqp::Context & context,GLenum target,GLuint id,GLint base_level,GLint max_level)1256 void Utils::makeTextureComplete(deqp::Context &context, GLenum target, GLuint id, GLint base_level, GLint max_level)
1257 {
1258     const Functions &gl = context.getRenderContext().getFunctions();
1259 
1260     if (GL_RENDERBUFFER == target)
1261     {
1262         return;
1263     }
1264 
1265     /* Translate proxies into real targets */
1266     target = transRealToBindTarget(transProxyToRealTarget(target));
1267 
1268     gl.bindTexture(target, id);
1269     GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1270 
1271     /* Set levels */
1272     if (GL_TEXTURE_BUFFER != target)
1273     {
1274         gl.texParameteri(target, GL_TEXTURE_BASE_LEVEL, base_level);
1275         GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
1276 
1277         gl.texParameteri(target, GL_TEXTURE_MAX_LEVEL, max_level);
1278         GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
1279 
1280         /* Integer textures won't be complete with the default min filter
1281          * of GL_NEAREST_MIPMAP_LINEAR (or GL_LINEAR for rectangle textures)
1282          * and default mag filter of GL_LINEAR, so switch to nearest.
1283          */
1284         if (GL_TEXTURE_2D_MULTISAMPLE != target && GL_TEXTURE_2D_MULTISAMPLE_ARRAY != target)
1285         {
1286             gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1287             if (GL_TEXTURE_RECTANGLE != target)
1288             {
1289                 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1290                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
1291             }
1292             else
1293             {
1294                 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1295                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
1296             }
1297         }
1298     }
1299 
1300     /* Clean binding point */
1301     gl.bindTexture(target, 0);
1302     GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1303 }
1304 
1305 /** Generate and initialize texture for given target
1306  *
1307  * @param context   Test context
1308  * @param target    GLenum representing target of texture that should be created
1309  * @param n_samples Number of samples
1310  *
1311  * @return "name" of texture
1312  **/
prepareMultisampleTex(deqp::Context & context,GLenum target,GLsizei n_samples)1313 GLuint Utils::prepareMultisampleTex(deqp::Context &context, GLenum target, GLsizei n_samples)
1314 {
1315     static const GLuint depth           = 6;
1316     const Functions &gl                 = context.getRenderContext().getFunctions();
1317     static const GLuint height          = 16;
1318     static const GLenum internal_format = GL_RGBA8;
1319     GLuint name                         = 0;
1320     static const GLuint width           = 16;
1321 
1322     gl.genTextures(1, &name);
1323     GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
1324 
1325     /* Initialize */
1326     switch (target)
1327     {
1328     case GL_TEXTURE_2D_MULTISAMPLE:
1329         gl.bindTexture(target, name);
1330         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1331 
1332         gl.texImage2DMultisample(target, n_samples, internal_format, width, height, GL_FALSE /* fixedsamplelocation */);
1333         GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2DMultisample");
1334 
1335         break;
1336 
1337     case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1338         gl.bindTexture(target, name);
1339         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1340 
1341         gl.texImage3DMultisample(target, n_samples, internal_format, width, height, depth,
1342                                  GL_FALSE /* fixedsamplelocation */);
1343         GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3DMultisample");
1344 
1345         break;
1346 
1347     default:
1348         TCU_FAIL("Invalid enum");
1349     }
1350 
1351     /* Clean binding point */
1352     gl.bindTexture(target, 0);
1353     GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1354 
1355     return name;
1356 }
1357 
1358 /** Generate and initialize texture for given target
1359  *
1360  * @param context         Test context
1361  * @param internal_format Internal format of render buffer
1362  *
1363  * @return "name" of texture
1364  **/
prepareRenderBuffer(deqp::Context & context,GLenum internal_format)1365 GLuint Utils::prepareRenderBuffer(deqp::Context &context, GLenum internal_format)
1366 {
1367     const Functions &gl        = context.getRenderContext().getFunctions();
1368     static const GLuint height = 16;
1369     GLuint name                = 0;
1370     static const GLuint width  = 16;
1371 
1372     gl.genRenderbuffers(1, &name);
1373     GLU_EXPECT_NO_ERROR(gl.getError(), "GenRenderbuffers");
1374 
1375     /* Initialize */
1376     gl.bindRenderbuffer(GL_RENDERBUFFER, name);
1377     GLU_EXPECT_NO_ERROR(gl.getError(), "BindRenderbuffer");
1378 
1379     gl.renderbufferStorage(GL_RENDERBUFFER, internal_format, width, height);
1380     GLU_EXPECT_NO_ERROR(gl.getError(), "RenderbufferStorage");
1381 
1382     /* Clean binding point */
1383     gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
1384     GLU_EXPECT_NO_ERROR(gl.getError(), "BindRenderbuffer");
1385 
1386     return name;
1387 }
1388 
1389 /** Generate and initialize texture for given target
1390  *
1391  * @param context         Test context
1392  * @param target          GLenum representing target of texture that should be created
1393  * @param internal_format <internalformat>
1394  * @param format          <format>
1395  * @param type            <type>
1396  * @param out_buf_id      ID of buffer that will be used for TEXTURE_BUFFER
1397  *
1398  * @return "name" of texture
1399  **/
prepareTex16x16x6(deqp::Context & context,GLenum target,GLenum internal_format,GLenum format,GLenum type,GLuint & out_buf_id)1400 GLuint Utils::prepareTex16x16x6(deqp::Context &context, GLenum target, GLenum internal_format, GLenum format,
1401                                 GLenum type, GLuint &out_buf_id)
1402 {
1403     static const GLuint depth   = 6;
1404     static const GLuint height  = 16;
1405     static const GLuint level   = 0;
1406     GLuint name                 = 0;
1407     static const GLchar *pixels = 0;
1408     static const GLuint width   = 16;
1409 
1410     name = generateTexture(context, target);
1411 
1412     prepareTexture(context, name, target, internal_format, format, type, level, width, height, depth, pixels,
1413                    out_buf_id);
1414 
1415     return name;
1416 }
1417 
1418 /** Initialize texture
1419  *
1420  * @param context         Test context
1421  * @param name            Name of texture object
1422  * @param target          GLenum representing target of texture that should be created
1423  * @param internal_format <internalformat>
1424  * @param format          <format>
1425  * @param type            <type>
1426  * @param level           <level>
1427  * @param width           <width>
1428  * @param height          <height>
1429  * @param depth           <depth>
1430  * @param pixels          <pixels>
1431  * @param out_buf_id      ID of buffer that will be used for TEXTURE_BUFFER
1432  *
1433  * @return "name" of texture
1434  **/
prepareTexture(deqp::Context & context,GLuint name,GLenum target,GLenum internal_format,GLenum format,GLenum type,GLuint level,GLuint width,GLuint height,GLuint depth,const GLvoid * pixels,GLuint & out_buf_id)1435 void Utils::prepareTexture(deqp::Context &context, GLuint name, GLenum target, GLenum internal_format, GLenum format,
1436                            GLenum type, GLuint level, GLuint width, GLuint height, GLuint depth, const GLvoid *pixels,
1437                            GLuint &out_buf_id)
1438 {
1439     static const GLint border    = 0;
1440     GLenum error                 = 0;
1441     const GLchar *function_name  = "unknown";
1442     const Functions &gl          = context.getRenderContext().getFunctions();
1443     static const GLsizei samples = 1;
1444 
1445     /* Translate proxies into real targets */
1446     target = transProxyToRealTarget(target);
1447 
1448     /* Initialize */
1449     switch (target)
1450     {
1451     case GL_RENDERBUFFER:
1452         gl.bindRenderbuffer(target, name);
1453         GLU_EXPECT_NO_ERROR(gl.getError(), "BindRenderbuffer");
1454 
1455         gl.renderbufferStorage(target, internal_format, width, height);
1456         GLU_EXPECT_NO_ERROR(gl.getError(), "RenderbufferStorage");
1457 
1458         gl.bindRenderbuffer(target, 0);
1459         GLU_EXPECT_NO_ERROR(gl.getError(), "BindRenderbuffer");
1460 
1461         break;
1462 
1463     case GL_TEXTURE_1D:
1464         gl.bindTexture(target, name);
1465         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1466 
1467         gl.texImage1D(target, level, internal_format, width, border, format, type, pixels);
1468         error         = gl.getError();
1469         function_name = "TexImage1D";
1470 
1471         break;
1472 
1473     case GL_TEXTURE_1D_ARRAY:
1474     case GL_TEXTURE_2D:
1475     case GL_TEXTURE_RECTANGLE:
1476         gl.bindTexture(target, name);
1477 
1478         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1479 
1480         gl.texImage2D(target, level, internal_format, width, height, border, format, type, pixels);
1481         error         = gl.getError();
1482         function_name = "TexImage2D";
1483 
1484         break;
1485 
1486     case GL_TEXTURE_2D_MULTISAMPLE:
1487         gl.bindTexture(target, name);
1488         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1489 
1490         gl.texImage2DMultisample(target, samples, internal_format, width, height, GL_FALSE /* fixedsamplelocation */);
1491         error         = gl.getError();
1492         function_name = "TexImage2DMultisample";
1493 
1494         break;
1495 
1496     case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1497         gl.bindTexture(target, name);
1498         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1499 
1500         gl.texImage3DMultisample(target, samples, internal_format, width, height, depth,
1501                                  GL_FALSE /* fixedsamplelocation */);
1502         error         = gl.getError();
1503         function_name = "TexImage3DMultisample";
1504 
1505         break;
1506 
1507     case GL_TEXTURE_2D_ARRAY:
1508     case GL_TEXTURE_3D:
1509     case GL_TEXTURE_CUBE_MAP_ARRAY:
1510         gl.bindTexture(target, name);
1511 
1512         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1513 
1514         gl.texImage3D(target, level, internal_format, width, height, depth, border, format, type, pixels);
1515         error         = gl.getError();
1516         function_name = "TexImage3D";
1517 
1518         break;
1519 
1520     case GL_TEXTURE_BUFFER:
1521         gl.genBuffers(1, &out_buf_id);
1522         GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
1523 
1524         gl.bindBuffer(GL_TEXTURE_BUFFER, out_buf_id);
1525         GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
1526 
1527         {
1528             GLsizei size       = 16;
1529             const GLvoid *data = 0;
1530 
1531             if (0 != pixels)
1532             {
1533                 size = width;
1534                 data = pixels;
1535             }
1536 
1537             gl.bufferData(GL_TEXTURE_BUFFER, size, data, GL_DYNAMIC_COPY);
1538             GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
1539         }
1540 
1541         gl.bindTexture(GL_TEXTURE_BUFFER, name);
1542         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1543 
1544         gl.texBuffer(GL_TEXTURE_BUFFER, internal_format, out_buf_id);
1545         GLU_EXPECT_NO_ERROR(gl.getError(), "TexBuffer");
1546 
1547         break;
1548 
1549     case GL_TEXTURE_CUBE_MAP:
1550     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1551     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1552     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1553     case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1554     case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1555     case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1556         /* Change target to CUBE_MAP, it will be used later to change base and max level */
1557         target = GL_TEXTURE_CUBE_MAP;
1558         gl.bindTexture(target, name);
1559         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1560 
1561         gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, border, format, type,
1562                       pixels);
1563         gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, border, format, type,
1564                       pixels);
1565         gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, border, format, type,
1566                       pixels);
1567         gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, border, format, type,
1568                       pixels);
1569         gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, border, format, type,
1570                       pixels);
1571         gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, border, format, type,
1572                       pixels);
1573         error         = gl.getError();
1574         function_name = "TexImage2D";
1575 
1576         break;
1577 
1578     default:
1579         TCU_FAIL("Invalid enum");
1580     }
1581 
1582     if (GL_NO_ERROR != error)
1583     {
1584         context.getTestContext().getLog()
1585             << tcu::TestLog::Message << "Error: " << glu::getErrorStr(error) << ". Function: " << function_name
1586             << ". Target: " << glu::getTextureTargetStr(target)
1587             << ". Format: " << glu::getInternalFormatParameterStr(internal_format) << ", "
1588             << glu::getTextureFormatName(format) << ", " << glu::getTypeStr(type) << tcu::TestLog::EndMessage;
1589         TCU_FAIL("Failed to create texture");
1590     }
1591 
1592     if (GL_RENDERBUFFER != target)
1593     {
1594         /* Clean binding point */
1595         gl.bindTexture(target, 0);
1596         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1597     }
1598 }
1599 
1600 /** Translate proxies into real targets
1601  *
1602  * @param target Target to be converted
1603  *
1604  * @return Converted target for proxies, <target> otherwise
1605  **/
transProxyToRealTarget(GLenum target)1606 GLenum Utils::transProxyToRealTarget(GLenum target)
1607 {
1608     switch (target)
1609     {
1610     case GL_PROXY_TEXTURE_1D:
1611         target = GL_TEXTURE_1D;
1612         break;
1613     case GL_PROXY_TEXTURE_1D_ARRAY:
1614         target = GL_TEXTURE_1D_ARRAY;
1615         break;
1616     case GL_PROXY_TEXTURE_2D:
1617         target = GL_TEXTURE_2D;
1618         break;
1619     case GL_PROXY_TEXTURE_2D_ARRAY:
1620         target = GL_TEXTURE_2D_ARRAY;
1621         break;
1622     case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
1623         target = GL_TEXTURE_2D_MULTISAMPLE;
1624         break;
1625     case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
1626         target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
1627         break;
1628     case GL_PROXY_TEXTURE_3D:
1629         target = GL_TEXTURE_3D;
1630         break;
1631     case GL_PROXY_TEXTURE_CUBE_MAP:
1632         target = GL_TEXTURE_CUBE_MAP;
1633         break;
1634     case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
1635         target = GL_TEXTURE_CUBE_MAP_ARRAY;
1636         break;
1637     case GL_PROXY_TEXTURE_RECTANGLE:
1638         target = GL_TEXTURE_RECTANGLE;
1639         break;
1640     default:
1641         break;
1642     }
1643 
1644     return target;
1645 }
1646 
1647 /** Translate real targets into binding targets
1648  *
1649  * @param target Target to be converted
1650  *
1651  * @return Converted target for cube map faces, <target> otherwise
1652  **/
transRealToBindTarget(GLenum target)1653 GLenum Utils::transRealToBindTarget(GLenum target)
1654 {
1655     switch (target)
1656     {
1657     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1658         target = GL_TEXTURE_CUBE_MAP;
1659         break;
1660     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1661         target = GL_TEXTURE_CUBE_MAP;
1662         break;
1663     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1664         target = GL_TEXTURE_CUBE_MAP;
1665         break;
1666     case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1667         target = GL_TEXTURE_CUBE_MAP;
1668         break;
1669     case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1670         target = GL_TEXTURE_CUBE_MAP;
1671         break;
1672     case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1673         target = GL_TEXTURE_CUBE_MAP;
1674         break;
1675     default:
1676         break;
1677     }
1678 
1679     return target;
1680 }
1681 
1682 /** Read value of channel
1683  *
1684  * @tparam T Type used to store channel value
1685  *
1686  * @param channel   Channel index
1687  * @param pixel     Pixel data
1688  * @param out_value Read value
1689  **/
1690 template <typename T>
readBaseTypeFromUnsignedChannel(GLuint channel,const GLubyte * pixel,GLdouble & out_value)1691 void readBaseTypeFromUnsignedChannel(GLuint channel, const GLubyte *pixel, GLdouble &out_value)
1692 {
1693     static const T max = -1;
1694 
1695     const GLdouble d_max   = (GLdouble)max;
1696     const T *ptr           = (T *)pixel;
1697     const T t_value        = ptr[channel];
1698     const GLdouble d_value = (GLdouble)t_value;
1699 
1700     out_value = d_value / d_max;
1701 }
1702 
1703 /** Read value of channel
1704  *
1705  * @tparam T Type used to store channel value
1706  *
1707  * @param channel   Channel index
1708  * @param pixel     Pixel data
1709  * @param out_value Read value
1710  **/
1711 template <typename T>
readBaseTypeFromSignedChannel(GLuint channel,const GLubyte * pixel,GLdouble & out_value)1712 void readBaseTypeFromSignedChannel(GLuint channel, const GLubyte *pixel, GLdouble &out_value)
1713 {
1714     static const GLuint n_bytes = sizeof(T);
1715     static const GLuint n_bits  = 8u * n_bytes;
1716     static const T max          = (T)((1u << (n_bits - 1u)) - 1u);
1717 
1718     const GLdouble d_max   = (GLdouble)max;
1719     const T *ptr           = (T *)pixel;
1720     const T t_value        = ptr[channel];
1721     const GLdouble d_value = (GLdouble)t_value;
1722 
1723     out_value = d_value / d_max;
1724 }
1725 
1726 /** Read value of channel
1727  *
1728  * @tparam T Type used to store channel value
1729  *
1730  * @param channel   Channel index
1731  * @param pixel     Pixel data
1732  * @param out_value Read value
1733  **/
readBaseTypeFromFloatChannel(GLuint channel,const GLubyte * pixel,GLdouble & out_value)1734 void readBaseTypeFromFloatChannel(GLuint channel, const GLubyte *pixel, GLdouble &out_value)
1735 {
1736     const GLfloat *ptr     = (const GLfloat *)pixel;
1737     const GLfloat t_value  = ptr[channel];
1738     const GLdouble d_value = (GLdouble)t_value;
1739 
1740     out_value = d_value;
1741 }
1742 
1743 /** Read value of channel
1744  *
1745  * @tparam T Type used to store channel value
1746  *
1747  * @param channel   Channel index
1748  * @param pixel     Pixel data
1749  * @param out_value Read value
1750  **/
readBaseTypeFromHalfFloatChannel(GLuint channel,const GLubyte * pixel,GLdouble & out_value)1751 void readBaseTypeFromHalfFloatChannel(GLuint channel, const GLubyte *pixel, GLdouble &out_value)
1752 {
1753     const uint16_t *ptr = (const uint16_t *)pixel;
1754     const uint16_t bits = ptr[channel];
1755     tcu::Float16 val(bits);
1756     const GLdouble d_value = val.asDouble();
1757 
1758     out_value = d_value;
1759 }
1760 
1761 /** Read value of channel
1762  *
1763  * @tparam T      Type used to store pixel
1764  * @tparam size_1 Size of channel in bits
1765  * @tparam size_2 Size of channel in bits
1766  * @tparam size_3 Size of channel in bits
1767  * @tparam off_1  Offset of channel in bits
1768  * @tparam off_2  Offset of channel in bits
1769  * @tparam off_3  Offset of channel in bits
1770  *
1771  * @param channel   Channel index
1772  * @param pixel     Pixel data
1773  * @param out_value Read value
1774  **/
1775 template <typename T, unsigned int size_1, unsigned int size_2, unsigned int size_3, unsigned int off_1,
1776           unsigned int off_2, unsigned int off_3>
read3Channel(GLuint channel,const GLubyte * pixel,GLdouble & out_value)1777 void read3Channel(GLuint channel, const GLubyte *pixel, GLdouble &out_value)
1778 {
1779     T mask          = 0;
1780     T max           = 0;
1781     T off           = 0;
1782     const T *ptr    = (T *)pixel;
1783     T result        = 0;
1784     const T t_value = ptr[0];
1785 
1786     static const T max_1 = (1 << size_1) - 1;
1787     static const T max_2 = (1 << size_2) - 1;
1788     static const T max_3 = (1 << size_3) - 1;
1789 
1790     switch (channel)
1791     {
1792     case 0:
1793         mask = max_1;
1794         max  = max_1;
1795         off  = off_1;
1796         break;
1797     case 1:
1798         mask = max_2;
1799         max  = max_2;
1800         off  = off_2;
1801         break;
1802     case 2:
1803         mask = max_3;
1804         max  = max_3;
1805         off  = off_3;
1806         break;
1807     default:
1808         TCU_FAIL("Invalid channel");
1809         break;
1810     }
1811 
1812     result = (T)((t_value >> off) & mask);
1813 
1814     const GLdouble d_max   = (GLdouble)max;
1815     const GLdouble d_value = (GLdouble)result;
1816 
1817     out_value = d_value / d_max;
1818 }
1819 
1820 /** Read value of channel
1821  *
1822  * @tparam T      Type used to store pixel
1823  * @tparam size_1 Size of channel in bits
1824  * @tparam size_2 Size of channel in bits
1825  * @tparam size_3 Size of channel in bits
1826  * @tparam size_4 Size of channel in bits
1827  * @tparam off_1  Offset of channel in bits
1828  * @tparam off_2  Offset of channel in bits
1829  * @tparam off_3  Offset of channel in bits
1830  * @tparam off_4  Offset of channel in bits
1831  *
1832  * @param channel   Channel index
1833  * @param pixel     Pixel data
1834  * @param out_value Read value
1835  **/
1836 template <typename T, unsigned int size_1, unsigned int size_2, unsigned int size_3, unsigned int size_4,
1837           unsigned int off_1, unsigned int off_2, unsigned int off_3, unsigned int off_4>
read4Channel(GLuint channel,const GLubyte * pixel,GLdouble & out_value)1838 void read4Channel(GLuint channel, const GLubyte *pixel, GLdouble &out_value)
1839 {
1840     T mask          = 0;
1841     T max           = 0;
1842     T off           = 0;
1843     const T *ptr    = (T *)pixel;
1844     T result        = 0;
1845     const T t_value = ptr[0];
1846 
1847     static const T max_1 = (1 << size_1) - 1;
1848     static const T max_2 = (1 << size_2) - 1;
1849     static const T max_3 = (1 << size_3) - 1;
1850     static const T max_4 = (1 << size_4) - 1;
1851 
1852     switch (channel)
1853     {
1854     case 0:
1855         mask = max_1;
1856         max  = max_1;
1857         off  = off_1;
1858         break;
1859     case 1:
1860         mask = max_2;
1861         max  = max_2;
1862         off  = off_2;
1863         break;
1864     case 2:
1865         mask = max_3;
1866         max  = max_3;
1867         off  = off_3;
1868         break;
1869     case 3:
1870         mask = max_4;
1871         max  = max_4;
1872         off  = off_4;
1873         break;
1874     default:
1875         TCU_FAIL("Invalid channel");
1876         break;
1877     }
1878 
1879     result = (T)((t_value >> off) & mask);
1880 
1881     const GLdouble d_max   = (GLdouble)max;
1882     const GLdouble d_value = (GLdouble)result;
1883 
1884     out_value = d_value / d_max;
1885 }
1886 
1887 /** Read value of channel
1888  *
1889  * @param channel   Channel index
1890  * @param pixel     Pixel data
1891  * @param out_value Read value
1892  **/
read11F_11F_10F_Channel(GLuint channel,const GLubyte * pixel,GLdouble & out_value)1893 void read11F_11F_10F_Channel(GLuint channel, const GLubyte *pixel, GLdouble &out_value)
1894 {
1895     const uint32_t *ptr = (uint32_t *)pixel;
1896     uint32_t val        = *ptr;
1897 
1898     switch (channel)
1899     {
1900     case 0:
1901     {
1902         uint32_t bits = (val & 0x000007ff);
1903         tcu::Float<uint32_t, 5, 6, 15, tcu::FLOAT_SUPPORT_DENORM> temp_val(bits);
1904 
1905         out_value = temp_val.asDouble();
1906     }
1907     break;
1908     case 1:
1909     {
1910         uint32_t bits = ((val >> 11) & 0x000007ff);
1911         tcu::Float<uint32_t, 5, 6, 15, tcu::FLOAT_SUPPORT_DENORM> temp_val(bits);
1912 
1913         out_value = temp_val.asDouble();
1914     }
1915     break;
1916     case 2:
1917     {
1918         uint32_t bits = ((val >> 22) & 0x000003ff);
1919         tcu::Float<uint32_t, 5, 5, 15, tcu::FLOAT_SUPPORT_DENORM> temp_val(bits);
1920 
1921         out_value = temp_val.asDouble();
1922     }
1923     break;
1924     default:
1925         TCU_FAIL("Invalid channel");
1926     }
1927 }
1928 
1929 /** Write value of channel
1930  *
1931  * @tparam T Type used to store pixel
1932  *
1933  * @param channel Channel index
1934  * @param value   Value to write
1935  * @param pixel   Pixel data
1936  **/
1937 template <typename T>
writeBaseTypeToUnsignedChannel(GLuint channel,GLdouble value,GLubyte * pixel)1938 void writeBaseTypeToUnsignedChannel(GLuint channel, GLdouble value, GLubyte *pixel)
1939 {
1940     static const T max = -1;
1941 
1942     const GLdouble d_max   = (GLdouble)max;
1943     const GLdouble d_value = value * d_max;
1944     const T t_value        = (T)d_value;
1945 
1946     T *ptr = (T *)pixel;
1947 
1948     ptr[channel] = t_value;
1949 }
1950 
1951 /** Write value of channel
1952  *
1953  * @tparam T Type used to store pixel
1954  *
1955  * @param channel Channel index
1956  * @param value   Value to write
1957  * @param pixel   Pixel data
1958  **/
1959 template <typename T>
writeBaseTypeToSignedChannel(GLuint channel,GLdouble value,GLubyte * pixel)1960 void writeBaseTypeToSignedChannel(GLuint channel, GLdouble value, GLubyte *pixel)
1961 {
1962     static const GLuint n_bytes = sizeof(T);
1963     static const GLuint n_bits  = 8u * n_bytes;
1964     static const T max          = (T)((1u << (n_bits - 1u)) - 1u);
1965 
1966     const GLdouble d_max   = (GLdouble)max;
1967     const GLdouble d_value = value * d_max;
1968     const T t_value        = (T)d_value;
1969 
1970     T *ptr = (T *)pixel;
1971 
1972     ptr[channel] = t_value;
1973 }
1974 
1975 /** Write value of channel
1976  *
1977  * @param channel Channel index
1978  * @param value   Value to write
1979  * @param pixel   Pixel data
1980  **/
writeBaseTypeToFloatChannel(GLuint channel,GLdouble value,GLubyte * pixel)1981 void writeBaseTypeToFloatChannel(GLuint channel, GLdouble value, GLubyte *pixel)
1982 {
1983     const GLfloat t_value = (GLfloat)value;
1984 
1985     GLfloat *ptr = (GLfloat *)pixel;
1986 
1987     ptr[channel] = t_value;
1988 }
1989 
1990 /** Write value of channel
1991  *
1992  * @param channel Channel index
1993  * @param value   Value to write
1994  * @param pixel   Pixel data
1995  **/
writeBaseTypeToHalfFloatChannel(GLuint channel,GLdouble value,GLubyte * pixel)1996 void writeBaseTypeToHalfFloatChannel(GLuint channel, GLdouble value, GLubyte *pixel)
1997 {
1998     uint16_t *ptr = (uint16_t *)pixel;
1999 
2000     tcu::Float16 val(value);
2001 
2002     ptr[channel] = val.bits();
2003 }
2004 
2005 /** Write value of channel
2006  *
2007  * @tparam T      Type used to store pixel
2008  * @tparam size_1 Size of channel in bits
2009  * @tparam size_2 Size of channel in bits
2010  * @tparam size_3 Size of channel in bits
2011  * @tparam off_1  Offset of channel in bits
2012  * @tparam off_2  Offset of channel in bits
2013  * @tparam off_3  Offset of channel in bits
2014  *
2015  * @param channel Channel index
2016  * @param value   Value to write
2017  * @param pixel   Pixel data
2018  **/
2019 template <typename T, unsigned int size_1, unsigned int size_2, unsigned int size_3, unsigned int off_1,
2020           unsigned int off_2, unsigned int off_3>
write3Channel(GLuint channel,GLdouble value,GLubyte * pixel)2021 void write3Channel(GLuint channel, GLdouble value, GLubyte *pixel)
2022 {
2023     T mask   = 0;
2024     T max    = 0;
2025     T off    = 0;
2026     T *ptr   = (T *)pixel;
2027     T result = 0;
2028 
2029     static const T max_1 = (1 << size_1) - 1;
2030     static const T max_2 = (1 << size_2) - 1;
2031     static const T max_3 = (1 << size_3) - 1;
2032 
2033     switch (channel)
2034     {
2035     case 0:
2036         mask = max_1;
2037         max  = max_1;
2038         off  = off_1;
2039         break;
2040     case 1:
2041         mask = max_2;
2042         max  = max_2;
2043         off  = off_2;
2044         break;
2045     case 2:
2046         mask = max_3;
2047         max  = max_3;
2048         off  = off_3;
2049         break;
2050     default:
2051         TCU_FAIL("Invalid channel");
2052         break;
2053     }
2054 
2055     const GLdouble d_max   = (GLdouble)max;
2056     const GLdouble d_value = value * d_max;
2057     const T t_value        = (T)d_value;
2058 
2059     result = (T)((t_value & mask) << off);
2060 
2061     *ptr |= result;
2062 }
2063 
2064 /** Write value of channel
2065  *
2066  * @tparam T      Type used to store pixel
2067  * @tparam size_1 Size of channel in bits
2068  * @tparam size_2 Size of channel in bits
2069  * @tparam size_3 Size of channel in bits
2070  * @tparam size_4 Size of channel in bits
2071  * @tparam off_1  Offset of channel in bits
2072  * @tparam off_2  Offset of channel in bits
2073  * @tparam off_3  Offset of channel in bits
2074  * @tparam off_4  Offset of channel in bits
2075  *
2076  * @param channel Channel index
2077  * @param value   Value to write
2078  * @param pixel   Pixel data
2079  **/
2080 template <typename T, unsigned int size_1, unsigned int size_2, unsigned int size_3, unsigned int size_4,
2081           unsigned int off_1, unsigned int off_2, unsigned int off_3, unsigned int off_4>
write4Channel(GLuint channel,GLdouble value,GLubyte * pixel)2082 void write4Channel(GLuint channel, GLdouble value, GLubyte *pixel)
2083 {
2084     T mask   = 0;
2085     T max    = 0;
2086     T off    = 0;
2087     T *ptr   = (T *)pixel;
2088     T result = 0;
2089 
2090     static const T max_1 = (1 << size_1) - 1;
2091     static const T max_2 = (1 << size_2) - 1;
2092     static const T max_3 = (1 << size_3) - 1;
2093     static const T max_4 = (1 << size_4) - 1;
2094 
2095     switch (channel)
2096     {
2097     case 0:
2098         mask = max_1;
2099         max  = max_1;
2100         off  = off_1;
2101         break;
2102     case 1:
2103         mask = max_2;
2104         max  = max_2;
2105         off  = off_2;
2106         break;
2107     case 2:
2108         mask = max_3;
2109         max  = max_3;
2110         off  = off_3;
2111         break;
2112     case 3:
2113         mask = max_4;
2114         max  = max_4;
2115         off  = off_4;
2116         break;
2117     default:
2118         TCU_FAIL("Invalid channel");
2119         break;
2120     }
2121 
2122     const GLdouble d_max   = (GLdouble)max;
2123     const GLdouble d_value = value * d_max;
2124     const T t_value        = (T)d_value;
2125 
2126     result = (T)((t_value & mask) << off);
2127 
2128     *ptr |= result;
2129 }
2130 
2131 /** Write value of channel
2132  *
2133  * @param channel Channel index
2134  * @param value   Value to write
2135  * @param pixel   Pixel data
2136  **/
write11F_11F_10F_Channel(GLuint channel,GLdouble value,GLubyte * pixel)2137 void write11F_11F_10F_Channel(GLuint channel, GLdouble value, GLubyte *pixel)
2138 {
2139     uint32_t *ptr = (uint32_t *)pixel;
2140 
2141     switch (channel)
2142     {
2143     case 0:
2144     {
2145         tcu::Float<uint32_t, 5, 6, 15, tcu::FLOAT_SUPPORT_DENORM> val(value);
2146         uint32_t bits = val.bits();
2147 
2148         *ptr |= bits;
2149     }
2150     break;
2151     case 1:
2152     {
2153         tcu::Float<uint32_t, 5, 6, 15, tcu::FLOAT_SUPPORT_DENORM> val(value);
2154         uint32_t bits = val.bits();
2155 
2156         *ptr |= (bits << 11);
2157     }
2158     break;
2159     case 2:
2160     {
2161         tcu::Float<uint32_t, 5, 5, 15, tcu::FLOAT_SUPPORT_DENORM> val(value);
2162         uint32_t bits = val.bits();
2163 
2164         *ptr |= (bits << 22);
2165     }
2166     break;
2167     default:
2168         TCU_FAIL("Invalid channel");
2169     }
2170 }
2171 
2172 /** Read value of channel
2173  *
2174  * @param type    Type used by pixel
2175  * @param channel Channel index
2176  * @param pixel   Pixel data
2177  * @param value   Read value
2178  **/
readChannel(GLenum type,GLuint channel,const GLubyte * pixel,GLdouble & value)2179 void Utils::readChannel(GLenum type, GLuint channel, const GLubyte *pixel, GLdouble &value)
2180 {
2181     switch (type)
2182     {
2183     /* Base types */
2184     case GL_UNSIGNED_BYTE:
2185         readBaseTypeFromUnsignedChannel<GLubyte>(channel, pixel, value);
2186         break;
2187     case GL_UNSIGNED_SHORT:
2188         readBaseTypeFromUnsignedChannel<GLushort>(channel, pixel, value);
2189         break;
2190     case GL_UNSIGNED_INT:
2191         readBaseTypeFromUnsignedChannel<GLuint>(channel, pixel, value);
2192         break;
2193     case GL_BYTE:
2194         readBaseTypeFromSignedChannel<GLbyte>(channel, pixel, value);
2195         break;
2196     case GL_SHORT:
2197         readBaseTypeFromSignedChannel<GLshort>(channel, pixel, value);
2198         break;
2199     case GL_INT:
2200         readBaseTypeFromSignedChannel<GLint>(channel, pixel, value);
2201         break;
2202     case GL_HALF_FLOAT:
2203         readBaseTypeFromHalfFloatChannel(channel, pixel, value);
2204         break;
2205     case GL_FLOAT:
2206         readBaseTypeFromFloatChannel(channel, pixel, value);
2207         break;
2208 
2209     /* Complicated */
2210     /* 3 channels */
2211     case GL_UNSIGNED_BYTE_3_3_2:
2212         read3Channel<GLubyte, 3, 3, 2, 5, 2, 0>(channel, pixel, value);
2213         break;
2214     case GL_UNSIGNED_SHORT_5_6_5:
2215         read3Channel<GLushort, 5, 6, 5, 11, 5, 0>(channel, pixel, value);
2216         break;
2217 
2218     /* 4 channels */
2219     case GL_UNSIGNED_SHORT_4_4_4_4:
2220         read4Channel<GLushort, 4, 4, 4, 4, 12, 8, 4, 0>(channel, pixel, value);
2221         break;
2222     case GL_UNSIGNED_SHORT_5_5_5_1:
2223         read4Channel<GLushort, 5, 5, 5, 1, 11, 6, 1, 0>(channel, pixel, value);
2224         break;
2225     case GL_UNSIGNED_INT_2_10_10_10_REV:
2226         read4Channel<GLuint, 2, 10, 10, 10, 30, 20, 10, 0>(3 - channel, pixel, value);
2227         break;
2228     case GL_UNSIGNED_INT_5_9_9_9_REV:
2229         read4Channel<GLuint, 5, 9, 9, 9, 27, 18, 9, 0>(3 - channel, pixel, value);
2230         break;
2231 
2232     /* R11F_G11F_B10F - uber complicated */
2233     case GL_UNSIGNED_INT_10F_11F_11F_REV:
2234         read11F_11F_10F_Channel(channel, pixel, value);
2235         break;
2236 
2237     default:
2238         TCU_FAIL("Invalid enum");
2239     }
2240 }
2241 
2242 /** Write value of channel
2243  *
2244  * @param type    Type used by pixel
2245  * @param channel Channel index
2246  * @param value   Value to write
2247  * @param pixel   Pixel data
2248  **/
writeChannel(GLenum type,GLuint channel,GLdouble value,GLubyte * pixel)2249 void Utils::writeChannel(GLenum type, GLuint channel, GLdouble value, GLubyte *pixel)
2250 {
2251     switch (type)
2252     {
2253     /* Base types */
2254     case GL_UNSIGNED_BYTE:
2255         writeBaseTypeToUnsignedChannel<GLubyte>(channel, value, pixel);
2256         break;
2257     case GL_UNSIGNED_SHORT:
2258         writeBaseTypeToUnsignedChannel<GLushort>(channel, value, pixel);
2259         break;
2260     case GL_UNSIGNED_INT:
2261         writeBaseTypeToUnsignedChannel<GLuint>(channel, value, pixel);
2262         break;
2263     case GL_BYTE:
2264         writeBaseTypeToSignedChannel<GLbyte>(channel, value, pixel);
2265         break;
2266     case GL_SHORT:
2267         writeBaseTypeToSignedChannel<GLshort>(channel, value, pixel);
2268         break;
2269     case GL_INT:
2270         writeBaseTypeToSignedChannel<GLint>(channel, value, pixel);
2271         break;
2272     case GL_HALF_FLOAT:
2273         writeBaseTypeToHalfFloatChannel(channel, value, pixel);
2274         break;
2275     case GL_FLOAT:
2276         writeBaseTypeToFloatChannel(channel, value, pixel);
2277         break;
2278 
2279     /* Complicated */
2280 
2281     /* 3 channels */
2282     case GL_UNSIGNED_BYTE_3_3_2:
2283         write3Channel<GLubyte, 3, 3, 2, 5, 2, 0>(channel, value, pixel);
2284         break;
2285     case GL_UNSIGNED_SHORT_5_6_5:
2286         write3Channel<GLushort, 5, 6, 5, 11, 5, 0>(channel, value, pixel);
2287         break;
2288 
2289     /* 4 channels */
2290     case GL_UNSIGNED_SHORT_4_4_4_4:
2291         write4Channel<GLushort, 4, 4, 4, 4, 12, 8, 4, 0>(channel, value, pixel);
2292         break;
2293     case GL_UNSIGNED_SHORT_5_5_5_1:
2294         write4Channel<GLushort, 5, 5, 5, 1, 11, 6, 1, 0>(channel, value, pixel);
2295         break;
2296     case GL_UNSIGNED_INT_2_10_10_10_REV:
2297         write4Channel<GLuint, 2, 10, 10, 10, 30, 20, 10, 0>(3 - channel, value, pixel);
2298         break;
2299     case GL_UNSIGNED_INT_5_9_9_9_REV:
2300         write4Channel<GLuint, 5, 9, 9, 9, 27, 18, 9, 0>(3 - channel, value, pixel);
2301         break;
2302 
2303     /* R11F_G11F_B10F - uber complicated */
2304     case GL_UNSIGNED_INT_10F_11F_11F_REV:
2305         write11F_11F_10F_Channel(channel, value, pixel);
2306         break;
2307 
2308     default:
2309         TCU_FAIL("Invalid enum");
2310     }
2311 }
2312 
2313 /** Packs given channels to pixel
2314  *
2315  * @param internal_format Internal format of image
2316  * @param type            Type used by image
2317  * @param red             Red channel
2318  * @param green           Green channel
2319  * @param blue            Blue channel
2320  * @param alpha           Alpha channel
2321  * @param out_pixel       Pixel data
2322  **/
packPixel(GLenum internal_format,GLenum type,GLdouble red,GLdouble green,GLdouble blue,GLdouble alpha,GLubyte * out_pixel)2323 void Utils::packPixel(GLenum internal_format, GLenum type, GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha,
2324                       GLubyte *out_pixel)
2325 {
2326     switch (internal_format)
2327     {
2328     case GL_R8:
2329     case GL_R8_SNORM:
2330     case GL_R16:
2331     case GL_R16F:
2332     case GL_R16_SNORM:
2333     case GL_R32F:
2334     case GL_R8I:
2335     case GL_R8UI:
2336     case GL_R16I:
2337     case GL_R16UI:
2338     case GL_R32I:
2339     case GL_R32UI:
2340         writeChannel(type, 0, red, out_pixel);
2341         break;
2342 
2343     case GL_RG8:
2344     case GL_RG8_SNORM:
2345     case GL_RG16:
2346     case GL_RG16F:
2347     case GL_RG16_SNORM:
2348     case GL_RG32F:
2349     case GL_RG8I:
2350     case GL_RG8UI:
2351     case GL_RG16I:
2352     case GL_RG16UI:
2353     case GL_RG32I:
2354     case GL_RG32UI:
2355         writeChannel(type, 0, red, out_pixel);
2356         writeChannel(type, 1, green, out_pixel);
2357         break;
2358 
2359     case GL_R3_G3_B2:
2360     case GL_RGB4:
2361     case GL_RGB5:
2362     case GL_RGB8:
2363     case GL_RGB8_SNORM:
2364     case GL_RGB10:
2365     case GL_R11F_G11F_B10F:
2366     case GL_RGB12:
2367     case GL_RGB16:
2368     case GL_RGB16F:
2369     case GL_RGB16_SNORM:
2370     case GL_RGB32F:
2371     case GL_RGB8I:
2372     case GL_RGB8UI:
2373     case GL_RGB16I:
2374     case GL_RGB16UI:
2375     case GL_RGB32I:
2376     case GL_RGB32UI:
2377         writeChannel(type, 0, red, out_pixel);
2378         writeChannel(type, 1, green, out_pixel);
2379         writeChannel(type, 2, blue, out_pixel);
2380         break;
2381 
2382     case GL_RGB9_E5:
2383     case GL_RGBA2:
2384     case GL_RGBA4:
2385     case GL_RGB5_A1:
2386     case GL_RGBA8:
2387     case GL_RGBA8_SNORM:
2388     case GL_RGB10_A2:
2389     case GL_RGBA12:
2390     case GL_RGBA16:
2391     case GL_RGBA16F:
2392     case GL_RGBA16_SNORM:
2393     case GL_RGBA32F:
2394     case GL_RGBA8I:
2395     case GL_RGBA8UI:
2396     case GL_RGB10_A2UI:
2397     case GL_RGBA16I:
2398     case GL_RGBA16UI:
2399     case GL_RGBA32I:
2400     case GL_RGBA32UI:
2401         writeChannel(type, 0, red, out_pixel);
2402         writeChannel(type, 1, green, out_pixel);
2403         writeChannel(type, 2, blue, out_pixel);
2404         writeChannel(type, 3, alpha, out_pixel);
2405         break;
2406 
2407     default:
2408         TCU_FAIL("Invalid enum");
2409     }
2410 }
2411 
2412 /** Unpacks channels from pixel
2413  *
2414  * @param internal_format Internal format of image
2415  * @param type            Type used by image
2416  * @param pixel           Pixel data
2417  * @param red             Red channel
2418  * @param green           Green channel
2419  * @param blue            Blue channel
2420  * @param alpha           Alpha channel
2421  **/
unpackPixel(GLenum format,GLenum type,const GLubyte * pixel,GLdouble & out_red,GLdouble & out_green,GLdouble & out_blue,GLdouble & out_alpha)2422 void Utils::unpackPixel(GLenum format, GLenum type, const GLubyte *pixel, GLdouble &out_red, GLdouble &out_green,
2423                         GLdouble &out_blue, GLdouble &out_alpha)
2424 {
2425     switch (format)
2426     {
2427     case GL_RED:
2428     case GL_RED_INTEGER:
2429         readChannel(type, 0, pixel, out_red);
2430         out_green = 1.0;
2431         out_blue  = 1.0;
2432         out_alpha = 1.0;
2433         break;
2434     case GL_RG:
2435     case GL_RG_INTEGER:
2436         readChannel(type, 0, pixel, out_red);
2437         readChannel(type, 1, pixel, out_green);
2438         out_blue  = 1.0;
2439         out_alpha = 1.0;
2440         break;
2441     case GL_RGB:
2442     case GL_RGB_INTEGER:
2443         switch (type)
2444         {
2445         case GL_UNSIGNED_INT_5_9_9_9_REV:
2446             readChannel(type, 0, pixel, out_red);
2447             readChannel(type, 1, pixel, out_green);
2448             readChannel(type, 2, pixel, out_blue);
2449             readChannel(type, 3, pixel, out_alpha);
2450             break;
2451         default:
2452             readChannel(type, 0, pixel, out_red);
2453             readChannel(type, 1, pixel, out_green);
2454             readChannel(type, 2, pixel, out_blue);
2455             out_alpha = 1.0;
2456             break;
2457         }
2458         break;
2459     case GL_RGBA:
2460     case GL_RGBA_INTEGER:
2461         readChannel(type, 0, pixel, out_red);
2462         readChannel(type, 1, pixel, out_green);
2463         readChannel(type, 2, pixel, out_blue);
2464         readChannel(type, 3, pixel, out_alpha);
2465         break;
2466     default:
2467         TCU_FAIL("Invalid enum");
2468     }
2469 }
2470 
roundComponent(GLenum internal_format,GLenum component,GLdouble & value)2471 inline bool Utils::roundComponent(GLenum internal_format, GLenum component, GLdouble &value)
2472 {
2473     int exponent = (internal_format == GL_RGB4 ? 4 : (internal_format == GL_RGB5 ? 5 : 0));
2474     if (!exponent)
2475         return false; //Currently this only happens with GL_RGB4 and GL_RGB5 when stored as 565 type.
2476 
2477     int rounded_value = static_cast<int>(floor((pow(2, exponent) - 1) * value + 0.5));
2478     int multiplier    = (component == GL_GREEN ? 2 : 1);
2479     if (internal_format == GL_RGB4)
2480     {
2481         multiplier *= 2;
2482     }
2483     value = rounded_value * multiplier;
2484     return true;
2485 }
2486 
2487 /** Unpacks pixels and compars them
2488  *
2489  * @param left_format           Format of left image
2490  * @param left_type             Type of left image
2491  * @param left_internal_format  Internal format of left image
2492  * @param left_pixel            Data of left pixel
2493  * @param right_format          Format of right image
2494  * @param right_type            Type of right image
2495  * @param right_internal_format Internal format of right image
2496  * @param right_pixel           Data of right pixel
2497  *
2498  * @return true if pixels match, false otherwise
2499  **/
unpackAndComaprePixels(GLenum left_format,GLenum left_type,GLenum left_internal_format,const GLubyte * left_pixel,GLenum right_format,GLenum right_type,GLenum right_internal_format,const GLubyte * right_pixel)2500 bool Utils::unpackAndComaprePixels(GLenum left_format, GLenum left_type, GLenum left_internal_format,
2501                                    const GLubyte *left_pixel, GLenum right_format, GLenum right_type,
2502                                    GLenum right_internal_format, const GLubyte *right_pixel)
2503 {
2504     GLdouble left_red;
2505     GLdouble left_green;
2506     GLdouble left_blue;
2507     GLdouble left_alpha;
2508     GLdouble right_red;
2509     GLdouble right_green;
2510     GLdouble right_blue;
2511     GLdouble right_alpha;
2512 
2513     unpackPixel(left_format, left_type, left_pixel, left_red, left_green, left_blue, left_alpha);
2514 
2515     unpackPixel(right_format, right_type, right_pixel, right_red, right_green, right_blue, right_alpha);
2516 
2517     roundComponent(left_internal_format, GL_RED, left_red);
2518     roundComponent(left_internal_format, GL_GREEN, left_green);
2519     roundComponent(left_internal_format, GL_BLUE, left_blue);
2520 
2521     roundComponent(right_internal_format, GL_RED, right_red);
2522     roundComponent(right_internal_format, GL_GREEN, right_green);
2523     roundComponent(right_internal_format, GL_BLUE, right_blue);
2524 
2525     return comparePixels(left_internal_format, left_red, left_green, left_blue, left_alpha, right_internal_format,
2526                          right_red, right_green, right_blue, right_alpha);
2527 }
2528 
2529 /* FunctionalTest */
2530 #define FUNCTIONAL_TEST_N_LAYERS 12
2531 #define FUNCTIONAL_TEST_N_LEVELS 3
2532 
2533 /** Constructor
2534  *
2535  * @param context Text context
2536  **/
FunctionalTest(deqp::Context & context)2537 FunctionalTest::FunctionalTest(deqp::Context &context)
2538     : TestCase(context, "functional", "Test verifies CopyImageSubData copy data as requested")
2539     , m_dst_buf_name(0)
2540     , m_dst_tex_name(0)
2541     , m_rb_name(0)
2542     , m_src_buf_name(0)
2543     , m_src_tex_name(0)
2544     , m_test_case_index(0)
2545 {
2546     for (GLuint src_tgt_id = 0; src_tgt_id < s_n_valid_targets; ++src_tgt_id)
2547     {
2548         const GLenum src_target = s_valid_targets[src_tgt_id];
2549 
2550 #if COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_TARGETS == 0
2551         if ((GL_TEXTURE_1D == src_target) || (GL_TEXTURE_1D_ARRAY == src_target) || (GL_TEXTURE_2D == src_target) ||
2552             (GL_TEXTURE_CUBE_MAP == src_target) || (GL_TEXTURE_CUBE_MAP_ARRAY == src_target))
2553         {
2554             continue;
2555         }
2556 #endif /* COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_TARGETS == 0 */
2557 
2558         for (GLuint dst_tgt_id = 0; dst_tgt_id < s_n_valid_targets; ++dst_tgt_id)
2559         {
2560             const GLenum dst_target = s_valid_targets[dst_tgt_id];
2561 
2562 #if COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_TARGETS == 0
2563             if ((GL_TEXTURE_1D == dst_target) || (GL_TEXTURE_1D_ARRAY == dst_target) || (GL_TEXTURE_2D == dst_target) ||
2564                 (GL_TEXTURE_CUBE_MAP == dst_target) || (GL_TEXTURE_CUBE_MAP_ARRAY == dst_target))
2565             {
2566                 continue;
2567             }
2568 #endif /* COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_TARGETS == 0 */
2569 
2570             /* Skip render buffer as destination */
2571             if (GL_RENDERBUFFER == dst_target)
2572             {
2573                 continue;
2574             }
2575 
2576             /* Skip multisampled */
2577             if ((true == Utils::isTargetMultisampled(src_target)) || (true == Utils::isTargetMultisampled(dst_target)))
2578             {
2579                 continue;
2580             }
2581 
2582             for (GLuint src_frmt_id = 0; src_frmt_id < s_n_internal_formats; ++src_frmt_id)
2583             {
2584                 const GLenum src_format = s_internal_formats[src_frmt_id];
2585 
2586                 if (src_format == GL_RGB9_E5 && src_target == GL_RENDERBUFFER)
2587                 {
2588                     continue;
2589                 }
2590 
2591                 for (GLuint dst_frmt_id = 0; dst_frmt_id < s_n_internal_formats; ++dst_frmt_id)
2592                 {
2593                     const GLenum dst_format = s_internal_formats[dst_frmt_id];
2594 
2595                     /* Skip not compatible formats */
2596                     if (false == Utils::areFormatsCompatible(src_format, dst_format))
2597                     {
2598                         continue;
2599                     }
2600 
2601                     prepareTestCases(dst_format, dst_target, src_format, src_target);
2602                 }
2603             }
2604         }
2605     }
2606 }
2607 
2608 /** Execute test
2609  *
2610  * @return CONTINUE as long there are more test case, STOP otherwise
2611  **/
iterate()2612 tcu::TestNode::IterateResult FunctionalTest::iterate()
2613 {
2614     GLubyte *dst_pixels[FUNCTIONAL_TEST_N_LEVELS] = {0};
2615     const Functions &gl                           = m_context.getRenderContext().getFunctions();
2616     tcu::TestNode::IterateResult it_result        = tcu::TestNode::STOP;
2617     bool result                                   = false;
2618     GLubyte *src_pixels[FUNCTIONAL_TEST_N_LEVELS] = {0};
2619     const testCase &test_case                     = m_test_cases[m_test_case_index];
2620 
2621     gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
2622     gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
2623     GLU_EXPECT_NO_ERROR(gl.getError(), "PixelStorei");
2624 
2625     try
2626     {
2627         /* Prepare pixels */
2628         prepareDstPxls(test_case.m_dst, dst_pixels);
2629         prepareSrcPxls(test_case.m_src, test_case.m_dst.m_internal_format, src_pixels);
2630 
2631         /* Prepare textures */
2632         m_dst_tex_name = prepareTexture(test_case.m_dst, (const GLubyte **)dst_pixels, m_dst_buf_name);
2633 
2634         if (GL_RENDERBUFFER == test_case.m_src.m_target)
2635         {
2636             targetDesc desc = test_case.m_src;
2637             desc.m_target   = GL_TEXTURE_2D;
2638 
2639             m_rb_name      = prepareTexture(test_case.m_src, (const GLubyte **)src_pixels, m_src_buf_name);
2640             m_src_tex_name = prepareTexture(desc, (const GLubyte **)src_pixels, m_src_buf_name);
2641         }
2642         else
2643         {
2644             m_src_tex_name = prepareTexture(test_case.m_src, (const GLubyte **)src_pixels, m_src_buf_name);
2645         }
2646 
2647         /* Copy images and verify results */
2648         result = copyAndVerify(test_case, (const GLubyte **)dst_pixels, (const GLubyte **)src_pixels);
2649     }
2650     catch (tcu::Exception &exc)
2651     {
2652         clean();
2653         cleanPixels((GLubyte **)dst_pixels);
2654         cleanPixels((GLubyte **)src_pixels);
2655         throw exc;
2656     }
2657 
2658     /* Free resources */
2659     clean();
2660     cleanPixels((GLubyte **)dst_pixels);
2661     cleanPixels((GLubyte **)src_pixels);
2662 
2663     /* Set result */
2664     if (true == result)
2665     {
2666         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2667 
2668         /* Increase index */
2669         m_test_case_index += 1;
2670 
2671         /* Are there any test cases left */
2672         if (m_test_cases.size() > m_test_case_index)
2673         {
2674             it_result = tcu::TestNode::CONTINUE;
2675         }
2676     }
2677     else
2678     {
2679         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failure. " << tcu::TestLog::EndMessage;
2680 
2681         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2682     }
2683 
2684     /* Done */
2685     return it_result;
2686 }
2687 
2688 /** Calculate dimmensions of all levels based on size of specific level
2689  *
2690  * @param target      Target of image
2691  * @param level       Level index
2692  * @param width       Width of image at <level>
2693  * @param height      Height of image at <level>
2694  * @param out_widths  Calcualted widths, array of FUNCTIONAL_TEST_N_LEVELS'th elements
2695  * @param out_heights Calculated heights, array of FUNCTIONAL_TEST_N_LEVELS'th elements
2696  * @param out_depths  Calculated dephts, array of FUNCTIONAL_TEST_N_LEVELS'th elements
2697  **/
calculateDimmensions(GLenum target,GLuint level,GLuint width,GLuint height,GLuint * out_widths,GLuint * out_heights,GLuint * out_depths) const2698 void FunctionalTest::calculateDimmensions(GLenum target, GLuint level, GLuint width, GLuint height, GLuint *out_widths,
2699                                           GLuint *out_heights, GLuint *out_depths) const
2700 {
2701     GLuint divide = 100;
2702     GLuint factors[FUNCTIONAL_TEST_N_LEVELS];
2703     GLuint factor             = divide;
2704     const bool is_multi_layer = Utils::isTargetMultilayer(target);
2705     const GLuint n_layers     = (true == is_multi_layer) ? FUNCTIONAL_TEST_N_LAYERS : 1;
2706 
2707     for (GLint i = (GLint)level; i >= 0; --i)
2708     {
2709         factors[i] = factor;
2710         factor *= 2;
2711     }
2712 
2713     factor = divide / 2;
2714     for (GLuint i = level + 1; i < FUNCTIONAL_TEST_N_LEVELS; ++i)
2715     {
2716         factors[i] = factor;
2717         factor /= 2;
2718     }
2719 
2720     for (GLuint i = 0; i < FUNCTIONAL_TEST_N_LEVELS; ++i)
2721     {
2722         out_widths[i]  = width * factors[i] / divide;
2723         out_heights[i] = height * factors[i] / divide;
2724 
2725         if (GL_TEXTURE_3D == target)
2726         {
2727             out_depths[i] = FUNCTIONAL_TEST_N_LAYERS * factors[i] / divide;
2728         }
2729         else
2730         {
2731             out_depths[i] = n_layers;
2732         }
2733     }
2734 }
2735 
2736 /** Execute copyImageSubData for given test case and verify results
2737  *
2738  * @param test_case  Test case
2739  * @param dst_pixels Data of destination image
2740  * @param src_pixels Data of source image
2741  *
2742  * @return true if there is no error and results match expectations, false otherwise
2743  **/
copyAndVerify(const testCase & test_case,const GLubyte ** dst_pixels,const GLubyte ** src_pixels)2744 bool FunctionalTest::copyAndVerify(const testCase &test_case, const GLubyte **dst_pixels, const GLubyte **src_pixels)
2745 {
2746     GLenum error                  = GL_NO_ERROR;
2747     const Functions &gl           = m_context.getRenderContext().getFunctions();
2748     GLuint region_depth           = 1;
2749     GLuint dst_layer_step         = 0;
2750     const bool is_dst_multi_layer = Utils::isTargetMultilayer(test_case.m_dst.m_target);
2751     const bool is_src_multi_layer = Utils::isTargetMultilayer(test_case.m_src.m_target);
2752     bool result                   = false;
2753     GLuint src_layer_step         = 0;
2754     GLuint n_layers               = 1;
2755 
2756     /* Configure layers */
2757     if ((true == is_dst_multi_layer) || (true == is_src_multi_layer))
2758     {
2759         if (is_src_multi_layer == is_dst_multi_layer)
2760         {
2761             /* Both objects are multilayered, copy all layers at once, verify at once */
2762             region_depth = FUNCTIONAL_TEST_N_LAYERS;
2763         }
2764         else if (true == is_dst_multi_layer)
2765         {
2766             /* Destination is multilayered, copy each layer separetly, verify at once */
2767             n_layers       = FUNCTIONAL_TEST_N_LAYERS;
2768             dst_layer_step = 1;
2769         }
2770         else
2771         {
2772             /* Destination is multilayered, copy and verify each layer separetly */
2773             n_layers       = FUNCTIONAL_TEST_N_LAYERS;
2774             src_layer_step = 1;
2775         }
2776     }
2777 
2778     /* Copy and verification */
2779     {
2780         GLuint dst_layer = 0;
2781         GLuint src_layer = 0;
2782 
2783         /* For each layer */
2784         for (GLuint layer = 0; layer < n_layers; ++layer)
2785         {
2786             if (0 == m_rb_name)
2787             {
2788                 gl.copyImageSubData(m_src_tex_name, test_case.m_src.m_target, test_case.m_src.m_level,
2789                                     test_case.m_src_x, test_case.m_src_y, src_layer, m_dst_tex_name,
2790                                     test_case.m_dst.m_target, test_case.m_dst.m_level, test_case.m_dst_x,
2791                                     test_case.m_dst_y, dst_layer, test_case.m_width, test_case.m_height, region_depth);
2792             }
2793             else /* Copy from src to rb and from rb to dst */
2794             {
2795                 /* Src and rb shares differs only on target */
2796                 gl.copyImageSubData(m_src_tex_name, GL_TEXTURE_2D, test_case.m_src.m_level, test_case.m_src_x,
2797                                     test_case.m_src_y, src_layer, m_rb_name, test_case.m_src.m_target,
2798                                     test_case.m_src.m_level, test_case.m_src_x, test_case.m_src_y, src_layer,
2799                                     test_case.m_width, test_case.m_height, region_depth);
2800 
2801                 gl.copyImageSubData(m_rb_name, test_case.m_src.m_target, test_case.m_src.m_level, test_case.m_src_x,
2802                                     test_case.m_src_y, src_layer, m_dst_tex_name, test_case.m_dst.m_target,
2803                                     test_case.m_dst.m_level, test_case.m_dst_x, test_case.m_dst_y, dst_layer,
2804                                     test_case.m_width, test_case.m_height, region_depth);
2805             }
2806 
2807             /* Verify generated error */
2808             error = gl.getError();
2809 
2810             if (GL_NO_ERROR == error)
2811             {
2812                 /* Verify copy results */
2813                 result = verify(test_case, dst_layer, dst_pixels, src_layer, src_pixels, region_depth);
2814             }
2815 
2816             if ((GL_NO_ERROR != error) || (false == result))
2817             {
2818                 m_context.getTestContext().getLog()
2819                     << tcu::TestLog::Message
2820                     << "Failure. Targets src: " << glu::getTextureTargetStr(test_case.m_src.m_target)
2821                     << ", dst: " << glu::getTextureTargetStr(test_case.m_dst.m_target)
2822                     << ". Levels src: " << test_case.m_src.m_level << ", dst: " << test_case.m_dst.m_level
2823                     << ". Dimmensions src [" << test_case.m_src.m_width << ", " << test_case.m_src.m_height
2824                     << "], dst [" << test_case.m_dst.m_width << ", " << test_case.m_dst.m_height << "]. Region ["
2825                     << test_case.m_width << " x " << test_case.m_height << " x " << region_depth << "] from ["
2826                     << test_case.m_src_x << ", " << test_case.m_src_y << ", " << src_layer << "] to ["
2827                     << test_case.m_dst_x << ", " << test_case.m_dst_y << ", " << dst_layer
2828                     << "]. Format src: " << glu::getInternalFormatParameterStr(test_case.m_src.m_internal_format)
2829                     << ", dst: " << glu::getInternalFormatParameterStr(test_case.m_dst.m_internal_format)
2830                     << tcu::TestLog::EndMessage;
2831 
2832                 if (GL_NO_ERROR != error)
2833                 {
2834                     m_context.getTestContext().getLog()
2835                         << tcu::TestLog::Message << "Failed due to error: " << glu::getErrorStr(error)
2836                         << tcu::TestLog::EndMessage;
2837 
2838                     TCU_FAIL("Copy operation failed");
2839                 }
2840 
2841                 return false;
2842             }
2843 
2844             /* Step one layer */
2845             dst_layer += dst_layer_step;
2846             src_layer += src_layer_step;
2847         }
2848     }
2849 
2850     return true;
2851 }
2852 
2853 /** Cleans resources
2854  *
2855  **/
clean()2856 void FunctionalTest::clean()
2857 {
2858     const Functions &gl = m_context.getRenderContext().getFunctions();
2859 
2860     /* Clean textures and buffers. Errors ignored */
2861     gl.deleteTextures(1, &m_dst_tex_name);
2862     gl.deleteTextures(1, &m_src_tex_name);
2863 
2864     m_dst_tex_name = 0;
2865     m_src_tex_name = 0;
2866 
2867     if (0 != m_dst_buf_name)
2868     {
2869         gl.deleteBuffers(1, &m_dst_buf_name);
2870         m_dst_buf_name = 0;
2871     }
2872 
2873     if (0 != m_rb_name)
2874     {
2875         gl.deleteRenderbuffers(1, &m_rb_name);
2876         m_rb_name = 0;
2877     }
2878 
2879     if (0 != m_src_buf_name)
2880     {
2881         gl.deleteBuffers(1, &m_src_buf_name);
2882         m_src_buf_name = 0;
2883     }
2884 }
2885 
2886 /** Free memory allocated for images
2887  *
2888  * @param pixels Array of pointers to image data
2889  **/
cleanPixels(GLubyte ** pixels) const2890 void FunctionalTest::cleanPixels(GLubyte **pixels) const
2891 {
2892     for (GLuint i = 0; i < FUNCTIONAL_TEST_N_LEVELS; ++i)
2893     {
2894         if (0 != pixels[i])
2895         {
2896             delete[] pixels[i];
2897             pixels[i] = 0;
2898         }
2899     }
2900 }
2901 
2902 /** Compare two images
2903  * @param left_desc     Descriptor of left image
2904  * @param left_data     Data of left image
2905  * @param left_x        X of left image
2906  * @param left_y        Y of left image
2907  * @param left_layer    Layer of left image
2908  * @param left_level    Level of left image
2909  * @param right_desc    Descriptor of right image
2910  * @param right_data    Data of right image
2911  * @param right_x       X of right image
2912  * @param right_y       Y of right image
2913  * @param right_layer   Layer of right image
2914  * @param right_level   Level of right image
2915  * @param region_width  Width of region to compare
2916  * @param region_height Height of region to compare
2917  *
2918  * @return true if images are considered idenctial, false otherwise
2919  **/
compareImages(const targetDesc & left_desc,const GLubyte * left_data,GLuint left_x,GLuint left_y,GLuint left_layer,GLuint left_level,const targetDesc & right_desc,const glw::GLubyte * right_data,GLuint right_x,GLuint right_y,GLuint right_layer,GLuint right_level,GLuint region_width,GLuint region_height) const2920 bool FunctionalTest::compareImages(const targetDesc &left_desc, const GLubyte *left_data, GLuint left_x, GLuint left_y,
2921                                    GLuint left_layer, GLuint left_level, const targetDesc &right_desc,
2922                                    const glw::GLubyte *right_data, GLuint right_x, GLuint right_y, GLuint right_layer,
2923                                    GLuint right_level, GLuint region_width, GLuint region_height) const
2924 {
2925     /* Get level dimmensions */
2926     GLuint left_heights[FUNCTIONAL_TEST_N_LEVELS];
2927     GLuint left_widths[FUNCTIONAL_TEST_N_LEVELS];
2928     GLuint left_depths[FUNCTIONAL_TEST_N_LEVELS];
2929     GLuint right_heights[FUNCTIONAL_TEST_N_LEVELS];
2930     GLuint right_widths[FUNCTIONAL_TEST_N_LEVELS];
2931     GLuint right_depths[FUNCTIONAL_TEST_N_LEVELS];
2932 
2933     calculateDimmensions(left_desc.m_target, left_desc.m_level, left_desc.m_width, left_desc.m_height, left_widths,
2934                          left_heights, left_depths);
2935 
2936     calculateDimmensions(right_desc.m_target, right_desc.m_level, right_desc.m_width, right_desc.m_height, right_widths,
2937                          right_heights, right_depths);
2938 
2939     /* Constants */
2940     /* Dimmensions */
2941     const GLuint left_height  = left_heights[left_level];
2942     const GLuint left_width   = left_widths[left_level];
2943     const GLuint right_height = right_heights[right_level];
2944     const GLuint right_width  = right_widths[right_level];
2945     /* Sizes */
2946     const GLuint left_pixel_size  = Utils::getPixelSizeForFormat(left_desc.m_internal_format);
2947     const GLuint left_line_size   = left_pixel_size * left_width;
2948     const GLuint left_layer_size  = left_line_size * left_height;
2949     const GLuint right_pixel_size = Utils::getPixelSizeForFormat(right_desc.m_internal_format);
2950     const GLuint right_line_size  = right_pixel_size * right_width;
2951     const GLuint right_layer_size = right_line_size * right_height;
2952 
2953     /* Offsets */
2954     const GLuint left_layer_offset     = left_layer_size * left_layer;
2955     const GLuint left_reg_line_offset  = left_line_size * left_y;
2956     const GLuint left_reg_pix_offset   = left_pixel_size * left_x;
2957     const GLuint right_layer_offset    = right_layer_size * right_layer;
2958     const GLuint right_reg_line_offset = right_line_size * right_y;
2959     const GLuint right_reg_pix_offset  = right_pixel_size * right_x;
2960 
2961     /* Pointers */
2962     const GLubyte *left_layer_data  = left_data + left_layer_offset;
2963     const GLubyte *right_layer_data = right_data + right_layer_offset;
2964 
2965     /* For each line of region */
2966     for (GLuint y = 0; y < region_height; ++y)
2967     {
2968         /* Offsets */
2969         const GLuint left_line_offset  = left_reg_line_offset + y * left_line_size;
2970         const GLuint right_line_offset = right_reg_line_offset + y * right_line_size;
2971 
2972         /* Pointers */
2973         const GLubyte *left_line_data  = left_layer_data + left_line_offset;
2974         const GLubyte *right_line_data = right_layer_data + right_line_offset;
2975 
2976         /* For each pixel of region */
2977         for (GLuint x = 0; x < region_width; ++x)
2978         {
2979             /* Offsets */
2980             const GLuint left_pixel_offset  = left_reg_pix_offset + x * left_pixel_size;
2981             const GLuint right_pixel_offset = right_reg_pix_offset + x * right_pixel_size;
2982 
2983             /* Pointers */
2984             const GLubyte *left_pixel_data  = left_line_data + left_pixel_offset;
2985             const GLubyte *right_pixel_data = right_line_data + right_pixel_offset;
2986 
2987             /* Compare */
2988             if (false == Utils::comparePixels(left_pixel_size, left_pixel_data, right_pixel_size, right_pixel_data))
2989             {
2990                 if (false == Utils::unpackAndComaprePixels(left_desc.m_format, left_desc.m_type,
2991                                                            left_desc.m_internal_format, left_pixel_data,
2992                                                            right_desc.m_format, right_desc.m_type,
2993                                                            right_desc.m_internal_format, right_pixel_data))
2994                 {
2995                     m_context.getTestContext().getLog()
2996                         << tcu::TestLog::Message << "Not matching pixels found. Left: [" << x + left_x << ", "
2997                         << y + left_y << ", " << left_layer << "] lvl:" << left_level
2998                         << ", off: " << left_pixel_data - left_data
2999                         << ", data: " << Utils::getPixelString(left_desc.m_internal_format, left_pixel_data)
3000                         << ". Right: [" << x + right_x << ", " << y + right_y << ", " << right_layer
3001                         << "] lvl: " << right_level << ", off: " << right_pixel_data - right_data
3002                         << ", data: " << Utils::getPixelString(right_desc.m_internal_format, right_pixel_data)
3003                         << tcu::TestLog::EndMessage;
3004 
3005                     return false;
3006                 }
3007             }
3008         }
3009     }
3010 
3011     return true;
3012 }
3013 
3014 /** Prepare regions that should not be modified during test case
3015  *
3016  * @param test_case     Test case descriptor
3017  * @param dst_level     Level of destination image
3018  * @param out_regions   Number of regions
3019  * @param out_n_regions Regions
3020  **/
getCleanRegions(const testCase & test_case,GLuint dst_level,GLuint out_regions[4][4],GLuint & out_n_regions) const3021 void FunctionalTest::getCleanRegions(const testCase &test_case, GLuint dst_level, GLuint out_regions[4][4],
3022                                      GLuint &out_n_regions) const
3023 {
3024     GLuint dst_heights[FUNCTIONAL_TEST_N_LEVELS];
3025     GLuint dst_widths[FUNCTIONAL_TEST_N_LEVELS];
3026     GLuint dst_depths[FUNCTIONAL_TEST_N_LEVELS];
3027 
3028     out_n_regions = 0;
3029 
3030     calculateDimmensions(test_case.m_dst.m_target, dst_level, test_case.m_dst.m_width, test_case.m_dst.m_height,
3031                          dst_widths, dst_heights, dst_depths);
3032 
3033     /* Constants */
3034     /* Copied region */
3035     const GLuint reg_x = test_case.m_dst_x;
3036     const GLuint reg_y = test_case.m_dst_y;
3037     const GLuint reg_w = test_case.m_width;
3038     const GLuint reg_h = test_case.m_height;
3039     const GLuint reg_r = reg_x + reg_w;
3040     const GLuint reg_t = reg_y + reg_h;
3041 
3042     /* Image */
3043     const GLuint img_w = dst_widths[dst_level];
3044     const GLuint img_h = dst_heights[dst_level];
3045 
3046     /* Bottom row */
3047     if (0 != reg_y)
3048     {
3049         out_regions[out_n_regions][0] = 0;
3050         out_regions[out_n_regions][1] = 0;
3051         out_regions[out_n_regions][2] = img_w;
3052         out_regions[out_n_regions][3] = reg_y;
3053         out_n_regions += 1;
3054     }
3055 
3056     /* Left edge */
3057     if (0 != reg_x)
3058     {
3059         out_regions[out_n_regions][0] = 0;
3060         out_regions[out_n_regions][1] = reg_y;
3061         out_regions[out_n_regions][2] = reg_x;
3062         out_regions[out_n_regions][3] = reg_h;
3063         out_n_regions += 1;
3064     }
3065 
3066     /* Right edge */
3067     if (img_w != reg_r)
3068     {
3069         out_regions[out_n_regions][0] = reg_r;
3070         out_regions[out_n_regions][1] = reg_y;
3071         out_regions[out_n_regions][2] = img_w - reg_r;
3072         out_regions[out_n_regions][3] = reg_h;
3073         out_n_regions += 1;
3074     }
3075 
3076     /* Top row */
3077     if (img_h != reg_t)
3078     {
3079         out_regions[out_n_regions][0] = 0;
3080         out_regions[out_n_regions][1] = reg_t;
3081         out_regions[out_n_regions][2] = img_w;
3082         out_regions[out_n_regions][3] = img_h - reg_t;
3083         out_n_regions += 1;
3084     }
3085 }
3086 
3087 /** Get pixel data for image
3088  *
3089  * @param name       Name of image
3090  * @param desc       Descriptor of image
3091  * @param level      Level to capture
3092  * @param out_pixels Pixels
3093  **/
getPixels(GLuint name,const targetDesc & desc,GLuint level,GLubyte * out_pixels) const3094 void FunctionalTest::getPixels(GLuint name, const targetDesc &desc, GLuint level, GLubyte *out_pixels) const
3095 {
3096     const Functions &gl = m_context.getRenderContext().getFunctions();
3097 
3098     gl.bindTexture(desc.m_target, name);
3099     GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
3100 
3101     gl.getTexImage(desc.m_target, level, desc.m_format, desc.m_type, out_pixels);
3102     GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
3103 
3104     gl.bindTexture(desc.m_target, 0);
3105     GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
3106 }
3107 
3108 /** Prepare data for destination image
3109  *
3110  * @param desc       Descriptor
3111  * @param out_pixels Array of pointer to image data
3112  **/
prepareDstPxls(const FunctionalTest::targetDesc & desc,GLubyte ** out_pixels) const3113 void FunctionalTest::prepareDstPxls(const FunctionalTest::targetDesc &desc, GLubyte **out_pixels) const
3114 {
3115     const GLenum internal_format = desc.m_internal_format;
3116     const bool is_multi_level    = Utils::isTargetMultilevel(desc.m_target);
3117     GLuint n_levels              = 1;
3118     const GLuint pixel_size      = Utils::getPixelSizeForFormat(desc.m_internal_format);
3119     const GLenum type            = desc.m_type;
3120 
3121     /* Configure levels */
3122     if (true == is_multi_level)
3123     {
3124         n_levels = FUNCTIONAL_TEST_N_LEVELS;
3125     }
3126 
3127     /* Calculate dimmensions */
3128     GLuint heights[FUNCTIONAL_TEST_N_LEVELS];
3129     GLuint widths[FUNCTIONAL_TEST_N_LEVELS];
3130     GLuint depths[FUNCTIONAL_TEST_N_LEVELS];
3131 
3132     calculateDimmensions(desc.m_target, desc.m_level, desc.m_width, desc.m_height, widths, heights, depths);
3133 
3134     /* Prepare storage */
3135     for (GLuint i = 0; i < n_levels; ++i)
3136     {
3137         const GLuint req_memory_per_layer = pixel_size * widths[i] * heights[i];
3138         const GLuint req_memory_for_level = req_memory_per_layer * depths[i];
3139 
3140         out_pixels[i] = new GLubyte[req_memory_for_level];
3141 
3142         if (0 == out_pixels[i])
3143         {
3144             TCU_FAIL("Memory allocation failed");
3145         }
3146 
3147         memset(out_pixels[i], 0, req_memory_for_level);
3148     }
3149 
3150     /* Fill pixels */
3151     for (GLuint i = 0; i < n_levels; ++i)
3152     {
3153         const GLuint n_layers = depths[i];
3154         const GLuint n_pixels = widths[i] * heights[i];
3155         GLubyte *ptr          = (GLubyte *)out_pixels[i];
3156 
3157         for (GLuint j = 0; j < n_pixels * n_layers; ++j)
3158         {
3159             GLubyte *pixel_data = ptr + j * pixel_size;
3160 
3161             Utils::packPixel(internal_format, type, 1.0, 1.0, 1.0, 1.0, pixel_data);
3162         }
3163     }
3164 }
3165 
3166 /** Prepare data for source image
3167  *
3168  * @param desc                Descriptor
3169  * @param dst_internal_format Internal format of destination image
3170  * @param out_pixels          Array of pointer to image data
3171  **/
prepareSrcPxls(const FunctionalTest::targetDesc & desc,GLenum,GLubyte ** out_pixels) const3172 void FunctionalTest::prepareSrcPxls(const FunctionalTest::targetDesc &desc, GLenum /* dst_internal_format */,
3173                                     GLubyte **out_pixels) const
3174 {
3175     const GLenum internal_format = desc.m_internal_format;
3176     const bool is_multi_level    = Utils::isTargetMultilevel(desc.m_target);
3177     GLuint n_levels              = 1;
3178     const GLuint pixel_size      = Utils::getPixelSizeForFormat(desc.m_internal_format);
3179     const GLenum type            = desc.m_type;
3180 
3181     /* Configure levels */
3182     if (true == is_multi_level)
3183     {
3184         n_levels = FUNCTIONAL_TEST_N_LEVELS;
3185     }
3186 
3187     /* Calculate dimmensions */
3188     GLuint heights[FUNCTIONAL_TEST_N_LEVELS];
3189     GLuint widths[FUNCTIONAL_TEST_N_LEVELS];
3190     GLuint depths[FUNCTIONAL_TEST_N_LEVELS];
3191 
3192     calculateDimmensions(desc.m_target, desc.m_level, desc.m_width, desc.m_height, widths, heights, depths);
3193 
3194     /* Prepare storage */
3195     for (GLuint i = 0; i < n_levels; ++i)
3196     {
3197         const GLuint req_memory_per_layer = pixel_size * widths[i] * heights[i];
3198         const GLuint req_memory_for_level = req_memory_per_layer * depths[i];
3199 
3200         out_pixels[i] = new GLubyte[req_memory_for_level];
3201 
3202         if (0 == out_pixels[i])
3203         {
3204             TCU_FAIL("Memory allocation failed");
3205         }
3206 
3207         memset(out_pixels[i], 0, req_memory_for_level);
3208     }
3209 
3210     for (GLuint lvl = 0; lvl < n_levels; ++lvl)
3211     {
3212         const GLuint n_layers             = depths[lvl];
3213         const GLuint line_size            = pixel_size * widths[lvl];
3214         const GLuint req_memory_per_layer = line_size * heights[lvl];
3215         GLubyte *level                    = (GLubyte *)out_pixels[lvl];
3216 
3217         for (GLuint lay = 0; lay < n_layers; ++lay)
3218         {
3219             const GLuint layer_offset = lay * req_memory_per_layer;
3220 
3221             GLubyte *layer = ((GLubyte *)level) + layer_offset;
3222 
3223             for (GLuint y = 0; y < heights[lvl]; ++y)
3224             {
3225                 const GLuint line_offset = line_size * y;
3226 
3227                 GLubyte *line = layer + line_offset;
3228 
3229                 for (GLuint x = 0; x < widths[lvl]; ++x)
3230                 {
3231                     const GLuint pixel_offset = x * pixel_size;
3232 
3233                     GLubyte *pixel = line + pixel_offset;
3234 
3235                     /* 255 is max ubyte. 1/15.9375 = 16/255 */
3236                     const GLdouble red   = ((GLdouble)x) / 255.0 + (((GLdouble)y) / 15.9375);
3237                     const GLdouble green = ((GLdouble)lay) / 255.0 + (((GLdouble)lvl) / 15.9375);
3238                     const GLdouble blue  = 0.125;
3239                     const GLdouble alpha = 1.0; /* This value has special meaning for some internal_formats */
3240 
3241                     Utils::packPixel(internal_format, type, red, green, blue, alpha, pixel);
3242                 }
3243             }
3244         }
3245     }
3246 }
3247 
3248 /** Prepare test cases for given targets and internal formats
3249  *
3250  * @param dst_internal_format Internal format of destination image
3251  * @param dst_target          Target of destination image
3252  * @param src_internal_format Internal format of source image
3253  * @param src_target          Target of source image
3254  **/
prepareTestCases(GLenum dst_internal_format,GLenum dst_target,GLenum src_internal_format,GLenum src_target)3255 void FunctionalTest::prepareTestCases(GLenum dst_internal_format, GLenum dst_target, GLenum src_internal_format,
3256                                       GLenum src_target)
3257 {
3258     static const GLuint image_dimmensions[] = {
3259         7,
3260 #if COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_IMG_DIM
3261         8,
3262         9,
3263         10,
3264         11,
3265         12,
3266         13,
3267         14,
3268 #endif /* COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_IMG_DIM */
3269         15
3270     };
3271 
3272     static const GLuint region_dimmensions[] = {
3273         1,
3274 #if COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_REG_DIM
3275         2,
3276         3,
3277         4,
3278         5,
3279         6,
3280 #endif /* COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_REG_DIM */
3281         7
3282     };
3283 
3284     static const GLuint n_image_dimmensions  = sizeof(image_dimmensions) / sizeof(image_dimmensions[0]);
3285     static const GLuint n_region_dimmensions = sizeof(region_dimmensions) / sizeof(region_dimmensions[0]);
3286 
3287     const bool is_dst_multi_level = Utils::isTargetMultilevel(dst_target);
3288     const bool is_src_multi_level = Utils::isTargetMultilevel(src_target);
3289     const GLenum dst_format       = Utils::getFormat(dst_internal_format);
3290     const GLuint dst_n_levels     = (true == is_dst_multi_level) ? FUNCTIONAL_TEST_N_LEVELS : 1;
3291     const GLenum dst_type         = Utils::getType(dst_internal_format);
3292     const GLenum src_format       = Utils::getFormat(src_internal_format);
3293     const GLuint src_n_levels     = (true == is_src_multi_level) ? FUNCTIONAL_TEST_N_LEVELS : 1;
3294     const GLenum src_type         = Utils::getType(src_internal_format);
3295 
3296     for (GLuint src_level = 0; src_level < src_n_levels; ++src_level)
3297     {
3298         for (GLuint dst_level = 0; dst_level < dst_n_levels; ++dst_level)
3299         {
3300             for (GLuint src_img_dim_id = 0; src_img_dim_id < n_image_dimmensions; ++src_img_dim_id)
3301             {
3302                 const GLuint src_image_dimmension = image_dimmensions[src_img_dim_id];
3303 
3304                 for (GLuint dst_img_dim_id = 0; dst_img_dim_id < n_image_dimmensions; ++dst_img_dim_id)
3305                 {
3306                     const GLuint dst_image_dimmension = image_dimmensions[dst_img_dim_id];
3307 
3308                     for (GLuint reg_dim_id = 0; reg_dim_id < n_region_dimmensions; ++reg_dim_id)
3309                     {
3310                         const GLuint region_dimmension = region_dimmensions[reg_dim_id];
3311                         GLuint dst_coord[3]            = {0, 0, 0};
3312                         const GLuint dst_dim_diff      = dst_image_dimmension - region_dimmension;
3313                         GLuint n_dst_coords            = 1;
3314 #if COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_REG_POS
3315                         GLuint n_src_coords = 1;
3316 #endif /* COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_REG_POS */
3317                         GLuint src_coord[3]       = {0, 0, 0};
3318                         const GLuint src_dim_diff = src_image_dimmension - region_dimmension;
3319 
3320                         /* Calculate coords */
3321                         if (1 == dst_dim_diff)
3322                         {
3323                             dst_coord[1] = 1;
3324                             n_dst_coords = 2;
3325                         }
3326                         else if (1 < dst_dim_diff)
3327                         {
3328                             dst_coord[1] = dst_dim_diff / 2;
3329                             dst_coord[2] = dst_dim_diff;
3330                             n_dst_coords = 3;
3331                         }
3332 
3333                         if (1 == src_dim_diff)
3334                         {
3335                             src_coord[1] = 1;
3336 #if COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_REG_POS
3337                             n_src_coords = 2;
3338 #endif /* COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_REG_POS */
3339                         }
3340                         else if (1 < src_dim_diff)
3341                         {
3342                             src_coord[1] = src_dim_diff / 2;
3343                             src_coord[2] = src_dim_diff;
3344 #if COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_REG_POS
3345                             n_src_coords = 3;
3346 #endif /* COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_REG_POS */
3347                         }
3348 
3349                         testCase test_case = {
3350                             {                                  /* m_dst */
3351                              dst_target, dst_image_dimmension, /* width */
3352                              dst_image_dimmension,             /* height */
3353                              dst_level, dst_internal_format, dst_format, dst_type},
3354                             0,                                 /* dst_x */
3355                             0,                                 /* dst_y */
3356                             {                                  /* m_src */
3357                              src_target, src_image_dimmension, /* width */
3358                              src_image_dimmension,             /* height */
3359                              src_level, src_internal_format, src_format, src_type},
3360                             0,                 /* src_x */
3361                             0,                 /* src_y */
3362                             region_dimmension, /* width */
3363                             region_dimmension, /* height */
3364                         };
3365 
3366 #if COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_REG_POS
3367                         for (GLuint src_x = 0; src_x < n_src_coords; ++src_x)
3368                         {
3369                             for (GLuint src_y = 0; src_y < n_src_coords; ++src_y)
3370                             {
3371                                 for (GLuint dst_x = 0; dst_x < n_dst_coords; ++dst_x)
3372                                 {
3373                                     for (GLuint dst_y = 0; dst_y < n_dst_coords; ++dst_y)
3374                                     {
3375                                         test_case.m_dst_x = dst_coord[dst_x];
3376                                         test_case.m_dst_y = dst_coord[dst_y];
3377                                         test_case.m_src_x = src_coord[src_x];
3378                                         test_case.m_src_y = src_coord[src_y];
3379 
3380                                         m_test_cases.push_back(test_case);
3381                                     }
3382                                 }
3383                             }
3384                         }
3385 #else  /* COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_REG_POS */
3386                         test_case.m_dst_x = dst_coord[n_dst_coords - 1];
3387                         test_case.m_dst_y = dst_coord[n_dst_coords - 1];
3388                         test_case.m_src_x = src_coord[0];
3389                         test_case.m_src_y = src_coord[0];
3390 
3391                         m_test_cases.push_back(test_case);
3392 #endif /* COPY_IMAGE_FUNCTIONAL_TEST_ENABLE_ALL_REG_POS */
3393 
3394                         /* Whole image, for non 7x7 */
3395                         if ((dst_image_dimmension == src_image_dimmension) &&
3396                             (image_dimmensions[0] != dst_image_dimmension))
3397                         {
3398                             test_case.m_dst_x  = 0;
3399                             test_case.m_dst_y  = 0;
3400                             test_case.m_src_x  = 0;
3401                             test_case.m_src_y  = 0;
3402                             test_case.m_width  = dst_image_dimmension;
3403                             test_case.m_height = dst_image_dimmension;
3404 
3405                             m_test_cases.push_back(test_case);
3406                         }
3407                     }
3408                 }
3409             }
3410         }
3411     }
3412 }
3413 
3414 /** Prepare texture
3415  *
3416  * @param desc       Descriptor
3417  * @param pixels     Image data
3418  * @param out_buf_id Id of buffer used by texture buffer
3419  *
3420  * @return Name of iamge
3421  **/
prepareTexture(const targetDesc & desc,const GLubyte ** pixels,GLuint & out_buf_id)3422 GLuint FunctionalTest::prepareTexture(const targetDesc &desc, const GLubyte **pixels, GLuint &out_buf_id)
3423 {
3424     GLuint name = Utils::generateTexture(m_context, desc.m_target);
3425 
3426     if (false == Utils::isTargetMultilevel(desc.m_target))
3427     {
3428         Utils::prepareTexture(m_context, name, desc.m_target, desc.m_internal_format, desc.m_format, desc.m_type,
3429                               0 /* level */, desc.m_width, desc.m_height,
3430                               FUNCTIONAL_TEST_N_LAYERS /* depth - 12 for multilayered, 1D and 2D will ignore that */,
3431                               pixels[0], out_buf_id);
3432 
3433         Utils::makeTextureComplete(m_context, desc.m_target, name, 0 /* base */, 0 /* max */);
3434     }
3435     else
3436     {
3437         /* Calculate dimmensions */
3438         GLuint heights[FUNCTIONAL_TEST_N_LEVELS];
3439         GLuint widths[FUNCTIONAL_TEST_N_LEVELS];
3440         GLuint depths[FUNCTIONAL_TEST_N_LEVELS];
3441 
3442         calculateDimmensions(desc.m_target, desc.m_level, desc.m_width, desc.m_height, widths, heights, depths);
3443 
3444         for (GLuint level = 0; level < FUNCTIONAL_TEST_N_LEVELS; ++level)
3445         {
3446             Utils::prepareTexture(m_context, name, desc.m_target, desc.m_internal_format, desc.m_format, desc.m_type,
3447                                   level, widths[level], heights[level], depths[level], pixels[level], out_buf_id);
3448 
3449             Utils::makeTextureComplete(m_context, desc.m_target, name, 0 /* base */, 2 /* max */);
3450         }
3451     }
3452 
3453     return name;
3454 }
3455 
3456 /** Verify copy operation
3457  *
3458  * @param test_case  Test case
3459  * @param dst_layer  First layer modified by copy
3460  * @param dst_pixels Origiranl data of destination image
3461  * @param src_layer  First layer read by copy
3462  * @param src_pixels Original data of source image
3463  * @param depth      Number of copied layers
3464  *
3465  * @return true if everything is as expected, false otherwise
3466  **/
verify(const testCase & test_case,GLuint dst_layer,const GLubyte ** dst_pixels,GLuint src_layer,const GLubyte ** src_pixels,GLuint depth)3467 bool FunctionalTest::verify(const testCase &test_case, GLuint dst_layer, const GLubyte **dst_pixels, GLuint src_layer,
3468                             const GLubyte **src_pixels, GLuint depth)
3469 {
3470     const bool is_dst_multi_level = Utils::isTargetMultilevel(test_case.m_dst.m_target);
3471     const bool is_src_multi_level = Utils::isTargetMultilevel(test_case.m_src.m_target);
3472     const GLuint dst_level        = test_case.m_dst.m_level;
3473     std::vector<GLubyte> dst_level_data;
3474     const GLuint dst_pixel_size = Utils::getPixelSizeForFormat(test_case.m_dst.m_internal_format);
3475     targetDesc src_desc         = test_case.m_src;
3476     const GLuint src_level      = src_desc.m_level;
3477     std::vector<GLubyte> src_level_data;
3478     const GLuint src_pixel_size = Utils::getPixelSizeForFormat(src_desc.m_internal_format);
3479 
3480     if (0 != m_rb_name)
3481     {
3482         src_desc.m_target = GL_TEXTURE_2D;
3483     }
3484 
3485     /* Calculate storage requirements */
3486     GLuint dst_req_mem_per_layer[FUNCTIONAL_TEST_N_LEVELS];
3487     GLuint dst_heights[FUNCTIONAL_TEST_N_LEVELS];
3488     GLuint dst_widths[FUNCTIONAL_TEST_N_LEVELS];
3489     GLuint dst_depths[FUNCTIONAL_TEST_N_LEVELS];
3490     GLuint src_req_mem_per_layer[FUNCTIONAL_TEST_N_LEVELS];
3491     GLuint src_heights[FUNCTIONAL_TEST_N_LEVELS];
3492     GLuint src_widths[FUNCTIONAL_TEST_N_LEVELS];
3493     GLuint src_depths[FUNCTIONAL_TEST_N_LEVELS];
3494 
3495     calculateDimmensions(test_case.m_dst.m_target, dst_level, test_case.m_dst.m_width, test_case.m_dst.m_height,
3496                          dst_widths, dst_heights, dst_depths);
3497 
3498     calculateDimmensions(src_desc.m_target, src_level, src_desc.m_width, src_desc.m_height, src_widths, src_heights,
3499                          src_depths);
3500 
3501     for (GLuint i = 0; i < FUNCTIONAL_TEST_N_LEVELS; ++i)
3502     {
3503         dst_req_mem_per_layer[i] = dst_widths[i] * dst_heights[i] * dst_pixel_size;
3504         src_req_mem_per_layer[i] = src_widths[i] * src_heights[i] * src_pixel_size;
3505     }
3506 
3507     /* Prepare storage, use 0 level as it is the biggest one */
3508     dst_level_data.resize(dst_req_mem_per_layer[0] * dst_depths[0]);
3509     src_level_data.resize(src_req_mem_per_layer[0] * src_depths[0]);
3510 
3511     /* Verification of contents
3512      * - source image                                           - expect no modification
3513      * - destination image, mipmap before and after dst_level   - expect no modification
3514      * - destination image, mipmap at dst_level:
3515      *   * layers after dst_layer + depth                       - expect no modification
3516      *   * layers <0, dst_layer + depth>                        - expect that contents at selected region were copied
3517      */
3518 
3519     /* Check if source image was not modified */
3520     {
3521         const GLuint n_levels = (true == is_src_multi_level) ? FUNCTIONAL_TEST_N_LEVELS : 1;
3522 
3523         for (GLuint level = 0; level < n_levels; ++level)
3524         {
3525             getPixels(m_src_tex_name, src_desc, level, &src_level_data[0]);
3526 
3527             for (GLuint layer = 0; layer < src_depths[level]; ++layer)
3528             {
3529                 if (false == compareImages(src_desc, src_pixels[level], 0, 0, layer, level, src_desc,
3530                                            &src_level_data[0], 0, 0, layer, level, src_widths[level],
3531                                            src_heights[level]))
3532                 {
3533                     m_context.getTestContext().getLog()
3534                         << tcu::TestLog::Message
3535                         << "CopyImageSubData modified contents of source image. Original data: left."
3536                         << tcu::TestLog::EndMessage;
3537                     return false;
3538                 }
3539             }
3540         }
3541     }
3542 
3543     /* Check if contents of destination at levels != dst_level were not modified */
3544     {
3545         const GLuint n_levels = (true == is_dst_multi_level) ? FUNCTIONAL_TEST_N_LEVELS : 1;
3546 
3547         for (GLuint level = 0; level < n_levels; ++level)
3548         {
3549             if (dst_level == level)
3550             {
3551                 continue;
3552             }
3553 
3554             getPixels(m_dst_tex_name, test_case.m_dst, level, &dst_level_data[0]);
3555 
3556             for (GLuint layer = 0; layer < dst_depths[level]; ++layer)
3557             {
3558                 if (false == compareImages(test_case.m_dst, dst_pixels[level], 0, 0, layer, level, test_case.m_dst,
3559                                            &dst_level_data[0], 0, 0, layer, level, dst_widths[level],
3560                                            dst_heights[level]))
3561                 {
3562                     m_context.getTestContext().getLog()
3563                         << tcu::TestLog::Message
3564                         << "CopyImageSubData modified contents of wrong mipmap level. Original data: left."
3565                         << tcu::TestLog::EndMessage;
3566 
3567                     return false;
3568                 }
3569             }
3570         }
3571     }
3572 
3573     /* Check contents of modified level */
3574     {
3575         getPixels(m_dst_tex_name, test_case.m_dst, dst_level, &dst_level_data[0]);
3576 
3577         /* Check anything after dst_layer + depth */
3578         {
3579             for (GLuint layer = dst_layer + depth; layer < dst_depths[dst_level]; ++layer)
3580             {
3581                 if (false == compareImages(test_case.m_dst, dst_pixels[dst_level], 0, 0, layer, dst_level,
3582                                            test_case.m_dst, &dst_level_data[0], 0, 0, layer, dst_level,
3583                                            dst_widths[dst_level], dst_heights[dst_level]))
3584                 {
3585                     m_context.getTestContext().getLog()
3586                         << tcu::TestLog::Message
3587                         << "CopyImageSubData modified contents of wrong layer. Original data: left."
3588                         << tcu::TestLog::EndMessage;
3589 
3590                     return false;
3591                 }
3592             }
3593         }
3594 
3595         /* Check modified layers */
3596         for (GLuint layer = 0; layer < depth; ++layer)
3597         {
3598             /* Check contents outside of copied region */
3599             {
3600                 GLuint n_regions     = 0;
3601                 GLuint regions[4][4] = {{0}};
3602 
3603                 getCleanRegions(test_case, dst_level, regions, n_regions);
3604 
3605                 for (GLuint region = 0; region < n_regions; ++region)
3606                 {
3607                     const GLuint x = regions[region][0];
3608                     const GLuint y = regions[region][1];
3609                     const GLuint w = regions[region][2];
3610                     const GLuint h = regions[region][3];
3611 
3612                     if (false == compareImages(test_case.m_dst, dst_pixels[dst_level], x, y, layer + dst_layer,
3613                                                dst_level, test_case.m_dst, &dst_level_data[0], x, y, layer + dst_layer,
3614                                                dst_level, w, h))
3615                     {
3616                         m_context.getTestContext().getLog()
3617                             << tcu::TestLog::Message
3618                             << "CopyImageSubData modified contents outside of copied region. Original data: left."
3619                             << tcu::TestLog::EndMessage;
3620                         return false;
3621                     }
3622                 }
3623             }
3624 
3625             /* Check contents of copied region */
3626             if (false == compareImages(test_case.m_dst, &dst_level_data[0], test_case.m_dst_x, test_case.m_dst_y,
3627                                        layer + dst_layer, dst_level, src_desc, src_pixels[src_level], test_case.m_src_x,
3628                                        test_case.m_src_y, layer + src_layer, src_level, test_case.m_width,
3629                                        test_case.m_height))
3630             {
3631                 m_context.getTestContext().getLog()
3632                     << tcu::TestLog::Message
3633                     << "CopyImageSubData stored invalid data in copied region. Destination data: left."
3634                     << tcu::TestLog::EndMessage;
3635                 return false;
3636             }
3637         }
3638     }
3639 
3640     return true;
3641 }
3642 
3643 /* SmokeTest */
3644 /* Constants */
3645 const GLuint SmokeTest::m_width  = 16;
3646 const GLuint SmokeTest::m_height = 16;
3647 const GLuint SmokeTest::m_depth  = 1;
3648 
3649 /** Constructor
3650  *
3651  * @param context Text context
3652  **/
SmokeTest(deqp::Context & context)3653 SmokeTest::SmokeTest(deqp::Context &context)
3654     : TestCase(context, "smoke_test", "Test tries all formats and targets")
3655     , m_dst_buf_name(0)
3656     , m_dst_tex_name(0)
3657     , m_rb_name(0)
3658     , m_src_buf_name(0)
3659     , m_src_tex_name(0)
3660     , m_test_case_index(0)
3661 {
3662     /* Iterate over valid targets */
3663     for (GLuint tgt_id = 0; tgt_id < s_n_valid_targets; ++tgt_id)
3664     {
3665         const GLenum target = s_valid_targets[tgt_id];
3666 
3667         if (true == Utils::isTargetMultisampled(target))
3668         {
3669             continue;
3670         }
3671 
3672         const testCase test_case = {target, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT};
3673 
3674         m_test_cases.push_back(test_case);
3675     }
3676 
3677     /* Iterate over internal formats */
3678     for (GLuint fmt_id = 0; fmt_id < s_n_internal_formats; ++fmt_id)
3679     {
3680         const GLenum internal_format = s_internal_formats[fmt_id];
3681         const GLenum format          = Utils::getFormat(internal_format);
3682         const GLenum type            = Utils::getType(internal_format);
3683 
3684         const testCase test_case = {GL_TEXTURE_2D, internal_format, format, type};
3685 
3686         m_test_cases.push_back(test_case);
3687     }
3688 }
3689 
3690 /** Cleans resources
3691  *
3692  **/
clean()3693 void SmokeTest::clean()
3694 {
3695     const Functions &gl = m_context.getRenderContext().getFunctions();
3696 
3697     /* Clean textures and buffers. Errors ignored */
3698     gl.deleteTextures(1, &m_dst_tex_name);
3699     gl.deleteTextures(1, &m_src_tex_name);
3700 
3701     m_dst_tex_name = 0;
3702     m_src_tex_name = 0;
3703 
3704     if (0 != m_dst_buf_name)
3705     {
3706         gl.deleteBuffers(1, &m_dst_buf_name);
3707         m_dst_buf_name = 0;
3708     }
3709 
3710     if (0 != m_rb_name)
3711     {
3712         gl.deleteRenderbuffers(1, &m_rb_name);
3713         m_rb_name = 0;
3714     }
3715 
3716     if (0 != m_src_buf_name)
3717     {
3718         gl.deleteBuffers(1, &m_src_buf_name);
3719         m_src_buf_name = 0;
3720     }
3721 }
3722 
3723 /** Free memory allocated for images
3724  *
3725  * @param pixels Pointers to image data
3726  **/
cleanPixels(GLubyte * & pixels) const3727 void SmokeTest::cleanPixels(GLubyte *&pixels) const
3728 {
3729     if (0 == pixels)
3730     {
3731         return;
3732     }
3733 
3734     delete[] pixels;
3735     pixels = 0;
3736 }
3737 
3738 /** Compare two images
3739  * @param test_case     Test case descriptor
3740  * @param left_data     Data of left image
3741  * @param right_data    Data of right image
3742  *
3743  * @return true if images are considered idenctial, false otherwise
3744  **/
compareImages(const testCase & test_case,const GLubyte * left_data,const GLubyte * right_data) const3745 bool SmokeTest::compareImages(const testCase &test_case, const GLubyte *left_data, const GLubyte *right_data) const
3746 {
3747     /* Constants */
3748     /* Sizes */
3749     const GLuint pixel_size = Utils::getPixelSizeForFormat(test_case.m_internal_format);
3750     const GLuint line_size  = pixel_size * m_width;
3751 
3752     GLuint height = m_height;
3753 
3754     if ((GL_TEXTURE_1D == test_case.m_target) || (GL_TEXTURE_1D_ARRAY == test_case.m_target))
3755     {
3756         height = 1;
3757     }
3758 
3759     /* For each line */
3760     for (GLuint y = 0; y < height; ++y)
3761     {
3762         /* Offsets */
3763         const GLuint line_offset = y * line_size;
3764 
3765         /* Pointers */
3766         const GLubyte *left_line_data  = left_data + line_offset;
3767         const GLubyte *right_line_data = right_data + line_offset;
3768 
3769         /* For each pixel of region */
3770         for (GLuint x = 0; x < m_width; ++x)
3771         {
3772             /* Offsets */
3773             const GLuint pixel_offset = x * pixel_size;
3774 
3775             /* Pointers */
3776             const GLubyte *left_pixel_data  = left_line_data + pixel_offset;
3777             const GLubyte *right_pixel_data = right_line_data + pixel_offset;
3778 
3779             /* Compare */
3780             if (false == Utils::comparePixels(pixel_size, left_pixel_data, pixel_size, right_pixel_data))
3781             {
3782                 if (false == Utils::unpackAndComaprePixels(
3783                                  test_case.m_format, test_case.m_type, test_case.m_internal_format, left_pixel_data,
3784                                  test_case.m_format, test_case.m_type, test_case.m_internal_format, right_pixel_data))
3785                 {
3786                     m_context.getTestContext().getLog()
3787                         << tcu::TestLog::Message << "Not matching pixels found. "
3788                         << "[" << x << ", " << y << "], off: " << left_pixel_data - left_data
3789                         << ". Data left: " << Utils::getPixelString(test_case.m_internal_format, left_pixel_data)
3790                         << ", right: " << Utils::getPixelString(test_case.m_internal_format, right_pixel_data)
3791                         << tcu::TestLog::EndMessage;
3792 
3793                     return false;
3794                 }
3795             }
3796         }
3797     }
3798 
3799     return true;
3800 }
3801 
3802 /** Execute copyImageSubData for given test case and verify results
3803  *
3804  * @param test_case  Test case
3805  * @param src_pixels Data of source image
3806  *
3807  * @return true if there is no error and results match expectations, false otherwise
3808  **/
copyAndVerify(const testCase & test_case,const GLubyte * src_pixels)3809 bool SmokeTest::copyAndVerify(const testCase &test_case, const GLubyte *src_pixels)
3810 {
3811     GLenum error        = GL_NO_ERROR;
3812     const Functions &gl = m_context.getRenderContext().getFunctions();
3813     bool result         = false;
3814 
3815     /* Copy and verification */
3816     {
3817         if (0 == m_rb_name)
3818         {
3819             GLuint height = m_height;
3820 
3821             if ((GL_TEXTURE_1D == test_case.m_target) || (GL_TEXTURE_1D_ARRAY == test_case.m_target))
3822             {
3823                 height = 1;
3824             }
3825 
3826             gl.copyImageSubData(m_src_tex_name, test_case.m_target, 0 /* srcLevel */, 0 /* srcX */, 0 /* srcY */,
3827                                 0 /* srcZ */, m_dst_tex_name, test_case.m_target, 0 /* dstLevel */, 0 /* dstX */,
3828                                 0 /* dstY */, 0 /* dstZ */, m_width, height, m_depth);
3829         }
3830         else /* Copy from src to rb and from rb to dst */
3831         {
3832             /* Src and rb shares differs only on target */
3833             gl.copyImageSubData(m_src_tex_name, GL_TEXTURE_2D, 0 /* srcLevel */, 0 /* srcX */, 0 /* srcY */,
3834                                 0 /* srcZ */, m_rb_name, test_case.m_target, 0 /* dstLevel */, 0 /* dstX */,
3835                                 0 /* dstY */, 0 /* dstZ */, m_width, m_height, m_depth);
3836 
3837             gl.copyImageSubData(m_rb_name, test_case.m_target, 0 /* dstLevel */, 0 /* dstX */, 0 /* dstY */,
3838                                 0 /* dstZ */, m_dst_tex_name, GL_TEXTURE_2D, 0 /* dstLevel */, 0 /* dstX */,
3839                                 0 /* dstY */, 0 /* dstZ */, m_width, m_height, m_depth);
3840         }
3841 
3842         /* Verify generated error */
3843         error = gl.getError();
3844 
3845         if (GL_NO_ERROR == error)
3846         {
3847             /* Verify copy results */
3848             result = verify(test_case, src_pixels);
3849         }
3850 
3851         if ((GL_NO_ERROR != error) || (false == result))
3852         {
3853             m_context.getTestContext().getLog()
3854                 << tcu::TestLog::Message << "Failure. Target: " << glu::getTextureTargetStr(test_case.m_target)
3855                 << ". Format: " << glu::getInternalFormatParameterStr(test_case.m_internal_format)
3856                 << tcu::TestLog::EndMessage;
3857 
3858             if (GL_NO_ERROR != error)
3859             {
3860                 m_context.getTestContext().getLog()
3861                     << tcu::TestLog::Message << "Failed due to error: " << glu::getErrorStr(error)
3862                     << tcu::TestLog::EndMessage;
3863 
3864                 TCU_FAIL("Copy operation failed");
3865             }
3866 
3867             return false;
3868         }
3869     }
3870 
3871     return true;
3872 }
3873 
3874 /** Get pixel data for image
3875  *
3876  * @param name       Name of image
3877  * @param test_case  Test case descriptor
3878  * @param out_pixels Pixels
3879  **/
getPixels(GLuint name,const SmokeTest::testCase & test_case,GLubyte * out_pixels) const3880 void SmokeTest::getPixels(GLuint name, const SmokeTest::testCase &test_case, GLubyte *out_pixels) const
3881 {
3882     const Functions &gl = m_context.getRenderContext().getFunctions();
3883     GLenum tgt_bind     = test_case.m_target;
3884     GLenum tgt_get      = test_case.m_target;
3885 
3886     if (GL_RENDERBUFFER == test_case.m_target)
3887     {
3888         tgt_bind = GL_TEXTURE_2D;
3889         tgt_get  = GL_TEXTURE_2D;
3890     }
3891     else if (GL_TEXTURE_CUBE_MAP == test_case.m_target)
3892     {
3893         tgt_get = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
3894     }
3895 
3896     gl.bindTexture(tgt_bind, name);
3897     GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
3898 
3899     gl.getTexImage(tgt_get, 0 /* level */, test_case.m_format, test_case.m_type, out_pixels);
3900     GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
3901 
3902     gl.bindTexture(tgt_bind, 0);
3903     GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
3904 }
3905 
3906 /** Execute test
3907  *
3908  * @return CONTINUE as long there are more test case, STOP otherwise
3909  **/
iterate()3910 tcu::TestNode::IterateResult SmokeTest::iterate()
3911 {
3912     GLubyte *dst_pixels                    = 0;
3913     const Functions &gl                    = m_context.getRenderContext().getFunctions();
3914     tcu::TestNode::IterateResult it_result = tcu::TestNode::STOP;
3915     bool result                            = false;
3916     GLubyte *src_pixels                    = 0;
3917     const testCase &test_case              = m_test_cases[m_test_case_index];
3918 
3919     gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
3920     gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
3921     GLU_EXPECT_NO_ERROR(gl.getError(), "PixelStorei");
3922 
3923     try
3924     {
3925         /* Prepare pixels */
3926         prepareDstPxls(test_case, dst_pixels);
3927         prepareSrcPxls(test_case, src_pixels);
3928 
3929         /* Prepare textures */
3930         if (GL_RENDERBUFFER == test_case.m_target)
3931         {
3932             testCase desc  = test_case;
3933             GLuint ignored = 0;
3934 
3935             desc.m_target = GL_TEXTURE_2D;
3936 
3937             m_rb_name      = prepareTexture(test_case, 0 /* pixels */, ignored /* buffer name */);
3938             m_dst_tex_name = prepareTexture(desc, dst_pixels, m_dst_buf_name);
3939             m_src_tex_name = prepareTexture(desc, src_pixels, m_src_buf_name);
3940         }
3941         else
3942         {
3943             m_dst_tex_name = prepareTexture(test_case, dst_pixels, m_dst_buf_name);
3944             m_src_tex_name = prepareTexture(test_case, src_pixels, m_src_buf_name);
3945         }
3946 
3947         /* Copy images and verify results */
3948         result = copyAndVerify(test_case, src_pixels);
3949     }
3950     catch (tcu::Exception &exc)
3951     {
3952         clean();
3953         cleanPixels(dst_pixels);
3954         cleanPixels(src_pixels);
3955         throw exc;
3956     }
3957 
3958     /* Free resources */
3959     clean();
3960     cleanPixels(dst_pixels);
3961     cleanPixels(src_pixels);
3962 
3963     /* Set result */
3964     if (true == result)
3965     {
3966         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3967 
3968         /* Increase index */
3969         m_test_case_index += 1;
3970 
3971         /* Are there any test cases left */
3972         if (m_test_cases.size() > m_test_case_index)
3973         {
3974             it_result = tcu::TestNode::CONTINUE;
3975         }
3976     }
3977     else
3978     {
3979         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failure. " << tcu::TestLog::EndMessage;
3980 
3981         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3982     }
3983 
3984     /* Done */
3985     return it_result;
3986 }
3987 
3988 /** Prepare data for destination image
3989  *
3990  * @param test_case  Test case descriptor
3991  * @param out_pixels Pointer to image data
3992  **/
prepareDstPxls(const SmokeTest::testCase & test_case,GLubyte * & out_pixels) const3993 void SmokeTest::prepareDstPxls(const SmokeTest::testCase &test_case, GLubyte *&out_pixels) const
3994 {
3995     static const GLuint n_pixels_per_layer = m_width * m_height;
3996 
3997     const GLenum internal_format = test_case.m_internal_format;
3998     const GLuint n_layers        = (GL_TEXTURE_CUBE_MAP_ARRAY != test_case.m_target) ? m_depth : 6;
3999     const GLuint n_pixels        = n_pixels_per_layer * n_layers;
4000     const GLuint pixel_size      = Utils::getPixelSizeForFormat(internal_format);
4001     const GLuint req_memory      = pixel_size * n_pixels;
4002     const GLenum type            = test_case.m_type;
4003 
4004     /* Prepare storage */
4005     out_pixels = new GLubyte[req_memory];
4006 
4007     if (0 == out_pixels)
4008     {
4009         TCU_FAIL("Memory allocation failed");
4010     }
4011 
4012     memset(out_pixels, 0, req_memory);
4013 
4014     /* Fill pixels */
4015     for (GLuint j = 0; j < n_pixels; ++j)
4016     {
4017         GLubyte *pixel_data = out_pixels + j * pixel_size;
4018 
4019         Utils::packPixel(internal_format, type, 1.0, 1.0, 1.0, 1.0, pixel_data);
4020     }
4021 }
4022 
4023 /** Prepare data for source image
4024  *
4025  * @param test_case  Test case descriptor
4026  * @param out_pixels Pointer to image data
4027  **/
prepareSrcPxls(const SmokeTest::testCase & test_case,GLubyte * & out_pixels) const4028 void SmokeTest::prepareSrcPxls(const SmokeTest::testCase &test_case, GLubyte *&out_pixels) const
4029 {
4030     static const GLuint n_pixels_per_layer = m_width * m_height;
4031 
4032     const GLenum internal_format = test_case.m_internal_format;
4033     const GLuint n_layers        = (GL_TEXTURE_CUBE_MAP_ARRAY != test_case.m_target) ? m_depth : 6;
4034     const GLuint n_pixels        = n_pixels_per_layer * n_layers;
4035     const GLuint pixel_size      = Utils::getPixelSizeForFormat(internal_format);
4036     const GLuint layer_size      = pixel_size * n_pixels_per_layer;
4037     const GLuint line_size       = pixel_size * m_width;
4038     const GLuint req_memory      = pixel_size * n_pixels;
4039     const GLenum type            = test_case.m_type;
4040 
4041     /* Prepare storage */
4042     out_pixels = new GLubyte[req_memory];
4043 
4044     if (0 == out_pixels)
4045     {
4046         TCU_FAIL("Memory allocation failed");
4047     }
4048 
4049     memset(out_pixels, 0, req_memory);
4050 
4051     /* Fill pixels */
4052     for (GLuint layer = 0; layer < n_layers; ++layer)
4053     {
4054         const GLuint layer_offset = layer * layer_size;
4055 
4056         GLubyte *layer_data = out_pixels + layer_offset;
4057 
4058         for (GLuint y = 0; y < m_height; ++y)
4059         {
4060             const GLuint line_offset = line_size * y;
4061 
4062             GLubyte *line_data = layer_data + line_offset;
4063 
4064             for (GLuint x = 0; x < m_width; ++x)
4065             {
4066                 const GLuint pixel_offset = x * pixel_size;
4067 
4068                 GLubyte *pixel_data = line_data + pixel_offset;
4069 
4070                 /* 255 is max ubyte. 1/15.9375 = 16/255 */
4071                 const GLdouble red   = ((GLdouble)x) / 255.0 + (((GLdouble)y) / 15.9375);
4072                 const GLdouble green = ((GLdouble)layer) / 255.0 + (1.0 / 15.9375);
4073                 const GLdouble blue  = 0.125;
4074                 const GLdouble alpha = 1.0; /* This value has special meaning for some internal_formats */
4075 
4076                 Utils::packPixel(internal_format, type, red, green, blue, alpha, pixel_data);
4077             }
4078         }
4079     }
4080 }
4081 
4082 /** Prepare texture
4083  *
4084  * @param desc       Descriptor
4085  * @param pixels     Image data
4086  * @param out_buf_id Id of buffer used by texture buffer
4087  *
4088  * @return Name of iamge
4089  **/
prepareTexture(const testCase & test_case,const GLubyte * pixels,GLuint & out_buf_id)4090 GLuint SmokeTest::prepareTexture(const testCase &test_case, const GLubyte *pixels, GLuint &out_buf_id)
4091 {
4092     const GLuint n_layers = (GL_TEXTURE_CUBE_MAP_ARRAY != test_case.m_target) ? m_depth : 6;
4093     GLuint name           = Utils::generateTexture(m_context, test_case.m_target);
4094 
4095     Utils::prepareTexture(m_context, name, test_case.m_target, test_case.m_internal_format, test_case.m_format,
4096                           test_case.m_type, 0 /* level */, m_width, m_height, n_layers, pixels, out_buf_id);
4097 
4098     Utils::makeTextureComplete(m_context, test_case.m_target, name, 0 /* base */, 0 /* max */);
4099 
4100     return name;
4101 }
4102 
4103 /** Verify copy operation
4104  *
4105  * @param test_case  Test case
4106  * @param src_pixels Original data of source image
4107  *
4108  * @return true if everything is as expected, false otherwise
4109  **/
verify(const testCase & test_case,const GLubyte * src_pixels)4110 bool SmokeTest::verify(const testCase &test_case, const GLubyte *src_pixels)
4111 {
4112     std::vector<GLubyte> dst_data;
4113     const GLuint n_layers   = (GL_TEXTURE_CUBE_MAP_ARRAY != test_case.m_target) ? m_depth : 6;
4114     const GLuint pixel_size = Utils::getPixelSizeForFormat(test_case.m_internal_format);
4115     const GLuint line_size  = pixel_size * m_width;
4116     const GLuint req_memory = line_size * m_height * n_layers;
4117     std::vector<GLubyte> src_data;
4118 
4119     /* Prepare storage */
4120     dst_data.resize(req_memory);
4121     src_data.resize(req_memory);
4122 
4123     /* Check if source image was not modified */
4124     {
4125         getPixels(m_src_tex_name, test_case, &src_data[0]);
4126 
4127         if (false == compareImages(test_case, src_pixels, &src_data[0]))
4128         {
4129             m_context.getTestContext().getLog()
4130                 << tcu::TestLog::Message << "CopyImageSubData modified contents of source image. Original data: left."
4131                 << tcu::TestLog::EndMessage;
4132             return false;
4133         }
4134     }
4135 
4136     /* Check contents of destination image */
4137     {
4138         getPixels(m_dst_tex_name, test_case, &dst_data[0]);
4139 
4140         if (false == compareImages(test_case, src_pixels, &dst_data[0]))
4141         {
4142             m_context.getTestContext().getLog()
4143                 << tcu::TestLog::Message
4144                 << "CopyImageSubData stored invalid contents in destination image. Source data: left."
4145                 << tcu::TestLog::EndMessage;
4146 
4147             return false;
4148         }
4149     }
4150 
4151     return true;
4152 }
4153 
4154 /* InvalidTargetTest */
4155 /** Constructor
4156  *
4157  * @param context Text context
4158  **/
InvalidTargetTest(deqp::Context & context)4159 InvalidTargetTest::InvalidTargetTest(deqp::Context &context)
4160     : TestCase(context, "invalid_target",
4161                "Test verifies if INVALID_ENUM is generated when invalid target is provided to CopyImageSubData")
4162     , m_dst_buf_name(0)
4163     , m_dst_tex_name(0)
4164     , m_src_buf_name(0)
4165     , m_src_tex_name(0)
4166     , m_test_case_index(0)
4167 {
4168 
4169     /* Valid source, valid dst */
4170     for (GLuint src = 0; src < s_n_valid_targets; ++src)
4171     {
4172         for (GLuint dst = 0; dst < s_n_valid_targets; ++dst)
4173         {
4174             const GLenum src_target = s_valid_targets[src];
4175             const GLenum dst_target = s_valid_targets[dst];
4176             testCase test_case      = {src_target, dst_target, GL_NO_ERROR};
4177 
4178             if (Utils::isTargetMultisampled(dst_target) != Utils::isTargetMultisampled(src_target))
4179             {
4180                 test_case.m_expected_result = GL_INVALID_OPERATION;
4181             }
4182 
4183             m_test_cases.push_back(test_case);
4184         }
4185     }
4186 
4187     /* Invalid source, invalid dst */
4188     for (GLuint src = 0; src < s_n_invalid_targets; ++src)
4189     {
4190         for (GLuint dst = 0; dst < s_n_invalid_targets; ++dst)
4191         {
4192             const GLenum src_target  = s_invalid_targets[src];
4193             const GLenum dst_target  = s_invalid_targets[dst];
4194             const testCase test_case = {src_target, dst_target, GL_INVALID_ENUM};
4195 
4196             m_test_cases.push_back(test_case);
4197         }
4198     }
4199 
4200     /* Invalid source, valid dst */
4201     for (GLuint src = 0; src < s_n_invalid_targets; ++src)
4202     {
4203         for (GLuint dst = 0; dst < s_n_valid_targets; ++dst)
4204         {
4205             const GLenum src_target  = s_invalid_targets[src];
4206             const GLenum dst_target  = s_valid_targets[dst];
4207             const testCase test_case = {src_target, dst_target, GL_INVALID_ENUM};
4208 
4209             m_test_cases.push_back(test_case);
4210         }
4211     }
4212 
4213     /* Valid source, invalid dst */
4214     for (GLuint src = 0; src < s_n_valid_targets; ++src)
4215     {
4216         for (GLuint dst = 0; dst < s_n_invalid_targets; ++dst)
4217         {
4218             const GLenum src_target  = s_valid_targets[src];
4219             const GLenum dst_target  = s_invalid_targets[dst];
4220             const testCase test_case = {src_target, dst_target, GL_INVALID_ENUM};
4221 
4222             m_test_cases.push_back(test_case);
4223         }
4224     }
4225 }
4226 
4227 /** Execute test
4228  *
4229  * @return CONTINUE as long there are more test case, STOP otherwise
4230  **/
iterate()4231 tcu::TestNode::IterateResult InvalidTargetTest::iterate()
4232 {
4233     GLenum error                           = GL_NO_ERROR;
4234     const Functions &gl                    = m_context.getRenderContext().getFunctions();
4235     tcu::TestNode::IterateResult it_result = tcu::TestNode::STOP;
4236     bool result                            = false;
4237     const testCase &test_case              = m_test_cases[m_test_case_index];
4238 
4239     try
4240     {
4241         /* Prepare textures */
4242         m_dst_tex_name = Utils::prepareTex16x16x6(m_context, test_case.m_dst_target, GL_RGBA8, GL_RGBA,
4243                                                   GL_UNSIGNED_BYTE, m_dst_buf_name);
4244         m_src_tex_name = Utils::prepareTex16x16x6(m_context, test_case.m_src_target, GL_RGBA8, GL_RGBA,
4245                                                   GL_UNSIGNED_BYTE, m_src_buf_name);
4246 
4247         /* Make textures complete */
4248         Utils::makeTextureComplete(m_context, test_case.m_dst_target, m_dst_tex_name, 0 /* base */, 0 /* max */);
4249         Utils::makeTextureComplete(m_context, test_case.m_src_target, m_src_tex_name, 0 /* base */, 0 /* max */);
4250     }
4251     catch (tcu::Exception &exc)
4252     {
4253         clean();
4254         throw exc;
4255     }
4256 
4257     /* Execute CopyImageSubData */
4258     gl.copyImageSubData(m_src_tex_name, test_case.m_src_target, 0 /* srcLevel */, 0 /* srcX */, 0 /* srcY */,
4259                         0 /* srcZ */, m_dst_tex_name, test_case.m_dst_target, 0 /* dstLevel */, 0 /* dstX */,
4260                         0 /* dstY */, 0 /* dstZ */, 1 /* srcWidth */, 1 /* srcHeight */, 1 /* srcDepth */);
4261 
4262     /* Verify generated error */
4263     error  = gl.getError();
4264     result = (test_case.m_expected_result == error);
4265 
4266     /* Free resources */
4267     clean();
4268 
4269     /* Set result */
4270     if (true == result)
4271     {
4272         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4273 
4274         /* Increase index */
4275         m_test_case_index += 1;
4276 
4277         /* Are there any test cases left */
4278         if (m_test_cases.size() > m_test_case_index)
4279         {
4280             it_result = tcu::TestNode::CONTINUE;
4281         }
4282     }
4283     else
4284     {
4285         m_context.getTestContext().getLog()
4286             << tcu::TestLog::Message << "Failure. Expected result: " << glu::getErrorStr(test_case.m_expected_result)
4287             << " got: " << glu::getErrorStr(error)
4288             << ". Source target: " << glu::getTextureTargetStr(test_case.m_src_target)
4289             << ", destination target: " << glu::getTextureTargetStr(test_case.m_dst_target) << tcu::TestLog::EndMessage;
4290 
4291         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4292     }
4293 
4294     /* Done */
4295     return it_result;
4296 }
4297 
4298 /** Cleans resources
4299  *
4300  **/
clean()4301 void InvalidTargetTest::clean()
4302 {
4303     const Functions &gl       = m_context.getRenderContext().getFunctions();
4304     const testCase &test_case = m_test_cases[m_test_case_index];
4305 
4306     /* Clean textures and buffers. Errors ignored */
4307     Utils::deleteTexture(m_context, test_case.m_dst_target, m_dst_tex_name);
4308     Utils::deleteTexture(m_context, test_case.m_src_target, m_src_tex_name);
4309 
4310     m_dst_tex_name = 0;
4311     m_src_tex_name = 0;
4312 
4313     if (0 != m_dst_buf_name)
4314     {
4315         gl.deleteBuffers(1, &m_dst_buf_name);
4316         m_dst_buf_name = 0;
4317     }
4318 
4319     if (0 != m_src_buf_name)
4320     {
4321         gl.deleteBuffers(1, &m_src_buf_name);
4322         m_src_buf_name = 0;
4323     }
4324 }
4325 
4326 /* TargetMismatchTest */
4327 /** Constructor
4328  *
4329  * @param context Text context
4330  **/
TargetMismatchTest(deqp::Context & context)4331 TargetMismatchTest::TargetMismatchTest(deqp::Context &context)
4332     : TestCase(
4333           context, "target_miss_match",
4334           "Test verifies if INVALID_ENUM is generated when target provided to CopyImageSubData does not match texture")
4335     , m_dst_buf_name(0)
4336     , m_dst_tex_name(0)
4337     , m_src_buf_name(0)
4338     , m_src_tex_name(0)
4339     , m_test_case_index(0)
4340 {
4341     /* Wrong dst target */
4342     for (GLuint target = 0; target < s_n_valid_targets; ++target)
4343     {
4344         for (GLuint dst = 0; dst < s_n_valid_targets; ++dst)
4345         {
4346             const GLenum dst_target = s_valid_targets[dst];
4347             const GLenum src_target = s_valid_targets[target];
4348             const GLenum tex_target = s_valid_targets[target];
4349             testCase test_case      = {tex_target, src_target, dst_target, GL_INVALID_ENUM};
4350 
4351             /* Skip renderbuffers */
4352             if ((GL_RENDERBUFFER == tex_target) || (GL_RENDERBUFFER == dst_target) || (GL_RENDERBUFFER == src_target))
4353             {
4354                 continue;
4355             }
4356 
4357             /* Valid case */
4358             if (dst_target == tex_target)
4359             {
4360                 test_case.m_expected_result = GL_NO_ERROR;
4361             }
4362 
4363             /* Skip cases with multisampling conflict */
4364             if (Utils::isTargetMultisampled(dst_target) != Utils::isTargetMultisampled(src_target))
4365             {
4366                 continue;
4367             }
4368 
4369             m_test_cases.push_back(test_case);
4370         }
4371     }
4372 
4373     /* Wrong src target */
4374     for (GLuint target = 0; target < s_n_valid_targets; ++target)
4375     {
4376         for (GLuint src = 0; src < s_n_valid_targets; ++src)
4377         {
4378             const GLenum dst_target = s_valid_targets[target];
4379             const GLenum src_target = s_valid_targets[src];
4380             const GLenum tex_target = s_valid_targets[target];
4381             testCase test_case      = {tex_target, src_target, dst_target, GL_INVALID_ENUM};
4382 
4383             /* Skip renderbuffers */
4384             if ((GL_RENDERBUFFER == tex_target) || (GL_RENDERBUFFER == dst_target) || (GL_RENDERBUFFER == src_target))
4385             {
4386                 continue;
4387             }
4388 
4389             /* Valid case */
4390             if (src_target == tex_target)
4391             {
4392                 test_case.m_expected_result = GL_NO_ERROR;
4393             }
4394 
4395             /* Skip cases with multisampling conflict */
4396             if (Utils::isTargetMultisampled(dst_target) != Utils::isTargetMultisampled(src_target))
4397             {
4398                 continue;
4399             }
4400 
4401             m_test_cases.push_back(test_case);
4402         }
4403     }
4404 }
4405 
4406 /** Execute test
4407  *
4408  * @return CONTINUE as long there are more test case, STOP otherwise
4409  **/
iterate()4410 tcu::TestNode::IterateResult TargetMismatchTest::iterate()
4411 {
4412     GLenum error                           = GL_NO_ERROR;
4413     const Functions &gl                    = m_context.getRenderContext().getFunctions();
4414     tcu::TestNode::IterateResult it_result = tcu::TestNode::STOP;
4415     bool result                            = false;
4416     const testCase &test_case              = m_test_cases[m_test_case_index];
4417 
4418     try
4419     {
4420         /* Prepare textures */
4421         m_dst_tex_name = Utils::prepareTex16x16x6(m_context, test_case.m_tex_target, GL_RGBA8, GL_RGBA,
4422                                                   GL_UNSIGNED_BYTE, m_dst_buf_name);
4423         m_src_tex_name = Utils::prepareTex16x16x6(m_context, test_case.m_tex_target, GL_RGBA8, GL_RGBA,
4424                                                   GL_UNSIGNED_BYTE, m_src_buf_name);
4425 
4426         /* Make textures complete */
4427         Utils::makeTextureComplete(m_context, test_case.m_tex_target, m_dst_tex_name, 0 /* base */, 0 /* max */);
4428         Utils::makeTextureComplete(m_context, test_case.m_tex_target, m_src_tex_name, 0 /* base */, 0 /* max */);
4429     }
4430     catch (tcu::Exception &exc)
4431     {
4432         clean();
4433         throw exc;
4434     }
4435 
4436     /* Execute CopyImageSubData */
4437     gl.copyImageSubData(m_src_tex_name, test_case.m_src_target, 0 /* srcLevel */, 0 /* srcX */, 0 /* srcY */,
4438                         0 /* srcZ */, m_dst_tex_name, test_case.m_dst_target, 0 /* dstLevel */, 0 /* dstX */,
4439                         0 /* dstY */, 0 /* dstZ */, 1 /* srcWidth */, 1 /* srcHeight */, 1 /* srcDepth */);
4440 
4441     /* Verify generated error */
4442     error  = gl.getError();
4443     result = (test_case.m_expected_result == error);
4444 
4445     /* Remove resources */
4446     clean();
4447 
4448     if (true == result)
4449     {
4450         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4451 
4452         /* Increase index */
4453         m_test_case_index += 1;
4454 
4455         /* Are there any test cases left */
4456         if (m_test_cases.size() > m_test_case_index)
4457         {
4458             it_result = tcu::TestNode::CONTINUE;
4459         }
4460     }
4461     else
4462     {
4463         m_context.getTestContext().getLog()
4464             << tcu::TestLog::Message << "Failure. Expected result: " << glu::getErrorStr(test_case.m_expected_result)
4465             << " got: " << glu::getErrorStr(error)
4466             << ". Texture target: " << glu::getTextureTargetStr(test_case.m_tex_target)
4467             << ". Source target: " << glu::getTextureTargetStr(test_case.m_src_target)
4468             << ", destination target: " << glu::getTextureTargetStr(test_case.m_dst_target) << tcu::TestLog::EndMessage;
4469 
4470         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4471     }
4472 
4473     /* Done */
4474     return it_result;
4475 }
4476 
4477 /** Cleans resources
4478  *
4479  **/
clean()4480 void TargetMismatchTest::clean()
4481 {
4482     const Functions &gl = m_context.getRenderContext().getFunctions();
4483 
4484     /* Clean textures and buffers. Errors ignored */
4485     gl.deleteTextures(1, &m_dst_tex_name);
4486     gl.deleteTextures(1, &m_src_tex_name);
4487 
4488     m_dst_tex_name = 0;
4489     m_src_tex_name = 0;
4490 
4491     if (0 != m_dst_buf_name)
4492     {
4493         gl.deleteBuffers(1, &m_dst_buf_name);
4494         m_dst_buf_name = 0;
4495     }
4496 
4497     if (0 != m_src_buf_name)
4498     {
4499         gl.deleteBuffers(1, &m_src_buf_name);
4500         m_src_buf_name = 0;
4501     }
4502 }
4503 
4504 /* TargetMismatchTest */
4505 /** Constructor
4506  *
4507  * @param context Text context
4508  **/
IncompleteTexTest(deqp::Context & context)4509 IncompleteTexTest::IncompleteTexTest(deqp::Context &context)
4510     : TestCase(
4511           context, "incomplete_tex",
4512           "Test verifies if INVALID_OPERATION is generated when texture provided to CopyImageSubData is incomplete")
4513     , m_dst_buf_name(0)
4514     , m_dst_tex_name(0)
4515     , m_src_buf_name(0)
4516     , m_src_tex_name(0)
4517     , m_test_case_index(0)
4518 {
4519     for (GLuint target = 0; target < s_n_valid_targets; ++target)
4520     {
4521         const GLenum tex_target = s_valid_targets[target];
4522         testCase test_case      = {tex_target, false, false, GL_INVALID_OPERATION};
4523 
4524         /* Skip targets that are not multi level */
4525         if (false == Utils::isTargetMultilevel(tex_target))
4526         {
4527             continue;
4528         }
4529 
4530         m_test_cases.push_back(test_case);
4531 
4532         test_case.m_is_dst_complete = true;
4533         test_case.m_is_src_complete = false;
4534         m_test_cases.push_back(test_case);
4535 
4536         test_case.m_is_dst_complete = false;
4537         test_case.m_is_src_complete = true;
4538         m_test_cases.push_back(test_case);
4539 
4540         test_case.m_is_dst_complete = true;
4541         test_case.m_is_src_complete = true;
4542         test_case.m_expected_result = GL_NO_ERROR;
4543         m_test_cases.push_back(test_case);
4544     }
4545 }
4546 
4547 /** Execute test
4548  *
4549  * @return CONTINUE as long there are more test case, STOP otherwise
4550  **/
iterate()4551 tcu::TestNode::IterateResult IncompleteTexTest::iterate()
4552 {
4553     GLenum error                           = GL_NO_ERROR;
4554     const Functions &gl                    = m_context.getRenderContext().getFunctions();
4555     tcu::TestNode::IterateResult it_result = tcu::TestNode::STOP;
4556     bool result                            = false;
4557     const testCase &test_case              = m_test_cases[m_test_case_index];
4558 
4559     try
4560     {
4561         /* Prepare textures */
4562         m_dst_tex_name = Utils::prepareTex16x16x6(m_context, test_case.m_tex_target, GL_RGBA8, GL_RGBA,
4563                                                   GL_UNSIGNED_BYTE, m_dst_buf_name);
4564         m_src_tex_name = Utils::prepareTex16x16x6(m_context, test_case.m_tex_target, GL_RGBA8, GL_RGBA,
4565                                                   GL_UNSIGNED_BYTE, m_src_buf_name);
4566 
4567         /* Make textures complete */
4568         if (true == test_case.m_is_dst_complete)
4569         {
4570             Utils::makeTextureComplete(m_context, test_case.m_tex_target, m_dst_tex_name, 0 /* base */, 0 /* max */);
4571         }
4572 
4573         if (true == test_case.m_is_src_complete)
4574         {
4575             Utils::makeTextureComplete(m_context, test_case.m_tex_target, m_src_tex_name, 0 /* base */, 0 /* max */);
4576         }
4577     }
4578     catch (tcu::Exception &exc)
4579     {
4580         clean();
4581         throw exc;
4582     }
4583 
4584     /* Execute CopyImageSubData */
4585     gl.copyImageSubData(m_src_tex_name, test_case.m_tex_target, 0 /* srcLevel */, 0 /* srcX */, 0 /* srcY */,
4586                         0 /* srcZ */, m_dst_tex_name, test_case.m_tex_target, 0 /* dstLevel */, 0 /* dstX */,
4587                         0 /* dstY */, 0 /* dstZ */, 1 /* srcWidth */, 1 /* srcHeight */, 1 /* srcDepth */);
4588 
4589     /* Verify generated error */
4590     error  = gl.getError();
4591     result = (test_case.m_expected_result == error);
4592 
4593     /* Remove resources */
4594     clean();
4595 
4596     if (true == result)
4597     {
4598         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4599 
4600         /* Increase index */
4601         m_test_case_index += 1;
4602 
4603         /* Are there any test cases left */
4604         if (m_test_cases.size() > m_test_case_index)
4605         {
4606             it_result = tcu::TestNode::CONTINUE;
4607         }
4608     }
4609     else
4610     {
4611         m_context.getTestContext().getLog()
4612             << tcu::TestLog::Message << "Failure. Expected result: " << glu::getErrorStr(test_case.m_expected_result)
4613             << " got: " << glu::getErrorStr(error)
4614             << ". Texture target: " << glu::getTextureTargetStr(test_case.m_tex_target)
4615             << ". Is source complete: " << test_case.m_is_src_complete
4616             << ", is destination complete: " << test_case.m_is_dst_complete << tcu::TestLog::EndMessage;
4617 
4618         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4619     }
4620 
4621     /* Done */
4622     return it_result;
4623 }
4624 
4625 /** Cleans resources
4626  *
4627  **/
clean()4628 void IncompleteTexTest::clean()
4629 {
4630     const Functions &gl = m_context.getRenderContext().getFunctions();
4631 
4632     /* Clean textures and buffers. Errors ignored */
4633     gl.deleteTextures(1, &m_dst_tex_name);
4634     gl.deleteTextures(1, &m_src_tex_name);
4635 
4636     m_dst_tex_name = 0;
4637     m_src_tex_name = 0;
4638 
4639     if (0 != m_dst_buf_name)
4640     {
4641         gl.deleteBuffers(1, &m_dst_buf_name);
4642         m_dst_buf_name = 0;
4643     }
4644 
4645     if (0 != m_src_buf_name)
4646     {
4647         gl.deleteBuffers(1, &m_src_buf_name);
4648         m_src_buf_name = 0;
4649     }
4650 }
4651 
4652 /* IncompatibleFormatsTest */
4653 /** Constructor
4654  *
4655  * @param context Text context
4656  **/
IncompatibleFormatsTest(deqp::Context & context)4657 IncompatibleFormatsTest::IncompatibleFormatsTest(deqp::Context &context)
4658     : TestCase(
4659           context, "incompatible_formats",
4660           "Test verifies if INVALID_OPERATION is generated when textures provided to CopyImageSubData are incompatible")
4661     , m_dst_buf_name(0)
4662     , m_dst_tex_name(0)
4663     , m_src_buf_name(0)
4664     , m_src_tex_name(0)
4665     , m_test_case_index(0)
4666 {
4667     /* RGBA8UI vs RGBA16UI */
4668     for (GLuint target = 0; target < s_n_valid_targets; ++target)
4669     {
4670         const GLenum tex_target = s_valid_targets[target];
4671 
4672         testCase test_case = {tex_target,  GL_RGBA8UI,      GL_RGBA_INTEGER,   GL_UNSIGNED_BYTE,
4673                               GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_INVALID_OPERATION};
4674 
4675         /* Skip multisampled and rectangle targets */
4676         if (true == Utils::isTargetMultisampled(tex_target))
4677         {
4678             continue;
4679         }
4680 
4681         m_test_cases.push_back(test_case);
4682     }
4683 
4684     /* RGBA8UI vs RGBA32UI */
4685     for (GLuint target = 0; target < s_n_valid_targets; ++target)
4686     {
4687         const GLenum tex_target = s_valid_targets[target];
4688 
4689         testCase test_case = {tex_target,  GL_RGBA8UI,      GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
4690                               GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_INVALID_OPERATION};
4691 
4692         /* Skip multisampled and rectangle targets */
4693         if (true == Utils::isTargetMultisampled(tex_target))
4694         {
4695             continue;
4696         }
4697 
4698         m_test_cases.push_back(test_case);
4699     }
4700 
4701     /* RGBA16UI vs RG16UI */
4702     for (GLuint target = 0; target < s_n_valid_targets; ++target)
4703     {
4704         const GLenum tex_target = s_valid_targets[target];
4705 
4706         testCase test_case = {tex_target, GL_RGBA16UI,   GL_RGBA_INTEGER,   GL_UNSIGNED_SHORT,
4707                               GL_RG16UI,  GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_INVALID_OPERATION};
4708 
4709         /* Skip multisampled and rectangle targets */
4710         if (true == Utils::isTargetMultisampled(tex_target))
4711         {
4712             continue;
4713         }
4714 
4715         m_test_cases.push_back(test_case);
4716     }
4717 
4718     /* RGBA32UI vs RGBA32F */
4719     for (GLuint target = 0; target < s_n_valid_targets; ++target)
4720     {
4721         const GLenum tex_target = s_valid_targets[target];
4722 
4723         testCase test_case = {tex_target, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
4724                               GL_RGBA32F, GL_RGBA,     GL_FLOAT,        GL_NO_ERROR};
4725 
4726         /* Skip multisampled and rectangle targets */
4727         if (true == Utils::isTargetMultisampled(tex_target))
4728         {
4729             continue;
4730         }
4731 
4732         m_test_cases.push_back(test_case);
4733     }
4734 
4735     /* RGBA8 vs RGBA32F */
4736     for (GLuint target = 0; target < s_n_valid_targets; ++target)
4737     {
4738         const GLenum tex_target = s_valid_targets[target];
4739 
4740         testCase test_case = {tex_target, GL_RGBA8, GL_RGBA,  GL_UNSIGNED_BYTE,
4741                               GL_RGBA32F, GL_RGBA,  GL_FLOAT, GL_INVALID_OPERATION};
4742 
4743         /* Skip multisampled and rectangle targets */
4744         if (true == Utils::isTargetMultisampled(tex_target))
4745         {
4746             continue;
4747         }
4748 
4749         m_test_cases.push_back(test_case);
4750     }
4751 }
4752 
4753 /** Execute test
4754  *
4755  * @return CONTINUE as long there are more test case, STOP otherwise
4756  **/
iterate()4757 tcu::TestNode::IterateResult IncompatibleFormatsTest::iterate()
4758 {
4759     GLenum error                           = GL_NO_ERROR;
4760     const Functions &gl                    = m_context.getRenderContext().getFunctions();
4761     tcu::TestNode::IterateResult it_result = tcu::TestNode::STOP;
4762     bool result                            = false;
4763     const testCase &test_case              = m_test_cases[m_test_case_index];
4764 
4765     try
4766     {
4767         /* Prepare textures */
4768         m_dst_tex_name = Utils::prepareTex16x16x6(m_context, test_case.m_tex_target, test_case.m_dst_internal_format,
4769                                                   test_case.m_dst_format, test_case.m_dst_type, m_dst_buf_name);
4770         m_src_tex_name = Utils::prepareTex16x16x6(m_context, test_case.m_tex_target, test_case.m_src_internal_format,
4771                                                   test_case.m_src_format, test_case.m_src_type, m_src_buf_name);
4772 
4773         /* Make textures complete */
4774         Utils::makeTextureComplete(m_context, test_case.m_tex_target, m_dst_tex_name, 0 /* base */, 0 /* max */);
4775         Utils::makeTextureComplete(m_context, test_case.m_tex_target, m_src_tex_name, 0 /* base */, 0 /* max */);
4776     }
4777     catch (tcu::Exception &exc)
4778     {
4779         clean();
4780         throw exc;
4781     }
4782 
4783     /* Execute CopyImageSubData */
4784     gl.copyImageSubData(m_src_tex_name, test_case.m_tex_target, 0 /* srcLevel */, 0 /* srcX */, 0 /* srcY */,
4785                         0 /* srcZ */, m_dst_tex_name, test_case.m_tex_target, 0 /* dstLevel */, 0 /* dstX */,
4786                         0 /* dstY */, 0 /* dstZ */, 1 /* srcWidth */, 1 /* srcHeight */, 1 /* srcDepth */);
4787 
4788     /* Verify generated error */
4789     error  = gl.getError();
4790     result = (test_case.m_expected_result == error);
4791 
4792     /* Remove resources */
4793     clean();
4794 
4795     if (true == result)
4796     {
4797         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4798 
4799         /* Increase index */
4800         m_test_case_index += 1;
4801 
4802         /* Are there any test cases left */
4803         if (m_test_cases.size() > m_test_case_index)
4804         {
4805             it_result = tcu::TestNode::CONTINUE;
4806         }
4807     }
4808     else
4809     {
4810         m_context.getTestContext().getLog()
4811             << tcu::TestLog::Message << "Failure. Expected result: " << glu::getErrorStr(test_case.m_expected_result)
4812             << " got: " << glu::getErrorStr(error)
4813             << ". Texture target: " << glu::getTextureTargetStr(test_case.m_tex_target)
4814             << ". Source format: " << glu::getInternalFormatParameterStr(test_case.m_src_internal_format)
4815             << ". Destination format: " << glu::getInternalFormatParameterStr(test_case.m_dst_internal_format)
4816             << tcu::TestLog::EndMessage;
4817 
4818         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4819     }
4820 
4821     /* Done */
4822     return it_result;
4823 }
4824 
4825 /** Cleans resources
4826  *
4827  **/
clean()4828 void IncompatibleFormatsTest::clean()
4829 {
4830     const Functions &gl       = m_context.getRenderContext().getFunctions();
4831     const testCase &test_case = m_test_cases[m_test_case_index];
4832 
4833     /* Clean textures and buffers. Errors ignored */
4834     Utils::deleteTexture(m_context, test_case.m_tex_target, m_dst_tex_name);
4835     Utils::deleteTexture(m_context, test_case.m_tex_target, m_src_tex_name);
4836 
4837     m_dst_tex_name = 0;
4838     m_src_tex_name = 0;
4839 
4840     if (0 != m_dst_buf_name)
4841     {
4842         gl.deleteBuffers(1, &m_dst_buf_name);
4843         m_dst_buf_name = 0;
4844     }
4845 
4846     if (0 != m_src_buf_name)
4847     {
4848         gl.deleteBuffers(1, &m_src_buf_name);
4849         m_src_buf_name = 0;
4850     }
4851 }
4852 
4853 /* InvalidTargetTest */
4854 /** Constructor
4855  *
4856  * @param context Text context
4857  **/
SamplesMismatchTest(deqp::Context & context)4858 SamplesMismatchTest::SamplesMismatchTest(deqp::Context &context)
4859     : TestCase(context, "samples_mismatch",
4860                "Test verifies if INVALID_OPERATION is generated when textures provided "
4861                "to CopyImageSubData have different number of samples")
4862     , m_dst_tex_name(0)
4863     , m_src_tex_name(0)
4864     , m_test_case_index(0)
4865 {
4866     testCase test_case;
4867 
4868     static const GLsizei n_samples[2] = {1, 4};
4869 
4870     static const GLenum targets[2] = {GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY};
4871 
4872     for (GLuint src_sample = 0; src_sample < 2; ++src_sample)
4873     {
4874         for (GLuint dst_sample = 0; dst_sample < 2; ++dst_sample)
4875         {
4876             for (GLuint src_target = 0; src_target < 2; ++src_target)
4877             {
4878                 for (GLuint dst_target = 0; dst_target < 2; ++dst_target)
4879                 {
4880                     test_case.m_src_target    = targets[src_target];
4881                     test_case.m_src_n_samples = n_samples[src_sample];
4882                     test_case.m_dst_target    = targets[dst_target];
4883                     test_case.m_dst_n_samples = n_samples[dst_sample];
4884 
4885                     if (test_case.m_src_n_samples == test_case.m_dst_n_samples)
4886                     {
4887                         test_case.m_expected_result = GL_NO_ERROR;
4888                     }
4889                     else
4890                     {
4891                         test_case.m_expected_result = GL_INVALID_OPERATION;
4892                     }
4893 
4894                     m_test_cases.push_back(test_case);
4895                 }
4896             }
4897         }
4898     }
4899 }
4900 
4901 /** Execute test
4902  *
4903  * @return CONTINUE as long there are more test case, STOP otherwise
4904  **/
iterate()4905 tcu::TestNode::IterateResult SamplesMismatchTest::iterate()
4906 {
4907     GLenum error                           = GL_NO_ERROR;
4908     const Functions &gl                    = m_context.getRenderContext().getFunctions();
4909     tcu::TestNode::IterateResult it_result = tcu::TestNode::STOP;
4910     bool result                            = false;
4911     const testCase &test_case              = m_test_cases[m_test_case_index];
4912 
4913     try
4914     {
4915         /* Prepare textures */
4916         m_dst_tex_name = Utils::prepareMultisampleTex(m_context, test_case.m_dst_target, test_case.m_dst_n_samples);
4917         m_src_tex_name = Utils::prepareMultisampleTex(m_context, test_case.m_src_target, test_case.m_src_n_samples);
4918     }
4919     catch (tcu::Exception &exc)
4920     {
4921         clean();
4922         throw exc;
4923     }
4924 
4925     GLenum expected_result = test_case.m_expected_result;
4926 
4927     if (test_case.m_dst_n_samples > 0 && test_case.m_src_n_samples > 0)
4928     {
4929         /* Implementations are allowed to use more samples than requested, so we need
4930          * to verify the actual sample counts allocated by the hardware and adjust
4931          * the expected result if they are different from what we requested.
4932          */
4933         GLint num_src_samples;
4934         GLint num_dst_samples;
4935         gl.bindTexture(test_case.m_dst_target, m_dst_tex_name);
4936         gl.getTexLevelParameteriv(test_case.m_dst_target, 0, GL_TEXTURE_SAMPLES, &num_dst_samples);
4937         gl.bindTexture(test_case.m_src_target, m_src_tex_name);
4938         gl.getTexLevelParameteriv(test_case.m_src_target, 0, GL_TEXTURE_SAMPLES, &num_src_samples);
4939         if (num_dst_samples != test_case.m_dst_n_samples || num_src_samples != test_case.m_src_n_samples)
4940         {
4941             /* The hardware allocated a different number of samples, check if this affects the expected
4942              * result of the test. This can happen if we requested different sample counts but the
4943              * hardware ended up allocating the same or viceversa.
4944              */
4945             if (test_case.m_dst_n_samples != test_case.m_src_n_samples && num_dst_samples == num_src_samples)
4946             {
4947                 expected_result = GL_NO_ERROR;
4948             }
4949             else if (test_case.m_dst_n_samples == test_case.m_src_n_samples && num_dst_samples != num_src_samples)
4950             {
4951                 expected_result = GL_INVALID_OPERATION;
4952             }
4953         }
4954     }
4955 
4956     /* Execute CopyImageSubData */
4957     gl.copyImageSubData(m_src_tex_name, test_case.m_src_target, 0 /* srcLevel */, 0 /* srcX */, 0 /* srcY */,
4958                         0 /* srcZ */, m_dst_tex_name, test_case.m_dst_target, 0 /* dstLevel */, 0 /* dstX */,
4959                         0 /* dstY */, 0 /* dstZ */, 1 /* srcWidth */, 1 /* srcHeight */, 1 /* srcDepth */);
4960 
4961     /* Verify generated error */
4962     error  = gl.getError();
4963     result = (expected_result == error);
4964 
4965     /* Free resources */
4966     clean();
4967 
4968     /* Set result */
4969     if (true == result)
4970     {
4971         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4972 
4973         /* Increase index */
4974         m_test_case_index += 1;
4975 
4976         /* Are there any test cases left */
4977         if (m_test_cases.size() > m_test_case_index)
4978         {
4979             it_result = tcu::TestNode::CONTINUE;
4980         }
4981     }
4982     else
4983     {
4984         m_context.getTestContext().getLog()
4985             << tcu::TestLog::Message << "Failure. Expected result: " << glu::getErrorStr(expected_result)
4986             << " got: " << glu::getErrorStr(error)
4987             << ". Source target: " << glu::getTextureTargetStr(test_case.m_src_target)
4988             << " samples: " << test_case.m_src_n_samples
4989             << ", destination target: " << glu::getTextureTargetStr(test_case.m_dst_target)
4990             << " samples: " << test_case.m_dst_n_samples << tcu::TestLog::EndMessage;
4991 
4992         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4993     }
4994 
4995     /* Done */
4996     return it_result;
4997 }
4998 
4999 /** Cleans resources
5000  *
5001  **/
clean()5002 void SamplesMismatchTest::clean()
5003 {
5004     const Functions &gl = m_context.getRenderContext().getFunctions();
5005 
5006     /* Clean textures . Errors ignored */
5007     gl.deleteTextures(1, &m_dst_tex_name);
5008     gl.deleteTextures(1, &m_src_tex_name);
5009 
5010     m_dst_tex_name = 0;
5011     m_src_tex_name = 0;
5012 }
5013 
5014 /* IncompatibleFormatsCompressionTest */
5015 /** Constructor
5016  *
5017  * @param context Text context
5018  **/
IncompatibleFormatsCompressionTest(deqp::Context & context)5019 IncompatibleFormatsCompressionTest::IncompatibleFormatsCompressionTest(deqp::Context &context)
5020     : TestCase(context, "incompatible_formats_compression",
5021                "Test verifies if INVALID_OPERATION is generated when "
5022                "textures provided to CopyImageSubData are incompatible, "
5023                "one of formats is compressed")
5024     , m_dst_tex_name(0)
5025     , m_src_tex_name(0)
5026     , m_test_case_index(0)
5027 {
5028     for (GLuint target = 0; target < s_n_valid_targets; ++target)
5029     {
5030         const GLenum tex_target = s_valid_targets[target];
5031 
5032         /* Skip 1D targets, not supported */
5033         if ((GL_TEXTURE_1D == tex_target) || (GL_TEXTURE_1D_ARRAY == tex_target) || (GL_TEXTURE_3D == tex_target) ||
5034             (GL_TEXTURE_RECTANGLE == tex_target) || (GL_RENDERBUFFER == tex_target) ||
5035             (GL_TEXTURE_CUBE_MAP_ARRAY == tex_target))
5036         {
5037             continue;
5038         }
5039 
5040         /* Skip multisampled and rectangle targets */
5041         if (true == Utils::isTargetMultisampled(tex_target))
5042         {
5043             continue;
5044         }
5045 
5046         /* Compressed 128bit vs RGBA32UI */
5047         {
5048             testCase test_case = {
5049                 tex_target, GL_RGBA32UI,      GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_COMPRESSED_RG_RGTC2,
5050                 GL_RG,      GL_UNSIGNED_BYTE, GL_NO_ERROR};
5051 
5052             m_test_cases.push_back(test_case);
5053         }
5054 
5055         /* Compressed 128bit vs RGBA16UI */
5056         {
5057             testCase test_case = {
5058                 tex_target, GL_RGBA16UI,      GL_RGBA_INTEGER,     GL_UNSIGNED_SHORT, GL_COMPRESSED_RG_RGTC2,
5059                 GL_RG,      GL_UNSIGNED_BYTE, GL_INVALID_OPERATION};
5060 
5061             m_test_cases.push_back(test_case);
5062         }
5063     }
5064 }
5065 
5066 /** Execute test
5067  *
5068  * @return CONTINUE as long there are more test case, STOP otherwise
5069  **/
iterate()5070 tcu::TestNode::IterateResult IncompatibleFormatsCompressionTest::iterate()
5071 {
5072     GLenum error                           = GL_NO_ERROR;
5073     const Functions &gl                    = m_context.getRenderContext().getFunctions();
5074     tcu::TestNode::IterateResult it_result = tcu::TestNode::STOP;
5075     bool result                            = false;
5076     GLuint temp                            = 0;
5077     const testCase &test_case              = m_test_cases[m_test_case_index];
5078 
5079     try
5080     {
5081         /* Prepare textures */
5082         m_dst_tex_name = Utils::prepareTex16x16x6(m_context, test_case.m_tex_target, test_case.m_dst_internal_format,
5083                                                   test_case.m_dst_format, test_case.m_dst_type, temp);
5084         m_src_tex_name = Utils::prepareTex16x16x6(m_context, test_case.m_tex_target, test_case.m_src_internal_format,
5085                                                   test_case.m_src_format, test_case.m_src_type, temp);
5086 
5087         /* Make textures complete */
5088         Utils::makeTextureComplete(m_context, test_case.m_tex_target, m_dst_tex_name, 0 /* base */, 0 /* max */);
5089         Utils::makeTextureComplete(m_context, test_case.m_tex_target, m_src_tex_name, 0 /* base */, 0 /* max */);
5090     }
5091     catch (tcu::Exception &exc)
5092     {
5093         clean();
5094         throw exc;
5095     }
5096 
5097     /* Execute CopyImageSubData */
5098     gl.copyImageSubData(m_src_tex_name, test_case.m_tex_target, 0 /* srcLevel */, 0 /* srcX */, 0 /* srcY */,
5099                         0 /* srcZ */, m_dst_tex_name, test_case.m_tex_target, 0 /* dstLevel */, 0 /* dstX */,
5100                         0 /* dstY */, 0 /* dstZ */, 4 /* srcWidth */, 4 /* srcHeight */, 1 /* srcDepth */);
5101 
5102     /* Verify generated error */
5103     error  = gl.getError();
5104     result = (test_case.m_expected_result == error);
5105 
5106     /* Remove resources */
5107     clean();
5108 
5109     if (true == result)
5110     {
5111         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
5112 
5113         /* Increase index */
5114         m_test_case_index += 1;
5115 
5116         /* Are there any test cases left */
5117         if (m_test_cases.size() > m_test_case_index)
5118         {
5119             it_result = tcu::TestNode::CONTINUE;
5120         }
5121     }
5122     else
5123     {
5124         m_context.getTestContext().getLog()
5125             << tcu::TestLog::Message << "Failure. Expected result: " << glu::getErrorStr(test_case.m_expected_result)
5126             << " got: " << glu::getErrorStr(error)
5127             << ". Texture target: " << glu::getTextureTargetStr(test_case.m_tex_target)
5128             << ". Source format: " << glu::getInternalFormatParameterStr(test_case.m_src_internal_format)
5129             << ". Destination format: " << glu::getInternalFormatParameterStr(test_case.m_dst_internal_format)
5130             << tcu::TestLog::EndMessage;
5131 
5132         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5133     }
5134 
5135     /* Done */
5136     return it_result;
5137 }
5138 
5139 /** Cleans resources
5140  *
5141  **/
clean()5142 void IncompatibleFormatsCompressionTest::clean()
5143 {
5144     const Functions &gl = m_context.getRenderContext().getFunctions();
5145 
5146     /* Clean textures and buffers. Errors ignored */
5147     gl.deleteTextures(1, &m_dst_tex_name);
5148     gl.deleteTextures(1, &m_src_tex_name);
5149 
5150     m_dst_tex_name = 0;
5151     m_src_tex_name = 0;
5152 }
5153 
5154 /* InvalidObjectTest */
5155 /** Constructor
5156  *
5157  * @param context Text context
5158  **/
InvalidObjectTest(deqp::Context & context)5159 InvalidObjectTest::InvalidObjectTest(deqp::Context &context)
5160     : TestCase(
5161           context, "invalid_object",
5162           "Test verifies if INVALID_VALUE is generated when object & target provided to CopyImageSubData do not match")
5163     , m_dst_name(0)
5164     , m_src_name(0)
5165     , m_test_case_index(0)
5166 {
5167     static glw::GLenum arg_types[]  = {GL_TEXTURE_2D, GL_RENDERBUFFER};
5168     static const GLuint n_arg_types = sizeof(arg_types) / sizeof(arg_types[0]);
5169 
5170     for (GLuint dst = 0; dst < n_arg_types; dst++)
5171     {
5172         for (GLuint src = 0; src < n_arg_types; src++)
5173         {
5174             for (GLuint dst_valid = 0; dst_valid < 2; dst_valid++)
5175             {
5176                 for (GLuint src_valid = 0; src_valid < 2; src_valid++)
5177                 {
5178                     glw::GLenum expected_error = GL_INVALID_VALUE;
5179                     if (!!src_valid && !!dst_valid)
5180                     {
5181                         expected_error = GL_NO_ERROR;
5182                     }
5183                     const testCase test_case = {arg_types[dst], !!dst_valid, arg_types[src], !!src_valid,
5184                                                 expected_error};
5185 
5186                     m_test_cases.push_back(test_case);
5187                 }
5188             }
5189         }
5190     }
5191 }
5192 
5193 /** Execute test
5194  *
5195  * @return CONTINUE as long there are more test case, STOP otherwise
5196  **/
iterate()5197 tcu::TestNode::IterateResult InvalidObjectTest::iterate()
5198 {
5199     GLenum error                           = GL_NO_ERROR;
5200     const Functions &gl                    = m_context.getRenderContext().getFunctions();
5201     tcu::TestNode::IterateResult it_result = tcu::TestNode::STOP;
5202     bool result                            = false;
5203     GLuint temp                            = 0;
5204     const testCase &test_case              = m_test_cases[m_test_case_index];
5205 
5206     try
5207     {
5208         /* Prepare objects */
5209         if (GL_RENDERBUFFER == test_case.m_dst_target)
5210         {
5211             m_dst_name = Utils::prepareRenderBuffer(m_context, GL_RGBA8);
5212         }
5213         else
5214         {
5215             m_dst_name =
5216                 Utils::prepareTex16x16x6(m_context, test_case.m_dst_target, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, temp);
5217 
5218             /* Make textures complete */
5219             Utils::makeTextureComplete(m_context, test_case.m_dst_target, m_dst_name, 0 /* base */, 0 /* max */);
5220         }
5221 
5222         if (GL_RENDERBUFFER == test_case.m_src_target)
5223         {
5224             m_src_name = Utils::prepareRenderBuffer(m_context, GL_RGBA8);
5225         }
5226         else
5227         {
5228             m_src_name =
5229                 Utils::prepareTex16x16x6(m_context, test_case.m_src_target, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, temp);
5230 
5231             /* Make texture complete */
5232             Utils::makeTextureComplete(m_context, test_case.m_src_target, m_src_name, 0 /* base */, 0 /* max */);
5233         }
5234 
5235         /* If an object is invalid, free it before use to make it invalid */
5236         if (!test_case.m_dst_valid)
5237         {
5238             Utils::deleteTexture(m_context, test_case.m_dst_target, m_dst_name);
5239         }
5240 
5241         if (!test_case.m_src_valid)
5242         {
5243             Utils::deleteTexture(m_context, test_case.m_src_target, m_src_name);
5244         }
5245     }
5246     catch (tcu::Exception &exc)
5247     {
5248         clean();
5249         throw exc;
5250     }
5251 
5252     /* Execute CopyImageSubData */
5253     gl.copyImageSubData(m_src_name, test_case.m_src_target, 0 /* srcLevel */, 0 /* srcX */, 0 /* srcY */, 0 /* srcZ */,
5254                         m_dst_name, test_case.m_dst_target, 0 /* dstLevel */, 0 /* dstX */, 0 /* dstY */, 0 /* dstZ */,
5255                         1 /* srcWidth */, 1 /* srcHeight */, 1 /* srcDepth */);
5256 
5257     /* Verify generated error */
5258     error  = gl.getError();
5259     result = (test_case.m_expected_result == error);
5260 
5261     /* Remove resources */
5262     clean();
5263 
5264     if (true == result)
5265     {
5266         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
5267 
5268         /* Increase index */
5269         m_test_case_index += 1;
5270 
5271         /* Are there any test cases left */
5272         if (m_test_cases.size() > m_test_case_index)
5273         {
5274             it_result = tcu::TestNode::CONTINUE;
5275         }
5276     }
5277     else
5278     {
5279         m_context.getTestContext().getLog()
5280             << tcu::TestLog::Message << "Failure. Expected result: " << glu::getErrorStr(test_case.m_expected_result)
5281             << " got: " << glu::getErrorStr(error)
5282             << ". Destination target: " << glu::getTextureTargetStr(test_case.m_dst_target)
5283             << ". Destination valid: " << (test_case.m_src_valid ? "true" : "false")
5284             << ". Source target: " << glu::getTextureTargetStr(test_case.m_dst_target)
5285             << ". Source valid: " << (test_case.m_dst_valid ? "true" : "false") << "." << tcu::TestLog::EndMessage;
5286 
5287         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5288     }
5289 
5290     /* Done */
5291     return it_result;
5292 }
5293 
5294 /** Cleans resources
5295  *
5296  **/
clean()5297 void InvalidObjectTest::clean()
5298 {
5299     const Functions &gl       = m_context.getRenderContext().getFunctions();
5300     const testCase &test_case = m_test_cases[m_test_case_index];
5301 
5302     /* Clean textures or renderbuffers. Errors ignored */
5303     if (test_case.m_dst_valid)
5304     {
5305         if (GL_RENDERBUFFER == test_case.m_dst_target)
5306         {
5307             gl.deleteRenderbuffers(1, &m_dst_name);
5308         }
5309         else
5310         {
5311             gl.deleteTextures(1, &m_dst_name);
5312         }
5313     }
5314     if (test_case.m_src_valid)
5315     {
5316         if (GL_RENDERBUFFER == test_case.m_src_target)
5317         {
5318             gl.deleteRenderbuffers(1, &m_src_name);
5319         }
5320         else
5321         {
5322             gl.deleteTextures(1, &m_src_name);
5323         }
5324     }
5325 
5326     m_dst_name = 0;
5327     m_src_name = 0;
5328 }
5329 
5330 /* NonExistentMipMapTest */
5331 /** Constructor
5332  *
5333  * @param context Text context
5334  **/
NonExistentMipMapTest(deqp::Context & context)5335 NonExistentMipMapTest::NonExistentMipMapTest(deqp::Context &context)
5336     : TestCase(context, "non_existent_mipmap",
5337                "Test verifies if INVALID_VALUE is generated when CopyImageSubData is "
5338                "executed for mipmap that does not exist")
5339     , m_dst_tex_name(0)
5340     , m_src_tex_name(0)
5341     , m_test_case_index(0)
5342 {
5343     for (GLuint target = 0; target < s_n_valid_targets; ++target)
5344     {
5345         const GLenum tex_target = s_valid_targets[target];
5346         testCase test_case      = {tex_target, 0, 0, GL_NO_ERROR};
5347 
5348         if (GL_RENDERBUFFER == tex_target)
5349         {
5350             continue;
5351         }
5352 
5353         m_test_cases.push_back(test_case);
5354 
5355         /* Rest of cases is invalid */
5356         test_case.m_expected_result = GL_INVALID_VALUE;
5357 
5358         test_case.m_dst_level = 1;
5359         test_case.m_src_level = 0;
5360         m_test_cases.push_back(test_case);
5361 
5362         test_case.m_dst_level = 0;
5363         test_case.m_src_level = 1;
5364         m_test_cases.push_back(test_case);
5365 
5366         test_case.m_dst_level = 1;
5367         test_case.m_src_level = 1;
5368         m_test_cases.push_back(test_case);
5369     }
5370 }
5371 
5372 /** Execute test
5373  *
5374  * @return CONTINUE as long there are more test case, STOP otherwise
5375  **/
iterate()5376 tcu::TestNode::IterateResult NonExistentMipMapTest::iterate()
5377 {
5378     GLenum error                           = GL_NO_ERROR;
5379     const Functions &gl                    = m_context.getRenderContext().getFunctions();
5380     tcu::TestNode::IterateResult it_result = tcu::TestNode::STOP;
5381     bool result                            = false;
5382     GLuint temp                            = 0;
5383     const testCase &test_case              = m_test_cases[m_test_case_index];
5384 
5385     try
5386     {
5387         /* Prepare textures */
5388         m_dst_tex_name =
5389             Utils::prepareTex16x16x6(m_context, test_case.m_tex_target, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, temp);
5390         m_src_tex_name =
5391             Utils::prepareTex16x16x6(m_context, test_case.m_tex_target, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, temp);
5392 
5393         /* Make textures complete */
5394         Utils::makeTextureComplete(m_context, test_case.m_tex_target, m_dst_tex_name, 0 /* base */, 0 /* max */);
5395         Utils::makeTextureComplete(m_context, test_case.m_tex_target, m_src_tex_name, 0 /* base */, 0 /* max */);
5396     }
5397     catch (tcu::Exception &exc)
5398     {
5399         clean();
5400         throw exc;
5401     }
5402 
5403     /* Execute CopyImageSubData */
5404     gl.copyImageSubData(m_src_tex_name, test_case.m_tex_target, test_case.m_src_level, 0 /* srcX */, 0 /* srcY */,
5405                         0 /* srcZ */, m_dst_tex_name, test_case.m_tex_target, test_case.m_dst_level, 0 /* dstX */,
5406                         0 /* dstY */, 0 /* dstZ */, 1 /* srcWidth */, 1 /* srcHeight */, 1 /* srcDepth */);
5407 
5408     /* Verify generated error */
5409     error  = gl.getError();
5410     result = (test_case.m_expected_result == error);
5411 
5412     /* Free resources */
5413     clean();
5414 
5415     /* Set result */
5416     if (true == result)
5417     {
5418         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
5419 
5420         /* Increase index */
5421         m_test_case_index += 1;
5422 
5423         /* Are there any test cases left */
5424         if (m_test_cases.size() > m_test_case_index)
5425         {
5426             it_result = tcu::TestNode::CONTINUE;
5427         }
5428     }
5429     else
5430     {
5431         m_context.getTestContext().getLog()
5432             << tcu::TestLog::Message << "Failure. Expected result: " << glu::getErrorStr(test_case.m_expected_result)
5433             << " got: " << glu::getErrorStr(error)
5434             << ". Texture target: " << glu::getTextureTargetStr(test_case.m_tex_target)
5435             << ", source level: " << test_case.m_src_level << ", destination level: " << test_case.m_dst_level
5436             << tcu::TestLog::EndMessage;
5437 
5438         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5439     }
5440 
5441     /* Done */
5442     return it_result;
5443 }
5444 
5445 /** Cleans resources
5446  *
5447  **/
clean()5448 void NonExistentMipMapTest::clean()
5449 {
5450     const Functions &gl = m_context.getRenderContext().getFunctions();
5451 
5452     /* Clean textures and buffers. Errors ignored */
5453     gl.deleteTextures(1, &m_dst_tex_name);
5454     gl.deleteTextures(1, &m_src_tex_name);
5455 
5456     m_dst_tex_name = 0;
5457     m_src_tex_name = 0;
5458 }
5459 
5460 /* ExceedingBoundariesTest */
5461 const glw::GLuint ExceedingBoundariesTest::m_region_depth  = 4;
5462 const glw::GLuint ExceedingBoundariesTest::m_region_height = 4;
5463 const glw::GLuint ExceedingBoundariesTest::m_region_width  = 4;
5464 
5465 /** Constructor
5466  *
5467  * @param context Text context
5468  **/
ExceedingBoundariesTest(deqp::Context & context)5469 ExceedingBoundariesTest::ExceedingBoundariesTest(deqp::Context &context)
5470     : TestCase(context, "exceeding_boundaries",
5471                "Test verifies if INVALID_VALUE is generated when CopyImageSubData is "
5472                "executed for regions exceeding image boundaries")
5473     , m_dst_tex_name(0)
5474     , m_src_tex_name(0)
5475     , m_test_case_index(0)
5476 {
5477     /* 16x16x6 are values used by prepareTex16x16x6 */
5478     static const GLuint invalid_x = 16 - (m_region_width / 2);
5479     static const GLuint invalid_y = 16 - (m_region_height / 2);
5480     static const GLuint invalid_z = 6 - (m_region_depth / 2);
5481 
5482     static const GLuint x_vals[] = {0, invalid_x};
5483     static const GLuint y_vals[] = {0, invalid_y};
5484     static const GLuint z_vals[] = {0, invalid_z};
5485 
5486     static const GLuint n_x_vals = sizeof(x_vals) / sizeof(x_vals[0]);
5487     static const GLuint n_y_vals = sizeof(y_vals) / sizeof(y_vals[0]);
5488     static const GLuint n_z_vals = sizeof(z_vals) / sizeof(z_vals[0]);
5489 
5490     for (GLuint target = 0; target < s_n_valid_targets; ++target)
5491     {
5492         const GLenum tex_target = s_valid_targets[target];
5493         GLuint height           = m_region_height;
5494 
5495         if (GL_TEXTURE_BUFFER == tex_target)
5496         {
5497             continue;
5498         }
5499 
5500         if ((GL_TEXTURE_1D == tex_target) || (GL_TEXTURE_1D_ARRAY == tex_target))
5501         {
5502             height = 1;
5503         }
5504 
5505         for (GLuint x = 0; x < n_x_vals; ++x)
5506         {
5507             for (GLuint y = 0; y < n_y_vals; ++y)
5508             {
5509                 for (GLuint z = 0; z < n_z_vals; ++z)
5510                 {
5511                     const GLuint x_val = x_vals[x];
5512                     const GLuint y_val = y_vals[y];
5513                     const GLuint z_val = z_vals[z];
5514                     const GLenum res = ((0 == x_val) && (0 == y_val) && (0 == z_val)) ? GL_NO_ERROR : GL_INVALID_VALUE;
5515                     GLuint depth     = 1;
5516 
5517                     if (0 != z_val)
5518                     {
5519                         if (!((GL_TEXTURE_2D_ARRAY == tex_target) || (GL_TEXTURE_2D_MULTISAMPLE_ARRAY == tex_target) ||
5520                               (GL_TEXTURE_3D == tex_target) || (GL_TEXTURE_CUBE_MAP_ARRAY == tex_target)))
5521                         {
5522                             /* Skip z != 0 for 2d textures */
5523                             continue;
5524                         }
5525                         else
5526                         {
5527                             /* Set depth so as to exceed boundary */
5528                             depth = m_region_depth;
5529                         }
5530                     }
5531 
5532                     testCase src_test_case = {tex_target, depth, height, x_val, y_val, z_val, 0, 0, 0, res};
5533 
5534                     testCase dst_test_case = {tex_target, depth, height, 0, 0, 0, x_val, y_val, z_val, res};
5535 
5536                     m_test_cases.push_back(src_test_case);
5537                     m_test_cases.push_back(dst_test_case);
5538                 }
5539             }
5540         }
5541     }
5542 }
5543 
5544 /** Execute test
5545  *
5546  * @return CONTINUE as long there are more test case, STOP otherwise
5547  **/
iterate()5548 tcu::TestNode::IterateResult ExceedingBoundariesTest::iterate()
5549 {
5550     GLenum error                           = GL_NO_ERROR;
5551     const Functions &gl                    = m_context.getRenderContext().getFunctions();
5552     tcu::TestNode::IterateResult it_result = tcu::TestNode::STOP;
5553     bool result                            = false;
5554     GLuint temp                            = 0;
5555     const testCase &test_case              = m_test_cases[m_test_case_index];
5556 
5557     try
5558     {
5559         /* Prepare textures */
5560         m_dst_tex_name =
5561             Utils::prepareTex16x16x6(m_context, test_case.m_tex_target, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, temp);
5562         m_src_tex_name =
5563             Utils::prepareTex16x16x6(m_context, test_case.m_tex_target, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, temp);
5564 
5565         /* Make textures complete */
5566         Utils::makeTextureComplete(m_context, test_case.m_tex_target, m_dst_tex_name, 0 /* base */, 0 /* max */);
5567         Utils::makeTextureComplete(m_context, test_case.m_tex_target, m_src_tex_name, 0 /* base */, 0 /* max */);
5568     }
5569     catch (tcu::Exception &exc)
5570     {
5571         clean();
5572         throw exc;
5573     }
5574 
5575     /* Execute CopyImageSubData */
5576     gl.copyImageSubData(m_src_tex_name, test_case.m_tex_target, 0 /* level */, test_case.m_src_x /* srcX */,
5577                         test_case.m_src_y /* srcY */, test_case.m_src_z /* srcZ */, m_dst_tex_name,
5578                         test_case.m_tex_target, 0 /* level */, test_case.m_dst_x /* dstX */,
5579                         test_case.m_dst_y /* dstY */, test_case.m_dst_z /* dstZ */, m_region_width /* srcWidth */,
5580                         test_case.m_height /* srcHeight */, test_case.m_depth /* srcDepth */);
5581 
5582     /* Verify generated error */
5583     error  = gl.getError();
5584     result = (test_case.m_expected_result == error);
5585 
5586     /* Free resources */
5587     clean();
5588 
5589     /* Set result */
5590     if (true == result)
5591     {
5592         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
5593 
5594         /* Increase index */
5595         m_test_case_index += 1;
5596 
5597         /* Are there any test cases left */
5598         if (m_test_cases.size() > m_test_case_index)
5599         {
5600             it_result = tcu::TestNode::CONTINUE;
5601         }
5602     }
5603     else
5604     {
5605         m_context.getTestContext().getLog()
5606             << tcu::TestLog::Message << "Failure. Expected result: " << glu::getErrorStr(test_case.m_expected_result)
5607             << " got: " << glu::getErrorStr(error)
5608             << ". Texture target: " << glu::getTextureTargetStr(test_case.m_tex_target) << ", source: ["
5609             << test_case.m_src_x << ", " << test_case.m_src_y << ", " << test_case.m_src_z << "], destination: ["
5610             << test_case.m_src_x << ", " << test_case.m_src_y << ", " << test_case.m_src_z
5611             << "], depth: " << test_case.m_depth << tcu::TestLog::EndMessage;
5612 
5613         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5614     }
5615 
5616     /* Done */
5617     return it_result;
5618 }
5619 
5620 /** Cleans resources
5621  *
5622  **/
clean()5623 void ExceedingBoundariesTest::clean()
5624 {
5625     const testCase &test_case = m_test_cases[m_test_case_index];
5626 
5627     /* Clean textures and buffers. Errors ignored */
5628     Utils::deleteTexture(m_context, test_case.m_tex_target, m_dst_tex_name);
5629     Utils::deleteTexture(m_context, test_case.m_tex_target, m_src_tex_name);
5630 
5631     m_dst_tex_name = 0;
5632     m_src_tex_name = 0;
5633 }
5634 
5635 /* InvalidAlignmentTest */
5636 /** Constructor
5637  *
5638  * @param context Text context
5639  **/
InvalidAlignmentTest(deqp::Context & context)5640 InvalidAlignmentTest::InvalidAlignmentTest(deqp::Context &context)
5641     : TestCase(context, "invalid_alignment",
5642                "Test verifies if INVALID_VALUE is generated when CopyImageSubData is "
5643                "executed for regions with invalid alignment")
5644     , m_dst_tex_name(0)
5645     , m_src_tex_name(0)
5646     , m_test_case_index(0)
5647 {
5648     /* 16x16x6 are values used by prepareTex16x16x6 */
5649     static const GLuint invalid_h = 2;
5650     static const GLuint invalid_w = 2;
5651     static const GLuint invalid_x = 2;
5652     static const GLuint invalid_y = 2;
5653     static const GLuint valid_h   = 4;
5654     static const GLuint valid_w   = 4;
5655 
5656     static const GLuint h_vals[] = {valid_h, invalid_h};
5657     static const GLuint w_vals[] = {valid_w, invalid_w};
5658     static const GLuint x_vals[] = {0, invalid_x};
5659     static const GLuint y_vals[] = {0, invalid_y};
5660 
5661     static const GLuint n_h_vals = sizeof(h_vals) / sizeof(h_vals[0]);
5662     static const GLuint n_w_vals = sizeof(w_vals) / sizeof(w_vals[0]);
5663     static const GLuint n_x_vals = sizeof(x_vals) / sizeof(x_vals[0]);
5664     static const GLuint n_y_vals = sizeof(y_vals) / sizeof(y_vals[0]);
5665 
5666     for (GLuint x = 0; x < n_x_vals; ++x)
5667     {
5668         for (GLuint y = 0; y < n_y_vals; ++y)
5669         {
5670             for (GLuint h = 0; h < n_h_vals; ++h)
5671             {
5672                 for (GLuint w = 0; w < n_w_vals; ++w)
5673                 {
5674                     const GLuint h_val = h_vals[h];
5675                     const GLuint w_val = w_vals[w];
5676                     const GLuint x_val = x_vals[x];
5677                     const GLuint y_val = y_vals[y];
5678                     const GLenum res   = ((valid_h == h_val) && (valid_w == w_val) && (0 == x_val) && (0 == y_val)) ?
5679                                              GL_NO_ERROR :
5680                                              GL_INVALID_VALUE;
5681 
5682                     testCase dst_test_case = {h_val, w_val, 0, 0, x_val, y_val, res};
5683 
5684                     testCase src_test_case = {h_val, w_val, x_val, y_val, 0, 0, res};
5685 
5686                     m_test_cases.push_back(dst_test_case);
5687                     m_test_cases.push_back(src_test_case);
5688                 }
5689             }
5690         }
5691     }
5692 }
5693 
5694 /** Execute test
5695  *
5696  * @return CONTINUE as long there are more test case, STOP otherwise
5697  **/
iterate()5698 tcu::TestNode::IterateResult InvalidAlignmentTest::iterate()
5699 {
5700     GLenum error                           = GL_NO_ERROR;
5701     const Functions &gl                    = m_context.getRenderContext().getFunctions();
5702     tcu::TestNode::IterateResult it_result = tcu::TestNode::STOP;
5703     bool result                            = false;
5704     GLuint temp                            = 0;
5705     const testCase &test_case              = m_test_cases[m_test_case_index];
5706 
5707     try
5708     {
5709         /* Prepare textures */
5710         m_dst_tex_name =
5711             Utils::prepareTex16x16x6(m_context, GL_TEXTURE_2D, GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_BYTE, temp);
5712         m_src_tex_name =
5713             Utils::prepareTex16x16x6(m_context, GL_TEXTURE_2D, GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_BYTE, temp);
5714 
5715         /* Make textures complete */
5716         Utils::makeTextureComplete(m_context, GL_TEXTURE_2D, m_dst_tex_name, 0 /* base */, 0 /* max */);
5717         Utils::makeTextureComplete(m_context, GL_TEXTURE_2D, m_src_tex_name, 0 /* base */, 0 /* max */);
5718     }
5719     catch (tcu::Exception &exc)
5720     {
5721         clean();
5722         throw exc;
5723     }
5724 
5725     /* Execute CopyImageSubData */
5726     gl.copyImageSubData(m_src_tex_name, GL_TEXTURE_2D, 0 /* level */, test_case.m_src_x /* srcX */,
5727                         test_case.m_src_y /* srcY */, 0 /* srcZ */, m_dst_tex_name, GL_TEXTURE_2D, 0 /* level */,
5728                         test_case.m_dst_x /* dstX */, test_case.m_dst_y /* dstY */, 0 /* dstZ */,
5729                         test_case.m_width /* srcWidth */, test_case.m_height /* srcHeight */, 1 /* srcDepth */);
5730 
5731     /* Verify generated error */
5732     error  = gl.getError();
5733     result = (test_case.m_expected_result == error);
5734 
5735     /* Free resources */
5736     clean();
5737 
5738     /* Set result */
5739     if (true == result)
5740     {
5741         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
5742 
5743         /* Increase index */
5744         m_test_case_index += 1;
5745 
5746         /* Are there any test cases left */
5747         if (m_test_cases.size() > m_test_case_index)
5748         {
5749             it_result = tcu::TestNode::CONTINUE;
5750         }
5751     }
5752     else
5753     {
5754         m_context.getTestContext().getLog()
5755             << tcu::TestLog::Message << "Failure. Expected result: " << glu::getErrorStr(test_case.m_expected_result)
5756             << " got: " << glu::getErrorStr(error) << ". source: [" << test_case.m_src_x << ", " << test_case.m_src_y
5757             << "], destination: [" << test_case.m_src_x << ", " << test_case.m_src_y << "], size: " << test_case.m_width
5758             << " x " << test_case.m_height << tcu::TestLog::EndMessage;
5759 
5760         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5761     }
5762 
5763     /* Done */
5764     return it_result;
5765 }
5766 
5767 /** Cleans resources
5768  *
5769  **/
clean()5770 void InvalidAlignmentTest::clean()
5771 {
5772     const Functions &gl = m_context.getRenderContext().getFunctions();
5773 
5774     /* Clean textures and buffers. Errors ignored */
5775     gl.deleteTextures(1, &m_dst_tex_name);
5776     gl.deleteTextures(1, &m_src_tex_name);
5777 
5778     m_dst_tex_name = 0;
5779     m_src_tex_name = 0;
5780 }
5781 
5782 /** Constructor
5783  *
5784  * @param context Text context
5785  **/
IntegerTexTest(deqp::Context & context)5786 IntegerTexTest::IntegerTexTest(deqp::Context &context)
5787     : TestCase(
5788           context, "integer_tex",
5789           "Test verifies if INVALID_OPERATION is generated when texture provided to CopySubImageData is incomplete")
5790     , m_dst_buf_name(0)
5791     , m_dst_tex_name(0)
5792     , m_src_buf_name(0)
5793     , m_src_tex_name(0)
5794     , m_test_case_index(0)
5795 {
5796 }
5797 
5798 /** Execute test
5799  *
5800  * @return CONTINUE as long there are more test case, STOP otherwise
5801  **/
iterate()5802 tcu::TestNode::IterateResult IntegerTexTest::iterate()
5803 {
5804     testCase testCases[] = {{GL_R32I, GL_INT}, {GL_R32UI, GL_UNSIGNED_INT}};
5805 
5806     const unsigned int width  = 16;
5807     const unsigned int height = 16;
5808 
5809     const Functions &gl                    = m_context.getRenderContext().getFunctions();
5810     tcu::TestNode::IterateResult it_result = tcu::TestNode::STOP;
5811     const testCase &test_case              = testCases[m_test_case_index];
5812 
5813     std::vector<int> data_buf(width * height, 1);
5814     m_dst_tex_name = createTexture(width, height, test_case.m_internal_format, test_case.m_type, &data_buf[0],
5815                                    GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR);
5816     std::fill(data_buf.begin(), data_buf.end(), 2);
5817     m_src_tex_name = createTexture(width, height, test_case.m_internal_format, test_case.m_type, &data_buf[0],
5818                                    GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR);
5819 
5820     /* Execute CopyImageSubData */
5821     gl.copyImageSubData(m_src_tex_name, GL_TEXTURE_2D, 0 /* srcLevel */, 0 /* srcX */, 0 /* srcY */, 0 /* srcZ */,
5822                         m_dst_tex_name, GL_TEXTURE_2D, 0 /* dstLevel */, 0 /* dstX */, 0 /* dstY */, 0 /* dstZ */,
5823                         1 /* srcWidth */, 1 /* srcHeight */, 1 /* srcDepth */);
5824 
5825     /* Check generated error */
5826     GLenum error = gl.getError();
5827     if (error == GL_NO_ERROR)
5828     {
5829         /* Verify result */
5830         std::fill(data_buf.begin(), data_buf.end(), 3);
5831 
5832         gl.bindTexture(GL_TEXTURE_2D, m_dst_tex_name);
5833         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5834 
5835         gl.getTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &data_buf[0]);
5836         GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
5837 
5838         if ((data_buf[0] == 2) && (std::count(data_buf.begin(), data_buf.end(), 1) == (width * height - 1)))
5839         {
5840             m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
5841 
5842             /* Increase index */
5843             ++m_test_case_index;
5844 
5845             /* Are there any test cases left */
5846             if (DE_LENGTH_OF_ARRAY(testCases) > m_test_case_index)
5847                 it_result = tcu::TestNode::CONTINUE;
5848         }
5849         else
5850         {
5851             m_context.getTestContext().getLog()
5852                 << tcu::TestLog::Message << "Failure. Image data is not valid." << tcu::TestLog::EndMessage;
5853             m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5854         }
5855     }
5856     else
5857     {
5858         m_context.getTestContext().getLog()
5859             << tcu::TestLog::Message << "Failure. Expected no error, got: " << glu::getErrorStr(error)
5860             << ". Texture internal format: " << glu::getTextureFormatStr(test_case.m_internal_format)
5861             << tcu::TestLog::EndMessage;
5862         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5863     }
5864 
5865     /* Remove resources */
5866     clean();
5867 
5868     /* Done */
5869     return it_result;
5870 }
5871 
5872 /** Create texture
5873  *
5874  **/
createTexture(int width,int height,GLint internalFormat,GLuint type,const void * data,int minFilter,int magFilter)5875 unsigned int IntegerTexTest::createTexture(int width, int height, GLint internalFormat, GLuint type, const void *data,
5876                                            int minFilter, int magFilter)
5877 {
5878     const Functions &gl = m_context.getRenderContext().getFunctions();
5879     GLuint tex_name;
5880 
5881     gl.genTextures(1, &tex_name);
5882     GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
5883     gl.bindTexture(GL_TEXTURE_2D, tex_name);
5884     GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5885     gl.texImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, GL_RED_INTEGER, type, data);
5886     GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
5887     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5888     GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
5889     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5890     GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
5891     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
5892     GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
5893     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
5894     GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
5895     gl.bindTexture(GL_TEXTURE_2D, 0);
5896 
5897     return tex_name;
5898 }
5899 
5900 /** Cleans resources
5901  *
5902  **/
clean()5903 void IntegerTexTest::clean()
5904 {
5905     const Functions &gl = m_context.getRenderContext().getFunctions();
5906 
5907     /* Clean textures and buffers. Errors ignored */
5908     gl.deleteTextures(1, &m_dst_tex_name);
5909     gl.deleteTextures(1, &m_src_tex_name);
5910 
5911     m_dst_tex_name = 0;
5912     m_src_tex_name = 0;
5913 
5914     if (0 != m_dst_buf_name)
5915     {
5916         gl.deleteBuffers(1, &m_dst_buf_name);
5917         m_dst_buf_name = 0;
5918     }
5919 
5920     if (0 != m_src_buf_name)
5921     {
5922         gl.deleteBuffers(1, &m_src_buf_name);
5923         m_src_buf_name = 0;
5924     }
5925 }
5926 
5927 } /* namespace CopyImage */
5928 
CopyImageTests(deqp::Context & context)5929 CopyImageTests::CopyImageTests(deqp::Context &context) : TestCaseGroup(context, "copy_image", "")
5930 {
5931 }
5932 
~CopyImageTests(void)5933 CopyImageTests::~CopyImageTests(void)
5934 {
5935 }
5936 
init()5937 void CopyImageTests::init()
5938 {
5939     addChild(new CopyImage::FunctionalTest(m_context));
5940     addChild(new CopyImage::IncompleteTexTest(m_context));
5941     addChild(new CopyImage::InvalidObjectTest(m_context));
5942     addChild(new CopyImage::SmokeTest(m_context));
5943     addChild(new CopyImage::InvalidTargetTest(m_context));
5944     addChild(new CopyImage::TargetMismatchTest(m_context));
5945     addChild(new CopyImage::IncompatibleFormatsTest(m_context));
5946     addChild(new CopyImage::SamplesMismatchTest(m_context));
5947     addChild(new CopyImage::IncompatibleFormatsCompressionTest(m_context));
5948     addChild(new CopyImage::NonExistentMipMapTest(m_context));
5949     addChild(new CopyImage::ExceedingBoundariesTest(m_context));
5950     addChild(new CopyImage::InvalidAlignmentTest(m_context));
5951     addChild(new CopyImage::IntegerTexTest(m_context));
5952 }
5953 } /* namespace gl4cts */
5954