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