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