• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2017 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 es2cTexture3DTests.cpp
21  * \brief GL_OES_texture_3D tests definition.
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "es2cTexture3DTests.hpp"
25 #include "deDefs.hpp"
26 #include "deInt32.h"
27 #include "deRandom.hpp"
28 #include "deString.h"
29 #include "deStringUtil.hpp"
30 #include "deUniquePtr.hpp"
31 #include "gluContextInfo.hpp"
32 #include "gluDrawUtil.hpp"
33 #include "gluPixelTransfer.hpp"
34 #include "gluShaderProgram.hpp"
35 #include "gluTexture.hpp"
36 #include "gluTextureTestUtil.hpp"
37 #include "gluTextureUtil.hpp"
38 #include "glwEnums.hpp"
39 #include "glwFunctions.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuPixelFormat.hpp"
42 #include "tcuRenderTarget.hpp"
43 #include "tcuStringTemplate.hpp"
44 #include "tcuTexLookupVerifier.hpp"
45 #include "tcuTextureUtil.hpp"
46 #include "tcuVectorUtil.hpp"
47 
48 #include <map>
49 
50 using namespace glw;
51 using namespace glu::TextureTestUtil;
52 
53 namespace es2cts
54 {
55 
56 enum
57 {
58 	VIEWPORT_WIDTH  = 64,
59 	VIEWPORT_HEIGHT = 64,
60 };
61 
62 typedef std::pair<int, const char*> CompressedFormatName;
63 static CompressedFormatName compressedFormatNames[] = {
64 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ETC1_RGB8, "etc1_rgb8_oes"),
65 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_4x4_RGBA, "rgba_astc_4x4_khr"),
66 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_5x4_RGBA, "rgba_astc_5x4_khr"),
67 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_5x5_RGBA, "rgba_astc_5x5_khr"),
68 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_6x5_RGBA, "rgba_astc_6x5_khr"),
69 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_6x6_RGBA, "rgba_astc_6x6_khr"),
70 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_8x5_RGBA, "rgba_astc_8x5_khr"),
71 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_8x6_RGBA, "rgba_astc_8x6_khr"),
72 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_8x8_RGBA, "rgba_astc_8x8_khr"),
73 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_10x5_RGBA, "rgba_astc_10x5_khr"),
74 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_10x6_RGBA, "rgba_astc_10x6_khr"),
75 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_10x8_RGBA, "rgba_astc_10x8_khr"),
76 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_10x10_RGBA, "rgba_astc_10x10_khr"),
77 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_12x10_RGBA, "rgba_astc_12x10_khr"),
78 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_12x12_RGBA, "rgba_astc_12x12_khr"),
79 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_4x4_SRGB8_ALPHA8, "srgb8_alpha8_astc_4x4_khr"),
80 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_5x4_SRGB8_ALPHA8, "srgb8_alpha8_astc_5x4_khr"),
81 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_5x5_SRGB8_ALPHA8, "srgb8_alpha8_astc_5x5_khr"),
82 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_6x5_SRGB8_ALPHA8, "srgb8_alpha8_astc_6x5_khr"),
83 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_6x6_SRGB8_ALPHA8, "srgb8_alpha8_astc_6x6_khr"),
84 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_8x5_SRGB8_ALPHA8, "srgb8_alpha8_astc_8x5_khr"),
85 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_8x6_SRGB8_ALPHA8, "srgb8_alpha8_astc_8x6_khr"),
86 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_8x8_SRGB8_ALPHA8, "srgb8_alpha8_astc_8x8_khr"),
87 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_10x5_SRGB8_ALPHA8, "sgb8_alpha8_astc_10x5_khr"),
88 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_10x6_SRGB8_ALPHA8, "srgb8_alpha8_astc_10x6_khr"),
89 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_10x8_SRGB8_ALPHA8, "srgb8_alpha8_astc_10x8_khr"),
90 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_10x10_SRGB8_ALPHA8, "srgb8_alpha8_astc_10x10_khr"),
91 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_12x10_SRGB8_ALPHA8, "srgb8_alpha8_astc_12x10_khr"),
92 	CompressedFormatName(tcu::COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8, "srgb8_alpha8_astc_12x12_khr")
93 };
94 
getCompressedFormatName(tcu::CompressedTexFormat format)95 const char* getCompressedFormatName(tcu::CompressedTexFormat format)
96 {
97 	static std::map<int, const char*> formatMap(compressedFormatNames,
98 												compressedFormatNames + DE_LENGTH_OF_ARRAY(compressedFormatNames));
99 	return formatMap.at(format);
100 }
101 
102 class Texture3DBase : public deqp::TestCase
103 {
104 public:
105 	Texture3DBase(deqp::Context& context, const char* name, const char* description);
106 	virtual ~Texture3DBase(void);
107 
108 	bool isFeatureSupported() const;
109 	void getSupportedCompressedFormats(std::set<int>& validFormats) const;
110 	int calculateDataSize(deUint32 formats, int width, int height, int depth) const;
111 
112 	template <typename TextureType>
113 	void verifyTestResult(const float* texCoords, const tcu::Surface& rendered, const TextureType& reference,
114 						  const ReferenceParams& refParams, bool isNearestOnly) const;
115 
116 	void uploadTexture3D(const glu::Texture3D& texture) const;
117 
118 	void renderQuad(glu::TextureTestUtil::TextureType textureType, const float* texCoords) const;
119 
120 	void verifyError(GLenum expectedError, const char* missmatchMessage) const;
121 	void verifyError(GLenum expectedError1, GLenum expectedError2, const char* missmatchMessage) const;
122 
123 	// New methods wrappers.
124 	void callTexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
125 						GLint border, GLenum format, GLenum type, const void* pixels) const;
126 
127 	void callTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width,
128 						   GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) const;
129 
130 	void callCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x,
131 							   GLint y, GLsizei width, GLsizei height) const;
132 
133 	void callCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
134 								  GLsizei depth, GLint border, GLsizei imageSize, const void* data) const;
135 
136 	void callCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
137 									 GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize,
138 									 const void* data) const;
139 
140 	void callFramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level,
141 								  GLint zoffset) const;
142 };
143 
Texture3DBase(deqp::Context & context,const char * name,const char * description)144 Texture3DBase::Texture3DBase(deqp::Context& context, const char* name, const char* description)
145 	: deqp::TestCase(context, name, description)
146 {
147 }
148 
~Texture3DBase(void)149 Texture3DBase::~Texture3DBase(void)
150 {
151 }
152 
isFeatureSupported() const153 bool Texture3DBase::isFeatureSupported() const
154 {
155 	if (!m_context.getContextInfo().isExtensionSupported("GL_OES_texture_3D") &&
156 		!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 0)) &&
157 		!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)))
158 	{
159 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_OES_texture_3D");
160 		return false;
161 	}
162 	return true;
163 }
164 
getSupportedCompressedFormats(std::set<int> & formatsSet) const165 void Texture3DBase::getSupportedCompressedFormats(std::set<int>& formatsSet) const
166 {
167 	const glu::ContextInfo& contextInfo = m_context.getContextInfo();
168 
169 	formatsSet.clear();
170 	for (int formatNdx = 0; formatNdx < tcu::COMPRESSEDTEXFORMAT_LAST; formatNdx++)
171 	{
172 		// ETC2/EAC/BC (also known as DXT) texture compression algorithm
173 		// supports only two-dimensional images
174 		tcu::CompressedTexFormat format = static_cast<tcu::CompressedTexFormat>(formatNdx);
175 		if (tcu::isEtcFormat(format) || tcu::isBcFormat(format))
176 			continue;
177 
178 		int glFormat = glu::getGLFormat(format);
179 		if (contextInfo.isCompressedTextureFormatSupported(glFormat))
180 			formatsSet.insert(glFormat);
181 	}
182 }
183 
calculateDataSize(deUint32 formats,int width,int height,int depth) const184 int Texture3DBase::calculateDataSize(deUint32 formats, int width, int height, int depth) const
185 {
186 	tcu::CompressedTexFormat format			= glu::mapGLCompressedTexFormat(formats);
187 	const tcu::IVec3		 blockPixelSize = tcu::getBlockPixelSize(format);
188 	const int				 blockSize		= tcu::getBlockSize(format);
189 	return deDivRoundUp32(width, blockPixelSize.x()) * deDivRoundUp32(height, blockPixelSize.y()) *
190 		   deDivRoundUp32(depth, blockPixelSize.z()) * blockSize;
191 }
192 
193 template <typename TextureType>
verifyTestResult(const float * texCoords,const tcu::Surface & rendered,const TextureType & reference,const ReferenceParams & refParams,bool isNearestOnly) const194 void Texture3DBase::verifyTestResult(const float* texCoords, const tcu::Surface& rendered, const TextureType& reference,
195 									 const ReferenceParams& refParams, bool isNearestOnly) const
196 {
197 	const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat();
198 	const tcu::IVec4    refChannelBitDepth	= tcu::getTextureFormatBitDepth(reference.getFormat());
199 	const tcu::IVec4    colorBits = max(tcu::IVec4(de::min(pixelFormat.redBits, refChannelBitDepth[0]),
200 						de::min(pixelFormat.greenBits, refChannelBitDepth[1]),
201 						de::min(pixelFormat.blueBits, refChannelBitDepth[2]),
202 						de::min(pixelFormat.alphaBits, refChannelBitDepth[3])) - (isNearestOnly ? 1 : 2),
203 						tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
204 	tcu::LodPrecision	lodPrecision(18, 6);
205 	tcu::LookupPrecision lookupPrecision;
206 	lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
207 	lookupPrecision.coordBits	  = tcu::IVec3(20, 20, 20);
208 	lookupPrecision.uvwBits		   = tcu::IVec3(7, 7, 7);
209 	lookupPrecision.colorMask	  = getCompareMask(pixelFormat);
210 
211 	if (verifyTextureResult(m_testCtx, rendered.getAccess(), reference, texCoords, refParams, lookupPrecision,
212 							lodPrecision, pixelFormat))
213 	{
214 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
215 		return;
216 	}
217 
218 	// Evaluate against lower precision requirements.
219 	lodPrecision.lodBits	= 4;
220 	lookupPrecision.uvwBits = tcu::IVec3(4, 4, 4);
221 
222 	tcu::TestLog& log = m_testCtx.getLog();
223 	log << tcu::TestLog::Message
224 		<< "Warning: Verification against high precision requirements failed, trying with lower requirements."
225 		<< tcu::TestLog::EndMessage;
226 
227 	if (verifyTextureResult(m_testCtx, rendered.getAccess(), reference, texCoords, refParams, lookupPrecision,
228 							lodPrecision, pixelFormat))
229 	{
230 		m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality filtering result");
231 		return;
232 	}
233 
234 	log << tcu::TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case."
235 		<< tcu::TestLog::EndMessage;
236 	m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
237 }
238 
uploadTexture3D(const glu::Texture3D & texture) const239 void Texture3DBase::uploadTexture3D(const glu::Texture3D& texture) const
240 {
241 	// note: this function is modified version of glu::Texture3D::upload()
242 	// this was needed to support methods added by GL_OES_texture_3D extension
243 
244 	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
245 	deUint32			  textureName	  = texture.getGLTexture();
246 	const tcu::Texture3D& referenceTexture = texture.getRefTexture();
247 
248 	TCU_CHECK(textureName);
249 	gl.bindTexture(GL_TEXTURE_3D, textureName);
250 
251 	GLint pixelStorageMode = 1;
252 	int   pixelSize		   = referenceTexture.getFormat().getPixelSize();
253 	if (deIsPowerOfTwo32(pixelSize))
254 		pixelStorageMode = de::min(pixelSize, 8);
255 
256 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, pixelStorageMode);
257 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
258 
259 	glu::TransferFormat transferFormat = glu::getTransferFormat(referenceTexture.getFormat());
260 
261 	for (int levelNdx = 0; levelNdx < referenceTexture.getNumLevels(); levelNdx++)
262 	{
263 		if (referenceTexture.isLevelEmpty(levelNdx))
264 			continue; // Don't upload.
265 
266 		tcu::ConstPixelBufferAccess access = referenceTexture.getLevel(levelNdx);
267 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth());
268 		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize() * access.getWidth() * access.getHeight());
269 		callTexImage3D(GL_TEXTURE_3D, levelNdx, transferFormat.format, access.getWidth(), access.getHeight(),
270 					   access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType,
271 					   access.getDataPtr());
272 	}
273 
274 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
275 }
276 
renderQuad(glu::TextureTestUtil::TextureType textureType,const float * texCoords) const277 void Texture3DBase::renderQuad(glu::TextureTestUtil::TextureType textureType, const float* texCoords) const
278 {
279 	glu::RenderContext&   renderContext = m_context.getRenderContext();
280 	glu::GLSLVersion	  glslVersion   = glu::getContextTypeGLSLVersion(renderContext.getType());
281 	const glw::Functions& gl			= renderContext.getFunctions();
282 
283 	// Prepare data for rendering
284 	static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };
285 	static const float	position[]	= { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f };
286 
287 	static const char* vsTemplate = "${VERSION}\n"
288 									"attribute highp vec4 a_position;\n"
289 									"attribute highp ${TEXCOORD_TYPE} a_texCoord;\n"
290 									"varying highp ${TEXCOORD_TYPE} v_texCoord;\n"
291 									"void main (void) {\n"
292 									"  gl_Position = a_position;\n"
293 									"  v_texCoord = a_texCoord;\n"
294 									"}\n";
295 	static const char* fsTemplate = "${VERSION}\n"
296 									"${HEADER}\n"
297 									"varying highp ${TEXCOORD_TYPE} v_texCoord;\n"
298 									"uniform highp ${SAMPLER_TYPE} u_sampler;\n"
299 									"void main (void) {\n"
300 									"  gl_FragColor = ${LOOKUP}(u_sampler, v_texCoord);\n"
301 									"}\n";
302 
303 	int numComponents = 3;
304 
305 	std::map<std::string, std::string> specializationMap;
306 	specializationMap["VERSION"] = glu::getGLSLVersionDeclaration(glslVersion);
307 
308 	if (textureType == TEXTURETYPE_3D)
309 	{
310 		specializationMap["HEADER"]		   = "#extension GL_OES_texture_3D : enable";
311 		specializationMap["TEXCOORD_TYPE"] = "vec3";
312 		specializationMap["SAMPLER_TYPE"]  = "sampler3D";
313 		specializationMap["LOOKUP"]		   = "texture3D";
314 	}
315 	else if (textureType == TEXTURETYPE_2D)
316 	{
317 		numComponents					   = 2;
318 		specializationMap["HEADER"]		   = "";
319 		specializationMap["TEXCOORD_TYPE"] = "vec2";
320 		specializationMap["SAMPLER_TYPE"]  = "sampler2D";
321 		specializationMap["LOOKUP"]		   = "texture2D";
322 	}
323 	else
324 		TCU_FAIL("Unsuported texture type.");
325 
326 	// Specialize shaders
327 	std::string			vs = tcu::StringTemplate(vsTemplate).specialize(specializationMap);
328 	std::string			fs = tcu::StringTemplate(fsTemplate).specialize(specializationMap);
329 	glu::ProgramSources programSources(glu::makeVtxFragSources(vs, fs));
330 
331 	// Create program
332 	glu::ShaderProgram testProgram(renderContext, programSources);
333 	if (!testProgram.isOk())
334 	{
335 		m_testCtx.getLog() << testProgram;
336 		TCU_FAIL("Compile failed");
337 	}
338 
339 	// Set uniforms
340 	deUint32 programId = testProgram.getProgram();
341 	gl.useProgram(programId);
342 	gl.uniform1i(gl.getUniformLocation(programId, "u_sampler"), 0);
343 
344 	// Define vertex attributes
345 	const glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("a_position", 2, 4, 0, position),
346 													 glu::va::Float("a_texCoord", numComponents, 4, 0, texCoords) };
347 
348 	// Draw quad
349 	glu::draw(m_context.getRenderContext(), programId, DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
350 			  glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices));
351 }
352 
verifyError(GLenum expectedError,const char * missmatchMessage) const353 void Texture3DBase::verifyError(GLenum expectedError, const char* missmatchMessage) const
354 {
355 	const glw::Functions& gl		   = m_context.getRenderContext().getFunctions();
356 	GLenum				  currentError = gl.getError();
357 	if (currentError == expectedError)
358 		return;
359 
360 	m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect error was reported");
361 	m_testCtx.getLog() << tcu::TestLog::Message << glu::getErrorStr(static_cast<int>(expectedError))
362 					   << " was expected but got " << glu::getErrorStr(static_cast<int>(currentError)) << ". "
363 					   << missmatchMessage << tcu::TestLog::EndMessage;
364 }
365 
verifyError(GLenum expectedError1,GLenum expectedError2,const char * missmatchMessage) const366 void Texture3DBase::verifyError(GLenum expectedError1, GLenum expectedError2, const char* missmatchMessage) const
367 {
368 	const glw::Functions& gl		   = m_context.getRenderContext().getFunctions();
369 	GLenum				  currentError = gl.getError();
370 	if ((currentError == expectedError1) || (currentError == expectedError2))
371 		return;
372 
373 	m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect error was reported");
374 	m_testCtx.getLog() << tcu::TestLog::Message << glu::getErrorStr(static_cast<int>(expectedError1)) << " or "
375 					   << glu::getErrorStr(static_cast<int>(expectedError1)) << " was expected but got "
376 					   << glu::getErrorStr(static_cast<int>(currentError)) << ". " << missmatchMessage
377 					   << tcu::TestLog::EndMessage;
378 }
379 
callTexImage3D(GLenum target,GLint level,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const void * pixels) const380 void Texture3DBase::callTexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height,
381 								   GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) const
382 {
383 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
384 	if (gl.texImage3DOES)
385 		gl.texImage3DOES(target, level, internalFormat, width, height, depth, border, format, type, pixels);
386 	else if (gl.texImage3D)
387 		gl.texImage3D(target, level, static_cast<GLint>(internalFormat), width, height, depth, border, format, type,
388 					  pixels);
389 	else
390 		TCU_FAIL("glTexImage3D not supported");
391 }
392 
callTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels) const393 void Texture3DBase::callTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
394 									  GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
395 									  const void* pixels) const
396 {
397 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
398 	if (gl.texSubImage3DOES)
399 		gl.texSubImage3DOES(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
400 	else if (gl.texSubImage3D)
401 		gl.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
402 	else
403 		TCU_FAIL("glTexSubImage3D not supported");
404 }
405 
callCopyTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height) const406 void Texture3DBase::callCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
407 										  GLint x, GLint y, GLsizei width, GLsizei height) const
408 {
409 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
410 	if (gl.copyTexSubImage3DOES)
411 		gl.copyTexSubImage3DOES(target, level, xoffset, yoffset, zoffset, x, y, width, height);
412 	else if (gl.copyTexSubImage3D)
413 		gl.copyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
414 	else
415 		TCU_FAIL("glCopyTexSubImage3D not supported");
416 }
417 
callCompressedTexImage3D(GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,const void * data) const418 void Texture3DBase::callCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width,
419 											 GLsizei height, GLsizei depth, GLint border, GLsizei imageSize,
420 											 const void* data) const
421 {
422 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
423 	if (gl.compressedTexImage3DOES)
424 		gl.compressedTexImage3DOES(target, level, internalformat, width, height, depth, border, imageSize, data);
425 	else if (gl.compressedTexImage3D)
426 		gl.compressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data);
427 	else
428 		TCU_FAIL("gl.compressedTexImage3D not supported");
429 }
430 
callCompressedTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const void * data) const431 void Texture3DBase::callCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
432 												GLsizei width, GLsizei height, GLsizei depth, GLenum format,
433 												GLsizei imageSize, const void* data) const
434 {
435 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
436 	if (gl.compressedTexSubImage3DOES)
437 		gl.compressedTexSubImage3DOES(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize,
438 									  data);
439 	else if (gl.compressedTexSubImage3D)
440 		gl.compressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize,
441 								   data);
442 	else
443 		TCU_FAIL("gl.compressedTexSubImage3D not supported");
444 }
445 
callFramebufferTexture3D(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLint zoffset) const446 void Texture3DBase::callFramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
447 											 GLint level, GLint zoffset) const
448 {
449 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
450 	if (gl.framebufferTexture3DOES)
451 		gl.framebufferTexture3DOES(target, attachment, textarget, texture, level, zoffset);
452 	else if (gl.framebufferTexture3D)
453 		gl.framebufferTexture3D(target, attachment, textarget, texture, level, zoffset);
454 	else
455 		TCU_FAIL("glFramebufferTexture3D not supported");
456 }
457 
458 struct FilteringData
459 {
460 	GLint minFilter;
461 	GLint magFilter;
462 	GLint wrapS;
463 	GLint wrapT;
464 	GLint wrapR;
465 
466 	deUint32 internalFormat;
467 	int		 width;
468 	int		 height;
469 	int		 depth;
470 };
471 
472 class Texture3DFilteringCase : public Texture3DBase
473 {
474 public:
475 	Texture3DFilteringCase(deqp::Context& context, const char* name, const char* desc, const FilteringData& data);
476 	~Texture3DFilteringCase(void);
477 
478 	void		  init(void);
479 	void		  deinit(void);
480 	IterateResult iterate(void);
481 
482 private:
483 	struct FilterCase
484 	{
485 		const glu::Texture3D* texture;
486 		tcu::Vec3			  lod;
487 		tcu::Vec3			  offset;
488 
FilterCasees2cts::Texture3DFilteringCase::FilterCase489 		FilterCase(void) : texture(DE_NULL)
490 		{
491 		}
492 
FilterCasees2cts::Texture3DFilteringCase::FilterCase493 		FilterCase(const glu::Texture3D* tex_, const tcu::Vec3& lod_, const tcu::Vec3& offset_)
494 			: texture(tex_), lod(lod_), offset(offset_)
495 		{
496 		}
497 	};
498 
499 private:
500 	Texture3DFilteringCase(const Texture3DFilteringCase& other);
501 	Texture3DFilteringCase& operator=(const Texture3DFilteringCase& other);
502 
503 	const FilteringData m_filteringData;
504 
505 	glu::Texture3D* m_gradientTex;
506 	glu::Texture3D* m_gridTex;
507 
508 	std::vector<FilterCase> m_cases;
509 	int						m_caseNdx;
510 };
511 
Texture3DFilteringCase(deqp::Context & context,const char * name,const char * desc,const FilteringData & data)512 Texture3DFilteringCase::Texture3DFilteringCase(deqp::Context& context, const char* name, const char* desc,
513 											   const FilteringData& data)
514 	: Texture3DBase(context, name, desc)
515 	, m_filteringData(data)
516 	, m_gradientTex(DE_NULL)
517 	, m_gridTex(DE_NULL)
518 	, m_caseNdx(0)
519 {
520 }
521 
~Texture3DFilteringCase(void)522 Texture3DFilteringCase::~Texture3DFilteringCase(void)
523 {
524 	Texture3DFilteringCase::deinit();
525 }
526 
init(void)527 void Texture3DFilteringCase::init(void)
528 {
529 	if (!isFeatureSupported())
530 		return;
531 
532 	const deUint32 internalFormat = m_filteringData.internalFormat;
533 	const int	  width		  = m_filteringData.width;
534 	const int	  height		  = m_filteringData.height;
535 	const int	  depth		  = m_filteringData.depth;
536 
537 	const tcu::TextureFormat	 texFmt	= glu::mapGLInternalFormat(internalFormat);
538 	const tcu::TextureFormatInfo fmtInfo   = tcu::getTextureFormatInfo(texFmt);
539 	const tcu::Vec4				 cScale	= fmtInfo.valueMax - fmtInfo.valueMin;
540 	const tcu::Vec4				 cBias	 = fmtInfo.valueMin;
541 	const int					 numLevels = deLog2Floor32(de::max(de::max(width, height), depth)) + 1;
542 
543 	// Create textures.
544 	m_gradientTex = new glu::Texture3D(m_context.getRenderContext(), internalFormat, width, height, depth);
545 	m_gridTex	 = new glu::Texture3D(m_context.getRenderContext(), internalFormat, width, height, depth);
546 
547 	// Fill first gradient texture.
548 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
549 	{
550 		tcu::Vec4 gMin = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
551 		tcu::Vec4 gMax = tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) * cScale + cBias;
552 
553 		m_gradientTex->getRefTexture().allocLevel(levelNdx);
554 		tcu::fillWithComponentGradients(m_gradientTex->getRefTexture().getLevel(levelNdx), gMin, gMax);
555 	}
556 
557 	// Fill second with grid texture.
558 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
559 	{
560 		deUint32 step   = 0x00ffffff / numLevels;
561 		deUint32 rgb	= step * levelNdx;
562 		deUint32 colorA = 0xff000000 | rgb;
563 		deUint32 colorB = 0xff000000 | ~rgb;
564 
565 		m_gridTex->getRefTexture().allocLevel(levelNdx);
566 		tcu::fillWithGrid(m_gridTex->getRefTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec() * cScale + cBias,
567 						  tcu::RGBA(colorB).toVec() * cScale + cBias);
568 	}
569 
570 	// Upload.
571 	uploadTexture3D(*m_gradientTex);
572 	uploadTexture3D(*m_gridTex);
573 
574 	// Test cases
575 	m_cases.push_back(FilterCase(m_gradientTex, tcu::Vec3(1.5f, 2.8f, 1.0f), tcu::Vec3(-1.0f, -2.7f, -2.275f)));
576 	m_cases.push_back(FilterCase(m_gradientTex, tcu::Vec3(-2.0f, -1.5f, -1.8f), tcu::Vec3(-0.1f, 0.9f, -0.25f)));
577 	m_cases.push_back(FilterCase(m_gridTex, tcu::Vec3(0.2f, 0.175f, 0.3f), tcu::Vec3(-2.0f, -3.7f, -1.825f)));
578 	m_cases.push_back(FilterCase(m_gridTex, tcu::Vec3(-0.8f, -2.3f, -2.5f), tcu::Vec3(0.2f, -0.1f, 1.325f)));
579 
580 	m_caseNdx = 0;
581 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
582 }
583 
deinit(void)584 void Texture3DFilteringCase::deinit(void)
585 {
586 	delete m_gradientTex;
587 	delete m_gridTex;
588 
589 	m_gradientTex = DE_NULL;
590 	m_gridTex	 = DE_NULL;
591 
592 	m_cases.clear();
593 }
594 
iterate(void)595 Texture3DFilteringCase::IterateResult Texture3DFilteringCase::iterate(void)
596 {
597 	if (!isFeatureSupported())
598 		return STOP;
599 
600 	const glw::Functions&		 gl		 = m_context.getRenderContext().getFunctions();
601 	const FilterCase&			 curCase = m_cases[m_caseNdx];
602 	const tcu::TextureFormat	 texFmt  = curCase.texture->getRefTexture().getFormat();
603 	const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
604 	const tcu::ScopedLogSection  section(m_testCtx.getLog(), std::string("Test") + de::toString(m_caseNdx),
605 										std::string("Test ") + de::toString(m_caseNdx));
606 	tcu::TestLog&   log = m_testCtx.getLog();
607 	ReferenceParams refParams(TEXTURETYPE_3D);
608 	tcu::Surface	rendered(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
609 	tcu::Vec3		texCoord[4];
610 
611 	// Setup params for reference.
612 	refParams.sampler = glu::mapGLSampler(m_filteringData.wrapS, m_filteringData.wrapT, m_filteringData.wrapR,
613 										  m_filteringData.minFilter, m_filteringData.magFilter);
614 	refParams.samplerType = getSamplerType(texFmt);
615 	refParams.lodMode	 = LODMODE_EXACT;
616 	refParams.colorBias   = fmtInfo.lookupBias;
617 	refParams.colorScale  = fmtInfo.lookupScale;
618 
619 	// Compute texture coordinates.
620 	log << tcu::TestLog::Message << "Approximate lod per axis = " << curCase.lod << ", offset = " << curCase.offset
621 		<< tcu::TestLog::EndMessage;
622 
623 	{
624 		const float lodX = curCase.lod.x();
625 		const float lodY = curCase.lod.y();
626 		const float lodZ = curCase.lod.z();
627 		const float oX   = curCase.offset.x();
628 		const float oY   = curCase.offset.y();
629 		const float oZ   = curCase.offset.z();
630 		const float sX   = deFloatExp2(lodX) * float(VIEWPORT_WIDTH) / float(m_gradientTex->getRefTexture().getWidth());
631 		const float sY = deFloatExp2(lodY) * float(VIEWPORT_HEIGHT) / float(m_gradientTex->getRefTexture().getHeight());
632 		const float sZ = deFloatExp2(lodZ) * float(VIEWPORT_WIDTH) / float(m_gradientTex->getRefTexture().getDepth());
633 
634 		texCoord[0] = tcu::Vec3(oX, oY, oZ);
635 		texCoord[1] = tcu::Vec3(oX, oY + sY, oZ + sZ * 0.5f);
636 		texCoord[2] = tcu::Vec3(oX + sX, oY, oZ + sZ * 0.5f);
637 		texCoord[3] = tcu::Vec3(oX + sX, oY + sY, oZ + sZ);
638 	}
639 
640 	gl.bindTexture(GL_TEXTURE_3D, curCase.texture->getGLTexture());
641 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, m_filteringData.minFilter);
642 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, m_filteringData.magFilter);
643 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, m_filteringData.wrapS);
644 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, m_filteringData.wrapT);
645 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, m_filteringData.wrapR);
646 
647 	// Verify bound 3D texture.
648 	GLint resultName;
649 	gl.getIntegerv(GL_TEXTURE_BINDING_3D, &resultName);
650 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv");
651 	if (curCase.texture->getGLTexture() == static_cast<deUint32>(resultName))
652 	{
653 		// Render.
654 		gl.viewport(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
655 		renderQuad(TEXTURETYPE_3D, texCoord->getPtr());
656 		glu::readPixels(m_context.getRenderContext(), 0, 0, rendered.getAccess());
657 
658 		// Compare rendered image to reference.
659 		const bool isNearestOnly =
660 			(m_filteringData.minFilter == GL_NEAREST) && (m_filteringData.magFilter == GL_NEAREST);
661 		verifyTestResult(texCoord[0].getPtr(), rendered, curCase.texture->getRefTexture(), refParams, isNearestOnly);
662 	}
663 	else
664 	{
665 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid texture name");
666 	}
667 
668 	++m_caseNdx;
669 	return (m_caseNdx < static_cast<int>(m_cases.size())) ? CONTINUE : STOP;
670 }
671 
672 class TexSubImage3DCase : public Texture3DBase
673 {
674 public:
675 	TexSubImage3DCase(deqp::Context& context, const char* name, const char* desc, deUint32 internalFormat, int width,
676 					  int height, int depth);
677 
678 	IterateResult iterate(void);
679 
680 private:
681 	deUint32 m_internalFormat;
682 	int		 m_width;
683 	int		 m_height;
684 	int		 m_depth;
685 	int		 m_numLevels;
686 };
687 
TexSubImage3DCase(deqp::Context & context,const char * name,const char * desc,deUint32 internalFormat,int width,int height,int depth)688 TexSubImage3DCase::TexSubImage3DCase(deqp::Context& context, const char* name, const char* desc,
689 									 deUint32 internalFormat, int width, int height, int depth)
690 	: Texture3DBase(context, name, desc)
691 	, m_internalFormat(internalFormat)
692 	, m_width(width)
693 	, m_height(height)
694 	, m_depth(depth)
695 	, m_numLevels(static_cast<int>(deLog2Floor32(de::max(width, de::max(height, depth))) + 1))
696 {
697 }
698 
iterate(void)699 TexSubImage3DCase::IterateResult TexSubImage3DCase::iterate(void)
700 {
701 	if (!isFeatureSupported())
702 		return STOP;
703 
704 	glu::RenderContext&   renderCtx = m_context.getRenderContext();
705 	const glw::Functions& gl		= renderCtx.getFunctions();
706 
707 	tcu::Vec4					 firstColor(0.0f, 1.0f, 0.0f, 1.0f);
708 	tcu::Vec4					 secondColor(1.0f, 0.0f, 1.0f, 1.0f);
709 	glu::Texture3D				 texture(m_context.getRenderContext(), m_internalFormat, m_width, m_height, m_depth);
710 	const tcu::TextureFormat	 textureFormat = texture.getRefTexture().getFormat();
711 	const tcu::TextureFormatInfo formatInfo	= tcu::getTextureFormatInfo(textureFormat);
712 
713 	// Fill texture.
714 	for (int levelNdx = 0; levelNdx < m_numLevels; levelNdx++)
715 	{
716 		texture.getRefTexture().allocLevel(levelNdx);
717 		const tcu::PixelBufferAccess& pba = texture.getRefTexture().getLevel(levelNdx);
718 		tcu::fillWithComponentGradients(pba, firstColor, secondColor);
719 	}
720 
721 	// Upload texture
722 	uploadTexture3D(texture);
723 
724 	gl.bindTexture(GL_TEXTURE_3D, texture.getGLTexture());
725 	GLU_EXPECT_NO_ERROR(gl.getError(), "gl.bindTexture");
726 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
727 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri for GL_TEXTURE_WRAP_R");
728 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
729 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri for GL_TEXTURE_WRAP_T");
730 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
731 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri for GL_TEXTURE_WRAP_R");
732 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
733 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri for GL_TEXTURE_MIN_FILTER");
734 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
735 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri for GL_TEXTURE_MAG_FILTER");
736 
737 	// Re-specify parts of each level in uploaded texture and in reference texture
738 	tcu::TextureLevel data(textureFormat);
739 	for (int levelNdx = 0; levelNdx < m_numLevels - 2; levelNdx++)
740 	{
741 		int scale = levelNdx + 1;
742 		int w	 = de::max(1, m_width >> scale);
743 		int h	 = de::max(1, m_height >> scale);
744 		int d	 = de::max(1, m_depth >> levelNdx);
745 
746 		data.setSize(w, h, d);
747 		tcu::clear(data.getAccess(), secondColor);
748 
749 		glu::TransferFormat transferFormat = glu::getTransferFormat(textureFormat);
750 		callTexSubImage3D(GL_TEXTURE_3D, levelNdx, w, h, 0, w, h, d, transferFormat.format, transferFormat.dataType,
751 						  data.getAccess().getDataPtr());
752 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage3D");
753 
754 		const tcu::PixelBufferAccess& pba = texture.getRefTexture().getLevel(levelNdx);
755 		tcu::clear(getSubregion(pba, w, h, 0, w, h, d), secondColor);
756 	}
757 
758 	// Setup params for reference.
759 	ReferenceParams refParams(TEXTURETYPE_3D);
760 	refParams.sampler	 = glu::mapGLSampler(GL_REPEAT, GL_REPEAT, GL_REPEAT, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST);
761 	refParams.samplerType = getSamplerType(textureFormat);
762 	refParams.lodMode	 = LODMODE_EXACT;
763 	refParams.colorBias   = formatInfo.lookupBias;
764 	refParams.colorScale  = formatInfo.lookupScale;
765 
766 	tcu::Vec3 texCoord[4] = { tcu::Vec3(0.0f, 0.0f, 0.5f), tcu::Vec3(0.0f, 1.0f, 0.5f), tcu::Vec3(1.0f, 0.0f, 0.5f),
767 							  tcu::Vec3(1.0f, 1.0f, 0.5f) };
768 
769 	// Render.
770 	gl.viewport(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
771 	renderQuad(TEXTURETYPE_3D, texCoord[0].getPtr());
772 
773 	tcu::Surface rendered(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
774 	glu::readPixels(m_context.getRenderContext(), 0, 0, rendered.getAccess());
775 
776 	// Compare rendered image to reference.
777 	verifyTestResult(texCoord[0].getPtr(), rendered, texture.getRefTexture(), refParams, false);
778 	return STOP;
779 }
780 
781 class CopyTexSubImage3DCase : public Texture3DBase
782 {
783 public:
784 	CopyTexSubImage3DCase(deqp::Context& context, const char* name, const char* desc, deUint32 format,
785 						  deUint32 type, int width, int height, int depth);
786 
787 	IterateResult iterate(void);
788 
789 private:
790 	deUint32 m_format;
791 	deUint32 m_type;
792 	int		 m_width;
793 	int		 m_height;
794 	int		 m_depth;
795 	int		 m_numLevels;
796 };
797 
CopyTexSubImage3DCase(deqp::Context & context,const char * name,const char * desc,deUint32 format,deUint32 type,int width,int height,int depth)798 CopyTexSubImage3DCase::CopyTexSubImage3DCase(deqp::Context& context, const char* name, const char* desc,
799 											 deUint32 format, deUint32 type, int width, int height, int depth)
800 	: Texture3DBase(context, name, desc)
801 	, m_format(format)
802 	, m_type(type)
803 	, m_width(width)
804 	, m_height(height)
805 	, m_depth(depth)
806 	, m_numLevels(static_cast<int>(deLog2Floor32(de::max(width, de::max(height, depth))) + 1))
807 {
808 }
809 
iterate(void)810 CopyTexSubImage3DCase::IterateResult CopyTexSubImage3DCase::iterate(void)
811 {
812 	if (!isFeatureSupported())
813 		return STOP;
814 
815 	glu::RenderContext&   renderCtx = m_context.getRenderContext();
816 	const glw::Functions& gl		= renderCtx.getFunctions();
817 
818 	ReferenceParams				 refParams(TEXTURETYPE_3D);
819 	tcu::Surface				 rendered(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
820 	tcu::Vec4					 firstColor(0.0f, 1.0f, 0.0f, 1.0f);
821 	tcu::Vec4					 secondColor(1.0f, 0.0f, 1.0f, 1.0f);
822 	glu::Texture3D				 texture(m_context.getRenderContext(), m_format, m_type, m_width, m_height, m_depth);
823 	const tcu::TextureFormat	 textureFormat = texture.getRefTexture().getFormat();
824 	const tcu::TextureFormatInfo formatInfo	= tcu::getTextureFormatInfo(textureFormat);
825 
826 	glw::GLuint fbo = 0;
827 	gl.genFramebuffers(1, &fbo);
828 	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
829 	glw::GLuint new_dst_to = 0;
830 	gl.genTextures(1, &new_dst_to);
831 	gl.bindTexture(GL_TEXTURE_2D, new_dst_to);
832 
833 	/* The longest edge of texture(32*64*8) is 64, so we create a texture with 64*64 dimension. */
834 	gl.texImage2D(GL_TEXTURE_2D, 0, m_format, 64, 64, 0, m_format, m_type, NULL);
835 	GLU_EXPECT_NO_ERROR(gl.getError(),
836 						"Could not setup texture object for draw framebuffer color attachment.");
837 
838 	gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, new_dst_to, 0);
839 
840 	GLU_EXPECT_NO_ERROR(gl.getError(),
841 						"Could not attach texture object to draw framebuffer color attachment.");
842 	// Fill texture.
843 	for (int levelNdx = 0; levelNdx < m_numLevels; levelNdx++)
844 	{
845 		texture.getRefTexture().allocLevel(levelNdx);
846 		const tcu::PixelBufferAccess& pba = texture.getRefTexture().getLevel(levelNdx);
847 		tcu::fillWithComponentGradients(pba, firstColor, secondColor);
848 	}
849 
850 	// Upload texture.
851 	uploadTexture3D(texture);
852 
853 	gl.clearColor(secondColor[0], secondColor[1], secondColor[2], secondColor[3]);
854 	gl.clear(GL_COLOR_BUFFER_BIT);
855 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
856 
857 	gl.bindTexture(GL_TEXTURE_3D, texture.getGLTexture());
858 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
859 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
860 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
861 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
862 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
863 
864 	// Re-specify parts of each level in uploaded texture and in reference texture
865 	tcu::TextureLevel data(textureFormat);
866 	for (int levelNdx = 0; levelNdx < m_numLevels - 2; levelNdx++)
867 	{
868 		int scale = levelNdx + 1;
869 		int w	 = de::max(1, m_width >> scale);
870 		int h	 = de::max(1, m_height >> scale);
871 		int d	 = de::max(1, m_depth >> levelNdx);
872 
873 		data.setSize(w, h, d);
874 		tcu::clear(data.getAccess(), secondColor);
875 
876 		for (int depthNdx = 0; depthNdx < d; depthNdx++)
877 		{
878 			callCopyTexSubImage3D(GL_TEXTURE_3D, levelNdx, w, h, depthNdx, 0, 0, w, h);
879 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCopyTexSubImage3D");
880 		}
881 		const tcu::PixelBufferAccess& pba = texture.getRefTexture().getLevel(levelNdx);
882 		tcu::clear(getSubregion(pba, w, h, 0, w, h, d), secondColor);
883 	}
884 
885 	// Setup params for reference.
886 	refParams.sampler	 = glu::mapGLSampler(GL_REPEAT, GL_REPEAT, GL_REPEAT, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST);
887 	refParams.samplerType = getSamplerType(textureFormat);
888 	refParams.lodMode	 = LODMODE_EXACT;
889 	refParams.colorBias   = formatInfo.lookupBias;
890 	refParams.colorScale  = formatInfo.lookupScale;
891 
892 	tcu::Vec3 texCoord[4] = { tcu::Vec3(0.0f, 0.0f, 0.5f), tcu::Vec3(0.0f, 1.0f, 0.5f), tcu::Vec3(1.0f, 0.0f, 0.5f),
893 							  tcu::Vec3(1.0f, 1.0f, 0.5f) };
894 
895 	// Render.
896 	gl.viewport(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
897 	renderQuad(TEXTURETYPE_3D, texCoord[0].getPtr());
898 	glu::readPixels(m_context.getRenderContext(), 0, 0, rendered.getAccess());
899 
900 	// Compare rendered image to reference.
901 	verifyTestResult(texCoord[0].getPtr(), rendered, texture.getRefTexture(), refParams, false);
902 	gl.deleteTextures(1, &new_dst_to);
903 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
904 	gl.deleteFramebuffers(1, &fbo);
905 	return STOP;
906 }
907 
908 class FramebufferTexture3DCase : public Texture3DBase
909 {
910 public:
911 	FramebufferTexture3DCase(deqp::Context& context, const char* name, const char* desc, deUint32 format,
912 	                         deUint32 type, int width, int height, int depth);
913 
914 	IterateResult iterate(void);
915 
916 private:
917 	deUint32 m_format;
918 	deUint32 m_type;
919 	int		 m_width;
920 	int		 m_height;
921 	int		 m_depth;
922 	int		 m_numLevels;
923 };
924 
FramebufferTexture3DCase(deqp::Context & context,const char * name,const char * desc,deUint32 format,deUint32 type,int width,int height,int depth)925 FramebufferTexture3DCase::FramebufferTexture3DCase(deqp::Context& context, const char* name, const char* desc,
926 												   deUint32 format, deUint32 type, int width, int height, int depth)
927 	: Texture3DBase(context, name, desc)
928 	, m_format(format)
929 	, m_type(type)
930 	, m_width(width)
931 	, m_height(height)
932 	, m_depth(depth)
933 	, m_numLevels(static_cast<int>(deLog2Floor32(de::max(width, de::max(height, depth))) + 1))
934 {
935 }
936 
iterate(void)937 FramebufferTexture3DCase::IterateResult FramebufferTexture3DCase::iterate(void)
938 {
939 	if (!isFeatureSupported())
940 		return STOP;
941 
942 	glu::RenderContext&   renderCtx = m_context.getRenderContext();
943 	const glw::Functions& gl		= renderCtx.getFunctions();
944 
945 	tcu::Vec4	  firstColor(0.0f, 1.0f, 0.0f, 1.0f);
946 	tcu::Vec4	  secondColor(1.0f, 0.0f, 1.0f, 1.0f);
947 	glu::Texture3D texture3D(m_context.getRenderContext(), m_format, m_type, m_width, m_height, m_depth);
948 	glu::Texture2D texture2D(m_context.getRenderContext(), m_format, m_type, m_width, m_height);
949 
950 	// Fill textures.
951 	texture3D.getRefTexture().allocLevel(0);
952 	const tcu::PixelBufferAccess& pba3D = texture3D.getRefTexture().getLevel(0);
953 	tcu::clear(pba3D, secondColor);
954 
955 	for (int levelNdx = 0; levelNdx < m_numLevels; levelNdx++)
956 	{
957 		texture2D.getRefTexture().allocLevel(levelNdx);
958 		const tcu::PixelBufferAccess& pba2D = texture2D.getRefTexture().getLevel(levelNdx);
959 		tcu::fillWithGrid(pba2D, 4, firstColor, secondColor);
960 	}
961 
962 	// Upload textures.
963 	uploadTexture3D(texture3D);
964 	texture2D.upload();
965 
966 	gl.bindTexture(GL_TEXTURE_3D, texture3D.getGLTexture());
967 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
968 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
969 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
970 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
971 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
972 
973 	// Create framebuffer.
974 	glw::GLuint fbo = 0;
975 	gl.genFramebuffers(1, &fbo);
976 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers");
977 	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
978 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffers");
979 	callFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, texture3D.getGLTexture(), 0, 1);
980 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture3D");
981 
982 	deUint32 status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
983 	if (status != GL_FRAMEBUFFER_COMPLETE)
984 		TCU_FAIL("Framebuffer is not complete");
985 
986 	gl.bindTexture(GL_TEXTURE_2D, texture2D.getGLTexture());
987 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
988 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
989 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
990 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
991 
992 	const tcu::TextureFormat	 textureFormat = texture2D.getRefTexture().getFormat();
993 	const tcu::TextureFormatInfo formatInfo	= tcu::getTextureFormatInfo(textureFormat);
994 
995 	tcu::Vec2 texCoord[4] = { tcu::Vec2(0.0f, 0.0f), tcu::Vec2(0.0f, 1.0f), tcu::Vec2(1.0f, 0.0f),
996 							  tcu::Vec2(1.0f, 1.0f) };
997 
998 	// Render to fbo.
999 	gl.viewport(0, 0, m_width, m_height);
1000 	renderQuad(TEXTURETYPE_2D, texCoord[0].getPtr());
1001 
1002 	// Setup params for reference.
1003 	ReferenceParams refParams(TEXTURETYPE_2D);
1004 	refParams.sampler	 = glu::mapGLSampler(GL_REPEAT, GL_REPEAT, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST);
1005 	refParams.samplerType = getSamplerType(textureFormat);
1006 	refParams.lodMode	 = LODMODE_EXACT;
1007 	refParams.colorBias   = formatInfo.lookupBias;
1008 	refParams.colorScale  = formatInfo.lookupScale;
1009 
1010 	// Compare image rendered to selected layer of 3d texture to reference.
1011 	tcu::Surface rendered(m_width, m_height);
1012 	glu::readPixels(m_context.getRenderContext(), 0, 0, rendered.getAccess());
1013 	verifyTestResult(texCoord[0].getPtr(), rendered, texture2D.getRefTexture(), refParams, false);
1014 
1015 	// Cleanup.
1016 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1017 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
1018 	gl.deleteFramebuffers(1, &fbo);
1019 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers");
1020 
1021 	return STOP;
1022 }
1023 
checkFormatSupport(const glu::ContextInfo & info,deUint32 format)1024 void checkFormatSupport(const glu::ContextInfo& info, deUint32 format)
1025 {
1026 	if (glu::isCompressedFormat(format))
1027 	{
1028 		if (isAstcFormat(glu::mapGLCompressedTexFormat(format)))
1029 		{
1030 			if (!info.isExtensionSupported("GL_KHR_texture_compression_astc_hdr") &&
1031 				!info.isExtensionSupported("GL_OES_texture_compression_astc"))
1032 			{
1033 				TCU_THROW(NotSupportedError, "requires HDR astc support.");
1034 			}
1035 		}
1036 	}
1037 }
1038 
1039 class CompressedTexture3DCase : public Texture3DBase
1040 {
1041 public:
1042 	CompressedTexture3DCase(deqp::Context& context, const char* name, deUint32 format);
1043 
1044 	IterateResult iterate(void);
1045 
1046 private:
1047 	int m_compressedFormat;
1048 };
1049 
CompressedTexture3DCase(deqp::Context & context,const char * name,deUint32 format)1050 CompressedTexture3DCase::CompressedTexture3DCase(deqp::Context& context, const char* name, deUint32 format)
1051 	: Texture3DBase(context, name, ""), m_compressedFormat(static_cast<int>(format))
1052 {
1053 }
1054 
iterate(void)1055 CompressedTexture3DCase::IterateResult CompressedTexture3DCase::iterate(void)
1056 {
1057 	if (!isFeatureSupported())
1058 		return STOP;
1059 
1060 	const glw::Functions&	gl			 = m_context.getRenderContext().getFunctions();
1061 	const glu::ContextInfo&  contextInfo = m_context.getContextInfo();
1062 	tcu::CompressedTexFormat format		 = glu::mapGLCompressedTexFormat(m_compressedFormat);
1063 
1064 	if (!contextInfo.isCompressedTextureFormatSupported(m_compressedFormat))
1065 	{
1066 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Compressed format not supported by implementation");
1067 		return STOP;
1068 	}
1069 
1070 	checkFormatSupport(contextInfo, m_compressedFormat);
1071 
1072 	const deInt32 width		  = 64;
1073 	const deInt32 height	  = 64;
1074 	const deInt32 depth		  = 4;
1075 	const deInt32 levelsCount = 4;
1076 
1077 	GLuint textureName;
1078 	gl.genTextures(1, &textureName);
1079 	GLU_EXPECT_NO_ERROR(gl.getError(), "gl.genTextures");
1080 	gl.bindTexture(GL_TEXTURE_3D, textureName);
1081 	GLU_EXPECT_NO_ERROR(gl.getError(), "gl.bindTexture");
1082 
1083 	// Create 3D texture with random data.
1084 	for (deInt32 levelIndex = 0; levelIndex < levelsCount; ++levelIndex)
1085 	{
1086 		deInt32 levelWidth  = de::max(width >> levelIndex, 1);
1087 		deInt32 levelHeight = de::max(height >> levelIndex, 1);
1088 		deInt32 levelDepth  = de::max(depth >> levelIndex, 1);
1089 
1090 		tcu::CompressedTexture level(format, levelWidth, levelHeight, levelDepth);
1091 		const int			   dataSize = level.getDataSize();
1092 		deUint8* const		   data		= static_cast<deUint8*>(level.getData());
1093 		de::Random			   rnd(deStringHash(getName()) + levelIndex);
1094 
1095 		for (int i  = 0; i < dataSize; i++)
1096 			data[i] = rnd.getUint32() & 0xff;
1097 
1098 		callCompressedTexImage3D(GL_TEXTURE_3D, levelIndex, m_compressedFormat, level.getWidth(), level.getHeight(),
1099 								 level.getDepth(), 0 /* border */, level.getDataSize(), level.getData());
1100 		GLU_EXPECT_NO_ERROR(gl.getError(), "callCompressedTexImage3D");
1101 	}
1102 
1103 	// Replace whole texture data.
1104 	for (deInt32 levelIndex = levelsCount - 2; levelIndex >= 0; --levelIndex)
1105 	{
1106 		deInt32 partWidth  = de::max(width >> levelIndex, 1);
1107 		deInt32 partHeight = de::max(height >> levelIndex, 1);
1108 		deInt32 partDepth  = de::max(depth >> levelIndex, 1);
1109 
1110 		tcu::CompressedTexture dataPart(format, partWidth, partHeight, partDepth);
1111 		const int			   dataSize = dataPart.getDataSize();
1112 		deUint8* const		   data		= static_cast<deUint8*>(dataPart.getData());
1113 		de::Random			   rnd(deStringHash(getName()) + levelIndex);
1114 
1115 		for (int i  = 0; i < dataSize; i++)
1116 			data[i] = rnd.getUint32() & 0xff;
1117 
1118 		callCompressedTexSubImage3D(GL_TEXTURE_3D, levelIndex, 0, 0, 0, dataPart.getWidth(), dataPart.getHeight(),
1119 									dataPart.getDepth(), m_compressedFormat, dataPart.getDataSize(),
1120 									dataPart.getData());
1121 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexSubImage3D");
1122 	}
1123 
1124 	gl.deleteTextures(1, &textureName);
1125 	GLU_EXPECT_NO_ERROR(gl.getError(), "gl.deleteTextures");
1126 
1127 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1128 	return STOP;
1129 }
1130 
1131 class NegativeTexImage3DCase : public Texture3DBase
1132 {
1133 public:
1134 	NegativeTexImage3DCase(deqp::Context& context, const char* name);
1135 
1136 	IterateResult iterate(void);
1137 };
1138 
NegativeTexImage3DCase(deqp::Context & context,const char * name)1139 NegativeTexImage3DCase::NegativeTexImage3DCase(deqp::Context& context, const char* name)
1140 	: Texture3DBase(context, name, "")
1141 {
1142 }
1143 
iterate(void)1144 NegativeTexImage3DCase::IterateResult NegativeTexImage3DCase::iterate(void)
1145 {
1146 	if (!isFeatureSupported())
1147 		return STOP;
1148 
1149 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1150 
1151 	/* Integer textures supported for OpenGL ES 3.0+ */
1152 	int major = 0;
1153 	gl.getIntegerv(GL_MAJOR_VERSION, &major);
1154 	bool supportsIntegerTextures = major >= 3;
1155 
1156 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1157 
1158 	// negative usage
1159 	{
1160 		const char* message1 = "GL_INVALID_ENUM is generated if target is invalid.";
1161 		callTexImage3D(0, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1162 		verifyError(GL_INVALID_ENUM, message1);
1163 		callTexImage3D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1164 		verifyError(GL_INVALID_ENUM, message1);
1165 
1166 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, 0, 0);
1167 		verifyError(GL_INVALID_ENUM, "GL_INVALID_ENUM is generated if type is not a type constant.");
1168 
1169 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, 0, GL_UNSIGNED_BYTE, 0);
1170 		verifyError(GL_INVALID_ENUM, "GL_INVALID_ENUM is generated if format is not an accepted format constant.");
1171 
1172 		callTexImage3D(GL_TEXTURE_3D, 0, 0, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1173 		verifyError(GL_INVALID_VALUE, "GL_INVALID_VALUE is generated if internalFormat is not one of the accepted "
1174 									  "resolution and format symbolic constants.");
1175 
1176 		const char* message2 = "GL_INVALID_OPERATION is generated if target is GL_TEXTURE_3D and format is "
1177 							   "GL_DEPTH_COMPONENT, or GL_DEPTH_STENCIL.";
1178 		callTexImage3D(GL_TEXTURE_3D, 0, GL_DEPTH_STENCIL, 1, 1, 1, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);
1179 		verifyError(GL_INVALID_OPERATION, message2);
1180 		callTexImage3D(GL_TEXTURE_3D, 0, GL_DEPTH_COMPONENT, 1, 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
1181 		verifyError(GL_INVALID_OPERATION, message2);
1182 
1183 		const char* message3 =
1184 			"GL_INVALID_OPERATION is generated if the combination of internalFormat, format and type is invalid.";
1185 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1186 		verifyError(GL_INVALID_OPERATION, message3);
1187 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_4_4_4_4, 0);
1188 		verifyError(GL_INVALID_OPERATION, message3);
1189 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGB5_A1, 1, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1, 0);
1190 		verifyError(GL_INVALID_OPERATION, message3);
1191 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGB10_A2, 1, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_2_10_10_10_REV, 0);
1192 		verifyError(GL_INVALID_OPERATION, message3);
1193 
1194 		if (supportsIntegerTextures) {
1195 			callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32UI, 1, 1, 1, 0, GL_RGBA_INTEGER, GL_INT, 0);
1196 			verifyError(GL_INVALID_OPERATION, message3);
1197 		}
1198 	}
1199 
1200 	// invalid leve
1201 	{
1202 		const char* message = "GL_INVALID_VALUE is generated if level is less than 0.";
1203 		callTexImage3D(GL_TEXTURE_3D, -1, GL_RGB, 1, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
1204 		verifyError(GL_INVALID_VALUE, message);
1205 	}
1206 
1207 	// maximal level
1208 	{
1209 		int max3DTexSize;
1210 		gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max3DTexSize);
1211 		GLint log2Max3DTextureSize = deLog2Floor32(max3DTexSize) + 1;
1212 		callTexImage3D(GL_TEXTURE_3D, log2Max3DTextureSize, GL_RGB, 1, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
1213 		verifyError(GL_INVALID_VALUE,
1214 					"GL_INVALID_VALUE is generated if level is greater than log_2(GL_MAX_3D_TEXTURE_SIZE).");
1215 	}
1216 
1217 	// negative dimensions
1218 	{
1219 		const char* message = "GL_INVALID_VALUE is generated if width or height is less than 0.";
1220 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, -1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1221 		verifyError(GL_INVALID_VALUE, message);
1222 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, -1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1223 		verifyError(GL_INVALID_VALUE, message);
1224 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, -1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1225 		verifyError(GL_INVALID_VALUE, message);
1226 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, -1, -1, -1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1227 		verifyError(GL_INVALID_VALUE, message);
1228 	}
1229 
1230 	// maximal dimensions
1231 	{
1232 		int aboveMax3DTextureSize;
1233 		gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &aboveMax3DTextureSize);
1234 		int aboveMaxTextureSize;
1235 		gl.getIntegerv(GL_MAX_TEXTURE_SIZE, &aboveMaxTextureSize);
1236 		++aboveMax3DTextureSize;
1237 		++aboveMaxTextureSize;
1238 
1239 		const char* message =
1240 			"GL_INVALID_VALUE is generated if width, height or depth is greater than GL_MAX_3D_TEXTURE_SIZE.";
1241 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, aboveMax3DTextureSize, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1242 		verifyError(GL_INVALID_VALUE, message);
1243 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, aboveMax3DTextureSize, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1244 		verifyError(GL_INVALID_VALUE, message);
1245 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, aboveMax3DTextureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1246 		verifyError(GL_INVALID_VALUE, message);
1247 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, aboveMax3DTextureSize, aboveMax3DTextureSize, aboveMax3DTextureSize,
1248 					   0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1249 		verifyError(GL_INVALID_VALUE, message);
1250 	}
1251 
1252 	// invalid border
1253 	{
1254 		const char* message = "GL_INVALID_VALUE is generated if border is not 0 or 1.";
1255 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 1, 1, 1, -1, GL_RGB, GL_UNSIGNED_BYTE, 0);
1256 		verifyError(GL_INVALID_VALUE, message);
1257 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 1, 1, 1, 2, GL_RGB, GL_UNSIGNED_BYTE, 0);
1258 		verifyError(GL_INVALID_VALUE, message);
1259 	}
1260 
1261 	return STOP;
1262 }
1263 
1264 class NegativeCompressedTexImage3DCase : public Texture3DBase
1265 {
1266 public:
1267 	NegativeCompressedTexImage3DCase(deqp::Context& context, const char* name);
1268 
1269 	IterateResult iterate(void);
1270 };
1271 
NegativeCompressedTexImage3DCase(deqp::Context & context,const char * name)1272 NegativeCompressedTexImage3DCase::NegativeCompressedTexImage3DCase(deqp::Context& context, const char* name)
1273 	: Texture3DBase(context, name, "")
1274 {
1275 }
1276 
1277 class NegativeTexSubImage3DCase : public Texture3DBase
1278 {
1279 public:
1280 	NegativeTexSubImage3DCase(deqp::Context& context, const char* name);
1281 
1282 	IterateResult iterate(void);
1283 };
1284 
NegativeTexSubImage3DCase(deqp::Context & context,const char * name)1285 NegativeTexSubImage3DCase::NegativeTexSubImage3DCase(deqp::Context& context, const char* name)
1286 	: Texture3DBase(context, name, "")
1287 {
1288 }
1289 
iterate(void)1290 NegativeTexSubImage3DCase::IterateResult NegativeTexSubImage3DCase::iterate(void)
1291 {
1292 	if (!isFeatureSupported())
1293 		return STOP;
1294 
1295 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1296 
1297 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1298 
1299 	// negative usage
1300 	{
1301 		deUint32 texture = 0x1234;
1302 		gl.genTextures(1, &texture);
1303 		gl.bindTexture(GL_TEXTURE_3D, texture);
1304 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1305 		gl.getError(); // reset error
1306 
1307 		const char* message1 = "GL_INVALID_ENUM is generated if target is invalid.";
1308 		callTexSubImage3D(0, 0, 0, 0, 0, 4, 4, 4, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1309 		verifyError(GL_INVALID_ENUM, message1);
1310 		callTexSubImage3D(GL_TEXTURE_2D, 0, 0, 0, 0, 4, 4, 4, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1311 		verifyError(GL_INVALID_ENUM, message1);
1312 
1313 		callTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 4, 4, 4, GL_UNSIGNED_BYTE, 0);
1314 		verifyError(GL_INVALID_ENUM, "GL_INVALID_ENUM is generated if format is not an accepted format constant.");
1315 
1316 		callTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 4, 4, 4, GL_RGB, 0, 0);
1317 		verifyError(GL_INVALID_ENUM, "GL_INVALID_ENUM is generated if type is not a type constant.");
1318 
1319 		const char* message2 = "GL_INVALID_OPERATION is generated if the combination of internalFormat of "
1320 							   "the previously specified texture array, format and type is not valid.";
1321 		callTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 4, 4, 4, GL_RGB, GL_UNSIGNED_SHORT_4_4_4_4, 0);
1322 		verifyError(GL_INVALID_OPERATION, message2);
1323 		callTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 4, 4, 4, GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1, 0);
1324 		verifyError(GL_INVALID_OPERATION, message2);
1325 		callTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 4, 4, 4, GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1, 0);
1326 		verifyError(GL_INVALID_OPERATION, message2);
1327 
1328 		gl.deleteTextures(1, &texture);
1329 	}
1330 
1331 	// negative level
1332 	{
1333 		deUint32 texture;
1334 		gl.genTextures(1, &texture);
1335 		gl.bindTexture(GL_TEXTURE_3D, texture);
1336 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1337 		gl.getError(); // reset error
1338 
1339 		const char* message = "GL_INVALID_VALUE is generated if level is less than 0.";
1340 		callTexSubImage3D(GL_TEXTURE_3D, -1, 0, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1341 		verifyError(GL_INVALID_VALUE, message);
1342 
1343 		gl.deleteTextures(1, &texture);
1344 	}
1345 
1346 	// maximal level
1347 	{
1348 		deUint32 texture;
1349 		gl.genTextures(1, &texture);
1350 		gl.bindTexture(GL_TEXTURE_3D, texture);
1351 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1352 		gl.getError(); // reset error
1353 
1354 		int maxSize;
1355 		gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &maxSize);
1356 		GLint log2Max3DTextureSize = deLog2Floor32(maxSize) + 1;
1357 
1358 		callTexSubImage3D(GL_TEXTURE_3D, log2Max3DTextureSize, 0, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1359 		verifyError(GL_INVALID_VALUE,
1360 					"GL_INVALID_VALUE is generated if level is greater than log_2(GL_MAX_3D_TEXTURE_SIZE).");
1361 
1362 		gl.deleteTextures(1, &texture);
1363 	}
1364 
1365 	// negative offset
1366 	{
1367 		deUint32 texture;
1368 		gl.genTextures(1, &texture);
1369 		gl.bindTexture(GL_TEXTURE_3D, texture);
1370 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1371 		gl.getError(); // reset error
1372 
1373 		const char* message = "GL_INVALID_VALUE is generated if xoffset, yoffset or zoffset are negative.";
1374 		callTexSubImage3D(GL_TEXTURE_3D, 0, -1, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1375 		verifyError(GL_INVALID_VALUE, message);
1376 		callTexSubImage3D(GL_TEXTURE_3D, 0, 0, -1, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1377 		verifyError(GL_INVALID_VALUE, message);
1378 		callTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, -1, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1379 		verifyError(GL_INVALID_VALUE, message);
1380 		callTexSubImage3D(GL_TEXTURE_3D, 0, -1, -1, -1, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1381 		verifyError(GL_INVALID_VALUE, message);
1382 
1383 		gl.deleteTextures(1, &texture);
1384 	}
1385 
1386 	// invalid offset
1387 	{
1388 		deUint32 texture = 0x1234;
1389 		gl.genTextures(1, &texture);
1390 		gl.bindTexture(GL_TEXTURE_3D, texture);
1391 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1392 
1393 		callTexSubImage3D(GL_TEXTURE_3D, 0, 2, 0, 0, 4, 4, 4, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1394 		verifyError(GL_INVALID_VALUE, "GL_INVALID_VALUE is generated if xoffset + width > texture_width.");
1395 		callTexSubImage3D(GL_TEXTURE_3D, 0, 0, 2, 0, 4, 4, 4, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1396 		verifyError(GL_INVALID_VALUE, "GL_INVALID_VALUE is generated if yoffset + height > texture_height.");
1397 		callTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 2, 4, 4, 4, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1398 		verifyError(GL_INVALID_VALUE, "GL_INVALID_VALUE is generated if zoffset + depth > texture_depth.");
1399 
1400 		gl.deleteTextures(1, &texture);
1401 	}
1402 
1403 	// negative dimensions
1404 	{
1405 		const char* message = "GL_INVALID_VALUE is generated if width, height or depth is less than 0.";
1406 		callTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, -1, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1407 		verifyError(GL_INVALID_VALUE, message);
1408 		callTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, -1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1409 		verifyError(GL_INVALID_VALUE, message);
1410 		callTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, -1, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1411 		verifyError(GL_INVALID_VALUE, message);
1412 		callTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, -1, -1, -1, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1413 		verifyError(GL_INVALID_VALUE, message);
1414 	}
1415 
1416 	return STOP;
1417 }
1418 
1419 class NegativeCopyTexSubImage3DCase : public Texture3DBase
1420 {
1421 public:
1422 	NegativeCopyTexSubImage3DCase(deqp::Context& context, const char* name);
1423 
1424 	IterateResult iterate(void);
1425 };
1426 
NegativeCopyTexSubImage3DCase(deqp::Context & context,const char * name)1427 NegativeCopyTexSubImage3DCase::NegativeCopyTexSubImage3DCase(deqp::Context& context, const char* name)
1428 	: Texture3DBase(context, name, "")
1429 {
1430 }
1431 
iterate(void)1432 NegativeCopyTexSubImage3DCase::IterateResult NegativeCopyTexSubImage3DCase::iterate(void)
1433 {
1434 	if (!isFeatureSupported())
1435 		return STOP;
1436 
1437 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1438 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1439 
1440 	// invalid usage
1441 	{
1442 		GLuint texture = 0x1234;
1443 		gl.genTextures(1, &texture);
1444 		gl.bindTexture(GL_TEXTURE_3D, texture);
1445 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1446 
1447 		callCopyTexSubImage3D(0, 0, 0, 0, 0, 0, 0, 4, 4);
1448 		verifyError(GL_INVALID_ENUM, "GL_INVALID_ENUM is generated if target is invalid.");
1449 
1450 		gl.deleteTextures(1, &texture);
1451 	}
1452 
1453 	// negative level
1454 	{
1455 		deUint32 texture;
1456 		gl.genTextures(1, &texture);
1457 		gl.bindTexture(GL_TEXTURE_3D, texture);
1458 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1459 		gl.getError(); // reset error
1460 
1461 		const char* message = "GL_INVALID_VALUE is generated if level is less than 0.";
1462 		callCopyTexSubImage3D(GL_TEXTURE_3D, -1, 0, 0, 0, 0, 0, 4, 4);
1463 		verifyError(GL_INVALID_VALUE, message);
1464 
1465 		gl.deleteTextures(1, &texture);
1466 	}
1467 
1468 	// maximal level
1469 	{
1470 		int maxSize;
1471 		int max3DSize;
1472 		gl.getIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
1473 		gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max3DSize);
1474 		deUint32 log2Max3DTextureSize = deLog2Floor32(max3DSize) + 1;
1475 
1476 		deUint32 texture;
1477 		gl.genTextures(1, &texture);
1478 		gl.bindTexture(GL_TEXTURE_3D, texture);
1479 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1480 		gl.getError(); // reset error
1481 
1482 		callCopyTexSubImage3D(GL_TEXTURE_3D, log2Max3DTextureSize, 0, 0, 0, 0, 0, 4, 4);
1483 		verifyError(GL_INVALID_VALUE,
1484 					"GL_INVALID_VALUE is generated if level is greater than log_2(GL_MAX_3D_TEXTURE_SIZE).");
1485 
1486 		gl.deleteTextures(1, &texture);
1487 	}
1488 
1489 	// negative offset
1490 	{
1491 		GLuint texture = 0x1234;
1492 		gl.genTextures(1, &texture);
1493 		gl.bindTexture(GL_TEXTURE_3D, texture);
1494 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1495 		gl.getError(); // reset error
1496 
1497 		const char* message = "GL_INVALID_VALUE is generated if xoffset, yoffset or zoffset is negative.";
1498 		callCopyTexSubImage3D(GL_TEXTURE_3D, 0, -1, 0, 0, 0, 0, 4, 4);
1499 		verifyError(GL_INVALID_VALUE, message);
1500 		callCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, -1, 0, 0, 0, 4, 4);
1501 		verifyError(GL_INVALID_VALUE, message);
1502 		callCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, -1, 0, 0, 4, 4);
1503 		verifyError(GL_INVALID_VALUE, message);
1504 		callCopyTexSubImage3D(GL_TEXTURE_3D, 0, -1, -1, -1, 0, 0, 4, 4);
1505 		verifyError(GL_INVALID_VALUE, message);
1506 
1507 		gl.deleteTextures(1, &texture);
1508 	}
1509 
1510 	// invalid offset
1511 	{
1512 		GLuint texture = 0x1234;
1513 		gl.genTextures(1, &texture);
1514 		gl.bindTexture(GL_TEXTURE_3D, texture);
1515 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1516 		gl.getError(); // reset error
1517 
1518 		callCopyTexSubImage3D(GL_TEXTURE_3D, 0, 1, 0, 0, 0, 0, 4, 4);
1519 		verifyError(GL_INVALID_VALUE, "GL_INVALID_VALUE is generated if xoffset + width > texture_width.");
1520 
1521 		callCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 1, 0, 0, 0, 4, 4);
1522 		verifyError(GL_INVALID_VALUE, "GL_INVALID_VALUE is generated if yoffset + height > texture_height.");
1523 
1524 		callCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 4, 0, 0, 4, 4);
1525 		verifyError(GL_INVALID_VALUE, "GL_INVALID_VALUE is generated if zoffset + 1 > texture_depth.");
1526 
1527 		gl.deleteTextures(1, &texture);
1528 	}
1529 
1530 	// negative dimensions
1531 	{
1532 		GLuint texture = 0x1234;
1533 		gl.genTextures(1, &texture);
1534 		gl.bindTexture(GL_TEXTURE_3D, texture);
1535 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1536 		gl.getError(); // reset error
1537 
1538 		callCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, -4, 4);
1539 		verifyError(GL_INVALID_VALUE, "GL_INVALID_VALUE is generated if width < 0.");
1540 
1541 		callCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 4, -4);
1542 		verifyError(GL_INVALID_VALUE, "GL_INVALID_VALUE is generated if height < 0.");
1543 
1544 		gl.deleteTextures(1, &texture);
1545 	}
1546 
1547 	// incomplete_framebuffer
1548 	{
1549 		GLuint fbo = 0x1234;
1550 		GLuint texture;
1551 
1552 		gl.genTextures(1, &texture);
1553 		gl.bindTexture(GL_TEXTURE_3D, texture);
1554 		callTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
1555 		gl.genFramebuffers(1, &fbo);
1556 		gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
1557 		gl.checkFramebufferStatus(GL_FRAMEBUFFER);
1558 
1559 		const char* message = "GL_INVALID_FRAMEBUFFER_OPERATION is generated if the currently "
1560 							  "bound framebuffer is not framebuffer complete.";
1561 		callCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 4, 4);
1562 		verifyError(GL_INVALID_FRAMEBUFFER_OPERATION, message);
1563 
1564 		gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1565 		gl.deleteFramebuffers(1, &fbo);
1566 		gl.deleteTextures(1, &texture);
1567 	}
1568 
1569 	return STOP;
1570 }
1571 
1572 class NegativeFramebufferTexture3DCase : public Texture3DBase
1573 {
1574 public:
1575 	NegativeFramebufferTexture3DCase(deqp::Context& context, const char* name);
1576 
1577 	IterateResult iterate(void);
1578 };
1579 
NegativeFramebufferTexture3DCase(deqp::Context & context,const char * name)1580 NegativeFramebufferTexture3DCase::NegativeFramebufferTexture3DCase(deqp::Context& context, const char* name)
1581 	: Texture3DBase(context, name, "")
1582 {
1583 }
1584 
iterate(void)1585 NegativeFramebufferTexture3DCase::IterateResult NegativeFramebufferTexture3DCase::iterate(void)
1586 {
1587 	if (!isFeatureSupported())
1588 		return STOP;
1589 
1590 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1591 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1592 
1593 	GLuint fbo = 0x1234;
1594 	gl.genFramebuffers(1, &fbo);
1595 	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
1596 
1597 	GLuint tex3D = 0x1234;
1598 	gl.genTextures(1, &tex3D);
1599 	gl.bindTexture(GL_TEXTURE_3D, tex3D);
1600 
1601 	GLint maxTexSize = 0x1234;
1602 	gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE_OES, &maxTexSize);
1603 	gl.getError(); // reset error
1604 
1605 	callFramebufferTexture3D(-1, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, tex3D, 0, 0);
1606 	verifyError(GL_INVALID_ENUM, "GL_INVALID_ENUM is generated if target is not one of the accepted tokens.");
1607 
1608 	callFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex3D, 0, 0);
1609 	verifyError(GL_INVALID_OPERATION,
1610 				"GL_INVALID_OPERATION is generated if textarget is not an accepted texture target.");
1611 
1612 	callFramebufferTexture3D(GL_FRAMEBUFFER, -1, GL_TEXTURE_3D, tex3D, 0, 0);
1613 	verifyError(GL_INVALID_ENUM, "GL_INVALID_ENUM is generated if attachment is not an accepted token.");
1614 
1615 	const char* message1 =
1616 		"GL_INVALID_VALUE is generated if level is less than 0 or larger than log_2 of maximum texture size.";
1617 	callFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, tex3D, -1, 0);
1618 	verifyError(GL_INVALID_VALUE, message1);
1619 	GLint maxSize = deLog2Floor32(maxTexSize) + 1;
1620 	callFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, tex3D, maxSize, 0);
1621 	verifyError(GL_INVALID_VALUE, message1);
1622 
1623 	callFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, -1, 0, 0);
1624 	verifyError(
1625 		GL_INVALID_OPERATION,
1626 		"GL_INVALID_OPERATION is generated if texture is neither 0 nor the name of an existing texture object.");
1627 
1628 	const char* message2 = "GL_INVALID_OPERATION is generated if textarget and texture are not compatible.";
1629 	callFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, tex3D, 0, 0);
1630 	verifyError(GL_INVALID_OPERATION, message2);
1631 	callFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex3D, 0, 0);
1632 	verifyError(GL_INVALID_OPERATION, message2);
1633 	gl.deleteTextures(1, &tex3D);
1634 
1635 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1636 	callFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, 0, 0, 0);
1637 	verifyError(GL_INVALID_OPERATION, "GL_INVALID_OPERATION is generated if zero is bound to target.");
1638 
1639 	gl.deleteFramebuffers(1, &fbo);
1640 	return STOP;
1641 }
1642 
iterate(void)1643 NegativeCompressedTexImage3DCase::IterateResult NegativeCompressedTexImage3DCase::iterate(void)
1644 {
1645 	if (!isFeatureSupported())
1646 		return STOP;
1647 
1648 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1649 	const glu::ContextInfo&  contextInfo = m_context.getContextInfo();
1650 
1651 	std::set<int> supportedFormats;
1652 	getSupportedCompressedFormats(supportedFormats);
1653 
1654 	if (supportedFormats.empty())
1655 	{
1656 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "No supported compressed texture formats.");
1657 		return STOP;
1658 	}
1659 
1660 	GLenum supportedCompressedFormat = static_cast<GLenum>(*(supportedFormats.begin()));
1661 	checkFormatSupport(contextInfo, supportedCompressedFormat);
1662 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1663 
1664 	// negative usage
1665 	{
1666 		const char* message1 = "GL_INVALID_ENUM is generated if target is invalid.";
1667 		callCompressedTexImage3D(0, 0, supportedCompressedFormat, 0, 0, 0, 0, 0, 0);
1668 		verifyError(GL_INVALID_ENUM, message1);
1669 		callCompressedTexImage3D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, supportedCompressedFormat, 0, 0, 0, 0, 0, 0);
1670 		verifyError(GL_INVALID_ENUM, message1);
1671 
1672 		const char* message2 =
1673 			"GL_INVALID_ENUM is generated if internalformat is not one of the specific compressed internal formats.";
1674 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 0, 0);
1675 		verifyError(GL_INVALID_ENUM, message2);
1676 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 0, 0, 0, 0, 0, 0);
1677 		verifyError(GL_INVALID_ENUM, message2);
1678 
1679 		const char* message3 = "INVALID_OPERATION is generated if internalformat is an ETC2/EAC format.";
1680 		for (int formatNdx = 0; formatNdx < tcu::COMPRESSEDTEXFORMAT_LAST; formatNdx++)
1681 		{
1682 			tcu::CompressedTexFormat format = static_cast<tcu::CompressedTexFormat>(formatNdx);
1683 			if (tcu::isEtcFormat(format) && (format != tcu::COMPRESSEDTEXFORMAT_ETC1_RGB8))
1684 			{
1685 				deUint32 compressedFormat = glu::getGLFormat(format);
1686 				callCompressedTexImage3D(GL_TEXTURE_3D, 0, compressedFormat, 0, 0, 0, 0, 0, 0);
1687 				verifyError(GL_INVALID_OPERATION, message3);
1688 			}
1689 		}
1690 	}
1691 
1692 	// negative level
1693 	{
1694 		callCompressedTexImage3D(GL_TEXTURE_3D, -1, supportedCompressedFormat, 0, 0, 0, 0, 0, 0);
1695 		verifyError(GL_INVALID_VALUE, "GL_INVALID_VALUE is generated if level is less than 0.");
1696 	}
1697 
1698 	// maximal level
1699 	{
1700 		int maxSize;
1701 		gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &maxSize);
1702 		GLint log2MaxTextureSize = deLog2Floor32(maxSize) + 1;
1703 		callCompressedTexImage3D(GL_TEXTURE_3D, log2MaxTextureSize, supportedCompressedFormat, 0, 0, 0, 0, 0, 0);
1704 		verifyError(GL_INVALID_VALUE,
1705 					"GL_INVALID_VALUE is generated if level is greater than log_2(GL_MAX_TEXTURE_SIZE).");
1706 	}
1707 
1708 	// negative dimensions
1709 	{
1710 		const char* message = "GL_INVALID_VALUE is generated if width, height or depth is less than 0.";
1711 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, -1, 0, 0, 0, 0, 0);
1712 		verifyError(GL_INVALID_VALUE, message);
1713 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, 0, -1, 0, 0, 0, 0);
1714 		verifyError(GL_INVALID_VALUE, message);
1715 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, 0, 0, -1, 0, 0, 0);
1716 		verifyError(GL_INVALID_VALUE, message);
1717 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, -1, -1, -1, 0, 0, 0);
1718 		verifyError(GL_INVALID_VALUE, message);
1719 	}
1720 
1721 	// maximal dimensions
1722 	{
1723 		int maxTextureSize;
1724 		gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE_OES, &maxTextureSize);
1725 		++maxTextureSize;
1726 
1727 		const char* message =
1728 			"GL_INVALID_VALUE is generated if width, height or depth is greater than GL_MAX_3D_TEXTURE_SIZE_OES.";
1729 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, maxTextureSize, 0, 0, 0, 0, 0);
1730 		verifyError(GL_INVALID_VALUE, message);
1731 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, 0, maxTextureSize, 0, 0, 0, 0);
1732 		verifyError(GL_INVALID_VALUE, message);
1733 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, 0, 0, maxTextureSize, 0, 0, 0);
1734 		verifyError(GL_INVALID_VALUE, message);
1735 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, maxTextureSize, maxTextureSize,
1736 								 maxTextureSize, 0, 0, 0);
1737 		verifyError(GL_INVALID_VALUE, message);
1738 	}
1739 
1740 	// invalid  border
1741 	{
1742 		const char* message = "GL_INVALID_VALUE is generated if border is not 0.";
1743 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, 0, 0, 0, -1, 0, 0);
1744 		verifyError(GL_INVALID_VALUE, message);
1745 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, 0, 0, 0, 1, 0, 0);
1746 		verifyError(GL_INVALID_VALUE, message);
1747 	}
1748 
1749 	// invalid size
1750 	{
1751 		const char* message = "GL_INVALID_VALUE is generated if imageSize is not consistent with the "
1752 							  "format, dimensions, and contents of the specified compressed image data.";
1753 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, 0, 0, 0, 0, -1, 0);
1754 		verifyError(GL_INVALID_VALUE, message);
1755 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, 16, 16, 1, 0, 9 * 4 * 8, 0);
1756 		verifyError(GL_INVALID_VALUE, message);
1757 	}
1758 
1759 	return STOP;
1760 }
1761 
1762 class NegativeCompressedTexSubImage3DCase : public Texture3DBase
1763 {
1764 public:
1765 	NegativeCompressedTexSubImage3DCase(deqp::Context& context, const char* name);
1766 
1767 	IterateResult iterate(void);
1768 };
1769 
NegativeCompressedTexSubImage3DCase(deqp::Context & context,const char * name)1770 NegativeCompressedTexSubImage3DCase::NegativeCompressedTexSubImage3DCase(deqp::Context& context, const char* name)
1771 	: Texture3DBase(context, name, "")
1772 {
1773 }
1774 
iterate(void)1775 NegativeCompressedTexSubImage3DCase::IterateResult NegativeCompressedTexSubImage3DCase::iterate(void)
1776 {
1777 	if (!isFeatureSupported())
1778 		return STOP;
1779 
1780 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1781 	const glu::ContextInfo&  contextInfo = m_context.getContextInfo();
1782 
1783 	std::set<int> supportedFormats;
1784 	getSupportedCompressedFormats(supportedFormats);
1785 
1786 	if (supportedFormats.empty())
1787 	{
1788 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "No supported compressed texture formats.");
1789 		return STOP;
1790 	}
1791 
1792 	GLenum supportedCompressedFormat = static_cast<GLenum>(*(supportedFormats.begin()));
1793 	int	textureSize				 = 16;
1794 	int	dataSize					 = calculateDataSize(supportedCompressedFormat, textureSize, textureSize, 1);
1795 
1796 	checkFormatSupport(contextInfo, supportedCompressedFormat);
1797 
1798 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1799 
1800 	// negative level
1801 	{
1802 		deUint32 texture;
1803 		gl.genTextures(1, &texture);
1804 		gl.bindTexture(GL_TEXTURE_3D, texture);
1805 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, textureSize, textureSize, 1, 0, dataSize,
1806 								 0);
1807 		gl.getError(); // reset error
1808 
1809 		callCompressedTexSubImage3D(GL_TEXTURE_3D, -1, 0, 0, 0, 0, 0, 0, supportedCompressedFormat, 0, 0);
1810 		verifyError(GL_INVALID_VALUE, "GL_INVALID_VALUE is generated if level is less than 0.");
1811 
1812 		gl.deleteTextures(1, &texture);
1813 	}
1814 
1815 	// invalid level
1816 	{
1817 		deUint32 texture;
1818 		gl.genTextures(1, &texture);
1819 		gl.bindTexture(GL_TEXTURE_3D, texture);
1820 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, textureSize, textureSize, 1, 0, dataSize,
1821 								 0);
1822 		gl.getError(); // reset error
1823 
1824 		GLint log2MaxTextureSize = deLog2Floor32(m_context.getContextInfo().getInt(GL_MAX_3D_TEXTURE_SIZE)) + 1;
1825 		callCompressedTexSubImage3D(GL_TEXTURE_3D, log2MaxTextureSize, 0, 0, 0, 0, 0, 0, supportedCompressedFormat, 0,
1826 									0);
1827 		verifyError(GL_INVALID_VALUE,
1828 					"GL_INVALID_VALUE is generated if level is greater than log_2(GL_MAX_3D_TEXTURE_SIZE).");
1829 
1830 		gl.deleteTextures(1, &texture);
1831 	}
1832 
1833 	// negative offsets
1834 	{
1835 		deUint32 texture;
1836 		gl.genTextures(1, &texture);
1837 		gl.bindTexture(GL_TEXTURE_3D, texture);
1838 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, textureSize, textureSize, 1, 0, dataSize,
1839 								 0);
1840 		gl.getError(); // reset error
1841 
1842 		const char* message =
1843 			"GL_INVALID_VALUE or GL_INVALID_OPERATION is generated if xoffset, yoffset or zoffset are negative.";
1844 		callCompressedTexSubImage3D(GL_TEXTURE_3D, 0, -4, 0, 0, 0, 0, 0, supportedCompressedFormat, 0, 0);
1845 		verifyError(GL_INVALID_VALUE, message);
1846 		callCompressedTexSubImage3D(GL_TEXTURE_3D, 0, 0, -4, 0, 0, 0, 0, supportedCompressedFormat, 0, 0);
1847 		verifyError(GL_INVALID_VALUE, message);
1848 		callCompressedTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, -4, 0, 0, 0, supportedCompressedFormat, 0, 0);
1849 		verifyError(GL_INVALID_VALUE, message);
1850 		callCompressedTexSubImage3D(GL_TEXTURE_3D, 0, -4, -4, -4, 0, 0, 0, supportedCompressedFormat, 0, 0);
1851 		verifyError(GL_INVALID_VALUE, message);
1852 
1853 		gl.deleteTextures(1, &texture);
1854 	}
1855 
1856 	// invalid offsets
1857 	{
1858 		deUint32 texture;
1859 		gl.genTextures(1, &texture);
1860 		gl.bindTexture(GL_TEXTURE_3D, texture);
1861 		dataSize = calculateDataSize(supportedCompressedFormat, 4, 4, 1);
1862 		callCompressedTexImage3D(GL_TEXTURE_3D, 0, supportedCompressedFormat, 4, 4, 1, 0, dataSize, 0);
1863 		gl.getError(); // reset error
1864 
1865 		const char* message = "GL_INVALID_VALUE or GL_INVALID_OPERATION is generated if xoffset + width > "
1866 							  "texture_width or yoffset + height > texture_height.";
1867 		dataSize = calculateDataSize(supportedCompressedFormat, 8, 4, 1);
1868 		callCompressedTexSubImage3D(GL_TEXTURE_3D, 0, 12, 0, 0, 8, 4, 1, supportedCompressedFormat, dataSize, 0);
1869 		verifyError(GL_INVALID_VALUE, GL_INVALID_OPERATION, message);
1870 		dataSize = calculateDataSize(supportedCompressedFormat, 4, 8, 1);
1871 		callCompressedTexSubImage3D(GL_TEXTURE_3D, 0, 0, 12, 0, 4, 8, 1, supportedCompressedFormat, dataSize, 0);
1872 		verifyError(GL_INVALID_VALUE, GL_INVALID_OPERATION, message);
1873 		dataSize = calculateDataSize(supportedCompressedFormat, 4, 4, 1);
1874 		callCompressedTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 12, 4, 4, 1, supportedCompressedFormat, dataSize, 0);
1875 		verifyError(GL_INVALID_VALUE, GL_INVALID_OPERATION, message);
1876 		dataSize = calculateDataSize(supportedCompressedFormat, 8, 8, 1);
1877 		callCompressedTexSubImage3D(GL_TEXTURE_3D, 0, 12, 12, 12, 8, 8, 1, supportedCompressedFormat, dataSize, 0);
1878 		verifyError(GL_INVALID_VALUE, GL_INVALID_OPERATION, message);
1879 
1880 		gl.deleteTextures(1, &texture);
1881 	}
1882 
1883 	return STOP;
1884 }
1885 
Texture3DTests(deqp::Context & context)1886 Texture3DTests::Texture3DTests(deqp::Context& context) : TestCaseGroup(context, "texture_3d", "")
1887 {
1888 }
1889 
~Texture3DTests(void)1890 Texture3DTests::~Texture3DTests(void)
1891 {
1892 }
1893 
init()1894 void Texture3DTests::init()
1895 {
1896 	static const struct
1897 	{
1898 		const char* name;
1899 		GLint		mode;
1900 	} wrapModes[] = { { "clamp", GL_CLAMP_TO_EDGE }, { "repeat", GL_REPEAT }, { "mirror", GL_MIRRORED_REPEAT } };
1901 
1902 	static const struct
1903 	{
1904 		const char* name;
1905 		GLint		mode;
1906 	} minFilterModes[] = { { "nearest", GL_NEAREST },
1907 						   { "linear", GL_LINEAR },
1908 						   { "nearest_mipmap_nearest", GL_NEAREST_MIPMAP_NEAREST },
1909 						   { "linear_mipmap_nearest", GL_LINEAR_MIPMAP_NEAREST },
1910 						   { "nearest_mipmap_linear", GL_NEAREST_MIPMAP_LINEAR },
1911 						   { "linear_mipmap_linear", GL_LINEAR_MIPMAP_LINEAR } };
1912 
1913 	static const struct
1914 	{
1915 		const char* name;
1916 		GLint		mode;
1917 	} magFilterModes[] = { { "nearest", GL_NEAREST }, { "linear", GL_LINEAR } };
1918 
1919 	static const struct
1920 	{
1921 		int width;
1922 		int height;
1923 		int depth;
1924 	} sizes[] = { { 4, 8, 8 }, { 32, 64, 16 }, { 128, 32, 64 }, { 3, 7, 5 }, { 63, 63, 63 } };
1925 
1926     static const struct
1927 	{
1928 		const char* name;
1929 		deUint32	format;
1930 		deUint32	type;
1931 	} filterableFormatsByType[] = {
1932 		{ "rgba", GL_RGBA, GL_UNSIGNED_BYTE },
1933 	};
1934 
1935 	static const struct
1936 	{
1937 		const char* name;
1938 		deUint32	format;
1939 	} sizedFilterableFormatsByType[] = {
1940 		{ "rgba8", GL_RGBA8 },
1941 	};
1942 
1943 	static const struct
1944 	{
1945 		tcu::CompressedTexFormat fmt;
1946 	} compressedFormats[] = {
1947 		{tcu::COMPRESSEDTEXFORMAT_ETC1_RGB8},
1948 		{tcu::COMPRESSEDTEXFORMAT_EAC_R11},
1949 		{tcu::COMPRESSEDTEXFORMAT_EAC_SIGNED_R11},
1950 		{tcu::COMPRESSEDTEXFORMAT_EAC_RG11},
1951 		{tcu::COMPRESSEDTEXFORMAT_EAC_SIGNED_RG11},
1952 		{tcu::COMPRESSEDTEXFORMAT_ETC2_RGB8},
1953 		{tcu::COMPRESSEDTEXFORMAT_ETC2_SRGB8},
1954 		{tcu::COMPRESSEDTEXFORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1},
1955 		{tcu::COMPRESSEDTEXFORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1},
1956 		{tcu::COMPRESSEDTEXFORMAT_ETC2_EAC_RGBA8},
1957 		{tcu::COMPRESSEDTEXFORMAT_ETC2_EAC_SRGB8_ALPHA8},
1958 		{tcu::COMPRESSEDTEXFORMAT_ASTC_4x4_RGBA},
1959 		{tcu::COMPRESSEDTEXFORMAT_ASTC_5x4_RGBA},
1960 		{tcu::COMPRESSEDTEXFORMAT_ASTC_5x5_RGBA},
1961 		{tcu::COMPRESSEDTEXFORMAT_ASTC_6x5_RGBA},
1962 		{tcu::COMPRESSEDTEXFORMAT_ASTC_6x6_RGBA},
1963 		{tcu::COMPRESSEDTEXFORMAT_ASTC_8x5_RGBA},
1964 		{tcu::COMPRESSEDTEXFORMAT_ASTC_8x6_RGBA},
1965 		{tcu::COMPRESSEDTEXFORMAT_ASTC_8x8_RGBA},
1966 		{tcu::COMPRESSEDTEXFORMAT_ASTC_10x5_RGBA},
1967 		{tcu::COMPRESSEDTEXFORMAT_ASTC_10x6_RGBA},
1968 		{tcu::COMPRESSEDTEXFORMAT_ASTC_10x8_RGBA},
1969 		{tcu::COMPRESSEDTEXFORMAT_ASTC_10x10_RGBA},
1970 		{tcu::COMPRESSEDTEXFORMAT_ASTC_12x10_RGBA},
1971 		{tcu::COMPRESSEDTEXFORMAT_ASTC_12x12_RGBA},
1972 		{tcu::COMPRESSEDTEXFORMAT_ASTC_4x4_SRGB8_ALPHA8},
1973 		{tcu::COMPRESSEDTEXFORMAT_ASTC_5x4_SRGB8_ALPHA8},
1974 		{tcu::COMPRESSEDTEXFORMAT_ASTC_5x5_SRGB8_ALPHA8},
1975 		{tcu::COMPRESSEDTEXFORMAT_ASTC_6x5_SRGB8_ALPHA8},
1976 		{tcu::COMPRESSEDTEXFORMAT_ASTC_6x6_SRGB8_ALPHA8},
1977 		{tcu::COMPRESSEDTEXFORMAT_ASTC_8x5_SRGB8_ALPHA8},
1978 		{tcu::COMPRESSEDTEXFORMAT_ASTC_8x6_SRGB8_ALPHA8},
1979 		{tcu::COMPRESSEDTEXFORMAT_ASTC_8x8_SRGB8_ALPHA8},
1980 		{tcu::COMPRESSEDTEXFORMAT_ASTC_10x5_SRGB8_ALPHA8},
1981 		{tcu::COMPRESSEDTEXFORMAT_ASTC_10x6_SRGB8_ALPHA8},
1982 		{tcu::COMPRESSEDTEXFORMAT_ASTC_10x8_SRGB8_ALPHA8},
1983 		{tcu::COMPRESSEDTEXFORMAT_ASTC_10x10_SRGB8_ALPHA8},
1984 		{tcu::COMPRESSEDTEXFORMAT_ASTC_12x10_SRGB8_ALPHA8},
1985 		{tcu::COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8},
1986 	};
1987 
1988 	// Texture3DFilteringCase
1989 	{
1990 		deqp::TestCaseGroup* texFilteringGroup =
1991 			new deqp::TestCaseGroup(m_context, "filtering", "3D Texture Filtering");
1992 		addChild(texFilteringGroup);
1993 
1994 		// Formats.
1995 		FilteringData		 data;
1996 		deqp::TestCaseGroup* formatsGroup = new deqp::TestCaseGroup(m_context, "formats", "3D Texture Formats");
1997 		texFilteringGroup->addChild(formatsGroup);
1998 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(sizedFilterableFormatsByType); fmtNdx++)
1999 		{
2000 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
2001 			{
2002 				data.minFilter		= minFilterModes[filterNdx].mode;
2003 				bool isMipmap		= data.minFilter != GL_NEAREST && data.minFilter != GL_LINEAR;
2004 				data.magFilter		= isMipmap ? GL_LINEAR : data.minFilter;
2005 				data.internalFormat = sizedFilterableFormatsByType[fmtNdx].format;
2006 				data.wrapS			= GL_REPEAT;
2007 				data.wrapT			= GL_REPEAT;
2008 				data.wrapR			= GL_REPEAT;
2009 				data.width			= 64;
2010 				data.height			= 64;
2011 				data.depth			= 64;
2012 
2013 				const char* formatName = sizedFilterableFormatsByType[fmtNdx].name;
2014 				const char* filterName = minFilterModes[filterNdx].name;
2015 				std::string name	   = std::string(formatName) + "_" + filterName;
2016 
2017 				formatsGroup->addChild(new Texture3DFilteringCase(m_context, name.c_str(), "", data));
2018 			}
2019 		}
2020 
2021 		// Sizes.
2022 		deqp::TestCaseGroup* sizesGroup = new deqp::TestCaseGroup(m_context, "sizes", "Texture Sizes");
2023 		texFilteringGroup->addChild(sizesGroup);
2024 		for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
2025 		{
2026 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
2027 			{
2028 				data.minFilter		= minFilterModes[filterNdx].mode;
2029 				data.internalFormat = GL_RGBA8;
2030 				bool isMipmap		= data.minFilter != GL_NEAREST && data.minFilter != GL_LINEAR;
2031 				data.magFilter		= isMipmap ? GL_LINEAR : data.minFilter;
2032 				data.wrapS			= GL_REPEAT;
2033 				data.wrapT			= GL_REPEAT;
2034 				data.wrapR			= GL_REPEAT;
2035 				data.width			= sizes[sizeNdx].width;
2036 				data.height			= sizes[sizeNdx].height;
2037 				data.depth			= sizes[sizeNdx].depth;
2038 
2039 				const char* filterName = minFilterModes[filterNdx].name;
2040 				std::string name	   = de::toString(data.width) + "x" + de::toString(data.height) + "x" +
2041 								   de::toString(data.depth) + "_" + filterName;
2042 
2043 				sizesGroup->addChild(new Texture3DFilteringCase(m_context, name.c_str(), "", data));
2044 			}
2045 		}
2046 
2047 		// Wrap modes.
2048 		deqp::TestCaseGroup* combinationsGroup =
2049 			new deqp::TestCaseGroup(m_context, "combinations", "Filter and wrap mode combinations");
2050 		texFilteringGroup->addChild(combinationsGroup);
2051 		for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
2052 		{
2053 			for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
2054 			{
2055 				for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
2056 				{
2057 					for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
2058 					{
2059 						for (int wrapRNdx = 0; wrapRNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapRNdx++)
2060 						{
2061 							data.minFilter		= minFilterModes[minFilterNdx].mode;
2062 							data.magFilter		= magFilterModes[magFilterNdx].mode;
2063 							data.internalFormat = GL_RGBA8;
2064 							data.wrapS			= wrapModes[wrapSNdx].mode;
2065 							data.wrapT			= wrapModes[wrapTNdx].mode;
2066 							data.wrapR			= wrapModes[wrapRNdx].mode;
2067 							data.width			= 63;
2068 							data.height			= 57;
2069 							data.depth			= 67;
2070 							std::string name	= std::string(minFilterModes[minFilterNdx].name) + "_" +
2071 											   magFilterModes[magFilterNdx].name + "_" + wrapModes[wrapSNdx].name +
2072 											   "_" + wrapModes[wrapTNdx].name + "_" + wrapModes[wrapRNdx].name;
2073 
2074 							combinationsGroup->addChild(new Texture3DFilteringCase(m_context, name.c_str(), "", data));
2075 						}
2076 					}
2077 				}
2078 			}
2079 		}
2080 
2081 		// negative tests.
2082 		combinationsGroup->addChild(new NegativeTexImage3DCase(m_context, "negative"));
2083 	}
2084 
2085 	// TexSubImage3DOES tests
2086 	{
2087 		tcu::TestCaseGroup* texSubImageGroup =
2088 			new tcu::TestCaseGroup(m_testCtx, "sub_image", "Basic glTexSubImage3D() usage");
2089 		addChild(texSubImageGroup);
2090 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(sizedFilterableFormatsByType); formatNdx++)
2091 		{
2092 			const char* fmtName = sizedFilterableFormatsByType[formatNdx].name;
2093 			deUint32	format  = sizedFilterableFormatsByType[formatNdx].format;
2094 			texSubImageGroup->addChild(new TexSubImage3DCase(m_context, fmtName, "", format, 32, 64, 8));
2095 		}
2096 		texSubImageGroup->addChild(new NegativeTexSubImage3DCase(m_context, "negative"));
2097 	}
2098 
2099 	// CopyTexSubImage3DOES tests
2100 	{
2101 		tcu::TestCaseGroup* copyTexSubImageGroup =
2102 			new tcu::TestCaseGroup(m_testCtx, "copy_sub_image", "Basic glCopyTexSubImage3D() usage");
2103 		addChild(copyTexSubImageGroup);
2104 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); formatNdx++)
2105 		{
2106 			const char* fmtName = filterableFormatsByType[formatNdx].name;
2107 			deUint32	format  = filterableFormatsByType[formatNdx].format;
2108 			deUint32	type    = filterableFormatsByType[formatNdx].type;
2109 			copyTexSubImageGroup->addChild(new CopyTexSubImage3DCase(m_context, fmtName, "", format, type, 32, 64, 8));
2110 		}
2111 		copyTexSubImageGroup->addChild(new NegativeCopyTexSubImage3DCase(m_context, "negative"));
2112 	}
2113 
2114 	// FramebufferTexture3DOES tests
2115 	{
2116 		tcu::TestCaseGroup* framebufferTextureGroup =
2117 			new tcu::TestCaseGroup(m_testCtx, "framebuffer_texture", "Basic glFramebufferTexture3D() usage");
2118 		addChild(framebufferTextureGroup);
2119 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); formatNdx++)
2120 		{
2121 			const char* fmtName = filterableFormatsByType[formatNdx].name;
2122 			deUint32	format  = filterableFormatsByType[formatNdx].format;
2123 			deUint32	type    = filterableFormatsByType[formatNdx].type;
2124 			framebufferTextureGroup->addChild(new FramebufferTexture3DCase(m_context, fmtName, "", format, type, 64, 64, 3));
2125 		}
2126 		framebufferTextureGroup->addChild(new NegativeFramebufferTexture3DCase(m_context, "negative"));
2127 	}
2128 
2129 	// CompressedTexImage3DOES and CompressedTexSubImage3DOES tests
2130 	{
2131 		tcu::TestCaseGroup* compressedTexGroup =
2132 			new tcu::TestCaseGroup(m_testCtx, "compressed_texture", "Basic gl.compressedTexImage3D() usage");
2133 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(compressedFormats); formatNdx++)
2134 		{
2135 			// ETC2/EAC texture compression algorithm supports only two-dimensional images
2136 			tcu::CompressedTexFormat format = static_cast<tcu::CompressedTexFormat>(formatNdx);
2137 			if (tcu::isEtcFormat(format))
2138 				continue;
2139 
2140 			deUint32	compressedFormat = glu::getGLFormat(format);
2141 			const char* name			 = getCompressedFormatName(format);
2142 			compressedTexGroup->addChild(new CompressedTexture3DCase(m_context, name, compressedFormat));
2143 		}
2144 		compressedTexGroup->addChild(new NegativeCompressedTexImage3DCase(m_context, "negative_compressed_tex_image"));
2145 		compressedTexGroup->addChild(
2146 			new NegativeCompressedTexSubImage3DCase(m_context, "negative_compressed_tex_sub_image"));
2147 		addChild(compressedTexGroup);
2148 	}
2149 }
2150 } // glcts namespace
2151