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