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