xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fTextureSpecificationTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Texture specification tests.
22  *
23  * \todo [pyry] Following tests are missing:
24  *  - Specify mipmap incomplete texture, use without mipmaps, re-specify
25  *    as complete and render.
26  *  - Randomly re-specify levels to eventually reach mipmap-complete texture.
27  *//*--------------------------------------------------------------------*/
28 
29 #include "es31fTextureSpecificationTests.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuImageCompare.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuVectorUtil.hpp"
34 #include "gluStrUtil.hpp"
35 #include "gluTexture.hpp"
36 #include "gluTextureUtil.hpp"
37 #include "sglrContextUtil.hpp"
38 #include "sglrContextWrapper.hpp"
39 #include "sglrGLContext.hpp"
40 #include "sglrReferenceContext.hpp"
41 #include "glsTextureTestUtil.hpp"
42 #include "deRandom.hpp"
43 #include "deStringUtil.hpp"
44 
45 // \todo [2012-04-29 pyry] Should be named SglrUtil
46 #include "es31fFboTestUtil.hpp"
47 
48 #include "glwEnums.hpp"
49 
50 namespace deqp
51 {
52 namespace gles31
53 {
54 namespace Functional
55 {
56 
57 using std::pair;
58 using std::string;
59 using std::vector;
60 using tcu::IVec4;
61 using tcu::TestLog;
62 using tcu::UVec4;
63 using tcu::Vec4;
64 using namespace FboTestUtil;
65 
66 enum
67 {
68     VIEWPORT_WIDTH  = 256,
69     VIEWPORT_HEIGHT = 256
70 };
71 
maxLevelCount(int size)72 static inline int maxLevelCount(int size)
73 {
74     return (int)deLog2Floor32(size) + 1;
75 }
76 
77 template <int Size>
78 static tcu::Vector<float, Size> randomVector(de::Random &rnd,
79                                              const tcu::Vector<float, Size> &minVal = tcu::Vector<float, Size>(0.0f),
80                                              const tcu::Vector<float, Size> &maxVal = tcu::Vector<float, Size>(1.0f))
81 {
82     tcu::Vector<float, Size> res;
83     for (int ndx = 0; ndx < Size; ndx++)
84         res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]);
85     return res;
86 }
87 
getCubeFaceFromNdx(int ndx)88 static tcu::CubeFace getCubeFaceFromNdx(int ndx)
89 {
90     switch (ndx)
91     {
92     case 0:
93         return tcu::CUBEFACE_POSITIVE_X;
94     case 1:
95         return tcu::CUBEFACE_NEGATIVE_X;
96     case 2:
97         return tcu::CUBEFACE_POSITIVE_Y;
98     case 3:
99         return tcu::CUBEFACE_NEGATIVE_Y;
100     case 4:
101         return tcu::CUBEFACE_POSITIVE_Z;
102     case 5:
103         return tcu::CUBEFACE_NEGATIVE_Z;
104     default:
105         DE_ASSERT(false);
106         return tcu::CUBEFACE_LAST;
107     }
108 }
109 
110 class TextureSpecCase : public TestCase, public sglr::ContextWrapper
111 {
112 public:
113     TextureSpecCase(Context &context, const char *name, const char *desc);
114     ~TextureSpecCase(void);
115 
116     IterateResult iterate(void);
117 
118 protected:
checkExtensionSupport(void)119     virtual bool checkExtensionSupport(void)
120     {
121         return true;
122     }
123 
124     virtual void createTexture(void)                                                              = DE_NULL;
125     virtual void verifyTexture(sglr::GLContext &gles3Context, sglr::ReferenceContext &refContext) = DE_NULL;
126 
127     // Utilities.
128     void renderTex(tcu::Surface &dst, uint32_t program, int width, int height);
129     void readPixels(tcu::Surface &dst, int x, int y, int width, int height);
130 
131 private:
132     TextureSpecCase(const TextureSpecCase &other);
133     TextureSpecCase &operator=(const TextureSpecCase &other);
134 };
135 
TextureSpecCase(Context & context,const char * name,const char * desc)136 TextureSpecCase::TextureSpecCase(Context &context, const char *name, const char *desc) : TestCase(context, name, desc)
137 {
138 }
139 
~TextureSpecCase(void)140 TextureSpecCase::~TextureSpecCase(void)
141 {
142 }
143 
iterate(void)144 TextureSpecCase::IterateResult TextureSpecCase::iterate(void)
145 {
146     glu::RenderContext &renderCtx         = TestCase::m_context.getRenderContext();
147     const tcu::RenderTarget &renderTarget = renderCtx.getRenderTarget();
148     tcu::TestLog &log                     = m_testCtx.getLog();
149 
150     if (renderTarget.getWidth() < VIEWPORT_WIDTH || renderTarget.getHeight() < VIEWPORT_HEIGHT)
151         throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
152 
153     if (!checkExtensionSupport())
154         throw tcu::NotSupportedError("Extension not supported", "", __FILE__, __LINE__);
155 
156     // Context size, and viewport for GLES3.1
157     de::Random rnd(deStringHash(getName()));
158     int width  = deMin32(renderTarget.getWidth(), VIEWPORT_WIDTH);
159     int height = deMin32(renderTarget.getHeight(), VIEWPORT_HEIGHT);
160     int x      = rnd.getInt(0, renderTarget.getWidth() - width);
161     int y      = rnd.getInt(0, renderTarget.getHeight() - height);
162 
163     // Contexts.
164     sglr::GLContext gles31Context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
165     sglr::ReferenceContextBuffers refBuffers(tcu::PixelFormat(8, 8, 8, renderTarget.getPixelFormat().alphaBits ? 8 : 0),
166                                              0 /* depth */, 0 /* stencil */, width, height);
167     sglr::ReferenceContext refContext(sglr::ReferenceContextLimits(renderCtx), refBuffers.getColorbuffer(),
168                                       refBuffers.getDepthbuffer(), refBuffers.getStencilbuffer());
169 
170     // Clear color buffer.
171     for (int ndx = 0; ndx < 2; ndx++)
172     {
173         setContext(ndx ? (sglr::Context *)&refContext : (sglr::Context *)&gles31Context);
174         glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
175         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
176     }
177 
178     // Construct texture using both GLES3.1 and reference contexts.
179     for (int ndx = 0; ndx < 2; ndx++)
180     {
181         setContext(ndx ? (sglr::Context *)&refContext : (sglr::Context *)&gles31Context);
182         createTexture();
183         TCU_CHECK(glGetError() == GL_NO_ERROR);
184     }
185 
186     // Initialize case result to pass.
187     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
188 
189     // Disable logging.
190     gles31Context.enableLogging(0);
191 
192     // Verify results.
193     verifyTexture(gles31Context, refContext);
194 
195     return STOP;
196 }
197 
renderTex(tcu::Surface & dst,uint32_t program,int width,int height)198 void TextureSpecCase::renderTex(tcu::Surface &dst, uint32_t program, int width, int height)
199 {
200     int targetW = getWidth();
201     int targetH = getHeight();
202 
203     float w = (float)width / (float)targetW;
204     float h = (float)height / (float)targetH;
205 
206     sglr::drawQuad(*getCurrentContext(), program, tcu::Vec3(-1.0f, -1.0f, 0.0f),
207                    tcu::Vec3(-1.0f + w * 2.0f, -1.0f + h * 2.0f, 0.0f));
208 
209     // Read pixels back.
210     readPixels(dst, 0, 0, width, height);
211 }
212 
readPixels(tcu::Surface & dst,int x,int y,int width,int height)213 void TextureSpecCase::readPixels(tcu::Surface &dst, int x, int y, int width, int height)
214 {
215     dst.setSize(width, height);
216     glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, dst.getAccess().getDataPtr());
217 }
218 
219 class TextureCubeArraySpecCase : public TextureSpecCase
220 {
221 public:
222     TextureCubeArraySpecCase(Context &context, const char *name, const char *desc, const tcu::TextureFormat &format,
223                              int size, int depth, int numLevels);
224     ~TextureCubeArraySpecCase(void);
225 
226 protected:
227     virtual bool checkExtensionSupport(void);
228     virtual void verifyTexture(sglr::GLContext &gles3Context, sglr::ReferenceContext &refContext);
229 
230     tcu::TextureFormat m_texFormat;
231     tcu::TextureFormatInfo m_texFormatInfo;
232     int m_size;
233     int m_depth;
234     int m_numLevels;
235 };
236 
TextureCubeArraySpecCase(Context & context,const char * name,const char * desc,const tcu::TextureFormat & format,int size,int depth,int numLevels)237 TextureCubeArraySpecCase::TextureCubeArraySpecCase(Context &context, const char *name, const char *desc,
238                                                    const tcu::TextureFormat &format, int size, int depth, int numLevels)
239     : TextureSpecCase(context, name, desc)
240     , m_texFormat(format)
241     , m_texFormatInfo(tcu::getTextureFormatInfo(format))
242     , m_size(size)
243     , m_depth(depth)
244     , m_numLevels(numLevels)
245 {
246 }
247 
~TextureCubeArraySpecCase(void)248 TextureCubeArraySpecCase::~TextureCubeArraySpecCase(void)
249 {
250 }
251 
checkExtensionSupport(void)252 bool TextureCubeArraySpecCase::checkExtensionSupport(void)
253 {
254     glu::ContextType contextType  = m_context.getRenderContext().getType();
255     const bool supportsES32orGL45 = glu::contextSupports(contextType, glu::ApiType::es(3, 2)) ||
256                                     glu::contextSupports(contextType, glu::ApiType::core(4, 5));
257     return supportsES32orGL45 || m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_cube_map_array");
258 }
259 
verifyTexture(sglr::GLContext & gles3Context,sglr::ReferenceContext & refContext)260 void TextureCubeArraySpecCase::verifyTexture(sglr::GLContext &gles3Context, sglr::ReferenceContext &refContext)
261 {
262     const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
263     TextureCubeArrayShader shader(glu::getSamplerCubeArrayType(m_texFormat), glu::TYPE_FLOAT_VEC4, glslVersion);
264     uint32_t shaderIDgles = gles3Context.createProgram(&shader);
265     uint32_t shaderIDRef  = refContext.createProgram(&shader);
266 
267     shader.setTexScaleBias(m_texFormatInfo.lookupScale, m_texFormatInfo.lookupBias);
268 
269     // Set state.
270     for (int ndx = 0; ndx < 2; ndx++)
271     {
272         sglr::Context *ctx =
273             ndx ? static_cast<sglr::Context *>(&refContext) : static_cast<sglr::Context *>(&gles3Context);
274 
275         setContext(ctx);
276 
277         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
278         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
279         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
280         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
281         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
282         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAX_LEVEL, m_numLevels - 1);
283     }
284 
285     for (int layerFaceNdx = 0; layerFaceNdx < m_depth; layerFaceNdx++)
286     {
287         const int layerNdx       = layerFaceNdx / 6;
288         const tcu::CubeFace face = getCubeFaceFromNdx(layerFaceNdx % 6);
289         bool layerOk             = true;
290 
291         shader.setLayer(layerNdx);
292         shader.setFace(face);
293 
294         for (int levelNdx = 0; levelNdx < m_numLevels; levelNdx++)
295         {
296             int levelSize = de::max(1, m_size >> levelNdx);
297             tcu::Surface reference;
298             tcu::Surface result;
299 
300             if (levelSize <= 2)
301                 continue; // Fuzzy compare doesn't work for images this small.
302 
303             for (int ndx = 0; ndx < 2; ndx++)
304             {
305                 tcu::Surface &dst = ndx ? reference : result;
306                 sglr::Context *ctx =
307                     ndx ? static_cast<sglr::Context *>(&refContext) : static_cast<sglr::Context *>(&gles3Context);
308                 uint32_t shaderID = ndx ? shaderIDRef : shaderIDgles;
309 
310                 setContext(ctx);
311                 shader.setUniforms(*ctx, shaderID);
312                 renderTex(dst, shaderID, levelSize, levelSize);
313             }
314 
315             const float threshold = 0.02f;
316             string levelStr       = de::toString(levelNdx);
317             string layerFaceStr   = de::toString(layerFaceNdx);
318             string name           = string("LayerFace") + layerFaceStr + "Level" + levelStr;
319             string desc           = string("Layer-face ") + layerFaceStr + ", Level " + levelStr;
320             bool isFaceOk         = tcu::fuzzyCompare(
321                 m_testCtx.getLog(), name.c_str(), desc.c_str(), reference, result, threshold,
322                 (levelNdx == 0 && layerFaceNdx == 0) == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
323 
324             if (!isFaceOk)
325             {
326                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
327                 layerOk = false;
328                 break;
329             }
330         }
331 
332         if (!layerOk)
333             break;
334     }
335 }
336 
337 // Basic TexImage3D() with cube map array texture usage
338 class BasicTexImageCubeArrayCase : public TextureCubeArraySpecCase
339 {
340 public:
BasicTexImageCubeArrayCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size,int numLayers)341     BasicTexImageCubeArrayCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int size,
342                                int numLayers)
343         : TextureCubeArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, numLayers,
344                                    maxLevelCount(size))
345         , m_internalFormat(internalFormat)
346     {
347     }
348 
349 protected:
createTexture(void)350     void createTexture(void)
351     {
352         uint32_t tex = 0;
353         de::Random rnd(deStringHash(getName()));
354         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
355         tcu::TextureLevel levelData(glu::mapGLTransferFormat(transferFmt.format, transferFmt.dataType));
356 
357         glGenTextures(1, &tex);
358         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
359         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
360 
361         for (int ndx = 0; ndx < m_numLevels; ndx++)
362         {
363             int levelW = de::max(1, m_size >> ndx);
364             Vec4 gMin  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
365             Vec4 gMax  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
366 
367             levelData.setSize(levelW, levelW, m_depth);
368             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
369 
370             glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, ndx, m_internalFormat, levelW, levelW, m_depth, 0,
371                          transferFmt.format, transferFmt.dataType, levelData.getAccess().getDataPtr());
372         }
373     }
374 
375     uint32_t m_internalFormat;
376 };
377 
378 // Basic glTexStorage3D() with cube map array texture usage
379 class BasicTexStorageCubeArrayCase : public TextureCubeArraySpecCase
380 {
381 public:
BasicTexStorageCubeArrayCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size,int numLayers,int numLevels)382     BasicTexStorageCubeArrayCase(Context &context, const char *name, const char *desc, uint32_t internalFormat,
383                                  int size, int numLayers, int numLevels)
384         : TextureCubeArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, numLayers,
385                                    numLevels)
386         , m_internalFormat(internalFormat)
387     {
388     }
389 
390 protected:
createTexture(void)391     void createTexture(void)
392     {
393         uint32_t tex = 0;
394         de::Random rnd(deStringHash(getName()));
395         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
396         tcu::TextureLevel levelData(glu::mapGLTransferFormat(transferFmt.format, transferFmt.dataType));
397 
398         glGenTextures(1, &tex);
399         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
400         glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, m_numLevels, m_internalFormat, m_size, m_size, m_depth);
401 
402         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
403 
404         for (int ndx = 0; ndx < m_numLevels; ndx++)
405         {
406             int levelW = de::max(1, m_size >> ndx);
407             Vec4 gMin  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
408             Vec4 gMax  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
409 
410             levelData.setSize(levelW, levelW, m_depth);
411             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
412 
413             glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, ndx, 0, 0, 0, levelW, levelW, m_depth, transferFmt.format,
414                             transferFmt.dataType, levelData.getAccess().getDataPtr());
415         }
416     }
417 
418     uint32_t m_internalFormat;
419 };
420 
421 // Pixel buffer object cases.
422 
423 // TexImage3D() cube map array from pixel buffer object.
424 class TexImageCubeArrayBufferCase : public TextureCubeArraySpecCase
425 {
426 public:
TexImageCubeArrayBufferCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size,int depth,int imageHeight,int rowLength,int skipImages,int skipRows,int skipPixels,int alignment,int offset)427     TexImageCubeArrayBufferCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int size,
428                                 int depth, int imageHeight, int rowLength, int skipImages, int skipRows, int skipPixels,
429                                 int alignment, int offset)
430         : TextureCubeArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, depth, 1)
431         , m_internalFormat(internalFormat)
432         , m_imageHeight(imageHeight)
433         , m_rowLength(rowLength)
434         , m_skipImages(skipImages)
435         , m_skipRows(skipRows)
436         , m_skipPixels(skipPixels)
437         , m_alignment(alignment)
438         , m_offset(offset)
439     {
440     }
441 
442 protected:
createTexture(void)443     void createTexture(void)
444     {
445         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
446         int pixelSize                   = m_texFormat.getPixelSize();
447         int rowLength                   = m_rowLength > 0 ? m_rowLength : m_size;
448         int rowPitch                    = deAlign32(rowLength * pixelSize, m_alignment);
449         int imageHeight                 = m_imageHeight > 0 ? m_imageHeight : m_size;
450         int slicePitch                  = imageHeight * rowPitch;
451         uint32_t tex                    = 0;
452         uint32_t buf                    = 0;
453         vector<uint8_t> data;
454 
455         DE_ASSERT(m_numLevels == 1);
456 
457         // Fill data with grid.
458         data.resize(slicePitch * (m_depth + m_skipImages) + m_offset);
459         {
460             Vec4 cScale = m_texFormatInfo.valueMax - m_texFormatInfo.valueMin;
461             Vec4 cBias  = m_texFormatInfo.valueMin;
462             Vec4 colorA = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
463             Vec4 colorB = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias;
464 
465             tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_size, m_size, m_depth, rowPitch, slicePitch,
466                                                      &data[0] + m_skipImages * slicePitch + m_skipRows * rowPitch +
467                                                          m_skipPixels * pixelSize + m_offset),
468                               4, colorA, colorB);
469         }
470 
471         glGenBuffers(1, &buf);
472         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
473         glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
474 
475         glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, m_imageHeight);
476         glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
477         glPixelStorei(GL_UNPACK_SKIP_IMAGES, m_skipImages);
478         glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
479         glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
480         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
481 
482         glGenTextures(1, &tex);
483         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
484         glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, m_internalFormat, m_size, m_size, m_depth, 0, transferFmt.format,
485                      transferFmt.dataType, (const void *)(uintptr_t)m_offset);
486     }
487 
488     uint32_t m_internalFormat;
489     int m_imageHeight;
490     int m_rowLength;
491     int m_skipImages;
492     int m_skipRows;
493     int m_skipPixels;
494     int m_alignment;
495     int m_offset;
496 };
497 
498 // TexSubImage3D() cube map array PBO case.
499 class TexSubImageCubeArrayBufferCase : public TextureCubeArraySpecCase
500 {
501 public:
TexSubImageCubeArrayBufferCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size,int depth,int subX,int subY,int subZ,int subW,int subH,int subD,int imageHeight,int rowLength,int skipImages,int skipRows,int skipPixels,int alignment,int offset)502     TexSubImageCubeArrayBufferCase(Context &context, const char *name, const char *desc, uint32_t internalFormat,
503                                    int size, int depth, int subX, int subY, int subZ, int subW, int subH, int subD,
504                                    int imageHeight, int rowLength, int skipImages, int skipRows, int skipPixels,
505                                    int alignment, int offset)
506         : TextureCubeArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, depth, 1)
507         , m_internalFormat(internalFormat)
508         , m_subX(subX)
509         , m_subY(subY)
510         , m_subZ(subZ)
511         , m_subW(subW)
512         , m_subH(subH)
513         , m_subD(subD)
514         , m_imageHeight(imageHeight)
515         , m_rowLength(rowLength)
516         , m_skipImages(skipImages)
517         , m_skipRows(skipRows)
518         , m_skipPixels(skipPixels)
519         , m_alignment(alignment)
520         , m_offset(offset)
521     {
522     }
523 
524 protected:
createTexture(void)525     void createTexture(void)
526     {
527         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
528         int pixelSize                   = m_texFormat.getPixelSize();
529         uint32_t tex                    = 0;
530         uint32_t buf                    = 0;
531         vector<uint8_t> data;
532 
533         DE_ASSERT(m_numLevels == 1);
534 
535         glGenTextures(1, &tex);
536         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
537 
538         // Fill with gradient.
539         {
540             int rowPitch   = deAlign32(pixelSize * m_size, 4);
541             int slicePitch = rowPitch * m_size;
542 
543             data.resize(slicePitch * m_depth);
544             tcu::fillWithComponentGradients(
545                 tcu::PixelBufferAccess(m_texFormat, m_size, m_size, m_depth, rowPitch, slicePitch, &data[0]),
546                 m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
547         }
548 
549         glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, m_internalFormat, m_size, m_size, m_depth, 0, transferFmt.format,
550                      transferFmt.dataType, &data[0]);
551 
552         // Fill data with grid.
553         {
554             int rowLength   = m_rowLength > 0 ? m_rowLength : m_subW;
555             int rowPitch    = deAlign32(rowLength * pixelSize, m_alignment);
556             int imageHeight = m_imageHeight > 0 ? m_imageHeight : m_subH;
557             int slicePitch  = imageHeight * rowPitch;
558             Vec4 cScale     = m_texFormatInfo.valueMax - m_texFormatInfo.valueMin;
559             Vec4 cBias      = m_texFormatInfo.valueMin;
560             Vec4 colorA     = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
561             Vec4 colorB     = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias;
562 
563             data.resize(slicePitch * (m_depth + m_skipImages) + m_offset);
564             tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, m_subD, rowPitch, slicePitch,
565                                                      &data[0] + m_skipImages * slicePitch + m_skipRows * rowPitch +
566                                                          m_skipPixels * pixelSize + m_offset),
567                               4, colorA, colorB);
568         }
569 
570         glGenBuffers(1, &buf);
571         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
572         glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
573 
574         glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, m_imageHeight);
575         glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
576         glPixelStorei(GL_UNPACK_SKIP_IMAGES, m_skipImages);
577         glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
578         glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
579         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
580         glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, m_subX, m_subY, m_subZ, m_subW, m_subH, m_subD,
581                         transferFmt.format, transferFmt.dataType, (const void *)(intptr_t)m_offset);
582     }
583 
584     uint32_t m_internalFormat;
585     int m_subX;
586     int m_subY;
587     int m_subZ;
588     int m_subW;
589     int m_subH;
590     int m_subD;
591     int m_imageHeight;
592     int m_rowLength;
593     int m_skipImages;
594     int m_skipRows;
595     int m_skipPixels;
596     int m_alignment;
597     int m_offset;
598 };
599 
600 // TexImage3D() depth case.
601 class TexImageCubeArrayDepthCase : public TextureCubeArraySpecCase
602 {
603 public:
TexImageCubeArrayDepthCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int imageSize,int numLayers)604     TexImageCubeArrayDepthCase(Context &context, const char *name, const char *desc, uint32_t internalFormat,
605                                int imageSize, int numLayers)
606         : TextureCubeArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageSize, numLayers,
607                                    maxLevelCount(imageSize))
608         , m_internalFormat(internalFormat)
609     {
610         // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
611         m_texFormatInfo.lookupBias  = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
612         m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
613     }
614 
createTexture(void)615     void createTexture(void)
616     {
617         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
618         uint32_t tex            = 0;
619         tcu::TextureLevel levelData(glu::mapGLTransferFormat(fmt.format, fmt.dataType));
620 
621         glGenTextures(1, &tex);
622         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
623         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
624         GLU_CHECK();
625 
626         for (int ndx = 0; ndx < m_numLevels; ndx++)
627         {
628             const int levelW = de::max(1, m_size >> ndx);
629             const Vec4 gMin  = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
630             const Vec4 gMax  = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
631 
632             levelData.setSize(levelW, levelW, m_depth);
633             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
634 
635             glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, ndx, m_internalFormat, levelW, levelW, m_depth, 0, fmt.format,
636                          fmt.dataType, levelData.getAccess().getDataPtr());
637         }
638     }
639 
640     const uint32_t m_internalFormat;
641 };
642 
643 // TexSubImage3D() depth case.
644 class TexSubImageCubeArrayDepthCase : public TextureCubeArraySpecCase
645 {
646 public:
TexSubImageCubeArrayDepthCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int imageSize,int numLayers)647     TexSubImageCubeArrayDepthCase(Context &context, const char *name, const char *desc, uint32_t internalFormat,
648                                   int imageSize, int numLayers)
649         : TextureCubeArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageSize, numLayers,
650                                    maxLevelCount(imageSize))
651         , m_internalFormat(internalFormat)
652     {
653         // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
654         m_texFormatInfo.lookupBias  = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
655         m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
656     }
657 
createTexture(void)658     void createTexture(void)
659     {
660         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
661         de::Random rnd(deStringHash(getName()));
662         uint32_t tex = 0;
663         tcu::TextureLevel levelData(glu::mapGLTransferFormat(fmt.format, fmt.dataType));
664 
665         glGenTextures(1, &tex);
666         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
667         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
668         GLU_CHECK();
669 
670         // First specify full texture.
671         for (int ndx = 0; ndx < m_numLevels; ndx++)
672         {
673             const int levelW = de::max(1, m_size >> ndx);
674             const Vec4 gMin  = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
675             const Vec4 gMax  = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
676 
677             levelData.setSize(levelW, levelW, m_depth);
678             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
679 
680             glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, ndx, m_internalFormat, levelW, levelW, m_depth, 0, fmt.format,
681                          fmt.dataType, levelData.getAccess().getDataPtr());
682         }
683 
684         // Re-specify parts of each level.
685         for (int ndx = 0; ndx < m_numLevels; ndx++)
686         {
687             const int levelW = de::max(1, m_size >> ndx);
688 
689             const int w = rnd.getInt(1, levelW);
690             const int h = rnd.getInt(1, levelW);
691             const int d = rnd.getInt(1, m_depth);
692             const int x = rnd.getInt(0, levelW - w);
693             const int y = rnd.getInt(0, levelW - h);
694             const int z = rnd.getInt(0, m_depth - d);
695 
696             const Vec4 colorA  = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
697             const Vec4 colorB  = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
698             const int cellSize = rnd.getInt(2, 16);
699 
700             levelData.setSize(w, h, d);
701             tcu::fillWithGrid(levelData.getAccess(), cellSize, colorA, colorB);
702 
703             glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, ndx, x, y, z, w, h, d, fmt.format, fmt.dataType,
704                             levelData.getAccess().getDataPtr());
705         }
706     }
707 
708     const uint32_t m_internalFormat;
709 };
710 
711 // TexImage3D() depth case with pbo.
712 class TexImageCubeArrayDepthBufferCase : public TextureCubeArraySpecCase
713 {
714 public:
TexImageCubeArrayDepthBufferCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int imageSize,int numLayers)715     TexImageCubeArrayDepthBufferCase(Context &context, const char *name, const char *desc, uint32_t internalFormat,
716                                      int imageSize, int numLayers)
717         : TextureCubeArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageSize, numLayers,
718                                    1)
719         , m_internalFormat(internalFormat)
720     {
721         // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
722         m_texFormatInfo.lookupBias  = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
723         m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
724     }
725 
createTexture(void)726     void createTexture(void)
727     {
728         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
729         int pixelSize                   = m_texFormat.getPixelSize();
730         int rowLength                   = m_size;
731         int alignment                   = 4;
732         int rowPitch                    = deAlign32(rowLength * pixelSize, alignment);
733         int imageHeight                 = m_size;
734         int slicePitch                  = imageHeight * rowPitch;
735         uint32_t tex                    = 0;
736         uint32_t buf                    = 0;
737         vector<uint8_t> data;
738 
739         DE_ASSERT(m_numLevels == 1);
740 
741         // Fill data with grid.
742         data.resize(slicePitch * m_depth);
743         {
744             const Vec4 gMin = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
745             const Vec4 gMax = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
746 
747             tcu::fillWithComponentGradients(
748                 tcu::PixelBufferAccess(m_texFormat, m_size, m_size, m_depth, rowPitch, slicePitch, &data[0]), gMin,
749                 gMax);
750         }
751 
752         glGenBuffers(1, &buf);
753         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
754         glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
755 
756         glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, imageHeight);
757         glPixelStorei(GL_UNPACK_ROW_LENGTH, rowLength);
758         glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
759         glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
760         glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
761         glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
762 
763         glGenTextures(1, &tex);
764         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
765         glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, m_internalFormat, m_size, m_size, m_depth, 0, transferFmt.format,
766                      transferFmt.dataType, DE_NULL);
767         glDeleteBuffers(1, &buf);
768     }
769 
770     const uint32_t m_internalFormat;
771 };
772 
TextureSpecificationTests(Context & context)773 TextureSpecificationTests::TextureSpecificationTests(Context &context)
774     : TestCaseGroup(context, "specification", "Texture Specification Tests")
775 {
776 }
777 
~TextureSpecificationTests(void)778 TextureSpecificationTests::~TextureSpecificationTests(void)
779 {
780 }
781 
init(void)782 void TextureSpecificationTests::init(void)
783 {
784     struct
785     {
786         const char *name;
787         uint32_t internalFormat;
788     } colorFormats[] = {{
789                             "rgba32f",
790                             GL_RGBA32F,
791                         },
792                         {
793                             "rgba32i",
794                             GL_RGBA32I,
795                         },
796                         {
797                             "rgba32ui",
798                             GL_RGBA32UI,
799                         },
800                         {
801                             "rgba16f",
802                             GL_RGBA16F,
803                         },
804                         {
805                             "rgba16i",
806                             GL_RGBA16I,
807                         },
808                         {
809                             "rgba16ui",
810                             GL_RGBA16UI,
811                         },
812                         {
813                             "rgba8",
814                             GL_RGBA8,
815                         },
816                         {
817                             "rgba8i",
818                             GL_RGBA8I,
819                         },
820                         {
821                             "rgba8ui",
822                             GL_RGBA8UI,
823                         },
824                         {
825                             "srgb8_alpha8",
826                             GL_SRGB8_ALPHA8,
827                         },
828                         {
829                             "rgb10_a2",
830                             GL_RGB10_A2,
831                         },
832                         {
833                             "rgb10_a2ui",
834                             GL_RGB10_A2UI,
835                         },
836                         {
837                             "rgba4",
838                             GL_RGBA4,
839                         },
840                         {
841                             "rgb5_a1",
842                             GL_RGB5_A1,
843                         },
844                         {
845                             "rgba8_snorm",
846                             GL_RGBA8_SNORM,
847                         },
848                         {
849                             "rgb8",
850                             GL_RGB8,
851                         },
852                         {
853                             "rgb565",
854                             GL_RGB565,
855                         },
856                         {
857                             "r11f_g11f_b10f",
858                             GL_R11F_G11F_B10F,
859                         },
860                         {
861                             "rgb32f",
862                             GL_RGB32F,
863                         },
864                         {
865                             "rgb32i",
866                             GL_RGB32I,
867                         },
868                         {
869                             "rgb32ui",
870                             GL_RGB32UI,
871                         },
872                         {
873                             "rgb16f",
874                             GL_RGB16F,
875                         },
876                         {
877                             "rgb16i",
878                             GL_RGB16I,
879                         },
880                         {
881                             "rgb16ui",
882                             GL_RGB16UI,
883                         },
884                         {
885                             "rgb8_snorm",
886                             GL_RGB8_SNORM,
887                         },
888                         {
889                             "rgb8i",
890                             GL_RGB8I,
891                         },
892                         {
893                             "rgb8ui",
894                             GL_RGB8UI,
895                         },
896                         {
897                             "srgb8",
898                             GL_SRGB8,
899                         },
900                         {
901                             "rgb9_e5",
902                             GL_RGB9_E5,
903                         },
904                         {
905                             "rg32f",
906                             GL_RG32F,
907                         },
908                         {
909                             "rg32i",
910                             GL_RG32I,
911                         },
912                         {
913                             "rg32ui",
914                             GL_RG32UI,
915                         },
916                         {
917                             "rg16f",
918                             GL_RG16F,
919                         },
920                         {
921                             "rg16i",
922                             GL_RG16I,
923                         },
924                         {
925                             "rg16ui",
926                             GL_RG16UI,
927                         },
928                         {
929                             "rg8",
930                             GL_RG8,
931                         },
932                         {
933                             "rg8i",
934                             GL_RG8I,
935                         },
936                         {
937                             "rg8ui",
938                             GL_RG8UI,
939                         },
940                         {
941                             "rg8_snorm",
942                             GL_RG8_SNORM,
943                         },
944                         {
945                             "r32f",
946                             GL_R32F,
947                         },
948                         {
949                             "r32i",
950                             GL_R32I,
951                         },
952                         {
953                             "r32ui",
954                             GL_R32UI,
955                         },
956                         {
957                             "r16f",
958                             GL_R16F,
959                         },
960                         {
961                             "r16i",
962                             GL_R16I,
963                         },
964                         {
965                             "r16ui",
966                             GL_R16UI,
967                         },
968                         {
969                             "r8",
970                             GL_R8,
971                         },
972                         {
973                             "r8i",
974                             GL_R8I,
975                         },
976                         {
977                             "r8ui",
978                             GL_R8UI,
979                         },
980                         {
981                             "r8_snorm",
982                             GL_R8_SNORM,
983                         }};
984 
985     static const struct
986     {
987         const char *name;
988         uint32_t internalFormat;
989     } depthStencilFormats[] = {// Depth and stencil formats
990                                {"depth_component32f", GL_DEPTH_COMPONENT32F},
991                                {"depth_component24", GL_DEPTH_COMPONENT24},
992                                {"depth_component16", GL_DEPTH_COMPONENT16},
993                                {"depth32f_stencil8", GL_DEPTH32F_STENCIL8},
994                                {"depth24_stencil8", GL_DEPTH24_STENCIL8}};
995 
996     // Basic TexImage3D usage.
997     {
998         tcu::TestCaseGroup *basicTexImageGroup =
999             new tcu::TestCaseGroup(m_testCtx, "basic_teximage3d", "Basic glTexImage3D() usage");
1000         addChild(basicTexImageGroup);
1001         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
1002         {
1003             const char *fmtName          = colorFormats[formatNdx].name;
1004             uint32_t format              = colorFormats[formatNdx].internalFormat;
1005             const int texCubeArraySize   = 64;
1006             const int texCubeArrayLayers = 6;
1007 
1008             basicTexImageGroup->addChild(new BasicTexImageCubeArrayCase(m_context,
1009                                                                         (string(fmtName) + "_cube_array").c_str(), "",
1010                                                                         format, texCubeArraySize, texCubeArrayLayers));
1011         }
1012     }
1013 
1014     // glTexImage3D() pbo cases.
1015     {
1016         tcu::TestCaseGroup *pboGroup = new tcu::TestCaseGroup(m_testCtx, "teximage3d_pbo", "glTexImage3D() from PBO");
1017         addChild(pboGroup);
1018 
1019         // Parameter cases
1020         static const struct
1021         {
1022             const char *name;
1023             uint32_t format;
1024             int size;
1025             int depth;
1026             int imageHeight;
1027             int rowLength;
1028             int skipImages;
1029             int skipRows;
1030             int skipPixels;
1031             int alignment;
1032             int offset;
1033         } parameterCases[] = {{"rgb8_offset", GL_RGB8, 23, 6, 0, 0, 0, 0, 0, 1, 67},
1034                               {"rgb8_alignment", GL_RGB8, 23, 6, 0, 0, 0, 0, 0, 2, 0},
1035                               {"rgb8_image_height", GL_RGB8, 23, 6, 26, 0, 0, 0, 0, 4, 0},
1036                               {"rgb8_row_length", GL_RGB8, 23, 6, 0, 27, 0, 0, 0, 4, 0},
1037                               {"rgb8_skip_images", GL_RGB8, 23, 6, 0, 0, 3, 0, 0, 4, 0},
1038                               {"rgb8_skip_rows", GL_RGB8, 23, 6, 26, 0, 0, 3, 0, 4, 0},
1039                               {"rgb8_skip_pixels", GL_RGB8, 23, 6, 0, 25, 0, 0, 2, 4, 0}};
1040 
1041         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
1042         {
1043             const string fmtName       = colorFormats[formatNdx].name;
1044             const uint32_t format      = colorFormats[formatNdx].internalFormat;
1045             const int texCubeArraySize = 20;
1046             const int texCubeDepth     = 6;
1047 
1048             pboGroup->addChild(new TexImageCubeArrayBufferCase(m_context, (fmtName + "_cube_array").c_str(), "", format,
1049                                                                texCubeArraySize, texCubeDepth, 0, 0, 0, 0, 0, 4, 0));
1050         }
1051 
1052         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(parameterCases); ndx++)
1053         {
1054             pboGroup->addChild(new TexImageCubeArrayBufferCase(
1055                 m_context, (string(parameterCases[ndx].name) + "_cube_array").c_str(), "", parameterCases[ndx].format,
1056                 parameterCases[ndx].size, parameterCases[ndx].depth, parameterCases[ndx].imageHeight,
1057                 parameterCases[ndx].rowLength, parameterCases[ndx].skipImages, parameterCases[ndx].skipRows,
1058                 parameterCases[ndx].skipPixels, parameterCases[ndx].alignment, parameterCases[ndx].offset));
1059         }
1060     }
1061 
1062     // glTexImage3D() depth cases.
1063     {
1064         tcu::TestCaseGroup *shadow3dGroup =
1065             new tcu::TestCaseGroup(m_testCtx, "teximage3d_depth", "glTexImage3D() with depth or depth/stencil format");
1066         addChild(shadow3dGroup);
1067 
1068         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
1069         {
1070             const int texCubeArraySize  = 64;
1071             const int texCubeArrayDepth = 6;
1072 
1073             shadow3dGroup->addChild(new TexImageCubeArrayDepthCase(
1074                 m_context, (std::string(depthStencilFormats[ndx].name) + "_cube_array").c_str(), "",
1075                 depthStencilFormats[ndx].internalFormat, texCubeArraySize, texCubeArrayDepth));
1076         }
1077     }
1078 
1079     // glTexImage3D() depth cases with pbo.
1080     {
1081         tcu::TestCaseGroup *shadow3dGroup = new tcu::TestCaseGroup(
1082             m_testCtx, "teximage3d_depth_pbo", "glTexImage3D() with depth or depth/stencil format with pbo");
1083         addChild(shadow3dGroup);
1084 
1085         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
1086         {
1087             const int texCubeArraySize  = 64;
1088             const int texCubeArrayDepth = 6;
1089 
1090             shadow3dGroup->addChild(new TexImageCubeArrayDepthBufferCase(
1091                 m_context, (std::string(depthStencilFormats[ndx].name) + "_cube_array").c_str(), "",
1092                 depthStencilFormats[ndx].internalFormat, texCubeArraySize, texCubeArrayDepth));
1093         }
1094     }
1095 
1096     // glTexSubImage3D() PBO cases.
1097     {
1098         tcu::TestCaseGroup *pboGroup =
1099             new tcu::TestCaseGroup(m_testCtx, "texsubimage3d_pbo", "glTexSubImage3D() pixel buffer object tests");
1100         addChild(pboGroup);
1101 
1102         static const struct
1103         {
1104             const char *name;
1105             uint32_t format;
1106             int size;
1107             int depth;
1108             int subX;
1109             int subY;
1110             int subZ;
1111             int subW;
1112             int subH;
1113             int subD;
1114             int imageHeight;
1115             int rowLength;
1116             int skipImages;
1117             int skipRows;
1118             int skipPixels;
1119             int alignment;
1120             int offset;
1121         } paramCases[] = {{"rgb8_offset", GL_RGB8, 26, 12, 1, 2, 1, 23, 19, 8, 0, 0, 0, 0, 0, 4, 67},
1122                           {"rgb8_image_height", GL_RGB8, 26, 12, 1, 2, 1, 23, 19, 8, 26, 0, 0, 0, 0, 4, 0},
1123                           {"rgb8_row_length", GL_RGB8, 26, 12, 1, 2, 1, 23, 19, 8, 0, 27, 0, 0, 0, 4, 0},
1124                           {"rgb8_skip_images", GL_RGB8, 26, 12, 1, 2, 1, 23, 19, 8, 0, 0, 3, 0, 0, 4, 0},
1125                           {"rgb8_skip_rows", GL_RGB8, 26, 12, 1, 2, 1, 23, 19, 8, 22, 0, 0, 3, 0, 4, 0},
1126                           {"rgb8_skip_pixels", GL_RGB8, 26, 12, 1, 2, 1, 23, 19, 8, 0, 25, 0, 0, 2, 4, 0}};
1127 
1128         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
1129         {
1130             pboGroup->addChild(new TexSubImageCubeArrayBufferCase(
1131                 m_context, (std::string(colorFormats[ndx].name) + "_cube_array").c_str(), "",
1132                 colorFormats[ndx].internalFormat,
1133                 26, // Size
1134                 12, // Depth
1135                 1,  // Sub X
1136                 2,  // Sub Y
1137                 0,  // Sub Z
1138                 23, // Sub W
1139                 19, // Sub H
1140                 8,  // Sub D
1141                 0,  // Image height
1142                 0,  // Row length
1143                 0,  // Skip images
1144                 0,  // Skip rows
1145                 0,  // Skip pixels
1146                 4,  // Alignment
1147                 0 /* offset */));
1148         }
1149 
1150         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(paramCases); ndx++)
1151         {
1152             pboGroup->addChild(new TexSubImageCubeArrayBufferCase(
1153                 m_context, (std::string(paramCases[ndx].name) + "_cube_array").c_str(), "", paramCases[ndx].format,
1154                 paramCases[ndx].size, paramCases[ndx].depth, paramCases[ndx].subX, paramCases[ndx].subY,
1155                 paramCases[ndx].subZ, paramCases[ndx].subW, paramCases[ndx].subH, paramCases[ndx].subD,
1156                 paramCases[ndx].imageHeight, paramCases[ndx].rowLength, paramCases[ndx].skipImages,
1157                 paramCases[ndx].skipRows, paramCases[ndx].skipPixels, paramCases[ndx].alignment,
1158                 paramCases[ndx].offset));
1159         }
1160     }
1161 
1162     // glTexSubImage3D() depth cases.
1163     {
1164         tcu::TestCaseGroup *shadow3dGroup = new tcu::TestCaseGroup(
1165             m_testCtx, "texsubimage3d_depth", "glTexSubImage3D() with depth or depth/stencil format");
1166         addChild(shadow3dGroup);
1167 
1168         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
1169         {
1170             const int texCubeArraySize   = 57;
1171             const int texCubeArrayLayers = 6;
1172 
1173             shadow3dGroup->addChild(new TexSubImageCubeArrayDepthCase(
1174                 m_context, (std::string(depthStencilFormats[ndx].name) + "_cube_array").c_str(), "",
1175                 depthStencilFormats[ndx].internalFormat, texCubeArraySize, texCubeArrayLayers));
1176         }
1177     }
1178 
1179     // glTexStorage3D() cases.
1180     {
1181         tcu::TestCaseGroup *texStorageGroup =
1182             new tcu::TestCaseGroup(m_testCtx, "texstorage3d", "Basic glTexStorage3D() usage");
1183         addChild(texStorageGroup);
1184 
1185         // All formats.
1186         tcu::TestCaseGroup *formatGroup =
1187             new tcu::TestCaseGroup(m_testCtx, "format", "glTexStorage3D() with all formats");
1188         texStorageGroup->addChild(formatGroup);
1189 
1190         // Color formats.
1191         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
1192         {
1193             const char *fmtName          = colorFormats[formatNdx].name;
1194             uint32_t internalFormat      = colorFormats[formatNdx].internalFormat;
1195             const int texCubeArraySize   = 57;
1196             const int texCubeArrayLayers = 6;
1197             int texCubeArrayLevels       = maxLevelCount(texCubeArraySize);
1198 
1199             formatGroup->addChild(new BasicTexStorageCubeArrayCase(m_context, (string(fmtName) + "_cube_array").c_str(),
1200                                                                    "", internalFormat, texCubeArraySize,
1201                                                                    texCubeArrayLayers, texCubeArrayLevels));
1202         }
1203 
1204         // Depth/stencil formats (only 2D texture array is supported).
1205         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); formatNdx++)
1206         {
1207             const char *fmtName          = depthStencilFormats[formatNdx].name;
1208             uint32_t internalFormat      = depthStencilFormats[formatNdx].internalFormat;
1209             const int texCubeArraySize   = 57;
1210             const int texCubeArrayLayers = 6;
1211             int texCubeArrayLevels       = maxLevelCount(texCubeArraySize);
1212 
1213             formatGroup->addChild(new BasicTexStorageCubeArrayCase(m_context, (string(fmtName) + "_cube_array").c_str(),
1214                                                                    "", internalFormat, texCubeArraySize,
1215                                                                    texCubeArrayLayers, texCubeArrayLevels));
1216         }
1217 
1218         // Sizes.
1219         static const struct
1220         {
1221             int size;
1222             int layers;
1223             int levels;
1224         } texCubeArraySizes[] = {//    Sz    La    Le
1225                                  {1, 6, 1}, {2, 6, 2}, {32, 6, 3}, {64, 6, 4}, {57, 12, 1}, {57, 12, 2}, {57, 12, 6}};
1226 
1227         tcu::TestCaseGroup *sizeGroup =
1228             new tcu::TestCaseGroup(m_testCtx, "size", "glTexStorage3D() with various sizes");
1229         texStorageGroup->addChild(sizeGroup);
1230 
1231         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(texCubeArraySizes); ndx++)
1232         {
1233             const uint32_t format = GL_RGBA8;
1234             int size              = texCubeArraySizes[ndx].size;
1235             int layers            = texCubeArraySizes[ndx].layers;
1236             int levels            = texCubeArraySizes[ndx].levels;
1237             string name           = string("cube_array_") + de::toString(size) + "x" + de::toString(size) + "x" +
1238                           de::toString(layers) + "_" + de::toString(levels) + "_levels";
1239 
1240             sizeGroup->addChild(
1241                 new BasicTexStorageCubeArrayCase(m_context, name.c_str(), "", format, size, layers, levels));
1242         }
1243     }
1244 }
1245 
1246 } // namespace Functional
1247 } // namespace gles31
1248 } // namespace deqp
1249