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