1/*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 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 */ /*!
26 * \file  gl4cSparseTextureTests.cpp
27 * \brief Conformance tests for the GL_ARB_sparse_texture functionality.
28 */ /*-------------------------------------------------------------------*/
29
30#include "gl4cSparseTextureTests.hpp"
31#include "gluContextInfo.hpp"
32#include "gluDefs.hpp"
33#include "glwEnums.hpp"
34#include "glwFunctions.hpp"
35#include "tcuTestLog.hpp"
36
37#include <algorithm>
38#include <cmath>
39#include <cstdlib>
40#include <string.h>
41#include <vector>
42
43using namespace glw;
44using namespace glu;
45
46namespace gl4cts
47{
48
49typedef std::pair<GLint, GLint> IntPair;
50
51/** Verifies last query error and generate proper log message
52 *
53 * @param funcName         Verified function name
54 * @param target           Target for which texture is binded
55 * @param pname            Parameter name
56 * @param error            Generated error code
57 * @param expectedError    Expected error code
58 *
59 * @return Returns true if queried value is as expected, returns false otherwise
60 */
61bool SparseTextureUtils::verifyQueryError(std::stringstream& log, const char* funcName, GLint target, GLint pname,
62										  GLint error, GLint expectedError)
63{
64	if (error != expectedError)
65	{
66		log << "QueryError [" << funcName << " return wrong error code"
67			<< ", target: " << target << ", pname: " << pname << ", expected: " << expectedError
68			<< ", returned: " << error << "] - ";
69
70		return false;
71	}
72
73	return true;
74}
75
76/** Verifies last operation error and generate proper log message
77 *
78 * @param funcName         Verified function name
79 * @param mesage           Error message
80 * @param error            Generated error code
81 * @param expectedError    Expected error code
82 *
83 * @return Returns true if queried value is as expected, returns false otherwise
84 */
85bool SparseTextureUtils::verifyError(std::stringstream& log, const char* funcName, GLint error, GLint expectedError)
86{
87	if (error != expectedError)
88	{
89		log << "Error [" << funcName << " return wrong error code "
90			<< ", expectedError: " << expectedError << ", returnedError: " << error << "] - ";
91
92		return false;
93	}
94
95	return true;
96}
97
98/** Get minimal depth value for target
99 *
100 * @param target   Texture target
101 *
102 * @return Returns depth value
103 */
104GLint SparseTextureUtils::getTargetDepth(GLint target)
105{
106	GLint depth;
107
108	if (target == GL_TEXTURE_3D || target == GL_TEXTURE_1D_ARRAY || target == GL_TEXTURE_2D_ARRAY ||
109		target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY || target == GL_TEXTURE_CUBE_MAP)
110	{
111		depth = 1;
112	}
113	else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
114		depth = 6;
115	else
116		depth = 0;
117
118	return depth;
119}
120
121/** Queries for virtual page sizes
122 *
123 * @param gl           GL functions
124 * @param target       Texture target
125 * @param format       Texture internal format
126 * @param pageSizeX    Texture page size reference for X dimension
127 * @param pageSizeY    Texture page size reference for X dimension
128 * @param pageSizeZ    Texture page size reference for X dimension
129 **/
130void SparseTextureUtils::getTexturePageSizes(const glw::Functions& gl, glw::GLint target, glw::GLint format,
131											 glw::GLint& pageSizeX, glw::GLint& pageSizeY, glw::GLint& pageSizeZ)
132{
133	gl.getInternalformativ(target, format, GL_VIRTUAL_PAGE_SIZE_X_ARB, sizeof(pageSizeX), &pageSizeX);
134	GLU_EXPECT_NO_ERROR(gl.getError(), "getInternalformativ error occurred for GL_VIRTUAL_PAGE_SIZE_X_ARB");
135
136	gl.getInternalformativ(target, format, GL_VIRTUAL_PAGE_SIZE_Y_ARB, sizeof(pageSizeY), &pageSizeY);
137	GLU_EXPECT_NO_ERROR(gl.getError(), "getInternalformativ error occurred for GL_VIRTUAL_PAGE_SIZE_Y_ARB");
138
139	gl.getInternalformativ(target, format, GL_VIRTUAL_PAGE_SIZE_Z_ARB, sizeof(pageSizeZ), &pageSizeZ);
140	GLU_EXPECT_NO_ERROR(gl.getError(), "getInternalformativ error occurred for GL_VIRTUAL_PAGE_SIZE_Z_ARB");
141}
142
143/** Calculate texture size for specific mipmap
144 *
145 * @param target  GL functions
146 * @param state   Texture current state
147 * @param level   Texture mipmap level
148 * @param width   Texture output width
149 * @param height  Texture output height
150 * @param depth   Texture output depth
151 **/
152void SparseTextureUtils::getTextureLevelSize(GLint target, TextureState& state, GLint level, GLint& width,
153											 GLint& height, GLint& depth)
154{
155	width = state.width / (int)pow(2, level);
156	if (target == GL_TEXTURE_1D || target == GL_TEXTURE_1D_ARRAY)
157		height = 1;
158	else
159		height = state.height / (int)pow(2, level);
160
161	if (target == GL_TEXTURE_3D)
162		depth = state.depth / (int)pow(2, level);
163	else if (target == GL_TEXTURE_1D_ARRAY || target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_CUBE_MAP_ARRAY)
164		depth = state.depth;
165	else
166		depth = 1;
167}
168
169/* Texture static fields */
170const GLuint Texture::m_invalid_id = -1;
171
172/** Bind texture to target
173 *
174 * @param gl       GL API functions
175 * @param id       Id of texture
176 * @param tex_type Type of texture
177 **/
178void Texture::Bind(const Functions& gl, GLuint id, GLenum target)
179{
180	gl.bindTexture(target, id);
181	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
182}
183
184/** Generate texture instance
185 *
186 * @param gl     GL functions
187 * @param out_id Id of texture
188 **/
189void Texture::Generate(const Functions& gl, GLuint& out_id)
190{
191	GLuint id = m_invalid_id;
192
193	gl.genTextures(1, &id);
194	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
195
196	if (m_invalid_id == id)
197	{
198		TCU_FAIL("Invalid id");
199	}
200
201	out_id = id;
202}
203
204/** Delete texture instance
205 *
206 * @param gl    GL functions
207 * @param id    Id of texture
208 **/
209void Texture::Delete(const Functions& gl, GLuint& id)
210{
211	gl.deleteTextures(1, &id);
212	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
213}
214
215/** Allocate storage for texture
216 *
217 * @param gl              GL functions
218 * @param target          Texture target
219 * @param levels          Number of levels
220 * @param internal_format Internal format of texture
221 * @param width           Width of texture
222 * @param height          Height of texture
223 * @param depth           Depth of texture
224 **/
225void Texture::Storage(const Functions& gl, GLenum target, GLsizei levels, GLenum internal_format, GLuint width,
226					  GLuint height, GLuint depth)
227{
228	switch (target)
229	{
230	case GL_TEXTURE_1D:
231		gl.texStorage1D(target, levels, internal_format, width);
232		break;
233	case GL_TEXTURE_1D_ARRAY:
234		gl.texStorage2D(target, levels, internal_format, width, depth);
235		break;
236	case GL_TEXTURE_2D:
237	case GL_TEXTURE_RECTANGLE:
238	case GL_TEXTURE_CUBE_MAP:
239		gl.texStorage2D(target, levels, internal_format, width, height);
240		break;
241	case GL_TEXTURE_3D:
242	case GL_TEXTURE_2D_ARRAY:
243	case GL_TEXTURE_CUBE_MAP_ARRAY:
244		gl.texStorage3D(target, levels, internal_format, width, height, depth);
245		break;
246	case GL_TEXTURE_2D_MULTISAMPLE:
247		gl.texStorage2DMultisample(target, levels /* samples */, internal_format, width, height, GL_TRUE);
248		break;
249	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
250		gl.texStorage3DMultisample(target, levels /* samples */, internal_format, width, height, depth, GL_TRUE);
251		break;
252	default:
253		TCU_FAIL("Invliad enum");
254		break;
255	}
256}
257
258/** Get texture data
259 *
260 * @param gl       GL functions
261 * @param target   Texture target
262 * @param format   Format of data
263 * @param type     Type of data
264 * @param out_data Buffer for data
265 **/
266void Texture::GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format,
267					  glw::GLenum type, glw::GLvoid* out_data)
268{
269	gl.getTexImage(target, level, format, type, out_data);
270}
271
272/** Set contents of texture
273 *
274 * @param gl              GL functions
275 * @param target          Texture target
276 * @param level           Mipmap level
277 * @param x               X offset
278 * @param y               Y offset
279 * @param z               Z offset
280 * @param width           Width of texture
281 * @param height          Height of texture
282 * @param depth           Depth of texture
283 * @param format          Format of data
284 * @param type            Type of data
285 * @param pixels          Buffer with image data
286 **/
287void Texture::SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
288					   glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
289					   glw::GLenum type, const glw::GLvoid* pixels)
290{
291	switch (target)
292	{
293	case GL_TEXTURE_1D:
294		gl.texSubImage1D(target, level, x, width, format, type, pixels);
295		break;
296	case GL_TEXTURE_1D_ARRAY:
297		gl.texSubImage2D(target, level, x, y, width, depth, format, type, pixels);
298		break;
299	case GL_TEXTURE_2D:
300	case GL_TEXTURE_RECTANGLE:
301		gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
302		break;
303	case GL_TEXTURE_CUBE_MAP:
304		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels);
305		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels);
306		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels);
307		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels);
308		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels);
309		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels);
310		break;
311	case GL_TEXTURE_3D:
312	case GL_TEXTURE_2D_ARRAY:
313	case GL_TEXTURE_CUBE_MAP_ARRAY:
314		gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
315		break;
316	default:
317		TCU_FAIL("Invliad enum");
318		break;
319	}
320}
321
322/** Constructor.
323 *
324 *  @param context     Rendering context
325 */
326TextureParameterQueriesTestCase::TextureParameterQueriesTestCase(deqp::Context& context)
327	: TestCase(
328		  context, "TextureParameterQueries",
329		  "Implements all glTexParameter* and glGetTexParameter* queries tests described in CTS_ARB_sparse_texture")
330{
331	/* Left blank intentionally */
332}
333
334/** Stub init method */
335void TextureParameterQueriesTestCase::init()
336{
337	mSupportedTargets.push_back(GL_TEXTURE_2D);
338	mSupportedTargets.push_back(GL_TEXTURE_2D_ARRAY);
339	mSupportedTargets.push_back(GL_TEXTURE_CUBE_MAP);
340	mSupportedTargets.push_back(GL_TEXTURE_CUBE_MAP_ARRAY);
341	mSupportedTargets.push_back(GL_TEXTURE_3D);
342	mSupportedTargets.push_back(GL_TEXTURE_RECTANGLE);
343
344	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture2"))
345	{
346		mNotSupportedTargets.push_back(GL_TEXTURE_1D);
347		mNotSupportedTargets.push_back(GL_TEXTURE_1D_ARRAY);
348		mNotSupportedTargets.push_back(GL_TEXTURE_2D_MULTISAMPLE);
349		mNotSupportedTargets.push_back(GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
350	}
351	else
352	{
353		mNotSupportedTargets.push_back(GL_TEXTURE_1D);
354		mNotSupportedTargets.push_back(GL_TEXTURE_1D_ARRAY);
355	}
356}
357
358/** Executes test iteration.
359 *
360 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
361 */
362tcu::TestNode::IterateResult TextureParameterQueriesTestCase::iterate()
363{
364	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture"))
365	{
366		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
367		return STOP;
368	}
369
370	const Functions& gl = m_context.getRenderContext().getFunctions();
371
372	bool result = true;
373
374	GLuint texture;
375
376	//Iterate through supported targets
377
378	for (std::vector<glw::GLint>::const_iterator iter = mSupportedTargets.begin(); iter != mSupportedTargets.end();
379		 ++iter)
380	{
381		const GLint& target = *iter;
382
383		mLog.str("");
384
385		Texture::Generate(gl, texture);
386		Texture::Bind(gl, texture, target);
387
388		result = testTextureSparseARB(gl, target) && testVirtualPageSizeIndexARB(gl, target) &&
389				 testNumSparseLevelsARB(gl, target);
390
391		Texture::Delete(gl, texture);
392
393		if (!result)
394		{
395			m_testCtx.getLog() << tcu::TestLog::Message << mLog.str() << "Fail [positive tests]"
396							   << tcu::TestLog::EndMessage;
397			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
398			return STOP;
399		}
400	}
401
402	//Iterate through not supported targets
403	for (std::vector<glw::GLint>::const_iterator iter = mNotSupportedTargets.begin();
404		 iter != mNotSupportedTargets.end(); ++iter)
405	{
406		const GLint& target = *iter;
407
408		mLog.str("");
409
410		Texture::Generate(gl, texture);
411		Texture::Bind(gl, texture, target);
412
413		result = testTextureSparseARB(gl, target, GL_INVALID_VALUE);
414
415		Texture::Delete(gl, texture);
416
417		if (!result)
418		{
419			m_testCtx.getLog() << tcu::TestLog::Message << mLog.str() << "Fail [positive tests]"
420							   << tcu::TestLog::EndMessage;
421			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail on negative tests");
422			return STOP;
423		}
424	}
425
426	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
427	return STOP;
428}
429
430/** Testing texParameter* functions for binded texture and GL_TEXTURE_SPARSE_ARB parameter name
431 *
432 * @param gl               GL API functions
433 * @param target           Target for which texture is binded
434 * @param expectedError    Expected error code (default value GL_NO_ERROR)
435 *
436 * @return Returns true if queried value is as expected, returns false otherwise
437 */
438bool TextureParameterQueriesTestCase::testTextureSparseARB(const Functions& gl, GLint target, GLint expectedError)
439{
440	const GLint pname = GL_TEXTURE_SPARSE_ARB;
441
442	bool result = true;
443
444	GLint   testValueInt;
445	GLuint  testValueUInt;
446	GLfloat testValueFloat;
447
448	mLog << "Testing TEXTURE_SPARSE_ARB for target: " << target << " - ";
449
450	//Check getTexParameter* default value
451	if (expectedError == GL_NO_ERROR)
452		result = checkGetTexParameter(gl, target, pname, GL_FALSE);
453
454	//Check getTexParameter* for manually set values
455	if (result)
456	{
457		//Query to set parameter
458		gl.texParameteri(target, pname, GL_TRUE);
459		if (expectedError == GL_NO_ERROR)
460		{
461			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred.");
462			result = checkGetTexParameter(gl, target, pname, GL_TRUE);
463
464			//If no error verification reset TEXTURE_SPARSE_ARB value
465			gl.texParameteri(target, pname, GL_FALSE);
466			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred.");
467		}
468		else
469			result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameteri", target, pname, gl.getError(),
470														  expectedError);
471	}
472
473	if (result)
474	{
475		gl.texParameterf(target, pname, GL_TRUE);
476		if (expectedError == GL_NO_ERROR)
477		{
478			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameterf error occurred.");
479			result = checkGetTexParameter(gl, target, pname, GL_TRUE);
480
481			gl.texParameteri(target, pname, GL_FALSE);
482			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred.");
483		}
484		else
485			result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameterf", target, pname, gl.getError(),
486														  expectedError);
487	}
488
489	if (result)
490	{
491		testValueInt = GL_TRUE;
492		gl.texParameteriv(target, pname, &testValueInt);
493		if (expectedError == GL_NO_ERROR)
494		{
495			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteriv error occurred.");
496			result = checkGetTexParameter(gl, target, pname, GL_TRUE);
497
498			gl.texParameteri(target, pname, GL_FALSE);
499			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred.");
500		}
501		else
502			result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameteriv", target, pname, gl.getError(),
503														  expectedError);
504	}
505
506	if (result)
507	{
508		testValueFloat = (GLfloat)GL_TRUE;
509		gl.texParameterfv(target, pname, &testValueFloat);
510		if (expectedError == GL_NO_ERROR)
511		{
512			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameterfv error occurred.");
513			result = checkGetTexParameter(gl, target, pname, GL_TRUE);
514
515			gl.texParameteri(target, pname, GL_FALSE);
516			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred.");
517		}
518		else
519			result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameterfv", target, pname, gl.getError(),
520														  expectedError);
521	}
522
523	if (result)
524	{
525		testValueInt = GL_TRUE;
526		gl.texParameterIiv(target, pname, &testValueInt);
527		if (expectedError == GL_NO_ERROR)
528		{
529			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameterIiv error occurred.");
530			result = checkGetTexParameter(gl, target, pname, GL_TRUE);
531
532			gl.texParameteri(target, pname, GL_FALSE);
533			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred.");
534		}
535		else
536			result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameterIiv", target, pname, gl.getError(),
537														  expectedError);
538	}
539
540	if (result)
541	{
542		testValueUInt = GL_TRUE;
543		gl.texParameterIuiv(target, pname, &testValueUInt);
544		if (expectedError == GL_NO_ERROR)
545		{
546			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameterIuiv error occurred.");
547			result = checkGetTexParameter(gl, target, pname, GL_TRUE);
548
549			gl.texParameteri(target, pname, GL_FALSE);
550			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred.");
551		}
552		else
553			result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameterIuiv", target, pname, gl.getError(),
554														  expectedError);
555	}
556
557	return result;
558}
559
560/** Testing texParameter* functions for binded texture and GL_VIRTUAL_PAGE_SIZE_INDEX_ARB parameter name
561 *
562 * @param gl               GL API functions
563 * @param target           Target for which texture is binded
564 * @param expectedError    Expected error code (default value GL_NO_ERROR)
565 *
566 * @return Returns true if queried value is as expected, returns false otherwise
567 */
568bool TextureParameterQueriesTestCase::testVirtualPageSizeIndexARB(const Functions& gl, GLint target,
569																  GLint expectedError)
570{
571	const GLint pname = GL_VIRTUAL_PAGE_SIZE_INDEX_ARB;
572
573	bool result = true;
574
575	GLint   testValueInt;
576	GLuint  testValueUInt;
577	GLfloat testValueFloat;
578
579	mLog << "Testing VIRTUAL_PAGE_SIZE_INDEX_ARB for target: " << target << " - ";
580
581	//Check getTexParameter* default value
582	if (expectedError == GL_NO_ERROR)
583		result = checkGetTexParameter(gl, target, pname, 0);
584
585	//Check getTexParameter* for manually set values
586	if (result)
587	{
588		gl.texParameteri(target, pname, 1);
589		if (expectedError == GL_NO_ERROR)
590		{
591			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred");
592			result = checkGetTexParameter(gl, target, pname, 1);
593
594			//If no error verification reset TEXTURE_SPARSE_ARB value
595			gl.texParameteri(target, pname, 0);
596			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred");
597		}
598		else
599			result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameteri", target, pname, gl.getError(),
600														  expectedError);
601	}
602
603	if (result)
604	{
605		gl.texParameterf(target, pname, 2.0f);
606		if (expectedError == GL_NO_ERROR)
607		{
608			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameterf error occurred");
609			result = checkGetTexParameter(gl, target, pname, 2);
610
611			gl.texParameteri(target, pname, 0);
612			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred");
613		}
614		else
615			result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameterf", target, pname, gl.getError(),
616														  expectedError);
617	}
618
619	if (result)
620	{
621		testValueInt = 8;
622		gl.texParameteriv(target, pname, &testValueInt);
623		if (expectedError == GL_NO_ERROR)
624		{
625			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteriv error occurred");
626			result = checkGetTexParameter(gl, target, pname, 8);
627
628			gl.texParameteri(target, pname, 0);
629			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred");
630		}
631		else
632			result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameteriv", target, pname, gl.getError(),
633														  expectedError);
634	}
635
636	if (result)
637	{
638		testValueFloat = 10.0f;
639		gl.texParameterfv(target, pname, &testValueFloat);
640		if (expectedError == GL_NO_ERROR)
641		{
642			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameterfv error occurred");
643			result = checkGetTexParameter(gl, target, pname, 10);
644
645			gl.texParameteri(target, pname, 0);
646			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred");
647		}
648		else
649			result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameterfv", target, pname, gl.getError(),
650														  expectedError);
651	}
652
653	if (result)
654	{
655		testValueInt = 6;
656		gl.texParameterIiv(target, pname, &testValueInt);
657		if (expectedError == GL_NO_ERROR)
658		{
659			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameterIiv error occurred");
660			result = checkGetTexParameter(gl, target, pname, 6);
661
662			gl.texParameteri(target, pname, 0);
663			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred");
664		}
665		else
666			result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameterIiv", target, pname, gl.getError(),
667														  expectedError);
668	}
669
670	if (result)
671	{
672		testValueUInt = 16;
673		gl.texParameterIuiv(target, pname, &testValueUInt);
674		if (expectedError == GL_NO_ERROR)
675		{
676			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameterIuiv error occurred");
677			result = checkGetTexParameter(gl, target, pname, 16);
678
679			gl.texParameteri(target, pname, 0);
680			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri error occurred");
681		}
682		else
683			result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameterIuiv", target, pname, gl.getError(),
684														  expectedError);
685	}
686
687	return result;
688}
689
690/** Testing getTexParameter* functions for binded texture and GL_NUM_SPARSE_LEVELS_ARB parameter name
691 *
692 * @param gl               GL API functions
693 * @param target           Target for which texture is binded
694 * @param expectedError    Expected error code (default value GL_NO_ERROR)
695 *
696 * @return Returns true if no error code was generated, throws exception otherwise
697 */
698bool TextureParameterQueriesTestCase::testNumSparseLevelsARB(const Functions& gl, GLint target)
699{
700	const GLint pname = GL_NUM_SPARSE_LEVELS_ARB;
701
702	bool result = true;
703
704	GLint   value_int;
705	GLuint  value_uint;
706	GLfloat value_float;
707
708	mLog << "Testing NUM_SPARSE_LEVELS_ARB for target: " << target << " - ";
709
710	gl.getTexParameteriv(target, pname, &value_int);
711	result = SparseTextureUtils::verifyError(mLog, "glGetTexParameteriv", gl.getError(), GL_NO_ERROR);
712
713	if (result)
714	{
715		gl.getTexParameterfv(target, pname, &value_float);
716		result = SparseTextureUtils::verifyError(mLog, "glGetTexParameterfv", gl.getError(), GL_NO_ERROR);
717
718		if (result)
719		{
720			gl.getTexParameterIiv(target, pname, &value_int);
721			result = SparseTextureUtils::verifyError(mLog, "glGetGexParameterIiv", gl.getError(), GL_NO_ERROR);
722
723			if (result)
724			{
725				gl.getTexParameterIuiv(target, pname, &value_uint);
726				result = SparseTextureUtils::verifyError(mLog, "getTexParameterIuiv", gl.getError(), GL_NO_ERROR);
727			}
728		}
729	}
730
731	return result;
732}
733
734/** Checking if getTexParameter* for binded texture returns value as expected
735 *
736 * @param gl           GL API functions
737 * @param target       Target for which texture is binded
738 * @param pname        Parameter name
739 * @param expected     Expected value (int because function is designed to query only int and boolean parameters)
740 *
741 * @return Returns true if queried value is as expected, returns false otherwise
742 */
743bool TextureParameterQueriesTestCase::checkGetTexParameter(const Functions& gl, GLint target, GLint pname,
744														   GLint expected)
745{
746	bool result = true;
747
748	GLint   value_int;
749	GLuint  value_uint;
750	GLfloat value_float;
751
752	mLog << "Testing GetTexParameter for target: " << target << " - ";
753
754	gl.getTexParameteriv(target, pname, &value_int);
755	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameteriv error occurred");
756	if (value_int != expected)
757	{
758		mLog << "glGetTexParameteriv return wrong value"
759			 << ", target: " << target << ", pname: " << pname << ", expected: " << expected
760			 << ", returned: " << value_int << " - ";
761
762		result = false;
763	}
764
765	gl.getTexParameterfv(target, pname, &value_float);
766	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameterfv error occurred");
767	if ((GLint)value_float != expected)
768	{
769		mLog << "glGetTexParameterfv return wrong value"
770			 << ", target: " << target << ", pname: " << pname << ", expected: " << expected
771			 << ", returned: " << (GLint)value_float << " - ";
772
773		result = false;
774	}
775
776	gl.getTexParameterIiv(target, pname, &value_int);
777	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetGexParameterIiv error occurred");
778	if (value_int != expected)
779	{
780		mLog << "glGetGexParameterIiv return wrong value"
781			 << ", target: " << target << ", pname: " << pname << ", expected: " << expected
782			 << ", returned: " << value_int << " - ";
783
784		result = false;
785	}
786
787	gl.getTexParameterIuiv(target, pname, &value_uint);
788	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetGexParameterIui error occurred");
789	if ((GLint)value_uint != expected)
790	{
791		mLog << "glGetGexParameterIui return wrong value"
792			 << ", target: " << target << ", pname: " << pname << ", expected: " << expected
793			 << ", returned: " << (GLint)value_uint << " - ";
794
795		result = false;
796	}
797
798	return result;
799}
800
801/** Constructor.
802 *
803 *  @param context     Rendering context
804 */
805InternalFormatQueriesTestCase::InternalFormatQueriesTestCase(deqp::Context& context)
806	: TestCase(context, "InternalFormatQueries",
807			   "Implements GetInternalformat query tests described in CTS_ARB_sparse_texture")
808{
809	/* Left blank intentionally */
810}
811
812/** Stub init method */
813void InternalFormatQueriesTestCase::init()
814{
815	mSupportedTargets.push_back(GL_TEXTURE_1D);
816	mSupportedTargets.push_back(GL_TEXTURE_1D_ARRAY);
817	mSupportedTargets.push_back(GL_TEXTURE_2D);
818	mSupportedTargets.push_back(GL_TEXTURE_2D_ARRAY);
819	mSupportedTargets.push_back(GL_TEXTURE_3D);
820	mSupportedTargets.push_back(GL_TEXTURE_CUBE_MAP);
821	mSupportedTargets.push_back(GL_TEXTURE_CUBE_MAP_ARRAY);
822	mSupportedTargets.push_back(GL_TEXTURE_RECTANGLE);
823	mSupportedTargets.push_back(GL_TEXTURE_BUFFER);
824	mSupportedTargets.push_back(GL_RENDERBUFFER);
825	mSupportedTargets.push_back(GL_TEXTURE_2D_MULTISAMPLE);
826	mSupportedTargets.push_back(GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
827
828	mSupportedInternalFormats.push_back(GL_R8);
829	mSupportedInternalFormats.push_back(GL_R8_SNORM);
830	mSupportedInternalFormats.push_back(GL_R16);
831	mSupportedInternalFormats.push_back(GL_R16_SNORM);
832	mSupportedInternalFormats.push_back(GL_RG8);
833	mSupportedInternalFormats.push_back(GL_RG8_SNORM);
834	mSupportedInternalFormats.push_back(GL_RG16);
835	mSupportedInternalFormats.push_back(GL_RG16_SNORM);
836	mSupportedInternalFormats.push_back(GL_RGB565);
837	mSupportedInternalFormats.push_back(GL_RGBA8);
838	mSupportedInternalFormats.push_back(GL_RGBA8_SNORM);
839	mSupportedInternalFormats.push_back(GL_RGB10_A2);
840	mSupportedInternalFormats.push_back(GL_RGB10_A2UI);
841	mSupportedInternalFormats.push_back(GL_RGBA16);
842	mSupportedInternalFormats.push_back(GL_RGBA16_SNORM);
843	mSupportedInternalFormats.push_back(GL_R16F);
844	mSupportedInternalFormats.push_back(GL_RG16F);
845	mSupportedInternalFormats.push_back(GL_RGBA16F);
846	mSupportedInternalFormats.push_back(GL_R32F);
847	mSupportedInternalFormats.push_back(GL_RG32F);
848	mSupportedInternalFormats.push_back(GL_RGBA32F);
849	mSupportedInternalFormats.push_back(GL_R11F_G11F_B10F);
850	mSupportedInternalFormats.push_back(GL_RGB9_E5);
851	mSupportedInternalFormats.push_back(GL_R8I);
852	mSupportedInternalFormats.push_back(GL_R8UI);
853	mSupportedInternalFormats.push_back(GL_R16I);
854	mSupportedInternalFormats.push_back(GL_R16UI);
855	mSupportedInternalFormats.push_back(GL_R32I);
856	mSupportedInternalFormats.push_back(GL_R32UI);
857	mSupportedInternalFormats.push_back(GL_RG8I);
858	mSupportedInternalFormats.push_back(GL_RG8UI);
859	mSupportedInternalFormats.push_back(GL_RG16I);
860	mSupportedInternalFormats.push_back(GL_RG16UI);
861	mSupportedInternalFormats.push_back(GL_RG32I);
862	mSupportedInternalFormats.push_back(GL_RG32UI);
863	mSupportedInternalFormats.push_back(GL_RGBA8I);
864	mSupportedInternalFormats.push_back(GL_RGBA8UI);
865	mSupportedInternalFormats.push_back(GL_RGBA16I);
866	mSupportedInternalFormats.push_back(GL_RGBA16UI);
867	mSupportedInternalFormats.push_back(GL_RGBA32I);
868}
869
870/** Executes test iteration.
871 *
872 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
873 */
874tcu::TestNode::IterateResult InternalFormatQueriesTestCase::iterate()
875{
876	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture"))
877	{
878		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
879		return STOP;
880	}
881
882	const Functions& gl = m_context.getRenderContext().getFunctions();
883
884	bool result = true;
885
886	mLog << "Testing getInternalformativ - ";
887
888	for (std::vector<glw::GLint>::const_iterator iter = mSupportedTargets.begin(); iter != mSupportedTargets.end();
889		 ++iter)
890	{
891		const GLint& target = *iter;
892
893		for (std::vector<glw::GLint>::const_iterator formIter = mSupportedInternalFormats.begin();
894			 formIter != mSupportedInternalFormats.end(); ++formIter)
895		{
896			const GLint& format = *formIter;
897			GLint		 value;
898
899			gl.getInternalformativ(target, format, GL_NUM_VIRTUAL_PAGE_SIZES_ARB, sizeof(value), &value);
900			GLU_EXPECT_NO_ERROR(gl.getError(), "getInternalformativ error occurred for GL_NUM_VIRTUAL_PAGE_SIZES_ARB");
901			if (value == 0)
902			{
903				mLog << "getInternalformativ for GL_NUM_VIRTUAL_PAGE_SIZES_ARB, target: " << target
904					 << ", format: " << format << " returns wrong value: " << value << " - ";
905
906				result = false;
907			}
908
909			if (result)
910			{
911				GLint pageSizeX;
912				GLint pageSizeY;
913				GLint pageSizeZ;
914				SparseTextureUtils::getTexturePageSizes(gl, target, format, pageSizeX, pageSizeY, pageSizeZ);
915			}
916			else
917			{
918				m_testCtx.getLog() << tcu::TestLog::Message << mLog.str() << "Fail" << tcu::TestLog::EndMessage;
919				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
920				return STOP;
921			}
922		}
923	}
924
925	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
926
927	return STOP;
928}
929
930/** Constructor.
931 *
932 *  @param context     Rendering context
933 */
934SimpleQueriesTestCase::SimpleQueriesTestCase(deqp::Context& context)
935	: TestCase(context, "SimpleQueries", "Implements Get* queries tests described in CTS_ARB_sparse_texture")
936{
937	/* Left blank intentionally */
938}
939
940/** Executes test iteration.
941 *
942 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
943 */
944tcu::TestNode::IterateResult SimpleQueriesTestCase::iterate()
945{
946	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture"))
947	{
948		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
949		return STOP;
950	}
951
952	const Functions& gl = m_context.getRenderContext().getFunctions();
953
954	testSipmleQueries(gl, GL_MAX_SPARSE_TEXTURE_SIZE_ARB);
955	testSipmleQueries(gl, GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB);
956	testSipmleQueries(gl, GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB);
957	testSipmleQueries(gl, GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB);
958
959	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
960	return STOP;
961}
962
963void SimpleQueriesTestCase::testSipmleQueries(const Functions& gl, GLint pname)
964{
965	std::stringstream log;
966	log << "Testing simple query for pname: " << pname << " - ";
967
968	bool result = true;
969
970	GLint	 value_int;
971	GLint64   value_int64;
972	GLfloat   value_float;
973	GLdouble  value_double;
974	GLboolean value_bool;
975
976	gl.getIntegerv(pname, &value_int);
977	result = SparseTextureUtils::verifyError(log, "getIntegerv", gl.getError(), GL_NO_ERROR);
978
979	if (result)
980	{
981		gl.getInteger64v(pname, &value_int64);
982		result = SparseTextureUtils::verifyError(log, "getInteger64v", gl.getError(), GL_NO_ERROR);
983
984		if (result)
985		{
986			gl.getFloatv(pname, &value_float);
987			result = SparseTextureUtils::verifyError(log, "getFloatv", gl.getError(), GL_NO_ERROR);
988
989			if (result)
990			{
991				gl.getDoublev(pname, &value_double);
992				result = SparseTextureUtils::verifyError(log, "getDoublev", gl.getError(), GL_NO_ERROR);
993
994				if (result)
995				{
996					gl.getBooleanv(pname, &value_bool);
997					result = SparseTextureUtils::verifyError(log, "getBooleanv", gl.getError(), GL_NO_ERROR);
998				}
999			}
1000		}
1001	}
1002
1003	if (!result)
1004	{
1005		TCU_FAIL(log.str().c_str());
1006	}
1007}
1008
1009/** Constructor.
1010 *
1011 *  @param context     Rendering context
1012 */
1013SparseTextureAllocationTestCase::SparseTextureAllocationTestCase(deqp::Context& context)
1014	: TestCase(context, "SparseTextureAllocation", "Verifies TexStorage* functionality added in CTS_ARB_sparse_texture")
1015{
1016	/* Left blank intentionally */
1017}
1018
1019/** Constructor.
1020 *
1021 *  @param context     Rendering context
1022 */
1023SparseTextureAllocationTestCase::SparseTextureAllocationTestCase(deqp::Context& context, const char* name,
1024																 const char* description)
1025	: TestCase(context, name, description)
1026{
1027	/* Left blank intentionally */
1028}
1029
1030/** Initializes the test group contents. */
1031void SparseTextureAllocationTestCase::init()
1032{
1033	mSupportedTargets.push_back(GL_TEXTURE_2D);
1034	mSupportedTargets.push_back(GL_TEXTURE_2D_ARRAY);
1035	mSupportedTargets.push_back(GL_TEXTURE_CUBE_MAP);
1036	mSupportedTargets.push_back(GL_TEXTURE_CUBE_MAP_ARRAY);
1037	mSupportedTargets.push_back(GL_TEXTURE_3D);
1038	mSupportedTargets.push_back(GL_TEXTURE_RECTANGLE);
1039
1040	mFullArrayTargets.push_back(GL_TEXTURE_1D_ARRAY);
1041	mFullArrayTargets.push_back(GL_TEXTURE_2D_ARRAY);
1042	mFullArrayTargets.push_back(GL_TEXTURE_CUBE_MAP);
1043	mFullArrayTargets.push_back(GL_TEXTURE_CUBE_MAP_ARRAY);
1044
1045	mSupportedInternalFormats.push_back(GL_R8);
1046	mSupportedInternalFormats.push_back(GL_R8_SNORM);
1047	mSupportedInternalFormats.push_back(GL_R16);
1048	mSupportedInternalFormats.push_back(GL_R16_SNORM);
1049	mSupportedInternalFormats.push_back(GL_RG8);
1050	mSupportedInternalFormats.push_back(GL_RG8_SNORM);
1051	mSupportedInternalFormats.push_back(GL_RG16);
1052	mSupportedInternalFormats.push_back(GL_RG16_SNORM);
1053	mSupportedInternalFormats.push_back(GL_RGB565);
1054	mSupportedInternalFormats.push_back(GL_RGBA8);
1055	mSupportedInternalFormats.push_back(GL_RGBA8_SNORM);
1056	mSupportedInternalFormats.push_back(GL_RGB10_A2);
1057	mSupportedInternalFormats.push_back(GL_RGB10_A2UI);
1058	mSupportedInternalFormats.push_back(GL_RGBA16);
1059	mSupportedInternalFormats.push_back(GL_RGBA16_SNORM);
1060	mSupportedInternalFormats.push_back(GL_R16F);
1061	mSupportedInternalFormats.push_back(GL_RG16F);
1062	mSupportedInternalFormats.push_back(GL_RGBA16F);
1063	mSupportedInternalFormats.push_back(GL_R32F);
1064	mSupportedInternalFormats.push_back(GL_RG32F);
1065	mSupportedInternalFormats.push_back(GL_RGBA32F);
1066	mSupportedInternalFormats.push_back(GL_R11F_G11F_B10F);
1067	mSupportedInternalFormats.push_back(GL_RGB9_E5);
1068	mSupportedInternalFormats.push_back(GL_R8I);
1069	mSupportedInternalFormats.push_back(GL_R8UI);
1070	mSupportedInternalFormats.push_back(GL_R16I);
1071	mSupportedInternalFormats.push_back(GL_R16UI);
1072	mSupportedInternalFormats.push_back(GL_R32I);
1073	mSupportedInternalFormats.push_back(GL_R32UI);
1074	mSupportedInternalFormats.push_back(GL_RG8I);
1075	mSupportedInternalFormats.push_back(GL_RG8UI);
1076	mSupportedInternalFormats.push_back(GL_RG16I);
1077	mSupportedInternalFormats.push_back(GL_RG16UI);
1078	mSupportedInternalFormats.push_back(GL_RG32I);
1079	mSupportedInternalFormats.push_back(GL_RG32UI);
1080	mSupportedInternalFormats.push_back(GL_RGBA8I);
1081	mSupportedInternalFormats.push_back(GL_RGBA8UI);
1082	mSupportedInternalFormats.push_back(GL_RGBA16I);
1083	mSupportedInternalFormats.push_back(GL_RGBA16UI);
1084	mSupportedInternalFormats.push_back(GL_RGBA32I);
1085}
1086
1087/** Executes test iteration.
1088 *
1089 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1090 */
1091tcu::TestNode::IterateResult SparseTextureAllocationTestCase::iterate()
1092{
1093	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture"))
1094	{
1095		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
1096		return STOP;
1097	}
1098
1099	const Functions& gl = m_context.getRenderContext().getFunctions();
1100
1101	bool result = true;
1102
1103	for (std::vector<glw::GLint>::const_iterator iter = mSupportedTargets.begin(); iter != mSupportedTargets.end();
1104		 ++iter)
1105	{
1106		const GLint& target = *iter;
1107
1108		for (std::vector<glw::GLint>::const_iterator formIter = mSupportedInternalFormats.begin();
1109			 formIter != mSupportedInternalFormats.end(); ++formIter)
1110		{
1111			const GLint& format = *formIter;
1112
1113			mLog.str("");
1114			mLog << "Testing sparse texture allocation for target: " << target << ", format: " << format << " - ";
1115
1116			result = positiveTesting(gl, target, format) && verifyTexParameterErrors(gl, target, format) &&
1117					 verifyTexStorageVirtualPageSizeIndexError(gl, target, format) &&
1118					 verifyTexStorageFullArrayCubeMipmapsError(gl, target, format) &&
1119					 verifyTexStorageInvalidValueErrors(gl, target, format);
1120
1121			if (!result)
1122			{
1123				m_testCtx.getLog() << tcu::TestLog::Message << mLog.str() << "Fail" << tcu::TestLog::EndMessage;
1124				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1125				return STOP;
1126			}
1127		}
1128	}
1129
1130	for (std::vector<glw::GLint>::const_iterator iter = mFullArrayTargets.begin(); iter != mFullArrayTargets.end();
1131		 ++iter)
1132	{
1133		const GLint& target = *iter;
1134
1135		for (std::vector<glw::GLint>::const_iterator formIter = mSupportedInternalFormats.begin();
1136			 formIter != mSupportedInternalFormats.end(); ++formIter)
1137		{
1138			const GLint& format = *formIter;
1139
1140			mLog.str("");
1141			mLog << "Testing sparse texture allocation for target [full array]: " << target << ", format: " << format
1142				 << " - ";
1143
1144			result = verifyTexStorageFullArrayCubeMipmapsError(gl, target, format) &&
1145					 verifyTexStorageInvalidValueErrors(gl, target, format);
1146
1147			if (!result)
1148			{
1149				m_testCtx.getLog() << tcu::TestLog::Message << mLog.str() << "Fail" << tcu::TestLog::EndMessage;
1150				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1151				return STOP;
1152			}
1153		}
1154	}
1155
1156	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1157	return STOP;
1158}
1159
1160/** Testing if texStorage* functionality added in ARB_sparse_texture extension works properly for given target and internal format
1161 *
1162 * @param gl           GL API functions
1163 * @param target       Target for which texture is binded
1164 * @param format       Texture internal format
1165 *
1166 * @return Returns true if no errors occurred, false otherwise.
1167 **/
1168bool SparseTextureAllocationTestCase::positiveTesting(const Functions& gl, GLint target, GLint format)
1169{
1170	mLog << "Positive Testing - ";
1171
1172	GLuint texture;
1173
1174	Texture::Generate(gl, texture);
1175	Texture::Bind(gl, texture, target);
1176
1177	GLint pageSizeX;
1178	GLint pageSizeY;
1179	GLint pageSizeZ;
1180	GLint depth = SparseTextureUtils::getTargetDepth(target);
1181	SparseTextureUtils::getTexturePageSizes(gl, target, format, pageSizeX, pageSizeY, pageSizeZ);
1182
1183	gl.texParameteri(target, GL_TEXTURE_SPARSE_ARB, GL_TRUE);
1184	if (!SparseTextureUtils::verifyError(mLog, "texParameteri", gl.getError(), GL_NO_ERROR))
1185	{
1186		Texture::Delete(gl, texture);
1187		return false;
1188	}
1189
1190	//The <width> and <height> has to be equal for cube map textures
1191	if (target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY)
1192	{
1193		if (pageSizeX > pageSizeY)
1194			pageSizeY = pageSizeX;
1195		else if (pageSizeX < pageSizeY)
1196			pageSizeX = pageSizeY;
1197	}
1198
1199	Texture::Storage(gl, target, 1, format, pageSizeX, pageSizeY, depth * pageSizeZ);
1200	if (!SparseTextureUtils::verifyError(mLog, "Texture::Storage", gl.getError(), GL_NO_ERROR))
1201	{
1202		Texture::Delete(gl, texture);
1203		return false;
1204	}
1205
1206	Texture::Delete(gl, texture);
1207	return true;
1208}
1209
1210/** Verifies if texParameter* generate proper errors for given target and internal format.
1211 *
1212 * @param gl           GL API functions
1213 * @param target       Target for which texture is binded
1214 * @param format       Texture internal format
1215 *
1216 * @return Returns true if errors are as expected, false otherwise.
1217 */
1218bool SparseTextureAllocationTestCase::verifyTexParameterErrors(const Functions& gl, GLint target, GLint format)
1219{
1220	mLog << "Verify TexParameter errors - ";
1221
1222	bool result = true;
1223
1224	GLuint texture;
1225	GLint  depth;
1226
1227	Texture::Generate(gl, texture);
1228	Texture::Bind(gl, texture, target);
1229
1230	depth = SparseTextureUtils::getTargetDepth(target);
1231
1232	Texture::Storage(gl, target, 1, format, 8, 8, depth);
1233	if (!SparseTextureUtils::verifyError(mLog, "TexStorage", gl.getError(), GL_NO_ERROR))
1234	{
1235		Texture::Delete(gl, texture);
1236		return false;
1237	}
1238
1239	GLint immutableFormat;
1240
1241	gl.getTexParameteriv(target, GL_TEXTURE_IMMUTABLE_FORMAT, &immutableFormat);
1242	if (!SparseTextureUtils::verifyQueryError(mLog, "getTexParameteriv", target, GL_TEXTURE_IMMUTABLE_FORMAT,
1243											  gl.getError(), GL_NO_ERROR))
1244	{
1245		Texture::Delete(gl, texture);
1246		return false;
1247	}
1248
1249	// Test error only if texture is immutable format, otherwise skip
1250	if (immutableFormat == GL_TRUE)
1251	{
1252		std::vector<IntPair> params;
1253		params.push_back(IntPair(GL_TEXTURE_SPARSE_ARB, GL_TRUE));
1254		params.push_back(IntPair(GL_VIRTUAL_PAGE_SIZE_INDEX_ARB, 1));
1255
1256		for (std::vector<IntPair>::const_iterator iter = params.begin(); iter != params.end(); ++iter)
1257		{
1258			const IntPair& param = *iter;
1259
1260			if (result)
1261			{
1262				gl.texParameteri(target, param.first, param.second);
1263				result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameteri", target, param.first,
1264															  gl.getError(), GL_INVALID_OPERATION);
1265			}
1266
1267			if (result)
1268			{
1269				gl.texParameterf(target, param.first, (GLfloat)param.second);
1270				result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameterf", target, param.first,
1271															  gl.getError(), GL_INVALID_OPERATION);
1272			}
1273
1274			if (result)
1275			{
1276				GLint value = param.second;
1277				gl.texParameteriv(target, param.first, &value);
1278				result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameteriv", target, param.first,
1279															  gl.getError(), GL_INVALID_OPERATION);
1280			}
1281
1282			if (result)
1283			{
1284				GLfloat value = (GLfloat)param.second;
1285				gl.texParameterfv(target, param.first, &value);
1286				result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameterfv", target, param.first,
1287															  gl.getError(), GL_INVALID_OPERATION);
1288			}
1289
1290			if (result)
1291			{
1292				GLint value = param.second;
1293				gl.texParameterIiv(target, param.first, &value);
1294				result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameterIiv", target, param.first,
1295															  gl.getError(), GL_INVALID_OPERATION);
1296			}
1297
1298			if (result)
1299			{
1300				GLuint value = param.second;
1301				gl.texParameterIuiv(target, param.first, &value);
1302				result = SparseTextureUtils::verifyQueryError(mLog, "glTexParameterIuiv", target, param.first,
1303															  gl.getError(), GL_INVALID_OPERATION);
1304			}
1305		}
1306	}
1307
1308	Texture::Delete(gl, texture);
1309	return result;
1310}
1311
1312/** Verifies if texStorage* generate proper error for given target and internal format when
1313 *  VIRTUAL_PAGE_SIZE_INDEX_ARB value is greater than NUM_VIRTUAL_PAGE_SIZES_ARB.
1314 *
1315 * @param gl           GL API functions
1316 * @param target       Target for which texture is binded
1317 * @param format       Texture internal format
1318 *
1319 * @return Returns true if errors are as expected, false otherwise.
1320 */
1321bool SparseTextureAllocationTestCase::verifyTexStorageVirtualPageSizeIndexError(const Functions& gl, GLint target,
1322																				GLint format)
1323{
1324	mLog << "Verify VirtualPageSizeIndex errors - ";
1325
1326	GLuint texture;
1327	GLint  depth;
1328	GLint  numPageSizes;
1329
1330	Texture::Generate(gl, texture);
1331	Texture::Bind(gl, texture, target);
1332
1333	gl.texParameteri(target, GL_TEXTURE_SPARSE_ARB, GL_TRUE);
1334	if (!SparseTextureUtils::verifyQueryError(mLog, "texParameteri", target, GL_TEXTURE_SPARSE_ARB, gl.getError(),
1335											  GL_NO_ERROR))
1336	{
1337		Texture::Delete(gl, texture);
1338		return false;
1339	}
1340
1341	gl.getInternalformativ(target, format, GL_NUM_VIRTUAL_PAGE_SIZES_ARB, sizeof(numPageSizes), &numPageSizes);
1342	if (!SparseTextureUtils::verifyQueryError(mLog, "getInternalformativ", target, GL_NUM_VIRTUAL_PAGE_SIZES_ARB,
1343											  gl.getError(), GL_NO_ERROR))
1344	{
1345		Texture::Delete(gl, texture);
1346		return false;
1347	}
1348
1349	numPageSizes += 1;
1350	gl.texParameteri(target, GL_VIRTUAL_PAGE_SIZE_INDEX_ARB, numPageSizes);
1351	if (!SparseTextureUtils::verifyQueryError(mLog, "texParameteri", target, GL_VIRTUAL_PAGE_SIZE_INDEX_ARB,
1352											  gl.getError(), GL_NO_ERROR))
1353	{
1354		Texture::Delete(gl, texture);
1355		return false;
1356	}
1357
1358	depth = SparseTextureUtils::getTargetDepth(target);
1359
1360	Texture::Storage(gl, target, 1, format, 8, 8, depth);
1361	if (!SparseTextureUtils::verifyError(mLog, "TexStorage", gl.getError(), GL_INVALID_OPERATION))
1362	{
1363		Texture::Delete(gl, texture);
1364		return false;
1365	}
1366
1367	Texture::Delete(gl, texture);
1368	return true;
1369}
1370
1371/** Verifies if texStorage* generate proper errors for given target and internal format and
1372 *  SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB value set to FALSE.
1373 *
1374 * @param gl           GL API functions
1375 * @param target       Target for which texture is binded
1376 * @param format       Texture internal format
1377 *
1378 * @return Returns true if errors are as expected, false otherwise.
1379 */
1380bool SparseTextureAllocationTestCase::verifyTexStorageFullArrayCubeMipmapsError(const Functions& gl, GLint target,
1381																				GLint format)
1382{
1383	mLog << "Verify FullArrayCubeMipmaps errors - ";
1384
1385	bool result = true;
1386
1387	GLuint texture;
1388	GLint  depth;
1389
1390	depth = SparseTextureUtils::getTargetDepth(target);
1391
1392	GLboolean fullArrayCubeMipmaps;
1393
1394	gl.getBooleanv(GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB, &fullArrayCubeMipmaps);
1395	if (!SparseTextureUtils::verifyQueryError(
1396			mLog, "getBooleanv", target, GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB, gl.getError(), GL_NO_ERROR))
1397		return false;
1398
1399	if (fullArrayCubeMipmaps == GL_FALSE)
1400	{
1401		if (target != GL_TEXTURE_1D_ARRAY && target != GL_TEXTURE_2D_ARRAY && target != GL_TEXTURE_CUBE_MAP &&
1402			target != GL_TEXTURE_CUBE_MAP_ARRAY)
1403		{
1404			// Case 1: test GL_TEXTURE_SPARSE_ARB
1405			Texture::Generate(gl, texture);
1406			Texture::Bind(gl, texture, target);
1407
1408			gl.texParameteri(target, GL_TEXTURE_SPARSE_ARB, GL_TRUE);
1409			if (!SparseTextureUtils::verifyQueryError(mLog, "texParameteri", target, GL_TEXTURE_SPARSE_ARB,
1410													  gl.getError(), GL_NO_ERROR))
1411				return false;
1412
1413			Texture::Storage(gl, target, 1, format, 8, 8, depth);
1414			if (!SparseTextureUtils::verifyError(mLog, "TexStorage [sparse texture]", gl.getError(),
1415												 GL_INVALID_OPERATION))
1416			{
1417				Texture::Delete(gl, texture);
1418				return false;
1419			}
1420
1421			// Case 2: test wrong texture size
1422			Texture::Generate(gl, texture);
1423			Texture::Bind(gl, texture, target);
1424
1425			GLint pageSizeX;
1426			GLint pageSizeY;
1427			GLint pageSizeZ;
1428			SparseTextureUtils::getTexturePageSizes(gl, target, format, pageSizeX, pageSizeY, pageSizeZ);
1429
1430			GLint levels = 4;
1431			GLint width  = pageSizeX * (int)pow(2, levels - 1);
1432			GLint height = pageSizeY * (int)pow(2, levels - 1);
1433
1434			// Check 2 different cases:
1435			// 1) wrong width
1436			// 2) wrong height
1437			Texture::Storage(gl, target, levels, format, width + pageSizeX, height, depth);
1438			result =
1439				SparseTextureUtils::verifyError(mLog, "TexStorage [wrong width]", gl.getError(), GL_INVALID_OPERATION);
1440
1441			if (result)
1442			{
1443				Texture::Storage(gl, target, levels, format, width, height + pageSizeY, depth);
1444				result = SparseTextureUtils::verifyError(mLog, "TexStorage [wrong height]", gl.getError(),
1445														 GL_INVALID_OPERATION);
1446			}
1447
1448			Texture::Delete(gl, texture);
1449		}
1450		else
1451		{
1452			// Case 3: test full array mipmaps targets
1453			Texture::Generate(gl, texture);
1454			Texture::Bind(gl, texture, target);
1455
1456			if (target == GL_TEXTURE_1D_ARRAY)
1457				Texture::Storage(gl, target, 1, format, 8, depth, 0);
1458			else
1459				Texture::Storage(gl, target, 1, format, 8, 8, depth);
1460
1461			result = SparseTextureUtils::verifyError(mLog, "TexStorage [case 3]", gl.getError(), GL_INVALID_OPERATION);
1462
1463			Texture::Delete(gl, texture);
1464		}
1465	}
1466
1467	return result;
1468}
1469
1470/** Verifies if texStorage* generate proper errors for given target and internal format when
1471 *  texture size are set greater than allowed.
1472 *
1473 * @param gl           GL API functions
1474 * @param target       Target for which texture is binded
1475 * @param format       Texture internal format
1476 *
1477 * @return Returns true if errors are as expected, false otherwise.
1478 */
1479bool SparseTextureAllocationTestCase::verifyTexStorageInvalidValueErrors(const Functions& gl, GLint target,
1480																		 GLint format)
1481{
1482	mLog << "Verify Invalid Value errors - ";
1483
1484	GLuint texture;
1485	GLint  pageSizeX;
1486	GLint  pageSizeY;
1487	GLint  pageSizeZ;
1488	SparseTextureUtils::getTexturePageSizes(gl, target, format, pageSizeX, pageSizeY, pageSizeZ);
1489
1490	Texture::Generate(gl, texture);
1491	Texture::Bind(gl, texture, target);
1492
1493	GLint width  = pageSizeX;
1494	GLint height = pageSizeY;
1495	GLint depth  = SparseTextureUtils::getTargetDepth(target) * pageSizeZ;
1496
1497	if (target == GL_TEXTURE_3D)
1498	{
1499		GLint max3DTextureSize;
1500
1501		gl.getIntegerv(GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB, &max3DTextureSize);
1502		if (!SparseTextureUtils::verifyQueryError(mLog, "getIntegerv", target, GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB,
1503												  gl.getError(), GL_NO_ERROR))
1504		{
1505			Texture::Delete(gl, texture);
1506			return false;
1507		}
1508
1509		// Check 3 different cases:
1510		// 1) wrong width
1511		// 2) wrong height
1512		// 3) wrong depth
1513		Texture::Storage(gl, target, 1, format, width + max3DTextureSize, height, depth);
1514		if (!SparseTextureUtils::verifyError(mLog, "TexStorage [GL_TEXTURE_3D wrong width]", gl.getError(),
1515											 GL_INVALID_VALUE))
1516		{
1517			Texture::Delete(gl, texture);
1518			return false;
1519		}
1520
1521		Texture::Storage(gl, target, 1, format, width, height + max3DTextureSize, depth);
1522		if (!SparseTextureUtils::verifyError(mLog, "TexStorage [GL_TEXTURE_3D wrong height]", gl.getError(),
1523											 GL_INVALID_VALUE))
1524		{
1525			Texture::Delete(gl, texture);
1526			return false;
1527		}
1528
1529		Texture::Storage(gl, target, 1, format, width, height, depth + max3DTextureSize);
1530		if (!SparseTextureUtils::verifyError(mLog, "TexStorage [GL_TEXTURE_3D wrong depth]", gl.getError(),
1531											 GL_INVALID_VALUE))
1532		{
1533			Texture::Delete(gl, texture);
1534			return false;
1535		}
1536	}
1537	else
1538	{
1539		GLint maxTextureSize;
1540
1541		gl.getIntegerv(GL_MAX_SPARSE_TEXTURE_SIZE_ARB, &maxTextureSize);
1542		if (!SparseTextureUtils::verifyQueryError(mLog, "getIntegerv", target, GL_MAX_SPARSE_TEXTURE_SIZE_ARB,
1543												  gl.getError(), GL_NO_ERROR))
1544		{
1545			Texture::Delete(gl, texture);
1546			return false;
1547		}
1548
1549		// Check 3 different cases:
1550		// 1) wrong width
1551		// 2) wrong height
1552		Texture::Storage(gl, target, 1, format, width + maxTextureSize, height, depth);
1553		if (!SparseTextureUtils::verifyError(mLog, "TexStorage [!GL_TEXTURE_3D wrong width]", gl.getError(),
1554											 GL_INVALID_VALUE))
1555		{
1556			Texture::Delete(gl, texture);
1557			return false;
1558		}
1559
1560		if (target != GL_TEXTURE_1D_ARRAY)
1561		{
1562			Texture::Storage(gl, target, 1, format, width, height + maxTextureSize, depth);
1563			if (!SparseTextureUtils::verifyError(mLog, "TexStorage [!GL_TEXTURE_3D wrong height]", gl.getError(),
1564												 GL_INVALID_VALUE))
1565			{
1566				Texture::Delete(gl, texture);
1567				return false;
1568			}
1569		}
1570
1571		GLint maxArrayTextureLayers;
1572
1573		gl.getIntegerv(GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB, &maxArrayTextureLayers);
1574		if (!SparseTextureUtils::verifyQueryError(mLog, "getIntegerv", target, GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB,
1575												  gl.getError(), GL_NO_ERROR))
1576		{
1577			Texture::Delete(gl, texture);
1578			return false;
1579		}
1580
1581		if (target == GL_TEXTURE_1D_ARRAY || target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_CUBE_MAP_ARRAY)
1582		{
1583			Texture::Storage(gl, target, 1, format, width, height, depth + maxArrayTextureLayers);
1584			if (!SparseTextureUtils::verifyError(mLog, "TexStorage [ARRAY wrong depth]", gl.getError(),
1585												 GL_INVALID_VALUE))
1586			{
1587				Texture::Delete(gl, texture);
1588				return false;
1589			}
1590		}
1591	}
1592
1593	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture2"))
1594	{
1595		if (pageSizeX > 1)
1596		{
1597			Texture::Storage(gl, target, 1, format, 1, height, depth);
1598			if (!SparseTextureUtils::verifyError(mLog, "TexStorage [wrong width]", gl.getError(), GL_INVALID_VALUE))
1599			{
1600				Texture::Delete(gl, texture);
1601				return false;
1602			}
1603		}
1604
1605		if (pageSizeY > 1)
1606		{
1607			Texture::Storage(gl, target, 1, format, width, 1, depth);
1608			if (!SparseTextureUtils::verifyError(mLog, "TexStorage [wrong height]", gl.getError(), GL_INVALID_VALUE))
1609			{
1610				Texture::Delete(gl, texture);
1611				return false;
1612			}
1613		}
1614
1615		if (pageSizeZ > 1)
1616		{
1617			Texture::Storage(gl, target, 1, format, width, height, SparseTextureUtils::getTargetDepth(target));
1618			if (!SparseTextureUtils::verifyError(mLog, "TexStorage [wrong depth]", gl.getError(), GL_INVALID_VALUE))
1619			{
1620				Texture::Delete(gl, texture);
1621				return false;
1622			}
1623		}
1624	}
1625
1626	Texture::Delete(gl, texture);
1627	return true;
1628}
1629
1630/** Constructor.
1631 *
1632 *  @param context     Rendering context
1633 */
1634SparseTextureCommitmentTestCase::SparseTextureCommitmentTestCase(deqp::Context& context)
1635	: TestCase(context, "SparseTextureCommitment",
1636			   "Verifies TexPageCommitmentARB functionality added in CTS_ARB_sparse_texture")
1637	, mState()
1638{
1639	/* Left blank intentionally */
1640}
1641
1642/** Constructor.
1643 *
1644 *  @param context     Rendering context
1645 *  @param name        Test name
1646 *  @param description Test description
1647 */
1648SparseTextureCommitmentTestCase::SparseTextureCommitmentTestCase(deqp::Context& context, const char* name,
1649																 const char* description)
1650	: TestCase(context, name, description), mState()
1651{
1652	/* Left blank intentionally */
1653}
1654
1655/** Initializes the test case. */
1656void SparseTextureCommitmentTestCase::init()
1657{
1658	mSupportedTargets.push_back(GL_TEXTURE_2D);
1659	mSupportedTargets.push_back(GL_TEXTURE_2D_ARRAY);
1660	mSupportedTargets.push_back(GL_TEXTURE_CUBE_MAP);
1661	mSupportedTargets.push_back(GL_TEXTURE_CUBE_MAP_ARRAY);
1662	mSupportedTargets.push_back(GL_TEXTURE_3D);
1663	mSupportedTargets.push_back(GL_TEXTURE_RECTANGLE);
1664
1665	mSupportedInternalFormats.push_back(GL_R8);
1666	mSupportedInternalFormats.push_back(GL_R8_SNORM);
1667	mSupportedInternalFormats.push_back(GL_R16);
1668	mSupportedInternalFormats.push_back(GL_R16_SNORM);
1669	mSupportedInternalFormats.push_back(GL_RG8);
1670	mSupportedInternalFormats.push_back(GL_RG8_SNORM);
1671	mSupportedInternalFormats.push_back(GL_RG16);
1672	mSupportedInternalFormats.push_back(GL_RG16_SNORM);
1673	mSupportedInternalFormats.push_back(GL_RGB565);
1674	mSupportedInternalFormats.push_back(GL_RGBA8);
1675	mSupportedInternalFormats.push_back(GL_RGBA8_SNORM);
1676	mSupportedInternalFormats.push_back(GL_RGB10_A2);
1677	mSupportedInternalFormats.push_back(GL_RGB10_A2UI);
1678	mSupportedInternalFormats.push_back(GL_RGBA16);
1679	mSupportedInternalFormats.push_back(GL_RGBA16_SNORM);
1680	mSupportedInternalFormats.push_back(GL_R16F);
1681	mSupportedInternalFormats.push_back(GL_RG16F);
1682	mSupportedInternalFormats.push_back(GL_RGBA16F);
1683	mSupportedInternalFormats.push_back(GL_R32F);
1684	mSupportedInternalFormats.push_back(GL_RG32F);
1685	mSupportedInternalFormats.push_back(GL_RGBA32F);
1686	mSupportedInternalFormats.push_back(GL_R11F_G11F_B10F);
1687	mSupportedInternalFormats.push_back(GL_RGB9_E5);
1688	mSupportedInternalFormats.push_back(GL_R8I);
1689	mSupportedInternalFormats.push_back(GL_R8UI);
1690	mSupportedInternalFormats.push_back(GL_R16I);
1691	mSupportedInternalFormats.push_back(GL_R16UI);
1692	mSupportedInternalFormats.push_back(GL_R32I);
1693	mSupportedInternalFormats.push_back(GL_R32UI);
1694	mSupportedInternalFormats.push_back(GL_RG8I);
1695	mSupportedInternalFormats.push_back(GL_RG8UI);
1696	mSupportedInternalFormats.push_back(GL_RG16I);
1697	mSupportedInternalFormats.push_back(GL_RG16UI);
1698	mSupportedInternalFormats.push_back(GL_RG32I);
1699	mSupportedInternalFormats.push_back(GL_RG32UI);
1700	mSupportedInternalFormats.push_back(GL_RGBA8I);
1701	mSupportedInternalFormats.push_back(GL_RGBA8UI);
1702	mSupportedInternalFormats.push_back(GL_RGBA16I);
1703	mSupportedInternalFormats.push_back(GL_RGBA16UI);
1704	mSupportedInternalFormats.push_back(GL_RGBA32I);
1705}
1706
1707/** Executes test iteration.
1708 *
1709 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1710 */
1711tcu::TestNode::IterateResult SparseTextureCommitmentTestCase::iterate()
1712{
1713	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture"))
1714	{
1715		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
1716		return STOP;
1717	}
1718
1719	const Functions& gl = m_context.getRenderContext().getFunctions();
1720
1721	bool result = true;
1722
1723	GLuint texture;
1724
1725	for (std::vector<glw::GLint>::const_iterator iter = mSupportedTargets.begin(); iter != mSupportedTargets.end();
1726		 ++iter)
1727	{
1728		const GLint& target = *iter;
1729
1730		for (std::vector<glw::GLint>::const_iterator formIter = mSupportedInternalFormats.begin();
1731			 formIter != mSupportedInternalFormats.end(); ++formIter)
1732		{
1733			const GLint& format = *formIter;
1734
1735			if (!caseAllowed(target, format))
1736				continue;
1737
1738			mLog.str("");
1739			mLog << "Testing sparse texture commitment for target: " << target << ", format: " << format << " - ";
1740
1741			//Checking if written data into not committed region generates no error
1742			sparseAllocateTexture(gl, target, format, texture, 3);
1743			for (int l = 0; l < mState.levels; ++l)
1744				writeDataToTexture(gl, target, format, texture, l);
1745
1746			//Checking if written data into committed region is as expected
1747			for (int l = 0; l < mState.levels; ++l)
1748			{
1749				if (commitTexturePage(gl, target, format, texture, l))
1750				{
1751					writeDataToTexture(gl, target, format, texture, l);
1752					result = verifyTextureData(gl, target, format, texture, l);
1753				}
1754
1755				if (!result)
1756					break;
1757			}
1758
1759			Texture::Delete(gl, texture);
1760
1761			//verify errors
1762			result = result && verifyInvalidOperationErrors(gl, target, format, texture);
1763			result = result && verifyInvalidValueErrors(gl, target, format, texture);
1764
1765			if (!result)
1766			{
1767				m_testCtx.getLog() << tcu::TestLog::Message << mLog.str() << "Fail" << tcu::TestLog::EndMessage;
1768				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1769				return STOP;
1770			}
1771		}
1772	}
1773
1774	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1775	return STOP;
1776}
1777
1778/** Bind texPageCommitmentARB function
1779 *
1780 * @param gl           GL API functions
1781 * @param target       Target for which texture is binded
1782 * @param format       Texture internal format
1783 * @param texture      Texture object
1784 * @param xOffset      Texture commitment x offset
1785 * @param yOffset      Texture commitment y offset
1786 * @param zOffset      Texture commitment z offset
1787 * @param width        Texture commitment width
1788 * @param height       Texture commitment height
1789 * @param depth        Texture commitment depth
1790 * @param commit       Commit or de-commit indicator
1791 **/
1792void SparseTextureCommitmentTestCase::texPageCommitment(const glw::Functions& gl, glw::GLint target, glw::GLint format,
1793														glw::GLuint& texture, GLint level, GLint xOffset, GLint yOffset,
1794														GLint zOffset, GLint width, GLint height, GLint depth,
1795														GLboolean commit)
1796{
1797	DE_UNREF(format);
1798	Texture::Bind(gl, texture, target);
1799
1800	gl.texPageCommitmentARB(target, level, xOffset, yOffset, zOffset, width, height, depth, commit);
1801}
1802
1803/** Check if specific combination of target and format is allowed
1804 *
1805 * @param target       Target for which texture is binded
1806 * @param format       Texture internal format
1807 *
1808 * @return Returns true if target/format combination is allowed, false otherwise.
1809 */
1810bool SparseTextureCommitmentTestCase::caseAllowed(GLint target, GLint format)
1811{
1812	DE_UNREF(target);
1813	DE_UNREF(format);
1814	return true;
1815}
1816
1817/** Preparing texture
1818 *
1819 * @param gl           GL API functions
1820 * @param target       Target for which texture is binded
1821 * @param format       Texture internal format
1822 * @param texture      Texture object
1823 *
1824 * @return Returns true if no error occurred, otherwise throws an exception.
1825 */
1826bool SparseTextureCommitmentTestCase::prepareTexture(const Functions& gl, GLint target, GLint format, GLuint& texture)
1827{
1828	Texture::Generate(gl, texture);
1829	Texture::Bind(gl, texture, target);
1830
1831	mState.minDepth = SparseTextureUtils::getTargetDepth(target);
1832	SparseTextureUtils::getTexturePageSizes(gl, target, format, mState.pageSizeX, mState.pageSizeY, mState.pageSizeZ);
1833
1834	//The <width> and <height> has to be equal for cube map textures
1835	if (target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY)
1836	{
1837		if (mState.pageSizeX > mState.pageSizeY)
1838			mState.pageSizeY = mState.pageSizeX;
1839		else if (mState.pageSizeX < mState.pageSizeY)
1840			mState.pageSizeX = mState.pageSizeY;
1841	}
1842
1843	mState.width  = 2 * mState.pageSizeX;
1844	mState.height = 2 * mState.pageSizeY;
1845	mState.depth  = 2 * mState.pageSizeZ * mState.minDepth;
1846
1847	mState.format = glu::mapGLInternalFormat(format);
1848
1849	return true;
1850}
1851
1852/** Allocating sparse texture memory using texStorage* function
1853 *
1854 * @param gl           GL API functions
1855 * @param target       Target for which texture is binded
1856 * @param format       Texture internal format
1857 * @param texture      Texture object
1858 * @param levels       Texture mipmaps level
1859 *
1860 * @return Returns true if no error occurred, otherwise throws an exception.
1861 */
1862bool SparseTextureCommitmentTestCase::sparseAllocateTexture(const Functions& gl, GLint target, GLint format,
1863															GLuint& texture, GLint levels)
1864{
1865	mLog << "Sparse Allocate [levels: " << levels << "] - ";
1866
1867	prepareTexture(gl, target, format, texture);
1868
1869	gl.texParameteri(target, GL_TEXTURE_SPARSE_ARB, GL_TRUE);
1870	GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri error occurred for GL_TEXTURE_SPARSE_ARB");
1871
1872	// GL_TEXTURE_RECTANGLE can have only one level
1873	if (target != GL_TEXTURE_RECTANGLE)
1874	{
1875		gl.getTexParameteriv(target, GL_NUM_SPARSE_LEVELS_ARB, &mState.levels);
1876		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameteriv");
1877
1878		mState.levels = deMin32(mState.levels, levels);
1879	}
1880	else
1881		mState.levels = 1;
1882
1883	Texture::Storage(gl, target, mState.levels, format, mState.width, mState.height, mState.depth);
1884	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage");
1885
1886	return true;
1887}
1888
1889/** Allocating texture memory using texStorage* function
1890 *
1891 * @param gl           GL API functions
1892 * @param target       Target for which texture is binded
1893 * @param format       Texture internal format
1894 * @param texture      Texture object
1895 * @param levels       Texture mipmaps level
1896 *
1897 * @return Returns true if no error occurred, otherwise throws an exception.
1898 */
1899bool SparseTextureCommitmentTestCase::allocateTexture(const Functions& gl, GLint target, GLint format, GLuint& texture,
1900													  GLint levels)
1901{
1902	mLog << "Allocate [levels: " << levels << "] - ";
1903
1904	prepareTexture(gl, target, format, texture);
1905
1906	//GL_TEXTURE_RECTANGLE can have only one level
1907	if (target != GL_TEXTURE_RECTANGLE)
1908		mState.levels = levels;
1909	else
1910		mState.levels = 1;
1911
1912	Texture::Storage(gl, target, mState.levels, format, mState.width, mState.height, mState.depth);
1913	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage");
1914
1915	return true;
1916}
1917
1918/** Writing data to generated texture
1919 *
1920 * @param gl           GL API functions
1921 * @param target       Target for which texture is binded
1922 * @param format       Texture internal format
1923 * @param texture      Texture object
1924 *
1925 * @return Returns true if no error occurred, otherwise throws an exception.
1926 */
1927bool SparseTextureCommitmentTestCase::writeDataToTexture(const Functions& gl, GLint target, GLint format,
1928														 GLuint& texture, GLint level)
1929{
1930	DE_UNREF(format);
1931	DE_UNREF(texture);
1932
1933	mLog << "Fill texture [level: " << level << "] - ";
1934
1935	if (level > mState.levels - 1)
1936		TCU_FAIL("Invalid level");
1937
1938	TransferFormat transferFormat = glu::getTransferFormat(mState.format);
1939
1940	GLint width;
1941	GLint height;
1942	GLint depth;
1943	SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1944
1945	if (width > 0 && height > 0 && depth >= mState.minDepth)
1946	{
1947		GLint texSize = width * height * depth * mState.format.getPixelSize();
1948
1949		std::vector<GLubyte> vecData;
1950		vecData.resize(texSize);
1951		GLubyte* data = vecData.data();
1952
1953		deMemset(data, 16 + 16 * level, texSize);
1954
1955		Texture::SubImage(gl, target, level, 0, 0, 0, width, height, depth, transferFormat.format,
1956						  transferFormat.dataType, (GLvoid*)data);
1957		GLU_EXPECT_NO_ERROR(gl.getError(), "SubImage");
1958	}
1959
1960	return true;
1961}
1962
1963/** Verify if data stored in texture is as expected
1964 *
1965 * @param gl           GL API functions
1966 * @param target       Target for which texture is binded
1967 * @param format       Texture internal format
1968 * @param texture      Texture object
1969 * @param level        Texture mipmap level
1970 *
1971 * @return Returns true if data is as expected, false if not, throws an exception if error occurred.
1972 */
1973bool SparseTextureCommitmentTestCase::verifyTextureData(const Functions& gl, GLint target, GLint format,
1974														GLuint& texture, GLint level)
1975{
1976	DE_UNREF(format);
1977	DE_UNREF(texture);
1978
1979	mLog << "Verify Texture [level: " << level << "] - ";
1980
1981	if (level > mState.levels - 1)
1982		TCU_FAIL("Invalid level");
1983
1984	TransferFormat transferFormat = glu::getTransferFormat(mState.format);
1985
1986	GLint width;
1987	GLint height;
1988	GLint depth;
1989	SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1990
1991	//Committed region is limited to 1/2 of width
1992	GLint widthCommitted = width / 2;
1993
1994	if (widthCommitted == 0 || height == 0 || depth < mState.minDepth)
1995		return true;
1996
1997	bool result = true;
1998
1999	if (target != GL_TEXTURE_CUBE_MAP)
2000	{
2001		GLint texSize = width * height * depth * mState.format.getPixelSize();
2002
2003		std::vector<GLubyte> vecExpData;
2004		std::vector<GLubyte> vecOutData;
2005		vecExpData.resize(texSize);
2006		vecOutData.resize(texSize);
2007		GLubyte* exp_data = vecExpData.data();
2008		GLubyte* out_data = vecOutData.data();
2009
2010		deMemset(exp_data, 16 + 16 * level, texSize);
2011		deMemset(out_data, 255, texSize);
2012
2013		Texture::GetData(gl, level, target, transferFormat.format, transferFormat.dataType, (GLvoid*)out_data);
2014		GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData");
2015
2016		//Verify only committed region
2017		for (GLint x = 0; x < widthCommitted; ++x)
2018			for (GLint y = 0; y < height; ++y)
2019				for (GLint z = 0; z < depth; ++z)
2020				{
2021					int		 pixelSize	 = mState.format.getPixelSize();
2022					GLubyte* dataRegion	= exp_data + ((x + y * width) * pixelSize);
2023					GLubyte* outDataRegion = out_data + ((x + y * width) * pixelSize);
2024					if (deMemCmp(dataRegion, outDataRegion, pixelSize) != 0)
2025						result = false;
2026				}
2027	}
2028	else
2029	{
2030		std::vector<GLint> subTargets;
2031
2032		subTargets.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
2033		subTargets.push_back(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
2034		subTargets.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
2035		subTargets.push_back(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
2036		subTargets.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
2037		subTargets.push_back(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
2038
2039		GLint texSize = width * height * mState.format.getPixelSize();
2040
2041		std::vector<GLubyte> vecExpData;
2042		std::vector<GLubyte> vecOutData;
2043		vecExpData.resize(texSize);
2044		vecOutData.resize(texSize);
2045		GLubyte* exp_data = vecExpData.data();
2046		GLubyte* out_data = vecOutData.data();
2047
2048		deMemset(exp_data, 16 + 16 * level, texSize);
2049		deMemset(out_data, 255, texSize);
2050
2051		for (size_t i = 0; i < subTargets.size(); ++i)
2052		{
2053			GLint subTarget = subTargets[i];
2054
2055			mLog << "Verify Subtarget [subtarget: " << subTarget << "] - ";
2056
2057			deMemset(out_data, 255, texSize);
2058
2059			Texture::GetData(gl, level, subTarget, transferFormat.format, transferFormat.dataType, (GLvoid*)out_data);
2060			GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData");
2061
2062			//Verify only committed region
2063			for (GLint x = 0; x < widthCommitted; ++x)
2064				for (GLint y = 0; y < height; ++y)
2065					for (GLint z = 0; z < depth; ++z)
2066					{
2067						int		 pixelSize	 = mState.format.getPixelSize();
2068						GLubyte* dataRegion	= exp_data + ((x + y * width) * pixelSize);
2069						GLubyte* outDataRegion = out_data + ((x + y * width) * pixelSize);
2070						if (deMemCmp(dataRegion, outDataRegion, pixelSize) != 0)
2071							result = false;
2072					}
2073
2074			if (!result)
2075				break;
2076		}
2077	}
2078
2079	return result;
2080}
2081
2082/** Commit texture page using texPageCommitment function
2083 *
2084 * @param gl           GL API functions
2085 * @param target       Target for which texture is binded
2086 * @param format       Texture internal format
2087 * @param texture      Texture object
2088 * @param level        Texture mipmap level
2089 *
2090 * @return Returns true if commitment is done properly, false if commitment is not allowed or throws exception if error occurred.
2091 */
2092bool SparseTextureCommitmentTestCase::commitTexturePage(const Functions& gl, GLint target, GLint format,
2093														GLuint& texture, GLint level)
2094{
2095	mLog << "Commit Region [level: " << level << "] - ";
2096
2097	if (level > mState.levels - 1)
2098		TCU_FAIL("Invalid level");
2099
2100	// Avoid not allowed commitments
2101	if (!isInPageSizesRange(target, level) || !isPageSizesMultiplication(target, level))
2102	{
2103		mLog << "Skip commitment [level: " << level << "] - ";
2104		return false;
2105	}
2106
2107	GLint width;
2108	GLint height;
2109	GLint depth;
2110	SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
2111
2112	if (target == GL_TEXTURE_CUBE_MAP)
2113		depth = 6 * depth;
2114
2115	GLint widthCommitted = width / 2;
2116
2117	Texture::Bind(gl, texture, target);
2118	texPageCommitment(gl, target, format, texture, level, 0, 0, 0, widthCommitted, height, depth, GL_TRUE);
2119	GLU_EXPECT_NO_ERROR(gl.getError(), "texPageCommitment");
2120
2121	return true;
2122}
2123
2124/** Check if current texture size for level is greater or equal page size in a corresponding direction
2125 *
2126 * @param target  Target for which texture is binded
2127 * @param level   Texture mipmap level
2128 *
2129 * @return Returns true if the texture size condition is fulfilled, false otherwise.
2130 */
2131bool SparseTextureCommitmentTestCase::isInPageSizesRange(GLint target, GLint level)
2132{
2133	GLint width;
2134	GLint height;
2135	GLint depth;
2136	SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
2137
2138	if (target == GL_TEXTURE_CUBE_MAP)
2139		depth = 6 * depth;
2140
2141	GLint widthCommitted = width / 2;
2142	if (widthCommitted >= mState.pageSizeX && height >= mState.pageSizeY &&
2143		(mState.minDepth == 0 || depth >= mState.pageSizeZ))
2144	{
2145		return true;
2146	}
2147
2148	return false;
2149}
2150
2151/** Check if current texture size for level is page size multiplication in a corresponding direction
2152 *
2153 * @param target  Target for which texture is binded
2154 * @param level   Texture mipmap level
2155 *
2156 * @return Returns true if the texture size condition is fulfilled, false otherwise.
2157 */
2158bool SparseTextureCommitmentTestCase::isPageSizesMultiplication(GLint target, GLint level)
2159{
2160	GLint width;
2161	GLint height;
2162	GLint depth;
2163	SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
2164
2165	if (target == GL_TEXTURE_CUBE_MAP)
2166		depth = 6 * depth;
2167
2168	GLint widthCommitted = width / 2;
2169	if ((widthCommitted % mState.pageSizeX) == 0 && (height % mState.pageSizeY) == 0 && (depth % mState.pageSizeZ) == 0)
2170	{
2171		return true;
2172	}
2173
2174	return false;
2175}
2176
2177/** Verifies if gltexPageCommitment generates INVALID_OPERATION error in expected use cases
2178 *
2179 * @param gl           GL API functions
2180 * @param target       Target for which texture is binded
2181 * @param format       Texture internal format
2182 * @param texture      Texture object
2183 *
2184 * @return Returns true if no error occurred, otherwise throws an exception.
2185 */
2186bool SparseTextureCommitmentTestCase::verifyInvalidOperationErrors(const Functions& gl, GLint target, GLint format,
2187																   GLuint& texture)
2188{
2189	mLog << "Verify INVALID_OPERATION Errors - ";
2190
2191	bool result = true;
2192
2193	// Case 1 - texture is not GL_TEXTURE_IMMUTABLE_FORMAT
2194	Texture::Generate(gl, texture);
2195	Texture::Bind(gl, texture, target);
2196
2197	gl.texParameteri(target, GL_TEXTURE_SPARSE_ARB, GL_TRUE);
2198	GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri error occurred for GL_TEXTURE_SPARSE_ARB");
2199
2200	GLint immutableFormat;
2201
2202	gl.getTexParameteriv(target, GL_TEXTURE_IMMUTABLE_FORMAT, &immutableFormat);
2203	GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv error occurred for GL_TEXTURE_IMMUTABLE_FORMAT");
2204
2205	if (immutableFormat == GL_FALSE)
2206	{
2207		texPageCommitment(gl, target, format, texture, 0, 0, 0, 0, mState.pageSizeX, mState.pageSizeY, mState.pageSizeZ,
2208						  GL_TRUE);
2209		result = SparseTextureUtils::verifyError(mLog, "texPageCommitment [GL_TEXTURE_IMMUTABLE_FORMAT texture]",
2210												 gl.getError(), GL_INVALID_OPERATION);
2211		if (!result)
2212			goto verifing_invalid_operation_end;
2213	}
2214
2215	Texture::Delete(gl, texture);
2216
2217	// Case 2 - texture is not TEXTURE_SPARSE_ARB
2218	allocateTexture(gl, target, format, texture, 1);
2219
2220	texPageCommitment(gl, target, format, texture, 0, 0, 0, 0, mState.pageSizeX, mState.pageSizeY, mState.pageSizeZ,
2221					  GL_TRUE);
2222	result = SparseTextureUtils::verifyError(mLog, "texPageCommitment [not TEXTURE_SPARSE_ARB texture]", gl.getError(),
2223											 GL_INVALID_OPERATION);
2224	if (!result)
2225		goto verifing_invalid_operation_end;
2226
2227	// Sparse allocate texture
2228	Texture::Delete(gl, texture);
2229	sparseAllocateTexture(gl, target, format, texture, 1);
2230
2231	// Case 3 - commitment sizes greater than expected
2232	texPageCommitment(gl, target, format, texture, 0, 0, 0, 0, mState.width + mState.pageSizeX, mState.height,
2233					  mState.depth, GL_TRUE);
2234	result = SparseTextureUtils::verifyError(mLog, "texPageCommitment [commitment width greater than expected]",
2235											 gl.getError(), GL_INVALID_OPERATION);
2236	if (!result)
2237		goto verifing_invalid_operation_end;
2238
2239	texPageCommitment(gl, target, format, texture, 0, 0, 0, 0, mState.width, mState.height + mState.pageSizeY,
2240					  mState.depth, GL_TRUE);
2241	result = SparseTextureUtils::verifyError(mLog, "texPageCommitment [commitment height greater than expected]",
2242											 gl.getError(), GL_INVALID_OPERATION);
2243	if (!result)
2244		goto verifing_invalid_operation_end;
2245
2246	if (target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_CUBE_MAP_ARRAY)
2247	{
2248		texPageCommitment(gl, target, format, texture, 0, 0, 0, 0, mState.width, mState.height,
2249						  mState.depth + mState.pageSizeZ, GL_TRUE);
2250		result = SparseTextureUtils::verifyError(mLog, "texPageCommitment [commitment depth greater than expected]",
2251												 gl.getError(), GL_INVALID_OPERATION);
2252		if (!result)
2253			goto verifing_invalid_operation_end;
2254	}
2255
2256	// Case 4 - commitment sizes not multiple of corresponding page sizes
2257	if (mState.pageSizeX > 1)
2258	{
2259		texPageCommitment(gl, target, format, texture, 0, 0, 0, 0, 1, mState.pageSizeY, mState.pageSizeZ, GL_TRUE);
2260		result =
2261			SparseTextureUtils::verifyError(mLog, "texPageCommitment [commitment width not multiple of page sizes X]",
2262											gl.getError(), GL_INVALID_OPERATION);
2263		if (!result)
2264			goto verifing_invalid_operation_end;
2265	}
2266
2267	if (mState.pageSizeY > 1)
2268	{
2269		texPageCommitment(gl, target, format, texture, 0, 0, 0, 0, mState.pageSizeX, 1, mState.pageSizeZ, GL_TRUE);
2270		result =
2271			SparseTextureUtils::verifyError(mLog, "texPageCommitment [commitment height not multiple of page sizes Y]",
2272											gl.getError(), GL_INVALID_OPERATION);
2273		if (!result)
2274			goto verifing_invalid_operation_end;
2275	}
2276
2277	if (mState.pageSizeZ > 1)
2278	{
2279		if (target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_CUBE_MAP_ARRAY)
2280		{
2281			texPageCommitment(gl, target, format, texture, 0, 0, 0, 0, mState.pageSizeX, mState.pageSizeY,
2282							  mState.minDepth, GL_TRUE);
2283			result = SparseTextureUtils::verifyError(
2284				mLog, "texPageCommitment [commitment depth not multiple of page sizes Z]", gl.getError(),
2285				GL_INVALID_OPERATION);
2286			if (!result)
2287				goto verifing_invalid_operation_end;
2288		}
2289	}
2290
2291verifing_invalid_operation_end:
2292
2293	Texture::Delete(gl, texture);
2294
2295	return result;
2296}
2297
2298/** Verifies if texPageCommitment generates INVALID_VALUE error in expected use cases
2299 *
2300 * @param gl           GL API functions
2301 * @param target       Target for which texture is binded
2302 * @param format       Texture internal format
2303 * @param texture      Texture object
2304 *
2305 * @return Returns true if no error occurred, otherwise throws an exception.
2306 */
2307bool SparseTextureCommitmentTestCase::verifyInvalidValueErrors(const Functions& gl, GLint target, GLint format,
2308															   GLuint& texture)
2309{
2310	mLog << "Verify INVALID_VALUE Errors - ";
2311
2312	bool result = true;
2313
2314	sparseAllocateTexture(gl, target, format, texture, 1);
2315
2316	// Case 1 - commitment offset not multiple of page size in corresponding dimension
2317	if (mState.pageSizeX > 1)
2318	{
2319		texPageCommitment(gl, target, format, texture, 0, 1, 0, 0, mState.pageSizeX, mState.pageSizeY, mState.pageSizeZ,
2320						  GL_TRUE);
2321		result =
2322			SparseTextureUtils::verifyError(mLog, "texPageCommitment [commitment offsetX not multiple of page size X]",
2323											gl.getError(), GL_INVALID_VALUE);
2324		if (!result)
2325			goto verifing_invalid_value_end;
2326	}
2327	if (mState.pageSizeY > 1)
2328	{
2329		texPageCommitment(gl, target, format, texture, 0, 0, 1, 0, mState.pageSizeX, mState.pageSizeY, mState.pageSizeZ,
2330						  GL_TRUE);
2331		result =
2332			SparseTextureUtils::verifyError(mLog, "texPageCommitment [commitment offsetY not multiple of page size Y]",
2333											gl.getError(), GL_INVALID_VALUE);
2334		if (!result)
2335			goto verifing_invalid_value_end;
2336	}
2337	if ((target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_CUBE_MAP_ARRAY) &&
2338		(mState.minDepth % mState.pageSizeZ))
2339	{
2340		texPageCommitment(gl, target, format, texture, 0, 0, 0, mState.minDepth, mState.pageSizeX, mState.pageSizeY,
2341						  mState.pageSizeZ, GL_TRUE);
2342		result =
2343			SparseTextureUtils::verifyError(mLog, "texPageCommitment [commitment offsetZ not multiple of page size Z]",
2344											gl.getError(), GL_INVALID_VALUE);
2345		if (!result)
2346			goto verifing_invalid_value_end;
2347	}
2348
2349verifing_invalid_value_end:
2350
2351	Texture::Delete(gl, texture);
2352
2353	return result;
2354}
2355
2356/** Constructor.
2357 *
2358 *  @param context     Rendering context
2359 */
2360SparseDSATextureCommitmentTestCase::SparseDSATextureCommitmentTestCase(deqp::Context& context)
2361	: SparseTextureCommitmentTestCase(context, "SparseDSATextureCommitment",
2362									  "Verifies texturePageCommitmentEXT functionality added in CTS_ARB_sparse_texture")
2363{
2364	/* Left blank intentionally */
2365}
2366
2367/** Executes test iteration.
2368 *
2369 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2370 */
2371tcu::TestNode::IterateResult SparseDSATextureCommitmentTestCase::iterate()
2372{
2373	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture"))
2374	{
2375		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
2376		return STOP;
2377	}
2378
2379	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_direct_state_access"))
2380	{
2381		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_EXT_direct_state_access extension is not supported.");
2382		return STOP;
2383	}
2384
2385	const Functions& gl = m_context.getRenderContext().getFunctions();
2386
2387	bool result = true;
2388
2389	GLuint texture;
2390
2391	for (std::vector<glw::GLint>::const_iterator iter = mSupportedTargets.begin(); iter != mSupportedTargets.end();
2392		 ++iter)
2393	{
2394		const GLint& target = *iter;
2395
2396		for (std::vector<glw::GLint>::const_iterator formIter = mSupportedInternalFormats.begin();
2397			 formIter != mSupportedInternalFormats.end(); ++formIter)
2398		{
2399			const GLint& format = *formIter;
2400
2401			mLog.str("");
2402			mLog << "Testing DSA sparse texture commitment for target: " << target << ", format: " << format << " - ";
2403
2404			//Checking if written data into committed region is as expected
2405			sparseAllocateTexture(gl, target, format, texture, 3);
2406			for (int l = 0; l < mState.levels; ++l)
2407			{
2408				if (commitTexturePage(gl, target, format, texture, l))
2409				{
2410					writeDataToTexture(gl, target, format, texture, l);
2411					result = verifyTextureData(gl, target, format, texture, l);
2412				}
2413
2414				if (!result)
2415					break;
2416			}
2417
2418			Texture::Delete(gl, texture);
2419
2420			//verify errors
2421			result = result && verifyInvalidOperationErrors(gl, target, format, texture);
2422			result = result && verifyInvalidValueErrors(gl, target, format, texture);
2423
2424			if (!result)
2425			{
2426				m_testCtx.getLog() << tcu::TestLog::Message << mLog.str() << "Fail" << tcu::TestLog::EndMessage;
2427				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2428				return STOP;
2429			}
2430		}
2431	}
2432
2433	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2434	return STOP;
2435}
2436
2437/** Bind DSA texturePageCommitmentEXT function
2438 *
2439 * @param gl           GL API functions
2440 * @param target       Target for which texture is binded
2441 * @param format       Texture internal format
2442 * @param texture      Texture object
2443 * @param xOffset      Texture commitment x offset
2444 * @param yOffset      Texture commitment y offset
2445 * @param zOffset      Texture commitment z offset
2446 * @param width        Texture commitment width
2447 * @param height       Texture commitment height
2448 * @param depth        Texture commitment depth
2449 * @param commit       Commit or de-commit indicator
2450 **/
2451void SparseDSATextureCommitmentTestCase::texPageCommitment(const glw::Functions& gl, glw::GLint target,
2452														   glw::GLint format, glw::GLuint& texture, GLint level,
2453														   GLint xOffset, GLint yOffset, GLint zOffset, GLint width,
2454														   GLint height, GLint depth, GLboolean commit)
2455{
2456	DE_UNREF(target);
2457	DE_UNREF(format);
2458	gl.texturePageCommitmentEXT(texture, level, xOffset, yOffset, zOffset, width, height, depth, commit);
2459}
2460
2461/** Constructor.
2462 *
2463 *  @param context Rendering context.
2464 */
2465SparseTextureTests::SparseTextureTests(deqp::Context& context)
2466	: TestCaseGroup(context, "sparse_texture_tests", "Verify conformance of CTS_ARB_sparse_texture implementation")
2467{
2468}
2469
2470/** Initializes the test group contents. */
2471void SparseTextureTests::init()
2472{
2473	addChild(new TextureParameterQueriesTestCase(m_context));
2474	addChild(new InternalFormatQueriesTestCase(m_context));
2475	addChild(new SimpleQueriesTestCase(m_context));
2476	addChild(new SparseTextureAllocationTestCase(m_context));
2477	addChild(new SparseTextureCommitmentTestCase(m_context));
2478	addChild(new SparseDSATextureCommitmentTestCase(m_context));
2479}
2480
2481} /* gl4cts namespace */
2482