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