1/*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-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
21 * \brief
22 */ /*-------------------------------------------------------------------*/
23
24/*!
25 * \file  esextcTextureCubeMapArraySubImage3D.cpp
26 * \brief Texture Cube Map Array SubImage3D (Test 5)
27 */ /*-------------------------------------------------------------------*/
28
29#include "esextcTextureCubeMapArraySubImage3D.hpp"
30#include "gluContextInfo.hpp"
31#include "gluDefs.hpp"
32#include "glwEnums.hpp"
33#include "glwFunctions.hpp"
34#include "tcuTestLog.hpp"
35#include <string.h>
36
37namespace glcts
38{
39const glw::GLuint TextureCubeMapArraySubImage3D::m_n_components   = 4;
40const glw::GLuint TextureCubeMapArraySubImage3D::m_n_dimensions   = 3;
41const glw::GLuint TextureCubeMapArraySubImage3D::m_n_resolutions  = 4;
42const glw::GLuint TextureCubeMapArraySubImage3D::m_n_storage_type = 2;
43
44/* Helper arrays for tests configuration */
45
46/* Different texture resolutions */
47const glw::GLuint resolutions[TextureCubeMapArraySubImage3D::m_n_resolutions]
48							 [TextureCubeMapArraySubImage3D::m_n_dimensions] = {
49								 /* Width , Height, Depth */
50								 { 32, 32, 12 },
51								 { 64, 64, 12 },
52								 { 16, 16, 18 },
53								 { 16, 16, 24 }
54							 };
55
56/* Location of dimension in array with texture resolutions */
57enum Dimensions_Location
58{
59	DL_WIDTH  = 0,
60	DL_HEIGHT = 1,
61	DL_DEPTH  = 2
62};
63
64/** Constructor
65 *
66 *  @param context              Test context
67 *  @param name                 Test case's name
68 *  @param description          Test case's description
69 */
70TextureCubeMapArraySubImage3D::TextureCubeMapArraySubImage3D(Context& context, const ExtParameters& extParams,
71															 const char* name, const char* description)
72	: TestCaseBase(context, extParams, name, description)
73	, m_read_fbo_id(0)
74	, m_pixel_buffer_id(0)
75	, m_tex_cube_map_array_id(0)
76	, m_tex_2d_id(0)
77{
78	/* Nothing to be done here */
79}
80
81/** Initialize test case */
82void TextureCubeMapArraySubImage3D::initTest(void)
83{
84	/* Check if texture_cube_map_array extension is supported */
85	if (!m_is_texture_cube_map_array_supported)
86	{
87		throw tcu::NotSupportedError(TEXTURE_CUBE_MAP_ARRAY_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
88	}
89
90	/* Get GL entry points */
91	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
92
93	gl.genFramebuffers(1, &m_read_fbo_id);
94	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating frame buffer object!");
95
96	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
97	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding frame buffer object!");
98}
99
100/** Deinitialize test case */
101void TextureCubeMapArraySubImage3D::deinit(void)
102{
103	/* Get GL entry points */
104	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
105
106	/* Reset GLES configuration */
107	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
108
109	/* Delete GLES objects */
110	if (m_read_fbo_id != 0)
111	{
112		gl.deleteFramebuffers(1, &m_read_fbo_id);
113		m_read_fbo_id = 0;
114	}
115
116	/* Delete pixel unpack buffer */
117	deletePixelUnpackBuffer();
118
119	/* Delete cube map array texture */
120	deleteCubeMapArrayTexture();
121
122	/* Delete 2D texture */
123	delete2DTexture();
124
125	/* Deinitialize base class */
126	TestCaseBase::deinit();
127}
128
129/** Executes the test.
130 *
131 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
132 *
133 *  Note the function throws exception should an error occur!
134 *
135 *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
136 */
137tcu::TestCase::IterateResult TextureCubeMapArraySubImage3D::iterate()
138{
139	initTest();
140
141	glw::GLboolean test_passed = true;
142
143	/* Execute test throught all storage types */
144	for (glw::GLuint storage_index = 0; storage_index < m_n_storage_type; ++storage_index)
145	{
146		/* Execute test throught all texture resolutions */
147		for (glw::GLuint resolution_index = 0; resolution_index < m_n_resolutions; ++resolution_index)
148		{
149			glw::GLuint width  = resolutions[resolution_index][DL_WIDTH];
150			glw::GLuint height = resolutions[resolution_index][DL_HEIGHT];
151			glw::GLuint depth  = resolutions[resolution_index][DL_DEPTH];
152
153			configureCubeMapArrayTexture(width, height, depth, static_cast<STORAGE_TYPE>(storage_index), 0);
154
155			/* A single whole layer-face at index 0 should be replaced (both functions) */
156			SubImage3DCopyParams copy_params;
157			copy_params.init(0, 0, 0, width, height, 1);
158
159			configureDataBuffer(width, height, depth, copy_params, 0);
160			configurePixelUnpackBuffer(copy_params);
161			configure2DTexture(copy_params);
162			testTexSubImage3D(width, height, depth, copy_params, test_passed);
163			testCopyTexSubImage3D(width, height, depth, copy_params, test_passed);
164			deletePixelUnpackBuffer();
165			delete2DTexture();
166
167			/* A region of a layer-face at index 0 should be replaced (both functions) */
168			copy_params.init(width / 2, height / 2, 0, width / 2, height / 2, 1);
169
170			configureDataBuffer(width, height, depth, copy_params, 0);
171			configurePixelUnpackBuffer(copy_params);
172			configure2DTexture(copy_params);
173			testTexSubImage3D(width, height, depth, copy_params, test_passed);
174			testCopyTexSubImage3D(width, height, depth, copy_params, test_passed);
175			deletePixelUnpackBuffer();
176			delete2DTexture();
177
178			/* 6 layer-faces, making up a single layer, should be replaced (glTexSubImage3D() only) */
179			copy_params.init(0, 0, 0, width, height, 6);
180
181			configureDataBuffer(width, height, depth, copy_params, 0);
182			configurePixelUnpackBuffer(copy_params);
183			testTexSubImage3D(width, height, depth, copy_params, test_passed);
184			deletePixelUnpackBuffer();
185
186			/* 6 layer-faces, making up two different layers (for instance: three last layer-faces of
187			 layer 1 and three first layer-faces of layer 2) should be replaced (glTexSubImage3D() only) */
188			copy_params.init(0, 0, 3, width, height, 6);
189
190			configureDataBuffer(width, height, depth, copy_params, 0);
191			configurePixelUnpackBuffer(copy_params);
192			testTexSubImage3D(width, height, depth, copy_params, test_passed);
193			deletePixelUnpackBuffer();
194
195			/* 6 layer-faces, making up a single layer, should be replaced (glTexSubImage3D() only),
196			 but limited to a quad */
197			copy_params.init(width / 2, height / 2, 0, width / 2, height / 2, 6);
198
199			configureDataBuffer(width, height, depth, copy_params, 0);
200			configurePixelUnpackBuffer(copy_params);
201			testTexSubImage3D(width, height, depth, copy_params, test_passed);
202			deletePixelUnpackBuffer();
203
204			/* 6 layer-faces, making up two different layers (for instance: three last layer-faces of
205			 layer 1 and three first layer-faces of layer 2) should be replaced (glTexSubImage3D() only),
206			 but limited to a quad */
207			copy_params.init(width / 2, height / 2, 3, width / 2, height / 2, 6);
208
209			configureDataBuffer(width, height, depth, copy_params, 0);
210			configurePixelUnpackBuffer(copy_params);
211			testTexSubImage3D(width, height, depth, copy_params, test_passed);
212			deletePixelUnpackBuffer();
213
214			deleteCubeMapArrayTexture();
215		}
216	}
217
218	if (test_passed)
219		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
220	else
221		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
222
223	return STOP;
224}
225
226/** Resizes data buffer and fills it with values
227 * @param width       - width of the texture
228 * @param height      - height of the texture
229 * @param depth       - depth of the texture
230 * @param copy_params - data structure specifying which region of the data store to replace
231 * @param clear_value - value with which to fill the data buffer outside of region specified by copy_params
232 */
233void TextureCubeMapArraySubImage3D::configureDataBuffer(glw::GLuint width, glw::GLuint height, glw::GLuint depth,
234														const SubImage3DCopyParams& copy_params,
235														glw::GLuint					clear_value)
236{
237	glw::GLuint index = 0;
238
239	m_copy_data_buffer.assign(copy_params.m_width * copy_params.m_height * copy_params.m_depth * m_n_components,
240							  clear_value);
241	for (glw::GLuint zoffset = copy_params.m_zoffset; zoffset < copy_params.m_zoffset + copy_params.m_depth; ++zoffset)
242	{
243		for (glw::GLuint yoffset = copy_params.m_yoffset; yoffset < copy_params.m_yoffset + copy_params.m_height;
244			 ++yoffset)
245		{
246			for (glw::GLuint xoffset = copy_params.m_xoffset; xoffset < copy_params.m_xoffset + copy_params.m_width;
247				 ++xoffset)
248			{
249				for (glw::GLuint component = 0; component < m_n_components; ++component)
250				{
251					m_copy_data_buffer[index++] =
252						(zoffset * width * height + yoffset * width + xoffset) * m_n_components + component;
253				}
254			}
255		}
256	}
257
258	m_expected_data_buffer.assign(width * height * depth * m_n_components, clear_value);
259	for (glw::GLuint zoffset = copy_params.m_zoffset; zoffset < copy_params.m_zoffset + copy_params.m_depth; ++zoffset)
260	{
261		for (glw::GLuint yoffset = copy_params.m_yoffset; yoffset < copy_params.m_yoffset + copy_params.m_height;
262			 ++yoffset)
263		{
264			for (glw::GLuint xoffset = copy_params.m_xoffset; xoffset < copy_params.m_xoffset + copy_params.m_width;
265				 ++xoffset)
266			{
267				glw::GLuint* data_pointer =
268					&m_expected_data_buffer[(zoffset * width * height + yoffset * width + xoffset) * m_n_components];
269				for (glw::GLuint component = 0; component < m_n_components; ++component)
270				{
271					data_pointer[component] =
272						(zoffset * width * height + yoffset * width + xoffset) * m_n_components + component;
273				}
274			}
275		}
276	}
277}
278
279/** Creates a pixel unpack buffer that will be used as data source for filling a region of cube map array texture with data
280 * @param copy_params - data structure specifying which region of the data store to replace
281 */
282void TextureCubeMapArraySubImage3D::configurePixelUnpackBuffer(const SubImage3DCopyParams& copy_params)
283{
284	/* Get GL entry points */
285	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
286
287	/* generate buffer for pixel unpack buffer */
288	gl.genBuffers(1, &m_pixel_buffer_id);
289	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate buffer object!");
290
291	/* bind buffer to PIXEL_UNPACK_BUFFER binding point */
292	gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pixel_buffer_id);
293	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object!");
294
295	/* fill buffer with data */
296	gl.bufferData(GL_PIXEL_UNPACK_BUFFER,
297				  copy_params.m_width * copy_params.m_height * copy_params.m_depth * m_n_components *
298					  sizeof(glw::GLuint),
299				  &m_copy_data_buffer[0], GL_STATIC_READ);
300	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not fill buffer object's data store with data!");
301
302	gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
303	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object!");
304}
305
306/** Creates cube map array texture and fills it with data
307 * @param width       - width of the texture
308 * @param height      - height of the texture
309 * @param depth       - depth of the texture
310 * @param storType    - mutable or immutable storage type
311 * @param clear_value - value with which to initialize the texture's data store
312 */
313void TextureCubeMapArraySubImage3D::configureCubeMapArrayTexture(glw::GLuint width, glw::GLuint height,
314																 glw::GLuint depth, STORAGE_TYPE storType,
315																 glw::GLuint clear_value)
316{
317	/* Get GL entry points */
318	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
319
320	gl.genTextures(1, &m_tex_cube_map_array_id);
321	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object!");
322
323	gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_tex_cube_map_array_id);
324	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
325
326	/* used glTexImage3D() method if texture should be MUTABLE */
327	if (storType == ST_MUTABLE)
328	{
329		gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BASE_LEVEL, 0);
330		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture parameter.");
331		gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAX_LEVEL, 0);
332		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture parameter.");
333
334		DataBufferVec data_buffer(width * height * depth * m_n_components, clear_value);
335
336		gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA32UI, width, height, depth, 0, GL_RGBA_INTEGER,
337					  GL_UNSIGNED_INT, &data_buffer[0]);
338		GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating texture object's data store");
339	}
340	/* used glTexStorage3D() method if texture should be IMMUTABLE */
341	else
342	{
343		gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA32UI, width, height, depth);
344		GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating texture object's data store");
345
346		clearCubeMapArrayTexture(width, height, depth, clear_value);
347	}
348}
349
350/** Fills cube map array texture's data store with data
351 * @param width       - width of the texture
352 * @param height      - height of the texture
353 * @param depth       - depth of the texture
354 * @param clear_value - value with which to fill the texture's data store
355 */
356void TextureCubeMapArraySubImage3D::clearCubeMapArrayTexture(glw::GLuint width, glw::GLuint height, glw::GLuint depth,
357															 glw::GLuint clear_value)
358{
359	/* Get GL entry points */
360	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
361
362	DataBufferVec data_buffer(width * height * depth * m_n_components, clear_value);
363
364	gl.texSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, width, height, depth, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
365					 &data_buffer[0]);
366	GLU_EXPECT_NO_ERROR(gl.getError(), "Error filling texture object's data store with data");
367}
368
369/** Creates 2D texture that will be used as data source by the glCopyTexSubImage3D call
370 * @param copy_params - data structure specifying which region of the data store to replace
371 */
372void TextureCubeMapArraySubImage3D::configure2DTexture(const SubImage3DCopyParams& copy_params)
373{
374	/* Get GL entry points */
375	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
376
377	gl.genTextures(1, &m_tex_2d_id);
378	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate texture object!");
379
380	gl.bindTexture(GL_TEXTURE_2D, m_tex_2d_id);
381	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind texture object!");
382
383	gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, copy_params.m_width, copy_params.m_height);
384	GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating texture object's data store");
385
386	gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, copy_params.m_width, copy_params.m_height, GL_RGBA_INTEGER,
387					 GL_UNSIGNED_INT, &m_copy_data_buffer[0]);
388	GLU_EXPECT_NO_ERROR(gl.getError(), "Error filling texture object's data store with data");
389}
390
391/** Replaces region of cube map array texture's data store using texSubImage3D function
392 * @param copy_params    - data structure specifying which region of the data store to replace
393 * @param data_pointer   - pointer to the data that should end up in the specified region of the data store
394 */
395void TextureCubeMapArraySubImage3D::texSubImage3D(const SubImage3DCopyParams& copy_params,
396												  const glw::GLuint*		  data_pointer)
397{
398	/* Get GL entry points */
399	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
400
401	gl.texSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, copy_params.m_xoffset, copy_params.m_yoffset, copy_params.m_zoffset,
402					 copy_params.m_width, copy_params.m_height, copy_params.m_depth, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
403					 data_pointer);
404	GLU_EXPECT_NO_ERROR(gl.getError(), "Error filling texture object's data store with data");
405}
406
407/** Replaces region of cube map array texture's data store using copyTexSubImage3D function
408 * @param copy_params    - data structure specifying which region of the data store to replace
409 */
410void TextureCubeMapArraySubImage3D::copyTexSubImage3D(const SubImage3DCopyParams& copy_params)
411{
412	/* Get GL entry points */
413	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
414
415	gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tex_2d_id, 0);
416	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not attach texture object to framebuffer's attachment");
417
418	checkFramebufferStatus(GL_READ_FRAMEBUFFER);
419
420	gl.copyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, copy_params.m_xoffset, copy_params.m_yoffset,
421						 copy_params.m_zoffset, 0, 0, copy_params.m_width, copy_params.m_height);
422	GLU_EXPECT_NO_ERROR(gl.getError(), "Error filling texture object's data store with data");
423}
424
425/** Compares the region of data specified by copy_params taken from the cube map array texture's data store with
426 *  the reference data stored in m_data_buffer.
427 * @param width       - width of the texture
428 * @param height      - height of the texture
429 * @param depth       - depth of the texture
430 * @return            - true if the result of comparison is that the regions contain the same data, false otherwise
431 */
432bool TextureCubeMapArraySubImage3D::checkResults(glw::GLuint width, glw::GLuint height, glw::GLuint depth)
433{
434	/* Get GL entry points */
435	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
436
437	glw::GLuint   n_elements = width * height * depth * m_n_components;
438	DataBufferVec result_data_buffer(n_elements, 0);
439
440	for (glw::GLuint layer_nr = 0; layer_nr < depth; ++layer_nr)
441	{
442		/* attach one layer to framebuffer's attachment */
443		gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_tex_cube_map_array_id, 0, layer_nr);
444		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not attach texture object to framebuffer's attachment");
445
446		/* check framebuffer status */
447		checkFramebufferStatus(GL_READ_FRAMEBUFFER);
448
449		/* read data from the texture */
450		gl.readPixels(0, 0, width, height, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
451					  &result_data_buffer[layer_nr * width * height * m_n_components]);
452		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read pixels from framebuffer's attachment!");
453	}
454
455	return memcmp(&result_data_buffer[0], &m_expected_data_buffer[0], n_elements * sizeof(glw::GLuint)) == 0;
456}
457
458/** Perform a full test of testTexSubImage3D function on cube map array texture, both with client pointer and pixel unpack buffer
459 * @param width          - width of the texture
460 * @param height         - height of the texture
461 * @param depth          - depth of the texture
462 * @param copy_params    - data structure specifying which region of the cube map array to test
463 * @param test_passed    - a boolean variable set to false if at any stage of the test we experience wrong result
464 */
465void TextureCubeMapArraySubImage3D::testTexSubImage3D(glw::GLuint width, glw::GLuint height, glw::GLuint depth,
466													  const SubImage3DCopyParams& copy_params,
467													  glw::GLboolean&			  test_passed)
468{
469	/* Get GL entry points */
470	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
471
472	clearCubeMapArrayTexture(width, height, depth, 0);
473
474	texSubImage3D(copy_params, &m_copy_data_buffer[0]);
475
476	if (!checkResults(width, height, depth))
477	{
478		m_testCtx.getLog()
479			<< tcu::TestLog::Message
480			<< "glTexSubImage3D failed to copy data to texture cube map array's data store from client's memory\n"
481			<< "Texture Cube Map Array Dimensions (width, height, depth) "
482			<< "(" << width << "," << height << "," << depth << ")\n"
483			<< "Texture Cube Map Array Offsets (xoffset, yoffset, zoffset) "
484			<< "(" << copy_params.m_xoffset << "," << copy_params.m_yoffset << "," << copy_params.m_zoffset << ")\n"
485			<< "Texture Cube Map Array Copy Size (width, height, depth) "
486			<< "(" << copy_params.m_width << "," << copy_params.m_height << "," << copy_params.m_depth << ")\n"
487			<< tcu::TestLog::EndMessage;
488
489		test_passed = false;
490	}
491
492	clearCubeMapArrayTexture(width, height, depth, 0);
493
494	gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pixel_buffer_id);
495	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
496
497	texSubImage3D(copy_params, 0);
498
499	if (!checkResults(width, height, depth))
500	{
501		m_testCtx.getLog() << tcu::TestLog::Message << "glTexSubImage3D failed to copy data to texture cube map "
502													   "array's data store from GL_PIXEL_UNPACK_BUFFER\n"
503						   << "Texture Cube Map Array Dimensions (width, height, depth) "
504						   << "(" << width << "," << height << "," << depth << ")\n"
505						   << "Texture Cube Map Array Offsets (xoffset, yoffset, zoffset) "
506						   << "(" << copy_params.m_xoffset << "," << copy_params.m_yoffset << ","
507						   << copy_params.m_zoffset << ")\n"
508						   << "Texture Cube Map Array Copy Size (width, height, depth) "
509						   << "(" << copy_params.m_width << "," << copy_params.m_height << "," << copy_params.m_depth
510						   << ")\n"
511						   << tcu::TestLog::EndMessage;
512
513		test_passed = false;
514	}
515
516	gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
517	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
518}
519
520/** Perform a full test of copyTexSubImage3D function on cube map array texture
521 * @param width          - width of the texture
522 * @param height         - height of the texture
523 * @param depth          - depth of the texture
524 * @param copy_params    - data structure specifying which region of the cube map array to test
525 * @param test_passed    - a boolean variable set to false if at any stage of the test we experience wrong result
526 */
527void TextureCubeMapArraySubImage3D::testCopyTexSubImage3D(glw::GLuint width, glw::GLuint height, glw::GLuint depth,
528														  const SubImage3DCopyParams& copy_params,
529														  glw::GLboolean&			  test_passed)
530{
531	clearCubeMapArrayTexture(width, height, depth, 0);
532
533	copyTexSubImage3D(copy_params);
534
535	if (!checkResults(width, height, depth))
536	{
537		m_testCtx.getLog() << tcu::TestLog::Message
538						   << "glCopyTexSubImage3D failed to copy data to texture cube map array's data store\n"
539						   << "Texture Cube Map Array Dimensions (width, height, depth) "
540						   << "(" << width << "," << height << "," << depth << ")\n"
541						   << "Texture Cube Map Array Offsets (xoffset, yoffset, zoffset) "
542						   << "(" << copy_params.m_xoffset << "," << copy_params.m_yoffset << ","
543						   << copy_params.m_zoffset << ")\n"
544						   << "Texture Cube Map Array Copy Size (width, height, depth) "
545						   << "(" << copy_params.m_width << "," << copy_params.m_height << "," << copy_params.m_depth
546						   << ")\n"
547						   << tcu::TestLog::EndMessage;
548
549		test_passed = false;
550	}
551}
552
553/** Delete pixel unpack buffer */
554void TextureCubeMapArraySubImage3D::deletePixelUnpackBuffer()
555{
556	/* Get GL entry points */
557	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
558
559	/* Reset GLES configuration */
560	gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
561
562	/* Delete buffer object */
563	if (m_pixel_buffer_id != 0)
564	{
565		gl.deleteBuffers(1, &m_pixel_buffer_id);
566		m_pixel_buffer_id = 0;
567	}
568}
569
570/** Delete cube map array texture */
571void TextureCubeMapArraySubImage3D::deleteCubeMapArrayTexture()
572{
573	/* Get GL entry points */
574	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
575
576	/* Reset GLES configuration */
577	gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
578
579	/* Delete texture object */
580	if (m_tex_cube_map_array_id != 0)
581	{
582		gl.deleteTextures(1, &m_tex_cube_map_array_id);
583		m_tex_cube_map_array_id = 0;
584	}
585}
586
587/* Delete 2D texture that had been used as data source by the glCopyTexSubImage3D call */
588void TextureCubeMapArraySubImage3D::delete2DTexture()
589{
590	/* Get GL entry points */
591	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
592
593	/* Reset GLES configuration */
594	gl.bindTexture(GL_TEXTURE_2D, 0);
595
596	/* Delete texture object */
597	if (m_tex_2d_id != 0)
598	{
599		gl.deleteTextures(1, &m_tex_2d_id);
600		m_tex_2d_id = 0;
601	}
602}
603
604} // namespace glcts
605