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