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