xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fTextureSpecificationTests.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 "es3fTextureSpecificationTests.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 "es3fFboTestUtil.hpp"
47 
48 #include "glwEnums.hpp"
49 
50 namespace deqp
51 {
52 namespace gles3
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 
mapGLUnsizedInternalFormat(uint32_t internalFormat)66 tcu::TextureFormat mapGLUnsizedInternalFormat(uint32_t internalFormat)
67 {
68     using tcu::TextureFormat;
69     switch (internalFormat)
70     {
71     case GL_ALPHA:
72         return TextureFormat(TextureFormat::A, TextureFormat::UNORM_INT8);
73     case GL_LUMINANCE:
74         return TextureFormat(TextureFormat::L, TextureFormat::UNORM_INT8);
75     case GL_LUMINANCE_ALPHA:
76         return TextureFormat(TextureFormat::LA, TextureFormat::UNORM_INT8);
77     case GL_RGB:
78         return TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8);
79     case GL_RGBA:
80         return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
81     default:
82         throw tcu::InternalError(string("Can't map GL unsized internal format (") +
83                                  tcu::toHex(internalFormat).toString() + ") to texture format");
84     }
85 }
86 
87 enum
88 {
89     VIEWPORT_WIDTH  = 256,
90     VIEWPORT_HEIGHT = 256
91 };
92 
maxLevelCount(int width,int height)93 static inline int maxLevelCount(int width, int height)
94 {
95     return (int)deLog2Floor32(de::max(width, height)) + 1;
96 }
97 
maxLevelCount(int width,int height,int depth)98 static inline int maxLevelCount(int width, int height, int depth)
99 {
100     return (int)deLog2Floor32(de::max(width, de::max(height, depth))) + 1;
101 }
102 
103 template <int Size>
104 static tcu::Vector<float, Size> randomVector(de::Random &rnd,
105                                              const tcu::Vector<float, Size> &minVal = tcu::Vector<float, Size>(0.0f),
106                                              const tcu::Vector<float, Size> &maxVal = tcu::Vector<float, Size>(1.0f))
107 {
108     tcu::Vector<float, Size> res;
109     for (int ndx = 0; ndx < Size; ndx++)
110         res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]);
111     return res;
112 }
113 
114 static const uint32_t s_cubeMapFaces[] = {
115     GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
116     GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
117 };
118 
getPixelFormatCompareDepth(const tcu::PixelFormat & pixelFormat,tcu::TextureFormat textureFormat)119 static tcu::IVec4 getPixelFormatCompareDepth(const tcu::PixelFormat &pixelFormat, tcu::TextureFormat textureFormat)
120 {
121     switch (textureFormat.order)
122     {
123     case tcu::TextureFormat::L:
124     case tcu::TextureFormat::LA:
125         return tcu::IVec4(pixelFormat.redBits, pixelFormat.redBits, pixelFormat.redBits, pixelFormat.alphaBits);
126     default:
127         return tcu::IVec4(pixelFormat.redBits, pixelFormat.greenBits, pixelFormat.blueBits, pixelFormat.alphaBits);
128     }
129 }
130 
getEffectiveTextureFormatBitDepth(tcu::TextureFormat textureFormat)131 static IVec4 getEffectiveTextureFormatBitDepth(tcu::TextureFormat textureFormat)
132 {
133     if (textureFormat.order == tcu::TextureFormat::DS)
134     {
135         // When sampling depth-stencil texture, we actually sample just
136         // the depth component.
137         return tcu::getTextureFormatBitDepth(
138             tcu::getEffectiveDepthStencilTextureFormat(textureFormat, tcu::Sampler::MODE_DEPTH));
139     }
140     else
141         return tcu::getTextureFormatBitDepth(textureFormat);
142 }
143 
computeCompareThreshold(const tcu::PixelFormat & pixelFormat,tcu::TextureFormat textureFormat)144 static tcu::UVec4 computeCompareThreshold(const tcu::PixelFormat &pixelFormat, tcu::TextureFormat textureFormat)
145 {
146     const IVec4 texFormatBits   = getEffectiveTextureFormatBitDepth(textureFormat);
147     const IVec4 pixelFormatBits = getPixelFormatCompareDepth(pixelFormat, textureFormat);
148     const IVec4 accurateFmtBits = min(pixelFormatBits, texFormatBits);
149     const IVec4 compareBits     = select(accurateFmtBits, IVec4(8), greaterThan(accurateFmtBits, IVec4(0))) - 1;
150 
151     return (IVec4(1) << (8 - compareBits)).asUint();
152 }
153 
154 class TextureSpecCase : public TestCase, public sglr::ContextWrapper
155 {
156 public:
157     TextureSpecCase(Context &context, const char *name, const char *desc);
158     ~TextureSpecCase(void);
159 
160     IterateResult iterate(void);
161 
162 protected:
163     virtual void createTexture(void)                                                              = DE_NULL;
164     virtual void verifyTexture(sglr::GLContext &gles3Context, sglr::ReferenceContext &refContext) = DE_NULL;
165 
166     // Utilities.
167     void renderTex(tcu::Surface &dst, uint32_t program, int width, int height);
168     void readPixels(tcu::Surface &dst, int x, int y, int width, int height);
169 
170 private:
171     TextureSpecCase(const TextureSpecCase &other);
172     TextureSpecCase &operator=(const TextureSpecCase &other);
173 };
174 
TextureSpecCase(Context & context,const char * name,const char * desc)175 TextureSpecCase::TextureSpecCase(Context &context, const char *name, const char *desc) : TestCase(context, name, desc)
176 {
177 }
178 
~TextureSpecCase(void)179 TextureSpecCase::~TextureSpecCase(void)
180 {
181 }
182 
iterate(void)183 TextureSpecCase::IterateResult TextureSpecCase::iterate(void)
184 {
185     glu::RenderContext &renderCtx         = TestCase::m_context.getRenderContext();
186     const tcu::RenderTarget &renderTarget = renderCtx.getRenderTarget();
187     tcu::TestLog &log                     = m_testCtx.getLog();
188 
189     if (renderTarget.getWidth() < VIEWPORT_WIDTH || renderTarget.getHeight() < VIEWPORT_HEIGHT)
190         throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
191 
192     // Context size, and viewport for GLES3
193     de::Random rnd(deStringHash(getName()));
194     int width  = deMin32(renderTarget.getWidth(), VIEWPORT_WIDTH);
195     int height = deMin32(renderTarget.getHeight(), VIEWPORT_HEIGHT);
196     int x      = rnd.getInt(0, renderTarget.getWidth() - width);
197     int y      = rnd.getInt(0, renderTarget.getHeight() - height);
198 
199     // Contexts.
200     sglr::GLContext gles3Context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
201     sglr::ReferenceContextBuffers refBuffers(tcu::PixelFormat(8, 8, 8, renderTarget.getPixelFormat().alphaBits ? 8 : 0),
202                                              0 /* depth */, 0 /* stencil */, width, height);
203     sglr::ReferenceContext refContext(sglr::ReferenceContextLimits(renderCtx), refBuffers.getColorbuffer(),
204                                       refBuffers.getDepthbuffer(), refBuffers.getStencilbuffer());
205 
206     // Clear color buffer.
207     for (int ndx = 0; ndx < 2; ndx++)
208     {
209         setContext(ndx ? (sglr::Context *)&refContext : (sglr::Context *)&gles3Context);
210         glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
211         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
212     }
213 
214     // Construct texture using both GLES3 and reference contexts.
215     for (int ndx = 0; ndx < 2; ndx++)
216     {
217         setContext(ndx ? (sglr::Context *)&refContext : (sglr::Context *)&gles3Context);
218         createTexture();
219         TCU_CHECK(glGetError() == GL_NO_ERROR);
220     }
221 
222     // Initialize case result to pass.
223     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
224 
225     // Disable logging.
226     gles3Context.enableLogging(0);
227 
228     // Verify results.
229     verifyTexture(gles3Context, refContext);
230 
231     return STOP;
232 }
233 
renderTex(tcu::Surface & dst,uint32_t program,int width,int height)234 void TextureSpecCase::renderTex(tcu::Surface &dst, uint32_t program, int width, int height)
235 {
236     int targetW = getWidth();
237     int targetH = getHeight();
238 
239     float w = (float)width / (float)targetW;
240     float h = (float)height / (float)targetH;
241 
242     sglr::drawQuad(*getCurrentContext(), program, tcu::Vec3(-1.0f, -1.0f, 0.0f),
243                    tcu::Vec3(-1.0f + w * 2.0f, -1.0f + h * 2.0f, 0.0f));
244 
245     // Read pixels back.
246     readPixels(dst, 0, 0, width, height);
247 }
248 
readPixels(tcu::Surface & dst,int x,int y,int width,int height)249 void TextureSpecCase::readPixels(tcu::Surface &dst, int x, int y, int width, int height)
250 {
251     dst.setSize(width, height);
252     glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, dst.getAccess().getDataPtr());
253 }
254 
255 class Texture2DSpecCase : public TextureSpecCase
256 {
257 public:
258     Texture2DSpecCase(Context &context, const char *name, const char *desc, const tcu::TextureFormat &format, int width,
259                       int height, int numLevels);
260     ~Texture2DSpecCase(void);
261 
262 protected:
263     virtual void verifyTexture(sglr::GLContext &gles3Context, sglr::ReferenceContext &refContext);
264 
265     tcu::TextureFormat m_texFormat;
266     tcu::TextureFormatInfo m_texFormatInfo;
267     int m_width;
268     int m_height;
269     int m_numLevels;
270 };
271 
Texture2DSpecCase(Context & context,const char * name,const char * desc,const tcu::TextureFormat & format,int width,int height,int numLevels)272 Texture2DSpecCase::Texture2DSpecCase(Context &context, const char *name, const char *desc,
273                                      const tcu::TextureFormat &format, int width, int height, int numLevels)
274     : TextureSpecCase(context, name, desc)
275     , m_texFormat(format)
276     , m_texFormatInfo(tcu::getTextureFormatInfo(format))
277     , m_width(width)
278     , m_height(height)
279     , m_numLevels(numLevels)
280 {
281 }
282 
~Texture2DSpecCase(void)283 Texture2DSpecCase::~Texture2DSpecCase(void)
284 {
285 }
286 
verifyTexture(sglr::GLContext & gles3Context,sglr::ReferenceContext & refContext)287 void Texture2DSpecCase::verifyTexture(sglr::GLContext &gles3Context, sglr::ReferenceContext &refContext)
288 {
289     Texture2DShader shader(DataTypes() << glu::getSampler2DType(m_texFormat), glu::TYPE_FLOAT_VEC4);
290     uint32_t shaderIDgles = gles3Context.createProgram(&shader);
291     uint32_t shaderIDRef  = refContext.createProgram(&shader);
292 
293     shader.setTexScaleBias(0, m_texFormatInfo.lookupScale, m_texFormatInfo.lookupBias);
294 
295     // Set state.
296     for (int ndx = 0; ndx < 2; ndx++)
297     {
298         sglr::Context *ctx =
299             ndx ? static_cast<sglr::Context *>(&refContext) : static_cast<sglr::Context *>(&gles3Context);
300 
301         setContext(ctx);
302 
303         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
304         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
305         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
306         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
307         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, m_numLevels - 1);
308     }
309 
310     for (int levelNdx = 0; levelNdx < m_numLevels; levelNdx++)
311     {
312         int levelW = de::max(1, m_width >> levelNdx);
313         int levelH = de::max(1, m_height >> levelNdx);
314         tcu::Surface reference;
315         tcu::Surface result;
316 
317         for (int ndx = 0; ndx < 2; ndx++)
318         {
319             tcu::Surface &dst = ndx ? reference : result;
320             sglr::Context *ctx =
321                 ndx ? static_cast<sglr::Context *>(&refContext) : static_cast<sglr::Context *>(&gles3Context);
322             uint32_t shaderID = ndx ? shaderIDRef : shaderIDgles;
323 
324             setContext(ctx);
325             shader.setUniforms(*ctx, shaderID);
326             renderTex(dst, shaderID, levelW, levelH);
327         }
328 
329         UVec4 threshold = computeCompareThreshold(m_context.getRenderTarget().getPixelFormat(), m_texFormat);
330         string levelStr = de::toString(levelNdx);
331         string name     = string("Level") + levelStr;
332         string desc     = string("Level ") + levelStr;
333         bool isOk = tcu::intThresholdCompare(m_testCtx.getLog(), name.c_str(), desc.c_str(), reference.getAccess(),
334                                              result.getAccess(), threshold,
335                                              levelNdx == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
336 
337         if (!isOk)
338         {
339             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
340             break;
341         }
342     }
343 }
344 
345 class TextureCubeSpecCase : public TextureSpecCase
346 {
347 public:
348     TextureCubeSpecCase(Context &context, const char *name, const char *desc, const tcu::TextureFormat &format,
349                         int size, int numLevels);
350     ~TextureCubeSpecCase(void);
351 
352 protected:
353     virtual void verifyTexture(sglr::GLContext &gles3Context, sglr::ReferenceContext &refContext);
354 
355     tcu::TextureFormat m_texFormat;
356     tcu::TextureFormatInfo m_texFormatInfo;
357     int m_size;
358     int m_numLevels;
359 };
360 
TextureCubeSpecCase(Context & context,const char * name,const char * desc,const tcu::TextureFormat & format,int size,int numLevels)361 TextureCubeSpecCase::TextureCubeSpecCase(Context &context, const char *name, const char *desc,
362                                          const tcu::TextureFormat &format, int size, int numLevels)
363     : TextureSpecCase(context, name, desc)
364     , m_texFormat(format)
365     , m_texFormatInfo(tcu::getTextureFormatInfo(format))
366     , m_size(size)
367     , m_numLevels(numLevels)
368 {
369 }
370 
~TextureCubeSpecCase(void)371 TextureCubeSpecCase::~TextureCubeSpecCase(void)
372 {
373 }
374 
verifyTexture(sglr::GLContext & gles3Context,sglr::ReferenceContext & refContext)375 void TextureCubeSpecCase::verifyTexture(sglr::GLContext &gles3Context, sglr::ReferenceContext &refContext)
376 {
377     TextureCubeShader shader(glu::getSamplerCubeType(m_texFormat), glu::TYPE_FLOAT_VEC4);
378     uint32_t shaderIDgles = gles3Context.createProgram(&shader);
379     uint32_t shaderIDRef  = refContext.createProgram(&shader);
380 
381     shader.setTexScaleBias(m_texFormatInfo.lookupScale, m_texFormatInfo.lookupBias);
382 
383     // Set state.
384     for (int ndx = 0; ndx < 2; ndx++)
385     {
386         sglr::Context *ctx =
387             ndx ? static_cast<sglr::Context *>(&refContext) : static_cast<sglr::Context *>(&gles3Context);
388 
389         setContext(ctx);
390 
391         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
392         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
393         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
394         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
395         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, m_numLevels - 1);
396     }
397 
398     for (int levelNdx = 0; levelNdx < m_numLevels; levelNdx++)
399     {
400         int levelSize = de::max(1, m_size >> levelNdx);
401         bool isOk     = true;
402 
403         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
404         {
405             tcu::Surface reference;
406             tcu::Surface result;
407 
408             if (levelSize <= 2)
409                 continue; // Fuzzy compare doesn't work for images this small.
410 
411             shader.setFace((tcu::CubeFace)face);
412 
413             for (int ndx = 0; ndx < 2; ndx++)
414             {
415                 tcu::Surface &dst = ndx ? reference : result;
416                 sglr::Context *ctx =
417                     ndx ? static_cast<sglr::Context *>(&refContext) : static_cast<sglr::Context *>(&gles3Context);
418                 uint32_t shaderID = ndx ? shaderIDRef : shaderIDgles;
419 
420                 setContext(ctx);
421                 shader.setUniforms(*ctx, shaderID);
422                 renderTex(dst, shaderID, levelSize, levelSize);
423             }
424 
425             const float threshold = 0.02f;
426             string faceStr        = de::toString((tcu::CubeFace)face);
427             string levelStr       = de::toString(levelNdx);
428             string name           = string("Level") + levelStr;
429             string desc           = string("Level ") + levelStr + ", face " + faceStr;
430             bool isFaceOk =
431                 tcu::fuzzyCompare(m_testCtx.getLog(), name.c_str(), desc.c_str(), reference, result, threshold,
432                                   levelNdx == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
433 
434             if (!isFaceOk)
435             {
436                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
437                 isOk = false;
438                 break;
439             }
440         }
441 
442         if (!isOk)
443             break;
444     }
445 }
446 
447 class Texture2DArraySpecCase : public TextureSpecCase
448 {
449 public:
450     Texture2DArraySpecCase(Context &context, const char *name, const char *desc, const tcu::TextureFormat &format,
451                            int width, int height, int numLayers, int numLevels);
452     ~Texture2DArraySpecCase(void);
453 
454 protected:
455     virtual void verifyTexture(sglr::GLContext &gles3Context, sglr::ReferenceContext &refContext);
456 
457     tcu::TextureFormat m_texFormat;
458     tcu::TextureFormatInfo m_texFormatInfo;
459     int m_width;
460     int m_height;
461     int m_numLayers;
462     int m_numLevels;
463 };
464 
Texture2DArraySpecCase(Context & context,const char * name,const char * desc,const tcu::TextureFormat & format,int width,int height,int numLayers,int numLevels)465 Texture2DArraySpecCase::Texture2DArraySpecCase(Context &context, const char *name, const char *desc,
466                                                const tcu::TextureFormat &format, int width, int height, int numLayers,
467                                                int numLevels)
468     : TextureSpecCase(context, name, desc)
469     , m_texFormat(format)
470     , m_texFormatInfo(tcu::getTextureFormatInfo(format))
471     , m_width(width)
472     , m_height(height)
473     , m_numLayers(numLayers)
474     , m_numLevels(numLevels)
475 {
476 }
477 
~Texture2DArraySpecCase(void)478 Texture2DArraySpecCase::~Texture2DArraySpecCase(void)
479 {
480 }
481 
verifyTexture(sglr::GLContext & gles3Context,sglr::ReferenceContext & refContext)482 void Texture2DArraySpecCase::verifyTexture(sglr::GLContext &gles3Context, sglr::ReferenceContext &refContext)
483 {
484     Texture2DArrayShader shader(glu::getSampler2DArrayType(m_texFormat), glu::TYPE_FLOAT_VEC4);
485     uint32_t shaderIDgles = gles3Context.createProgram(&shader);
486     uint32_t shaderIDRef  = refContext.createProgram(&shader);
487 
488     shader.setTexScaleBias(m_texFormatInfo.lookupScale, m_texFormatInfo.lookupBias);
489 
490     // Set state.
491     for (int ndx = 0; ndx < 2; ndx++)
492     {
493         sglr::Context *ctx =
494             ndx ? static_cast<sglr::Context *>(&refContext) : static_cast<sglr::Context *>(&gles3Context);
495 
496         setContext(ctx);
497 
498         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
499         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
500         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
501         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
502         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
503         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, m_numLevels - 1);
504     }
505 
506     for (int layerNdx = 0; layerNdx < m_numLayers; layerNdx++)
507     {
508         bool layerOk = true;
509 
510         shader.setLayer(layerNdx);
511 
512         for (int levelNdx = 0; levelNdx < m_numLevels; levelNdx++)
513         {
514             int levelW = de::max(1, m_width >> levelNdx);
515             int levelH = de::max(1, m_height >> levelNdx);
516             tcu::Surface reference;
517             tcu::Surface result;
518 
519             for (int ndx = 0; ndx < 2; ndx++)
520             {
521                 tcu::Surface &dst = ndx ? reference : result;
522                 sglr::Context *ctx =
523                     ndx ? static_cast<sglr::Context *>(&refContext) : static_cast<sglr::Context *>(&gles3Context);
524                 uint32_t shaderID = ndx ? shaderIDRef : shaderIDgles;
525 
526                 setContext(ctx);
527                 shader.setUniforms(*ctx, shaderID);
528                 renderTex(dst, shaderID, levelW, levelH);
529             }
530 
531             UVec4 threshold = computeCompareThreshold(m_context.getRenderTarget().getPixelFormat(), m_texFormat);
532             string levelStr = de::toString(levelNdx);
533             string layerStr = de::toString(layerNdx);
534             string name     = string("Layer") + layerStr + "Level" + levelStr;
535             string desc     = string("Layer ") + layerStr + ", Level " + levelStr;
536             bool depthOk    = tcu::intThresholdCompare(
537                 m_testCtx.getLog(), name.c_str(), desc.c_str(), reference.getAccess(), result.getAccess(), threshold,
538                 (levelNdx == 0 && layerNdx == 0) ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
539 
540             if (!depthOk)
541             {
542                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
543                 layerOk = false;
544                 break;
545             }
546         }
547 
548         if (!layerOk)
549             break;
550     }
551 }
552 
553 class Texture3DSpecCase : public TextureSpecCase
554 {
555 public:
556     Texture3DSpecCase(Context &context, const char *name, const char *desc, const tcu::TextureFormat &format, int width,
557                       int height, int depth, int numLevels);
558     ~Texture3DSpecCase(void);
559 
560 protected:
561     virtual void verifyTexture(sglr::GLContext &gles3Context, sglr::ReferenceContext &refContext);
562 
563     tcu::TextureFormat m_texFormat;
564     tcu::TextureFormatInfo m_texFormatInfo;
565     int m_width;
566     int m_height;
567     int m_depth;
568     int m_numLevels;
569 };
570 
Texture3DSpecCase(Context & context,const char * name,const char * desc,const tcu::TextureFormat & format,int width,int height,int depth,int numLevels)571 Texture3DSpecCase::Texture3DSpecCase(Context &context, const char *name, const char *desc,
572                                      const tcu::TextureFormat &format, int width, int height, int depth, int numLevels)
573     : TextureSpecCase(context, name, desc)
574     , m_texFormat(format)
575     , m_texFormatInfo(tcu::getTextureFormatInfo(format))
576     , m_width(width)
577     , m_height(height)
578     , m_depth(depth)
579     , m_numLevels(numLevels)
580 {
581 }
582 
~Texture3DSpecCase(void)583 Texture3DSpecCase::~Texture3DSpecCase(void)
584 {
585 }
586 
verifyTexture(sglr::GLContext & gles3Context,sglr::ReferenceContext & refContext)587 void Texture3DSpecCase::verifyTexture(sglr::GLContext &gles3Context, sglr::ReferenceContext &refContext)
588 {
589     Texture3DShader shader(glu::getSampler3DType(m_texFormat), glu::TYPE_FLOAT_VEC4);
590     uint32_t shaderIDgles = gles3Context.createProgram(&shader);
591     uint32_t shaderIDRef  = refContext.createProgram(&shader);
592 
593     shader.setTexScaleBias(m_texFormatInfo.lookupScale, m_texFormatInfo.lookupBias);
594 
595     // Set state.
596     for (int ndx = 0; ndx < 2; ndx++)
597     {
598         sglr::Context *ctx =
599             ndx ? static_cast<sglr::Context *>(&refContext) : static_cast<sglr::Context *>(&gles3Context);
600 
601         setContext(ctx);
602 
603         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
604         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
605         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
606         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
607         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
608         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, m_numLevels - 1);
609     }
610 
611     for (int levelNdx = 0; levelNdx < m_numLevels; levelNdx++)
612     {
613         int levelW   = de::max(1, m_width >> levelNdx);
614         int levelH   = de::max(1, m_height >> levelNdx);
615         int levelD   = de::max(1, m_depth >> levelNdx);
616         bool levelOk = true;
617 
618         for (int depth = 0; depth < levelD; depth++)
619         {
620             tcu::Surface reference;
621             tcu::Surface result;
622 
623             shader.setDepth(((float)depth + 0.5f) / (float)levelD);
624 
625             for (int ndx = 0; ndx < 2; ndx++)
626             {
627                 tcu::Surface &dst = ndx ? reference : result;
628                 sglr::Context *ctx =
629                     ndx ? static_cast<sglr::Context *>(&refContext) : static_cast<sglr::Context *>(&gles3Context);
630                 uint32_t shaderID = ndx ? shaderIDRef : shaderIDgles;
631 
632                 setContext(ctx);
633                 shader.setUniforms(*ctx, shaderID);
634                 renderTex(dst, shaderID, levelW, levelH);
635             }
636 
637             UVec4 threshold = computeCompareThreshold(m_context.getRenderTarget().getPixelFormat(), m_texFormat);
638             string levelStr = de::toString(levelNdx);
639             string sliceStr = de::toString(depth);
640             string name     = string("Level") + levelStr + "Slice" + sliceStr;
641             string desc     = string("Level ") + levelStr + ", Slice " + sliceStr;
642             bool depthOk    = tcu::intThresholdCompare(
643                 m_testCtx.getLog(), name.c_str(), desc.c_str(), reference.getAccess(), result.getAccess(), threshold,
644                 (levelNdx == 0 && depth == 0) ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
645 
646             if (!depthOk)
647             {
648                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
649                 levelOk = false;
650                 break;
651             }
652         }
653 
654         if (!levelOk)
655             break;
656     }
657 }
658 
659 // Basic TexImage2D() with 2D texture usage
660 class BasicTexImage2DCase : public Texture2DSpecCase
661 {
662 public:
663     // Unsized internal format.
BasicTexImage2DCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int width,int height)664     BasicTexImage2DCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
665                         int width, int height)
666         : Texture2DSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height,
667                             maxLevelCount(width, height))
668         , m_internalFormat(format)
669         , m_format(format)
670         , m_dataType(dataType)
671     {
672     }
673 
674     // Sized internal format.
BasicTexImage2DCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height)675     BasicTexImage2DCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
676                         int height)
677         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height,
678                             maxLevelCount(width, height))
679         , m_internalFormat(internalFormat)
680         , m_format(GL_NONE)
681         , m_dataType(GL_NONE)
682     {
683         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
684         m_format                = fmt.format;
685         m_dataType              = fmt.dataType;
686     }
687 
688 protected:
createTexture(void)689     void createTexture(void)
690     {
691         uint32_t tex = 0;
692         tcu::TextureLevel levelData(glu::mapGLTransferFormat(m_format, m_dataType));
693         de::Random rnd(deStringHash(getName()));
694 
695         glGenTextures(1, &tex);
696         glBindTexture(GL_TEXTURE_2D, tex);
697         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
698 
699         for (int ndx = 0; ndx < m_numLevels; ndx++)
700         {
701             int levelW = de::max(1, m_width >> ndx);
702             int levelH = de::max(1, m_height >> ndx);
703             Vec4 gMin  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
704             Vec4 gMax  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
705 
706             levelData.setSize(levelW, levelH);
707             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
708 
709             glTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, levelW, levelH, 0, m_format, m_dataType,
710                          levelData.getAccess().getDataPtr());
711         }
712     }
713 
714     uint32_t m_internalFormat;
715     uint32_t m_format;
716     uint32_t m_dataType;
717 };
718 
719 // Basic TexImage2D() with cubemap usage
720 class BasicTexImageCubeCase : public TextureCubeSpecCase
721 {
722 public:
723     // Unsized formats.
BasicTexImageCubeCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int size)724     BasicTexImageCubeCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
725                           int size)
726         : TextureCubeSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), size,
727                               deLog2Floor32(size) + 1)
728         , m_internalFormat(format)
729         , m_format(format)
730         , m_dataType(dataType)
731     {
732     }
733 
734     // Sized internal formats.
BasicTexImageCubeCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size)735     BasicTexImageCubeCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int size)
736         : TextureCubeSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), size,
737                               deLog2Floor32(size) + 1)
738         , m_internalFormat(internalFormat)
739         , m_format(GL_NONE)
740         , m_dataType(GL_NONE)
741     {
742         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
743         m_format                = fmt.format;
744         m_dataType              = fmt.dataType;
745     }
746 
747 protected:
createTexture(void)748     void createTexture(void)
749     {
750         uint32_t tex = 0;
751         tcu::TextureLevel levelData(glu::mapGLTransferFormat(m_format, m_dataType));
752         de::Random rnd(deStringHash(getName()));
753 
754         glGenTextures(1, &tex);
755         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
756         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
757 
758         for (int ndx = 0; ndx < m_numLevels; ndx++)
759         {
760             int levelSize = de::max(1, m_size >> ndx);
761 
762             levelData.setSize(levelSize, levelSize);
763 
764             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
765             {
766                 Vec4 gMin = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
767                 Vec4 gMax = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
768 
769                 tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
770 
771                 glTexImage2D(s_cubeMapFaces[face], ndx, m_internalFormat, levelSize, levelSize, 0, m_format, m_dataType,
772                              levelData.getAccess().getDataPtr());
773             }
774         }
775     }
776 
777     uint32_t m_internalFormat;
778     uint32_t m_format;
779     uint32_t m_dataType;
780 };
781 
782 // Basic TexImage3D() with 2D array texture usage
783 class BasicTexImage2DArrayCase : public Texture2DArraySpecCase
784 {
785 public:
BasicTexImage2DArrayCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int numLayers)786     BasicTexImage2DArrayCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
787                              int height, int numLayers)
788         : Texture2DArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height,
789                                  numLayers, maxLevelCount(width, height))
790         , m_internalFormat(internalFormat)
791     {
792     }
793 
794 protected:
createTexture(void)795     void createTexture(void)
796     {
797         uint32_t tex = 0;
798         de::Random rnd(deStringHash(getName()));
799         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
800         tcu::TextureLevel levelData(glu::mapGLTransferFormat(transferFmt.format, transferFmt.dataType));
801 
802         glGenTextures(1, &tex);
803         glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
804         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
805 
806         for (int ndx = 0; ndx < m_numLevels; ndx++)
807         {
808             int levelW = de::max(1, m_width >> ndx);
809             int levelH = de::max(1, m_height >> ndx);
810             Vec4 gMin  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
811             Vec4 gMax  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
812 
813             levelData.setSize(levelW, levelH, m_numLayers);
814             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
815 
816             glTexImage3D(GL_TEXTURE_2D_ARRAY, ndx, m_internalFormat, levelW, levelH, m_numLayers, 0, transferFmt.format,
817                          transferFmt.dataType, levelData.getAccess().getDataPtr());
818         }
819     }
820 
821     uint32_t m_internalFormat;
822 };
823 
824 // Basic TexImage3D() with 3D texture usage
825 class BasicTexImage3DCase : public Texture3DSpecCase
826 {
827 public:
BasicTexImage3DCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int depth)828     BasicTexImage3DCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
829                         int height, int depth)
830         : Texture3DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth,
831                             maxLevelCount(width, height, depth))
832         , m_internalFormat(internalFormat)
833     {
834     }
835 
836 protected:
createTexture(void)837     void createTexture(void)
838     {
839         uint32_t tex = 0;
840         de::Random rnd(deStringHash(getName()));
841         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
842         tcu::TextureLevel levelData(glu::mapGLTransferFormat(transferFmt.format, transferFmt.dataType));
843 
844         glGenTextures(1, &tex);
845         glBindTexture(GL_TEXTURE_3D, tex);
846         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
847 
848         for (int ndx = 0; ndx < m_numLevels; ndx++)
849         {
850             int levelW = de::max(1, m_width >> ndx);
851             int levelH = de::max(1, m_height >> ndx);
852             int levelD = de::max(1, m_depth >> ndx);
853             Vec4 gMin  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
854             Vec4 gMax  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
855 
856             levelData.setSize(levelW, levelH, levelD);
857             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
858 
859             glTexImage3D(GL_TEXTURE_3D, ndx, m_internalFormat, levelW, levelH, levelD, 0, transferFmt.format,
860                          transferFmt.dataType, levelData.getAccess().getDataPtr());
861         }
862     }
863 
864     uint32_t m_internalFormat;
865 };
866 
867 // Randomized 2D texture specification using TexImage2D
868 class RandomOrderTexImage2DCase : public Texture2DSpecCase
869 {
870 public:
RandomOrderTexImage2DCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int width,int height)871     RandomOrderTexImage2DCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
872                               int width, int height)
873         : Texture2DSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height,
874                             maxLevelCount(width, height))
875         , m_internalFormat(format)
876         , m_format(format)
877         , m_dataType(dataType)
878     {
879     }
880 
RandomOrderTexImage2DCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height)881     RandomOrderTexImage2DCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
882                               int height)
883         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height,
884                             maxLevelCount(width, height))
885         , m_internalFormat(internalFormat)
886         , m_format(GL_NONE)
887         , m_dataType(GL_NONE)
888     {
889         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
890         m_format                = fmt.format;
891         m_dataType              = fmt.dataType;
892     }
893 
894 protected:
createTexture(void)895     void createTexture(void)
896     {
897         uint32_t tex = 0;
898         tcu::TextureLevel levelData(glu::mapGLTransferFormat(m_format, m_dataType));
899         de::Random rnd(deStringHash(getName()));
900 
901         glGenTextures(1, &tex);
902         glBindTexture(GL_TEXTURE_2D, tex);
903         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
904 
905         vector<int> levels(m_numLevels);
906 
907         for (int i = 0; i < m_numLevels; i++)
908             levels[i] = i;
909         rnd.shuffle(levels.begin(), levels.end());
910 
911         for (int ndx = 0; ndx < m_numLevels; ndx++)
912         {
913             int levelNdx = levels[ndx];
914             int levelW   = de::max(1, m_width >> levelNdx);
915             int levelH   = de::max(1, m_height >> levelNdx);
916             Vec4 gMin    = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
917             Vec4 gMax    = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
918 
919             levelData.setSize(levelW, levelH);
920             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
921 
922             glTexImage2D(GL_TEXTURE_2D, levelNdx, m_internalFormat, levelW, levelH, 0, m_format, m_dataType,
923                          levelData.getAccess().getDataPtr());
924         }
925     }
926 
927     uint32_t m_internalFormat;
928     uint32_t m_format;
929     uint32_t m_dataType;
930 };
931 
932 // Randomized cubemap texture specification using TexImage2D
933 class RandomOrderTexImageCubeCase : public TextureCubeSpecCase
934 {
935 public:
RandomOrderTexImageCubeCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int size)936     RandomOrderTexImageCubeCase(Context &context, const char *name, const char *desc, uint32_t format,
937                                 uint32_t dataType, int size)
938         : TextureCubeSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), size,
939                               deLog2Floor32(size) + 1)
940         , m_internalFormat(GL_NONE)
941         , m_format(format)
942         , m_dataType(dataType)
943     {
944     }
945 
RandomOrderTexImageCubeCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size)946     RandomOrderTexImageCubeCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int size)
947         : TextureCubeSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), size,
948                               deLog2Floor32(size) + 1)
949         , m_internalFormat(internalFormat)
950         , m_format(GL_NONE)
951         , m_dataType(GL_NONE)
952     {
953         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
954         m_format                = fmt.format;
955         m_dataType              = fmt.dataType;
956     }
957 
958 protected:
createTexture(void)959     void createTexture(void)
960     {
961         uint32_t tex = 0;
962         tcu::TextureLevel levelData(glu::mapGLTransferFormat(m_format, m_dataType));
963         de::Random rnd(deStringHash(getName()));
964 
965         glGenTextures(1, &tex);
966         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
967         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
968 
969         // Level-face pairs.
970         vector<pair<int, tcu::CubeFace>> images(m_numLevels * 6);
971 
972         for (int ndx = 0; ndx < m_numLevels; ndx++)
973             for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
974                 images[ndx * 6 + face] = std::make_pair(ndx, (tcu::CubeFace)face);
975 
976         rnd.shuffle(images.begin(), images.end());
977 
978         for (int ndx = 0; ndx < (int)images.size(); ndx++)
979         {
980             int levelNdx       = images[ndx].first;
981             tcu::CubeFace face = images[ndx].second;
982             int levelSize      = de::max(1, m_size >> levelNdx);
983             Vec4 gMin          = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
984             Vec4 gMax          = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
985 
986             levelData.setSize(levelSize, levelSize);
987             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
988 
989             glTexImage2D(s_cubeMapFaces[face], levelNdx, m_internalFormat, levelSize, levelSize, 0, m_format,
990                          m_dataType, levelData.getAccess().getDataPtr());
991         }
992     }
993 
994     uint32_t m_internalFormat;
995     uint32_t m_format;
996     uint32_t m_dataType;
997 };
998 
999 // TexImage2D() unpack alignment case.
1000 class TexImage2DAlignCase : public Texture2DSpecCase
1001 {
1002 public:
TexImage2DAlignCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int width,int height,int numLevels,int alignment)1003     TexImage2DAlignCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
1004                         int width, int height, int numLevels, int alignment)
1005         : Texture2DSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height, numLevels)
1006         , m_internalFormat(format)
1007         , m_format(format)
1008         , m_dataType(dataType)
1009         , m_alignment(alignment)
1010     {
1011     }
1012 
TexImage2DAlignCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int numLevels,int alignment)1013     TexImage2DAlignCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
1014                         int height, int numLevels, int alignment)
1015         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, numLevels)
1016         , m_internalFormat(internalFormat)
1017         , m_format(GL_NONE)
1018         , m_dataType(GL_NONE)
1019         , m_alignment(alignment)
1020     {
1021         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1022         m_format                = fmt.format;
1023         m_dataType              = fmt.dataType;
1024     }
1025 
1026 protected:
createTexture(void)1027     void createTexture(void)
1028     {
1029         uint32_t tex = 0;
1030         vector<uint8_t> data;
1031 
1032         glGenTextures(1, &tex);
1033         glBindTexture(GL_TEXTURE_2D, tex);
1034         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1035 
1036         for (int ndx = 0; ndx < m_numLevels; ndx++)
1037         {
1038             int levelW  = de::max(1, m_width >> ndx);
1039             int levelH  = de::max(1, m_height >> ndx);
1040             Vec4 colorA = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * (m_texFormatInfo.valueMax - m_texFormatInfo.valueMin) +
1041                           m_texFormatInfo.valueMin;
1042             Vec4 colorB = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * (m_texFormatInfo.valueMax - m_texFormatInfo.valueMin) +
1043                           m_texFormatInfo.valueMin;
1044             int rowPitch = deAlign32(levelW * m_texFormat.getPixelSize(), m_alignment);
1045             int cellSize = de::max(1, de::min(levelW >> 2, levelH >> 2));
1046 
1047             data.resize(rowPitch * levelH);
1048             tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, levelW, levelH, 1, rowPitch, 0, &data[0]), cellSize,
1049                               colorA, colorB);
1050 
1051             glTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, levelW, levelH, 0, m_format, m_dataType, &data[0]);
1052         }
1053     }
1054 
1055     uint32_t m_internalFormat;
1056     uint32_t m_format;
1057     uint32_t m_dataType;
1058     int m_alignment;
1059 };
1060 
1061 // TexImage2D() unpack alignment case.
1062 class TexImageCubeAlignCase : public TextureCubeSpecCase
1063 {
1064 public:
TexImageCubeAlignCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int size,int numLevels,int alignment)1065     TexImageCubeAlignCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
1066                           int size, int numLevels, int alignment)
1067         : TextureCubeSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), size, numLevels)
1068         , m_internalFormat(format)
1069         , m_format(format)
1070         , m_dataType(dataType)
1071         , m_alignment(alignment)
1072     {
1073     }
1074 
TexImageCubeAlignCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size,int numLevels,int alignment)1075     TexImageCubeAlignCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int size,
1076                           int numLevels, int alignment)
1077         : TextureCubeSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, numLevels)
1078         , m_internalFormat(internalFormat)
1079         , m_format(GL_NONE)
1080         , m_dataType(GL_NONE)
1081         , m_alignment(alignment)
1082     {
1083         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1084         m_format                = fmt.format;
1085         m_dataType              = fmt.dataType;
1086     }
1087 
1088 protected:
createTexture(void)1089     void createTexture(void)
1090     {
1091         uint32_t tex = 0;
1092         vector<uint8_t> data;
1093 
1094         glGenTextures(1, &tex);
1095         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1096         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1097 
1098         for (int ndx = 0; ndx < m_numLevels; ndx++)
1099         {
1100             int levelSize = de::max(1, m_size >> ndx);
1101             int rowPitch  = deAlign32(m_texFormat.getPixelSize() * levelSize, m_alignment);
1102             Vec4 colorA   = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * (m_texFormatInfo.valueMax - m_texFormatInfo.valueMin) +
1103                           m_texFormatInfo.valueMin;
1104             Vec4 colorB = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * (m_texFormatInfo.valueMax - m_texFormatInfo.valueMin) +
1105                           m_texFormatInfo.valueMin;
1106             int cellSize = de::max(1, levelSize >> 2);
1107 
1108             data.resize(rowPitch * levelSize);
1109             tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, levelSize, levelSize, 1, rowPitch, 0, &data[0]),
1110                               cellSize, colorA, colorB);
1111 
1112             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1113                 glTexImage2D(s_cubeMapFaces[face], ndx, m_internalFormat, levelSize, levelSize, 0, m_format, m_dataType,
1114                              &data[0]);
1115         }
1116     }
1117 
1118     uint32_t m_internalFormat;
1119     uint32_t m_format;
1120     uint32_t m_dataType;
1121     int m_alignment;
1122 };
1123 
1124 // TexImage2D() unpack parameters case.
1125 class TexImage2DParamsCase : public Texture2DSpecCase
1126 {
1127 public:
TexImage2DParamsCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int rowLength,int skipRows,int skipPixels,int alignment)1128     TexImage2DParamsCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
1129                          int height, int rowLength, int skipRows, int skipPixels, int alignment)
1130         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, 1)
1131         , m_internalFormat(internalFormat)
1132         , m_rowLength(rowLength)
1133         , m_skipRows(skipRows)
1134         , m_skipPixels(skipPixels)
1135         , m_alignment(alignment)
1136     {
1137     }
1138 
1139 protected:
createTexture(void)1140     void createTexture(void)
1141     {
1142         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
1143         int pixelSize                   = m_texFormat.getPixelSize();
1144         int rowLength                   = m_rowLength > 0 ? m_rowLength : m_width;
1145         int rowPitch                    = deAlign32(rowLength * pixelSize, m_alignment);
1146         uint32_t tex                    = 0;
1147         vector<uint8_t> data;
1148 
1149         DE_ASSERT(m_numLevels == 1);
1150 
1151         // Fill data with grid.
1152         data.resize(pixelSize * m_skipPixels + rowPitch * (m_height + m_skipRows));
1153         {
1154             Vec4 cScale = m_texFormatInfo.valueMax - m_texFormatInfo.valueMin;
1155             Vec4 cBias  = m_texFormatInfo.valueMin;
1156             Vec4 colorA = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
1157             Vec4 colorB = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias;
1158 
1159             tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, 1, rowPitch, 0,
1160                                                      &data[0] + m_skipRows * rowPitch + m_skipPixels * pixelSize),
1161                               4, colorA, colorB);
1162         }
1163 
1164         glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
1165         glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
1166         glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
1167         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1168 
1169         glGenTextures(1, &tex);
1170         glBindTexture(GL_TEXTURE_2D, tex);
1171         glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFmt.format, transferFmt.dataType,
1172                      &data[0]);
1173     }
1174 
1175     uint32_t m_internalFormat;
1176     int m_rowLength;
1177     int m_skipRows;
1178     int m_skipPixels;
1179     int m_alignment;
1180 };
1181 
1182 // TexImage3D() unpack parameters case.
1183 class TexImage3DParamsCase : public Texture3DSpecCase
1184 {
1185 public:
TexImage3DParamsCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int depth,int imageHeight,int rowLength,int skipImages,int skipRows,int skipPixels,int alignment)1186     TexImage3DParamsCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
1187                          int height, int depth, int imageHeight, int rowLength, int skipImages, int skipRows,
1188                          int skipPixels, int alignment)
1189         : Texture3DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, 1)
1190         , m_internalFormat(internalFormat)
1191         , m_imageHeight(imageHeight)
1192         , m_rowLength(rowLength)
1193         , m_skipImages(skipImages)
1194         , m_skipRows(skipRows)
1195         , m_skipPixels(skipPixels)
1196         , m_alignment(alignment)
1197     {
1198     }
1199 
1200 protected:
createTexture(void)1201     void createTexture(void)
1202     {
1203         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
1204         int pixelSize                   = m_texFormat.getPixelSize();
1205         int rowLength                   = m_rowLength > 0 ? m_rowLength : m_width;
1206         int rowPitch                    = deAlign32(rowLength * pixelSize, m_alignment);
1207         int imageHeight                 = m_imageHeight > 0 ? m_imageHeight : m_height;
1208         int slicePitch                  = imageHeight * rowPitch;
1209         uint32_t tex                    = 0;
1210         vector<uint8_t> data;
1211 
1212         DE_ASSERT(m_numLevels == 1);
1213 
1214         // Fill data with grid.
1215         data.resize(pixelSize * m_skipPixels + rowPitch * m_skipRows + slicePitch * (m_skipImages + m_depth));
1216         {
1217             Vec4 cScale = m_texFormatInfo.valueMax - m_texFormatInfo.valueMin;
1218             Vec4 cBias  = m_texFormatInfo.valueMin;
1219             Vec4 colorA = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
1220             Vec4 colorB = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias;
1221 
1222             tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_depth, rowPitch, slicePitch,
1223                                                      &data[0] + m_skipImages * slicePitch + m_skipRows * rowPitch +
1224                                                          m_skipPixels * pixelSize),
1225                               4, colorA, colorB);
1226         }
1227 
1228         glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, m_imageHeight);
1229         glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
1230         glPixelStorei(GL_UNPACK_SKIP_IMAGES, m_skipImages);
1231         glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
1232         glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
1233         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1234 
1235         glGenTextures(1, &tex);
1236         glBindTexture(GL_TEXTURE_3D, tex);
1237         glTexImage3D(GL_TEXTURE_3D, 0, m_internalFormat, m_width, m_height, m_depth, 0, transferFmt.format,
1238                      transferFmt.dataType, &data[0]);
1239     }
1240 
1241     uint32_t m_internalFormat;
1242     int m_imageHeight;
1243     int m_rowLength;
1244     int m_skipImages;
1245     int m_skipRows;
1246     int m_skipPixels;
1247     int m_alignment;
1248 };
1249 
1250 // Basic TexSubImage2D() with 2D texture usage
1251 class BasicTexSubImage2DCase : public Texture2DSpecCase
1252 {
1253 public:
BasicTexSubImage2DCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int width,int height)1254     BasicTexSubImage2DCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
1255                            int width, int height)
1256         : Texture2DSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height,
1257                             maxLevelCount(width, height))
1258         , m_internalFormat(format)
1259         , m_format(format)
1260         , m_dataType(dataType)
1261     {
1262     }
1263 
BasicTexSubImage2DCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height)1264     BasicTexSubImage2DCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
1265                            int height)
1266         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height,
1267                             maxLevelCount(width, height))
1268         , m_internalFormat(internalFormat)
1269         , m_format(GL_NONE)
1270         , m_dataType(GL_NONE)
1271     {
1272         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1273         m_format                = fmt.format;
1274         m_dataType              = fmt.dataType;
1275     }
1276 
1277 protected:
createTexture(void)1278     void createTexture(void)
1279     {
1280         uint32_t tex = 0;
1281         tcu::TextureLevel data(m_texFormat);
1282         de::Random rnd(deStringHash(getName()));
1283 
1284         glGenTextures(1, &tex);
1285         glBindTexture(GL_TEXTURE_2D, tex);
1286         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1287 
1288         // First specify full texture.
1289         for (int ndx = 0; ndx < m_numLevels; ndx++)
1290         {
1291             int levelW = de::max(1, m_width >> ndx);
1292             int levelH = de::max(1, m_height >> ndx);
1293             Vec4 gMin  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1294             Vec4 gMax  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1295 
1296             data.setSize(levelW, levelH);
1297             tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1298 
1299             glTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, levelW, levelH, 0, m_format, m_dataType,
1300                          data.getAccess().getDataPtr());
1301         }
1302 
1303         // Re-specify parts of each level.
1304         for (int ndx = 0; ndx < m_numLevels; ndx++)
1305         {
1306             int levelW = de::max(1, m_width >> ndx);
1307             int levelH = de::max(1, m_height >> ndx);
1308 
1309             int w = rnd.getInt(1, levelW);
1310             int h = rnd.getInt(1, levelH);
1311             int x = rnd.getInt(0, levelW - w);
1312             int y = rnd.getInt(0, levelH - h);
1313 
1314             Vec4 colorA  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1315             Vec4 colorB  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1316             int cellSize = rnd.getInt(2, 16);
1317 
1318             data.setSize(w, h);
1319             tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
1320 
1321             glTexSubImage2D(GL_TEXTURE_2D, ndx, x, y, w, h, m_format, m_dataType, data.getAccess().getDataPtr());
1322         }
1323     }
1324 
1325     uint32_t m_internalFormat;
1326     uint32_t m_format;
1327     uint32_t m_dataType;
1328 };
1329 
1330 // Basic TexSubImage2D() with cubemap usage
1331 class BasicTexSubImageCubeCase : public TextureCubeSpecCase
1332 {
1333 public:
BasicTexSubImageCubeCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int size)1334     BasicTexSubImageCubeCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
1335                              int size)
1336         : TextureCubeSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), size,
1337                               deLog2Floor32(size) + 1)
1338         , m_internalFormat(format)
1339         , m_format(format)
1340         , m_dataType(dataType)
1341     {
1342     }
1343 
BasicTexSubImageCubeCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size)1344     BasicTexSubImageCubeCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int size)
1345         : TextureCubeSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), size,
1346                               deLog2Floor32(size) + 1)
1347         , m_internalFormat(internalFormat)
1348         , m_format(GL_NONE)
1349         , m_dataType(GL_NONE)
1350     {
1351         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1352         m_format                = fmt.format;
1353         m_dataType              = fmt.dataType;
1354     }
1355 
1356 protected:
createTexture(void)1357     void createTexture(void)
1358     {
1359         uint32_t tex = 0;
1360         tcu::TextureLevel data(m_texFormat);
1361         de::Random rnd(deStringHash(getName()));
1362 
1363         glGenTextures(1, &tex);
1364         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1365         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1366 
1367         for (int ndx = 0; ndx < m_numLevels; ndx++)
1368         {
1369             int levelSize = de::max(1, m_size >> ndx);
1370 
1371             data.setSize(levelSize, levelSize);
1372 
1373             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1374             {
1375                 Vec4 gMin = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1376                 Vec4 gMax = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1377 
1378                 tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1379 
1380                 glTexImage2D(s_cubeMapFaces[face], ndx, m_internalFormat, levelSize, levelSize, 0, m_format, m_dataType,
1381                              data.getAccess().getDataPtr());
1382             }
1383         }
1384 
1385         // Re-specify parts of each face and level.
1386         for (int ndx = 0; ndx < m_numLevels; ndx++)
1387         {
1388             int levelSize = de::max(1, m_size >> ndx);
1389 
1390             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1391             {
1392                 int w = rnd.getInt(1, levelSize);
1393                 int h = rnd.getInt(1, levelSize);
1394                 int x = rnd.getInt(0, levelSize - w);
1395                 int y = rnd.getInt(0, levelSize - h);
1396 
1397                 Vec4 colorA  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1398                 Vec4 colorB  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1399                 int cellSize = rnd.getInt(2, 16);
1400 
1401                 data.setSize(w, h);
1402                 tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
1403 
1404                 glTexSubImage2D(s_cubeMapFaces[face], ndx, x, y, w, h, m_format, m_dataType,
1405                                 data.getAccess().getDataPtr());
1406             }
1407         }
1408     }
1409 
1410     uint32_t m_internalFormat;
1411     uint32_t m_format;
1412     uint32_t m_dataType;
1413 };
1414 
1415 // TexSubImage2D() unpack parameters case.
1416 class TexSubImage2DParamsCase : public Texture2DSpecCase
1417 {
1418 public:
TexSubImage2DParamsCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int subX,int subY,int subW,int subH,int rowLength,int skipRows,int skipPixels,int alignment)1419     TexSubImage2DParamsCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
1420                             int height, int subX, int subY, int subW, int subH, int rowLength, int skipRows,
1421                             int skipPixels, int alignment)
1422         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, 1)
1423         , m_internalFormat(internalFormat)
1424         , m_subX(subX)
1425         , m_subY(subY)
1426         , m_subW(subW)
1427         , m_subH(subH)
1428         , m_rowLength(rowLength)
1429         , m_skipRows(skipRows)
1430         , m_skipPixels(skipPixels)
1431         , m_alignment(alignment)
1432     {
1433     }
1434 
1435 protected:
createTexture(void)1436     void createTexture(void)
1437     {
1438         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
1439         int pixelSize                   = m_texFormat.getPixelSize();
1440         uint32_t tex                    = 0;
1441         vector<uint8_t> data;
1442 
1443         DE_ASSERT(m_numLevels == 1);
1444 
1445         glGenTextures(1, &tex);
1446         glBindTexture(GL_TEXTURE_2D, tex);
1447 
1448         // First fill texture with gradient.
1449         data.resize(deAlign32(m_width * pixelSize, 4) * m_height);
1450         tcu::fillWithComponentGradients(
1451             tcu::PixelBufferAccess(m_texFormat, m_width, m_height, 1, deAlign32(m_width * pixelSize, 4), 0, &data[0]),
1452             m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1453         glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFmt.format, transferFmt.dataType,
1454                      &data[0]);
1455 
1456         // Fill data with grid.
1457         {
1458             int rowLength = m_rowLength > 0 ? m_rowLength : m_subW;
1459             int rowPitch  = deAlign32(rowLength * pixelSize, m_alignment);
1460             int height    = m_subH + m_skipRows;
1461             Vec4 cScale   = m_texFormatInfo.valueMax - m_texFormatInfo.valueMin;
1462             Vec4 cBias    = m_texFormatInfo.valueMin;
1463             Vec4 colorA   = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
1464             Vec4 colorB   = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias;
1465 
1466             data.resize(rowPitch * height);
1467             tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, 1, rowPitch, 0,
1468                                                      &data[0] + m_skipRows * rowPitch + m_skipPixels * pixelSize),
1469                               4, colorA, colorB);
1470         }
1471 
1472         glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
1473         glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
1474         glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
1475         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1476         glTexSubImage2D(GL_TEXTURE_2D, 0, m_subX, m_subY, m_subW, m_subH, transferFmt.format, transferFmt.dataType,
1477                         &data[0]);
1478     }
1479 
1480     uint32_t m_internalFormat;
1481     int m_subX;
1482     int m_subY;
1483     int m_subW;
1484     int m_subH;
1485     int m_rowLength;
1486     int m_skipRows;
1487     int m_skipPixels;
1488     int m_alignment;
1489 };
1490 
1491 // Basic TexSubImage3D() with 3D texture usage
1492 class BasicTexSubImage3DCase : public Texture3DSpecCase
1493 {
1494 public:
BasicTexSubImage3DCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int depth)1495     BasicTexSubImage3DCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
1496                            int height, int depth)
1497         : Texture3DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth,
1498                             maxLevelCount(width, height, depth))
1499         , m_internalFormat(internalFormat)
1500     {
1501     }
1502 
1503 protected:
createTexture(void)1504     void createTexture(void)
1505     {
1506         uint32_t tex = 0;
1507         tcu::TextureLevel data(m_texFormat);
1508         de::Random rnd(deStringHash(getName()));
1509         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
1510 
1511         glGenTextures(1, &tex);
1512         glBindTexture(GL_TEXTURE_3D, tex);
1513         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1514 
1515         // First specify full texture.
1516         for (int ndx = 0; ndx < m_numLevels; ndx++)
1517         {
1518             int levelW = de::max(1, m_width >> ndx);
1519             int levelH = de::max(1, m_height >> ndx);
1520             int levelD = de::max(1, m_depth >> ndx);
1521             Vec4 gMin  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1522             Vec4 gMax  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1523 
1524             data.setSize(levelW, levelH, levelD);
1525             tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1526 
1527             glTexImage3D(GL_TEXTURE_3D, ndx, m_internalFormat, levelW, levelH, levelD, 0, transferFmt.format,
1528                          transferFmt.dataType, data.getAccess().getDataPtr());
1529         }
1530 
1531         // Re-specify parts of each level.
1532         for (int ndx = 0; ndx < m_numLevels; ndx++)
1533         {
1534             int levelW = de::max(1, m_width >> ndx);
1535             int levelH = de::max(1, m_height >> ndx);
1536             int levelD = de::max(1, m_depth >> ndx);
1537 
1538             int w = rnd.getInt(1, levelW);
1539             int h = rnd.getInt(1, levelH);
1540             int d = rnd.getInt(1, levelD);
1541             int x = rnd.getInt(0, levelW - w);
1542             int y = rnd.getInt(0, levelH - h);
1543             int z = rnd.getInt(0, levelD - d);
1544 
1545             Vec4 colorA  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1546             Vec4 colorB  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1547             int cellSize = rnd.getInt(2, 16);
1548 
1549             data.setSize(w, h, d);
1550             tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
1551 
1552             glTexSubImage3D(GL_TEXTURE_3D, ndx, x, y, z, w, h, d, transferFmt.format, transferFmt.dataType,
1553                             data.getAccess().getDataPtr());
1554         }
1555     }
1556 
1557     uint32_t m_internalFormat;
1558 };
1559 
1560 // TexSubImage2D() to texture initialized with empty data
1561 class TexSubImage2DEmptyTexCase : public Texture2DSpecCase
1562 {
1563 public:
TexSubImage2DEmptyTexCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int width,int height)1564     TexSubImage2DEmptyTexCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
1565                               int width, int height)
1566         : Texture2DSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height,
1567                             maxLevelCount(width, height))
1568         , m_internalFormat(format)
1569         , m_format(format)
1570         , m_dataType(dataType)
1571     {
1572     }
1573 
TexSubImage2DEmptyTexCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height)1574     TexSubImage2DEmptyTexCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
1575                               int height)
1576         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height,
1577                             maxLevelCount(width, height))
1578         , m_internalFormat(internalFormat)
1579         , m_format(GL_NONE)
1580         , m_dataType(GL_NONE)
1581     {
1582         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1583         m_format                = fmt.format;
1584         m_dataType              = fmt.dataType;
1585     }
1586 
1587 protected:
createTexture(void)1588     void createTexture(void)
1589     {
1590         uint32_t tex = 0;
1591         tcu::TextureLevel data(m_texFormat);
1592         de::Random rnd(deStringHash(getName()));
1593 
1594         glGenTextures(1, &tex);
1595         glBindTexture(GL_TEXTURE_2D, tex);
1596         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1597 
1598         // First allocate storage for each level.
1599         for (int ndx = 0; ndx < m_numLevels; ndx++)
1600         {
1601             int levelW = de::max(1, m_width >> ndx);
1602             int levelH = de::max(1, m_height >> ndx);
1603 
1604             glTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, levelW, levelH, 0, m_format, m_dataType, DE_NULL);
1605         }
1606 
1607         // Specify pixel data to all levels using glTexSubImage2D()
1608         for (int ndx = 0; ndx < m_numLevels; ndx++)
1609         {
1610             int levelW = de::max(1, m_width >> ndx);
1611             int levelH = de::max(1, m_height >> ndx);
1612             Vec4 gMin  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1613             Vec4 gMax  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1614 
1615             data.setSize(levelW, levelH);
1616             tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1617 
1618             glTexSubImage2D(GL_TEXTURE_2D, ndx, 0, 0, levelW, levelH, m_format, m_dataType,
1619                             data.getAccess().getDataPtr());
1620         }
1621     }
1622 
1623     uint32_t m_internalFormat;
1624     uint32_t m_format;
1625     uint32_t m_dataType;
1626 };
1627 
1628 // TexSubImage2D() to empty cubemap texture
1629 class TexSubImageCubeEmptyTexCase : public TextureCubeSpecCase
1630 {
1631 public:
TexSubImageCubeEmptyTexCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int size)1632     TexSubImageCubeEmptyTexCase(Context &context, const char *name, const char *desc, uint32_t format,
1633                                 uint32_t dataType, int size)
1634         : TextureCubeSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), size,
1635                               deLog2Floor32(size) + 1)
1636         , m_internalFormat(format)
1637         , m_format(format)
1638         , m_dataType(dataType)
1639     {
1640     }
1641 
TexSubImageCubeEmptyTexCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size)1642     TexSubImageCubeEmptyTexCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int size)
1643         : TextureCubeSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), size,
1644                               deLog2Floor32(size) + 1)
1645         , m_internalFormat(internalFormat)
1646         , m_format(GL_NONE)
1647         , m_dataType(GL_NONE)
1648     {
1649         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1650         m_format                = fmt.format;
1651         m_dataType              = fmt.dataType;
1652     }
1653 
1654 protected:
createTexture(void)1655     void createTexture(void)
1656     {
1657         uint32_t tex = 0;
1658         tcu::TextureLevel data(m_texFormat);
1659         de::Random rnd(deStringHash(getName()));
1660 
1661         glGenTextures(1, &tex);
1662         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1663         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1664 
1665         // Specify storage for each level.
1666         for (int ndx = 0; ndx < m_numLevels; ndx++)
1667         {
1668             int levelSize = de::max(1, m_size >> ndx);
1669 
1670             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1671                 glTexImage2D(s_cubeMapFaces[face], ndx, m_internalFormat, levelSize, levelSize, 0, m_format, m_dataType,
1672                              DE_NULL);
1673         }
1674 
1675         // Specify data using glTexSubImage2D()
1676         for (int ndx = 0; ndx < m_numLevels; ndx++)
1677         {
1678             int levelSize = de::max(1, m_size >> ndx);
1679 
1680             data.setSize(levelSize, levelSize);
1681 
1682             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1683             {
1684                 Vec4 gMin = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1685                 Vec4 gMax = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1686 
1687                 tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1688 
1689                 glTexSubImage2D(s_cubeMapFaces[face], ndx, 0, 0, levelSize, levelSize, m_format, m_dataType,
1690                                 data.getAccess().getDataPtr());
1691             }
1692         }
1693     }
1694 
1695     uint32_t m_internalFormat;
1696     uint32_t m_format;
1697     uint32_t m_dataType;
1698 };
1699 
1700 // TexSubImage2D() unpack alignment with 2D texture
1701 class TexSubImage2DAlignCase : public Texture2DSpecCase
1702 {
1703 public:
TexSubImage2DAlignCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int width,int height,int subX,int subY,int subW,int subH,int alignment)1704     TexSubImage2DAlignCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
1705                            int width, int height, int subX, int subY, int subW, int subH, int alignment)
1706         : Texture2DSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height, 1)
1707         , m_internalFormat(format)
1708         , m_format(format)
1709         , m_dataType(dataType)
1710         , m_subX(subX)
1711         , m_subY(subY)
1712         , m_subW(subW)
1713         , m_subH(subH)
1714         , m_alignment(alignment)
1715     {
1716     }
1717 
TexSubImage2DAlignCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int subX,int subY,int subW,int subH,int alignment)1718     TexSubImage2DAlignCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
1719                            int height, int subX, int subY, int subW, int subH, int alignment)
1720         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, 1)
1721         , m_internalFormat(internalFormat)
1722         , m_format(GL_NONE)
1723         , m_dataType(GL_NONE)
1724         , m_subX(subX)
1725         , m_subY(subY)
1726         , m_subW(subW)
1727         , m_subH(subH)
1728         , m_alignment(alignment)
1729     {
1730         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1731         m_format                = fmt.format;
1732         m_dataType              = fmt.dataType;
1733     }
1734 
1735 protected:
createTexture(void)1736     void createTexture(void)
1737     {
1738         uint32_t tex = 0;
1739         vector<uint8_t> data;
1740 
1741         glGenTextures(1, &tex);
1742         glBindTexture(GL_TEXTURE_2D, tex);
1743 
1744         // Specify base level.
1745         data.resize(m_texFormat.getPixelSize() * m_width * m_height);
1746         tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, 1, &data[0]), Vec4(0.0f),
1747                                         Vec4(1.0f));
1748 
1749         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1750         glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, m_format, m_dataType, &data[0]);
1751 
1752         // Re-specify subrectangle.
1753         int rowPitch = deAlign32(m_texFormat.getPixelSize() * m_subW, m_alignment);
1754         data.resize(rowPitch * m_subH);
1755         tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, 1, rowPitch, 0, &data[0]), 4,
1756                           Vec4(1.0f, 0.0f, 0.0f, 1.0f), Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1757 
1758         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1759         glTexSubImage2D(GL_TEXTURE_2D, 0, m_subX, m_subY, m_subW, m_subH, m_format, m_dataType, &data[0]);
1760     }
1761 
1762     uint32_t m_internalFormat;
1763     uint32_t m_format;
1764     uint32_t m_dataType;
1765     int m_subX;
1766     int m_subY;
1767     int m_subW;
1768     int m_subH;
1769     int m_alignment;
1770 };
1771 
1772 // TexSubImage2D() unpack alignment with cubemap texture
1773 class TexSubImageCubeAlignCase : public TextureCubeSpecCase
1774 {
1775 public:
TexSubImageCubeAlignCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int size,int subX,int subY,int subW,int subH,int alignment)1776     TexSubImageCubeAlignCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
1777                              int size, int subX, int subY, int subW, int subH, int alignment)
1778         : TextureCubeSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), size, 1)
1779         , m_internalFormat(format)
1780         , m_format(format)
1781         , m_dataType(dataType)
1782         , m_subX(subX)
1783         , m_subY(subY)
1784         , m_subW(subW)
1785         , m_subH(subH)
1786         , m_alignment(alignment)
1787     {
1788     }
1789 
TexSubImageCubeAlignCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size,int subX,int subY,int subW,int subH,int alignment)1790     TexSubImageCubeAlignCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int size,
1791                              int subX, int subY, int subW, int subH, int alignment)
1792         : TextureCubeSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, 1)
1793         , m_internalFormat(internalFormat)
1794         , m_format(GL_NONE)
1795         , m_dataType(GL_NONE)
1796         , m_subX(subX)
1797         , m_subY(subY)
1798         , m_subW(subW)
1799         , m_subH(subH)
1800         , m_alignment(alignment)
1801     {
1802         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1803         m_format                = fmt.format;
1804         m_dataType              = fmt.dataType;
1805     }
1806 
1807 protected:
createTexture(void)1808     void createTexture(void)
1809     {
1810         uint32_t tex = 0;
1811         vector<uint8_t> data;
1812 
1813         glGenTextures(1, &tex);
1814         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1815 
1816         // Specify base level.
1817         data.resize(m_texFormat.getPixelSize() * m_size * m_size);
1818         tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_size, m_size, 1, &data[0]), Vec4(0.0f),
1819                                         Vec4(1.0f));
1820 
1821         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1822         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1823             glTexImage2D(s_cubeMapFaces[face], 0, m_internalFormat, m_size, m_size, 0, m_format, m_dataType, &data[0]);
1824 
1825         // Re-specify subrectangle.
1826         int rowPitch = deAlign32(m_texFormat.getPixelSize() * m_subW, m_alignment);
1827         data.resize(rowPitch * m_subH);
1828         tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, 1, rowPitch, 0, &data[0]), 4,
1829                           Vec4(1.0f, 0.0f, 0.0f, 1.0f), Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1830 
1831         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1832         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1833             glTexSubImage2D(s_cubeMapFaces[face], 0, m_subX, m_subY, m_subW, m_subH, m_format, m_dataType, &data[0]);
1834     }
1835 
1836     uint32_t m_internalFormat;
1837     uint32_t m_format;
1838     uint32_t m_dataType;
1839     int m_subX;
1840     int m_subY;
1841     int m_subW;
1842     int m_subH;
1843     int m_alignment;
1844 };
1845 
1846 // TexSubImage3D() unpack parameters case.
1847 class TexSubImage3DParamsCase : public Texture3DSpecCase
1848 {
1849 public:
TexSubImage3DParamsCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,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)1850     TexSubImage3DParamsCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
1851                             int height, int depth, int subX, int subY, int subZ, int subW, int subH, int subD,
1852                             int imageHeight, int rowLength, int skipImages, int skipRows, int skipPixels, int alignment)
1853         : Texture3DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, 1)
1854         , m_internalFormat(internalFormat)
1855         , m_subX(subX)
1856         , m_subY(subY)
1857         , m_subZ(subZ)
1858         , m_subW(subW)
1859         , m_subH(subH)
1860         , m_subD(subD)
1861         , m_imageHeight(imageHeight)
1862         , m_rowLength(rowLength)
1863         , m_skipImages(skipImages)
1864         , m_skipRows(skipRows)
1865         , m_skipPixels(skipPixels)
1866         , m_alignment(alignment)
1867     {
1868     }
1869 
1870 protected:
createTexture(void)1871     void createTexture(void)
1872     {
1873         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
1874         int pixelSize                   = m_texFormat.getPixelSize();
1875         uint32_t tex                    = 0;
1876         vector<uint8_t> data;
1877 
1878         DE_ASSERT(m_numLevels == 1);
1879 
1880         glGenTextures(1, &tex);
1881         glBindTexture(GL_TEXTURE_3D, tex);
1882 
1883         // Fill with gradient.
1884         {
1885             int rowPitch   = deAlign32(pixelSize * m_width, 4);
1886             int slicePitch = rowPitch * m_height;
1887 
1888             data.resize(slicePitch * m_depth);
1889             tcu::fillWithComponentGradients(
1890                 tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_depth, rowPitch, slicePitch, &data[0]),
1891                 m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1892         }
1893 
1894         glTexImage3D(GL_TEXTURE_3D, 0, m_internalFormat, m_width, m_height, m_depth, 0, transferFmt.format,
1895                      transferFmt.dataType, &data[0]);
1896 
1897         // Fill data with grid.
1898         {
1899             int rowLength   = m_rowLength > 0 ? m_rowLength : m_subW;
1900             int rowPitch    = deAlign32(rowLength * pixelSize, m_alignment);
1901             int imageHeight = m_imageHeight > 0 ? m_imageHeight : m_subH;
1902             int slicePitch  = imageHeight * rowPitch;
1903             Vec4 cScale     = m_texFormatInfo.valueMax - m_texFormatInfo.valueMin;
1904             Vec4 cBias      = m_texFormatInfo.valueMin;
1905             Vec4 colorA     = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
1906             Vec4 colorB     = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias;
1907 
1908             data.resize(slicePitch * (m_depth + m_skipImages));
1909             tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, m_subD, rowPitch, slicePitch,
1910                                                      &data[0] + m_skipImages * slicePitch + m_skipRows * rowPitch +
1911                                                          m_skipPixels * pixelSize),
1912                               4, colorA, colorB);
1913         }
1914 
1915         glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, m_imageHeight);
1916         glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
1917         glPixelStorei(GL_UNPACK_SKIP_IMAGES, m_skipImages);
1918         glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
1919         glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
1920         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1921         glTexSubImage3D(GL_TEXTURE_3D, 0, m_subX, m_subY, m_subZ, m_subW, m_subH, m_subD, transferFmt.format,
1922                         transferFmt.dataType, &data[0]);
1923     }
1924 
1925     uint32_t m_internalFormat;
1926     int m_subX;
1927     int m_subY;
1928     int m_subZ;
1929     int m_subW;
1930     int m_subH;
1931     int m_subD;
1932     int m_imageHeight;
1933     int m_rowLength;
1934     int m_skipImages;
1935     int m_skipRows;
1936     int m_skipPixels;
1937     int m_alignment;
1938 };
1939 
1940 // Basic CopyTexImage2D() with 2D texture usage
1941 class BasicCopyTexImage2DCase : public Texture2DSpecCase
1942 {
1943 public:
BasicCopyTexImage2DCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height)1944     BasicCopyTexImage2DCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
1945                             int height)
1946         : Texture2DSpecCase(context, name, desc, glu::mapGLTransferFormat(internalFormat, GL_UNSIGNED_BYTE), width,
1947                             height, maxLevelCount(width, height))
1948         , m_internalFormat(internalFormat)
1949     {
1950     }
1951 
1952 protected:
createTexture(void)1953     void createTexture(void)
1954     {
1955         const tcu::RenderTarget &renderTarget = TestCase::m_context.getRenderContext().getRenderTarget();
1956         bool targetHasRGB = renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 &&
1957                             renderTarget.getPixelFormat().blueBits > 0;
1958         bool targetHasAlpha    = renderTarget.getPixelFormat().alphaBits > 0;
1959         tcu::TextureFormat fmt = mapGLUnsizedInternalFormat(m_internalFormat);
1960         bool texHasRGB         = fmt.order != tcu::TextureFormat::A;
1961         bool texHasAlpha       = fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA ||
1962                            fmt.order == tcu::TextureFormat::A;
1963         uint32_t tex = 0;
1964         de::Random rnd(deStringHash(getName()));
1965         GradientShader shader(glu::TYPE_FLOAT_VEC4);
1966         uint32_t shaderID = getCurrentContext()->createProgram(&shader);
1967 
1968         if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
1969             throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
1970 
1971         // Fill render target with gradient.
1972         shader.setGradient(*getCurrentContext(), shaderID, Vec4(0.0f), Vec4(1.0f));
1973         sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
1974 
1975         glGenTextures(1, &tex);
1976         glBindTexture(GL_TEXTURE_2D, tex);
1977 
1978         for (int ndx = 0; ndx < m_numLevels; ndx++)
1979         {
1980             int levelW = de::max(1, m_width >> ndx);
1981             int levelH = de::max(1, m_height >> ndx);
1982             int x      = rnd.getInt(0, getWidth() - levelW);
1983             int y      = rnd.getInt(0, getHeight() - levelH);
1984 
1985             glCopyTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, x, y, levelW, levelH, 0);
1986         }
1987     }
1988 
1989     uint32_t m_internalFormat;
1990 };
1991 
1992 // Basic CopyTexImage2D() with cubemap usage
1993 class BasicCopyTexImageCubeCase : public TextureCubeSpecCase
1994 {
1995 public:
BasicCopyTexImageCubeCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size)1996     BasicCopyTexImageCubeCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int size)
1997         : TextureCubeSpecCase(context, name, desc, glu::mapGLTransferFormat(internalFormat, GL_UNSIGNED_BYTE), size,
1998                               deLog2Floor32(size) + 1)
1999         , m_internalFormat(internalFormat)
2000     {
2001     }
2002 
2003 protected:
createTexture(void)2004     void createTexture(void)
2005     {
2006         const tcu::RenderTarget &renderTarget = TestCase::m_context.getRenderContext().getRenderTarget();
2007         bool targetHasRGB = renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 &&
2008                             renderTarget.getPixelFormat().blueBits > 0;
2009         bool targetHasAlpha    = renderTarget.getPixelFormat().alphaBits > 0;
2010         tcu::TextureFormat fmt = mapGLUnsizedInternalFormat(m_internalFormat);
2011         bool texHasRGB         = fmt.order != tcu::TextureFormat::A;
2012         bool texHasAlpha       = fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA ||
2013                            fmt.order == tcu::TextureFormat::A;
2014         uint32_t tex = 0;
2015         de::Random rnd(deStringHash(getName()));
2016         GradientShader shader(glu::TYPE_FLOAT_VEC4);
2017         uint32_t shaderID = getCurrentContext()->createProgram(&shader);
2018 
2019         if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
2020             throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
2021 
2022         // Fill render target with gradient.
2023         shader.setGradient(*getCurrentContext(), shaderID, Vec4(0.0f), Vec4(1.0f));
2024         sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
2025 
2026         glGenTextures(1, &tex);
2027         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
2028 
2029         for (int ndx = 0; ndx < m_numLevels; ndx++)
2030         {
2031             int levelSize = de::max(1, m_size >> ndx);
2032 
2033             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
2034             {
2035                 int x = rnd.getInt(0, getWidth() - levelSize);
2036                 int y = rnd.getInt(0, getHeight() - levelSize);
2037 
2038                 glCopyTexImage2D(s_cubeMapFaces[face], ndx, m_internalFormat, x, y, levelSize, levelSize, 0);
2039             }
2040         }
2041     }
2042 
2043     uint32_t m_internalFormat;
2044 };
2045 
2046 // Basic CopyTexSubImage2D() with 2D texture usage
2047 class BasicCopyTexSubImage2DCase : public Texture2DSpecCase
2048 {
2049 public:
BasicCopyTexSubImage2DCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int width,int height)2050     BasicCopyTexSubImage2DCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
2051                                int width, int height)
2052         : Texture2DSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height,
2053                             maxLevelCount(width, height))
2054         , m_format(format)
2055         , m_dataType(dataType)
2056     {
2057     }
2058 
2059 protected:
createTexture(void)2060     void createTexture(void)
2061     {
2062         const tcu::RenderTarget &renderTarget = TestCase::m_context.getRenderContext().getRenderTarget();
2063         bool targetHasRGB = renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 &&
2064                             renderTarget.getPixelFormat().blueBits > 0;
2065         bool targetHasAlpha    = renderTarget.getPixelFormat().alphaBits > 0;
2066         tcu::TextureFormat fmt = glu::mapGLTransferFormat(m_format, m_dataType);
2067         bool texHasRGB         = fmt.order != tcu::TextureFormat::A;
2068         bool texHasAlpha       = fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA ||
2069                            fmt.order == tcu::TextureFormat::A;
2070         uint32_t tex = 0;
2071         tcu::TextureLevel data(fmt);
2072         de::Random rnd(deStringHash(getName()));
2073         GradientShader shader(glu::TYPE_FLOAT_VEC4);
2074         uint32_t shaderID = getCurrentContext()->createProgram(&shader);
2075 
2076         if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
2077             throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
2078 
2079         glGenTextures(1, &tex);
2080         glBindTexture(GL_TEXTURE_2D, tex);
2081         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2082 
2083         // First specify full texture.
2084         for (int ndx = 0; ndx < m_numLevels; ndx++)
2085         {
2086             int levelW = de::max(1, m_width >> ndx);
2087             int levelH = de::max(1, m_height >> ndx);
2088 
2089             Vec4 colorA  = randomVector<4>(rnd);
2090             Vec4 colorB  = randomVector<4>(rnd);
2091             int cellSize = rnd.getInt(2, 16);
2092 
2093             data.setSize(levelW, levelH);
2094             tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
2095 
2096             glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType,
2097                          data.getAccess().getDataPtr());
2098         }
2099 
2100         // Fill render target with gradient.
2101         shader.setGradient(*getCurrentContext(), shaderID, Vec4(0.0f), Vec4(1.0f));
2102         sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
2103 
2104         // Re-specify parts of each level.
2105         for (int ndx = 0; ndx < m_numLevels; ndx++)
2106         {
2107             int levelW = de::max(1, m_width >> ndx);
2108             int levelH = de::max(1, m_height >> ndx);
2109 
2110             int w  = rnd.getInt(1, levelW);
2111             int h  = rnd.getInt(1, levelH);
2112             int xo = rnd.getInt(0, levelW - w);
2113             int yo = rnd.getInt(0, levelH - h);
2114 
2115             int x = rnd.getInt(0, getWidth() - w);
2116             int y = rnd.getInt(0, getHeight() - h);
2117 
2118             glCopyTexSubImage2D(GL_TEXTURE_2D, ndx, xo, yo, x, y, w, h);
2119         }
2120     }
2121 
2122     uint32_t m_format;
2123     uint32_t m_dataType;
2124 };
2125 
2126 // Basic CopyTexSubImage2D() with cubemap usage
2127 class BasicCopyTexSubImageCubeCase : public TextureCubeSpecCase
2128 {
2129 public:
BasicCopyTexSubImageCubeCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,int size)2130     BasicCopyTexSubImageCubeCase(Context &context, const char *name, const char *desc, uint32_t format,
2131                                  uint32_t dataType, int size)
2132         : TextureCubeSpecCase(context, name, desc, glu::mapGLTransferFormat(format, dataType), size,
2133                               deLog2Floor32(size) + 1)
2134         , m_format(format)
2135         , m_dataType(dataType)
2136     {
2137     }
2138 
2139 protected:
createTexture(void)2140     void createTexture(void)
2141     {
2142         const tcu::RenderTarget &renderTarget = TestCase::m_context.getRenderContext().getRenderTarget();
2143         bool targetHasRGB = renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 &&
2144                             renderTarget.getPixelFormat().blueBits > 0;
2145         bool targetHasAlpha    = renderTarget.getPixelFormat().alphaBits > 0;
2146         tcu::TextureFormat fmt = glu::mapGLTransferFormat(m_format, m_dataType);
2147         bool texHasRGB         = fmt.order != tcu::TextureFormat::A;
2148         bool texHasAlpha       = fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA ||
2149                            fmt.order == tcu::TextureFormat::A;
2150         uint32_t tex = 0;
2151         tcu::TextureLevel data(fmt);
2152         de::Random rnd(deStringHash(getName()));
2153         GradientShader shader(glu::TYPE_FLOAT_VEC4);
2154         uint32_t shaderID = getCurrentContext()->createProgram(&shader);
2155 
2156         if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
2157             throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
2158 
2159         glGenTextures(1, &tex);
2160         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
2161         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2162 
2163         for (int ndx = 0; ndx < m_numLevels; ndx++)
2164         {
2165             int levelSize = de::max(1, m_size >> ndx);
2166 
2167             data.setSize(levelSize, levelSize);
2168 
2169             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
2170             {
2171                 Vec4 colorA  = randomVector<4>(rnd);
2172                 Vec4 colorB  = randomVector<4>(rnd);
2173                 int cellSize = rnd.getInt(2, 16);
2174 
2175                 tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
2176                 glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelSize, levelSize, 0, m_format, m_dataType,
2177                              data.getAccess().getDataPtr());
2178             }
2179         }
2180 
2181         // Fill render target with gradient.
2182         shader.setGradient(*getCurrentContext(), shaderID, Vec4(0.0f), Vec4(1.0f));
2183         sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
2184 
2185         // Re-specify parts of each face and level.
2186         for (int ndx = 0; ndx < m_numLevels; ndx++)
2187         {
2188             int levelSize = de::max(1, m_size >> ndx);
2189 
2190             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
2191             {
2192                 int w  = rnd.getInt(1, levelSize);
2193                 int h  = rnd.getInt(1, levelSize);
2194                 int xo = rnd.getInt(0, levelSize - w);
2195                 int yo = rnd.getInt(0, levelSize - h);
2196 
2197                 int x = rnd.getInt(0, getWidth() - w);
2198                 int y = rnd.getInt(0, getHeight() - h);
2199 
2200                 glCopyTexSubImage2D(s_cubeMapFaces[face], ndx, xo, yo, x, y, w, h);
2201             }
2202         }
2203     }
2204 
2205     uint32_t m_format;
2206     uint32_t m_dataType;
2207 };
2208 
2209 // Basic glTexStorage2D() with 2D texture usage
2210 class BasicTexStorage2DCase : public Texture2DSpecCase
2211 {
2212 public:
BasicTexStorage2DCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int numLevels)2213     BasicTexStorage2DCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
2214                           int height, int numLevels)
2215         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, numLevels)
2216         , m_internalFormat(internalFormat)
2217     {
2218     }
2219 
2220 protected:
createTexture(void)2221     void createTexture(void)
2222     {
2223         tcu::TextureFormat fmt          = glu::mapGLInternalFormat(m_internalFormat);
2224         glu::TransferFormat transferFmt = glu::getTransferFormat(fmt);
2225         uint32_t tex                    = 0;
2226         tcu::TextureLevel levelData(glu::mapGLTransferFormat(transferFmt.format, transferFmt.dataType));
2227         de::Random rnd(deStringHash(getName()));
2228 
2229         glGenTextures(1, &tex);
2230         glBindTexture(GL_TEXTURE_2D, tex);
2231         glTexStorage2D(GL_TEXTURE_2D, m_numLevels, m_internalFormat, m_width, m_height);
2232 
2233         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2234 
2235         for (int ndx = 0; ndx < m_numLevels; ndx++)
2236         {
2237             int levelW = de::max(1, m_width >> ndx);
2238             int levelH = de::max(1, m_height >> ndx);
2239             Vec4 gMin  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2240             Vec4 gMax  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2241 
2242             levelData.setSize(levelW, levelH);
2243             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
2244 
2245             glTexSubImage2D(GL_TEXTURE_2D, ndx, 0, 0, levelW, levelH, transferFmt.format, transferFmt.dataType,
2246                             levelData.getAccess().getDataPtr());
2247         }
2248     }
2249 
2250     uint32_t m_internalFormat;
2251 };
2252 
2253 // Basic glTexStorage2D() with cubemap usage
2254 class BasicTexStorageCubeCase : public TextureCubeSpecCase
2255 {
2256 public:
BasicTexStorageCubeCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size,int numLevels)2257     BasicTexStorageCubeCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int size,
2258                             int numLevels)
2259         : TextureCubeSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, numLevels)
2260         , m_internalFormat(internalFormat)
2261     {
2262     }
2263 
2264 protected:
createTexture(void)2265     void createTexture(void)
2266     {
2267         tcu::TextureFormat fmt          = glu::mapGLInternalFormat(m_internalFormat);
2268         glu::TransferFormat transferFmt = glu::getTransferFormat(fmt);
2269         uint32_t tex                    = 0;
2270         tcu::TextureLevel levelData(glu::mapGLTransferFormat(transferFmt.format, transferFmt.dataType));
2271         de::Random rnd(deStringHash(getName()));
2272 
2273         glGenTextures(1, &tex);
2274         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
2275         glTexStorage2D(GL_TEXTURE_CUBE_MAP, m_numLevels, m_internalFormat, m_size, m_size);
2276 
2277         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2278 
2279         for (int ndx = 0; ndx < m_numLevels; ndx++)
2280         {
2281             int levelSize = de::max(1, m_size >> ndx);
2282 
2283             levelData.setSize(levelSize, levelSize);
2284 
2285             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
2286             {
2287                 Vec4 gMin = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2288                 Vec4 gMax = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2289 
2290                 tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
2291 
2292                 glTexSubImage2D(s_cubeMapFaces[face], ndx, 0, 0, levelSize, levelSize, transferFmt.format,
2293                                 transferFmt.dataType, levelData.getAccess().getDataPtr());
2294             }
2295         }
2296     }
2297 
2298     uint32_t m_internalFormat;
2299 };
2300 
2301 // Basic glTexStorage3D() with 2D array texture usage
2302 class BasicTexStorage2DArrayCase : public Texture2DArraySpecCase
2303 {
2304 public:
BasicTexStorage2DArrayCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int numLayers,int numLevels)2305     BasicTexStorage2DArrayCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
2306                                int height, int numLayers, int numLevels)
2307         : Texture2DArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height,
2308                                  numLayers, numLevels)
2309         , m_internalFormat(internalFormat)
2310     {
2311     }
2312 
2313 protected:
createTexture(void)2314     void createTexture(void)
2315     {
2316         uint32_t tex = 0;
2317         de::Random rnd(deStringHash(getName()));
2318         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
2319         tcu::TextureLevel levelData(glu::mapGLTransferFormat(transferFmt.format, transferFmt.dataType));
2320 
2321         glGenTextures(1, &tex);
2322         glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
2323         glTexStorage3D(GL_TEXTURE_2D_ARRAY, m_numLevels, m_internalFormat, m_width, m_height, m_numLayers);
2324 
2325         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2326 
2327         for (int ndx = 0; ndx < m_numLevels; ndx++)
2328         {
2329             int levelW = de::max(1, m_width >> ndx);
2330             int levelH = de::max(1, m_height >> ndx);
2331             Vec4 gMin  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2332             Vec4 gMax  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2333 
2334             levelData.setSize(levelW, levelH, m_numLayers);
2335             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
2336 
2337             glTexSubImage3D(GL_TEXTURE_2D_ARRAY, ndx, 0, 0, 0, levelW, levelH, m_numLayers, transferFmt.format,
2338                             transferFmt.dataType, levelData.getAccess().getDataPtr());
2339         }
2340     }
2341 
2342     uint32_t m_internalFormat;
2343 };
2344 
2345 // Basic TexStorage3D() with 3D texture usage
2346 class BasicTexStorage3DCase : public Texture3DSpecCase
2347 {
2348 public:
BasicTexStorage3DCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int depth,int numLevels)2349     BasicTexStorage3DCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
2350                           int height, int depth, int numLevels)
2351         : Texture3DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth,
2352                             numLevels)
2353         , m_internalFormat(internalFormat)
2354     {
2355     }
2356 
2357 protected:
createTexture(void)2358     void createTexture(void)
2359     {
2360         uint32_t tex = 0;
2361         de::Random rnd(deStringHash(getName()));
2362         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
2363         tcu::TextureLevel levelData(glu::mapGLTransferFormat(transferFmt.format, transferFmt.dataType));
2364 
2365         glGenTextures(1, &tex);
2366         glBindTexture(GL_TEXTURE_3D, tex);
2367         glTexStorage3D(GL_TEXTURE_3D, m_numLevels, m_internalFormat, m_width, m_height, m_depth);
2368 
2369         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2370 
2371         for (int ndx = 0; ndx < m_numLevels; ndx++)
2372         {
2373             int levelW = de::max(1, m_width >> ndx);
2374             int levelH = de::max(1, m_height >> ndx);
2375             int levelD = de::max(1, m_depth >> ndx);
2376             Vec4 gMin  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2377             Vec4 gMax  = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2378 
2379             levelData.setSize(levelW, levelH, levelD);
2380             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
2381 
2382             glTexSubImage3D(GL_TEXTURE_3D, ndx, 0, 0, 0, levelW, levelH, levelD, transferFmt.format,
2383                             transferFmt.dataType, levelData.getAccess().getDataPtr());
2384         }
2385     }
2386 
2387     uint32_t m_internalFormat;
2388 };
2389 
2390 // Pixel buffer object cases.
2391 
2392 // TexImage2D() from pixel buffer object.
2393 class TexImage2DBufferCase : public Texture2DSpecCase
2394 {
2395 public:
TexImage2DBufferCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int rowLength,int skipRows,int skipPixels,int alignment,int offset)2396     TexImage2DBufferCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
2397                          int height, int rowLength, int skipRows, int skipPixels, int alignment, int offset)
2398         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, 1)
2399         , m_internalFormat(internalFormat)
2400         , m_rowLength(rowLength)
2401         , m_skipRows(skipRows)
2402         , m_skipPixels(skipPixels)
2403         , m_alignment(alignment)
2404         , m_offset(offset)
2405     {
2406     }
2407 
2408 protected:
createTexture(void)2409     void createTexture(void)
2410     {
2411         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
2412         int pixelSize                   = m_texFormat.getPixelSize();
2413         int rowLength                   = m_rowLength > 0 ? m_rowLength : m_width + m_skipPixels;
2414         int rowPitch                    = deAlign32(rowLength * pixelSize, m_alignment);
2415         int height                      = m_height + m_skipRows;
2416         uint32_t buf                    = 0;
2417         uint32_t tex                    = 0;
2418         vector<uint8_t> data;
2419 
2420         DE_ASSERT(m_numLevels == 1);
2421 
2422         // Fill data with grid.
2423         data.resize(rowPitch * height + m_offset);
2424         {
2425             Vec4 cScale = m_texFormatInfo.valueMax - m_texFormatInfo.valueMin;
2426             Vec4 cBias  = m_texFormatInfo.valueMin;
2427             Vec4 colorA = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
2428             Vec4 colorB = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias;
2429 
2430             tcu::fillWithGrid(
2431                 tcu::PixelBufferAccess(m_texFormat, m_width, m_height, 1, rowPitch, 0,
2432                                        &data[0] + m_skipRows * rowPitch + m_skipPixels * pixelSize + m_offset),
2433                 4, colorA, colorB);
2434         }
2435 
2436         // Create buffer and upload.
2437         glGenBuffers(1, &buf);
2438         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
2439         glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
2440 
2441         glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
2442         glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
2443         glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
2444         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
2445 
2446         glGenTextures(1, &tex);
2447         glBindTexture(GL_TEXTURE_2D, tex);
2448         glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFmt.format, transferFmt.dataType,
2449                      (const void *)(uintptr_t)m_offset);
2450     }
2451 
2452     uint32_t m_internalFormat;
2453     int m_rowLength;
2454     int m_skipRows;
2455     int m_skipPixels;
2456     int m_alignment;
2457     int m_offset;
2458 };
2459 
2460 // TexImage2D() cubemap from pixel buffer object case
2461 class TexImageCubeBufferCase : public TextureCubeSpecCase
2462 {
2463 public:
TexImageCubeBufferCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size,int rowLength,int skipRows,int skipPixels,int alignment,int offset)2464     TexImageCubeBufferCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int size,
2465                            int rowLength, int skipRows, int skipPixels, int alignment, int offset)
2466         : TextureCubeSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, 1)
2467         , m_internalFormat(internalFormat)
2468         , m_rowLength(rowLength)
2469         , m_skipRows(skipRows)
2470         , m_skipPixels(skipPixels)
2471         , m_alignment(alignment)
2472         , m_offset(offset)
2473     {
2474     }
2475 
2476 protected:
createTexture(void)2477     void createTexture(void)
2478     {
2479         de::Random rnd(deStringHash(getName()));
2480         uint32_t tex            = 0;
2481         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
2482         const int pixelSize     = m_texFormat.getPixelSize();
2483         const int rowLength     = m_rowLength > 0 ? m_rowLength : m_size + m_skipPixels;
2484         const int rowPitch      = deAlign32(rowLength * pixelSize, m_alignment);
2485         const int height        = m_size + m_skipRows;
2486         vector<vector<uint8_t>> data(DE_LENGTH_OF_ARRAY(s_cubeMapFaces));
2487 
2488         DE_ASSERT(m_numLevels == 1);
2489 
2490         glGenTextures(1, &tex);
2491         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
2492         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2493 
2494         for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
2495         {
2496             uint32_t buf = 0;
2497 
2498             {
2499                 const Vec4 gMin = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2500                 const Vec4 gMax = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2501 
2502                 data[face].resize(rowPitch * height + m_offset);
2503                 tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_size, m_size, 1, rowPitch, 0,
2504                                                                        &data[face][0] + m_skipRows * rowPitch +
2505                                                                            m_skipPixels * pixelSize + m_offset),
2506                                                 gMin, gMax);
2507             }
2508 
2509             // Create buffer and upload.
2510             glGenBuffers(1, &buf);
2511             glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
2512             glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data[face].size(), &data[face][0], GL_STATIC_DRAW);
2513 
2514             glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
2515             glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
2516             glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
2517             glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
2518 
2519             glTexImage2D(s_cubeMapFaces[face], 0, m_internalFormat, m_size, m_size, 0, fmt.format, fmt.dataType,
2520                          (const void *)(uintptr_t)m_offset);
2521         }
2522     }
2523 
2524     uint32_t m_internalFormat;
2525     int m_rowLength;
2526     int m_skipRows;
2527     int m_skipPixels;
2528     int m_alignment;
2529     int m_offset;
2530 };
2531 
2532 // TexImage3D() 2D array from pixel buffer object.
2533 class TexImage2DArrayBufferCase : public Texture2DArraySpecCase
2534 {
2535 public:
TexImage2DArrayBufferCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int depth,int imageHeight,int rowLength,int skipImages,int skipRows,int skipPixels,int alignment,int offset)2536     TexImage2DArrayBufferCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
2537                               int height, int depth, int imageHeight, int rowLength, int skipImages, int skipRows,
2538                               int skipPixels, int alignment, int offset)
2539         : Texture2DArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, 1)
2540         , m_internalFormat(internalFormat)
2541         , m_imageHeight(imageHeight)
2542         , m_rowLength(rowLength)
2543         , m_skipImages(skipImages)
2544         , m_skipRows(skipRows)
2545         , m_skipPixels(skipPixels)
2546         , m_alignment(alignment)
2547         , m_offset(offset)
2548     {
2549     }
2550 
2551 protected:
createTexture(void)2552     void createTexture(void)
2553     {
2554         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
2555         int pixelSize                   = m_texFormat.getPixelSize();
2556         int rowLength                   = m_rowLength > 0 ? m_rowLength : m_width;
2557         int rowPitch                    = deAlign32(rowLength * pixelSize, m_alignment);
2558         int imageHeight                 = m_imageHeight > 0 ? m_imageHeight : m_height;
2559         int slicePitch                  = imageHeight * rowPitch;
2560         uint32_t tex                    = 0;
2561         uint32_t buf                    = 0;
2562         vector<uint8_t> data;
2563 
2564         DE_ASSERT(m_numLevels == 1);
2565 
2566         // Fill data with grid.
2567         data.resize(slicePitch * (m_numLayers + m_skipImages) + m_offset);
2568         {
2569             Vec4 cScale = m_texFormatInfo.valueMax - m_texFormatInfo.valueMin;
2570             Vec4 cBias  = m_texFormatInfo.valueMin;
2571             Vec4 colorA = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
2572             Vec4 colorB = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias;
2573 
2574             tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_numLayers, rowPitch, slicePitch,
2575                                                      &data[0] + m_skipImages * slicePitch + m_skipRows * rowPitch +
2576                                                          m_skipPixels * pixelSize + m_offset),
2577                               4, colorA, colorB);
2578         }
2579 
2580         glGenBuffers(1, &buf);
2581         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
2582         glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
2583 
2584         glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, m_imageHeight);
2585         glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
2586         glPixelStorei(GL_UNPACK_SKIP_IMAGES, m_skipImages);
2587         glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
2588         glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
2589         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
2590 
2591         glGenTextures(1, &tex);
2592         glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
2593         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, m_internalFormat, m_width, m_height, m_numLayers, 0, transferFmt.format,
2594                      transferFmt.dataType, (const void *)(uintptr_t)m_offset);
2595     }
2596 
2597     uint32_t m_internalFormat;
2598     int m_imageHeight;
2599     int m_rowLength;
2600     int m_skipImages;
2601     int m_skipRows;
2602     int m_skipPixels;
2603     int m_alignment;
2604     int m_offset;
2605 };
2606 
2607 // TexImage3D() from pixel buffer object.
2608 class TexImage3DBufferCase : public Texture3DSpecCase
2609 {
2610 public:
TexImage3DBufferCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int depth,int imageHeight,int rowLength,int skipImages,int skipRows,int skipPixels,int alignment,int offset)2611     TexImage3DBufferCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
2612                          int height, int depth, int imageHeight, int rowLength, int skipImages, int skipRows,
2613                          int skipPixels, int alignment, int offset)
2614         : Texture3DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, 1)
2615         , m_internalFormat(internalFormat)
2616         , m_imageHeight(imageHeight)
2617         , m_rowLength(rowLength)
2618         , m_skipImages(skipImages)
2619         , m_skipRows(skipRows)
2620         , m_skipPixels(skipPixels)
2621         , m_alignment(alignment)
2622         , m_offset(offset)
2623     {
2624     }
2625 
2626 protected:
createTexture(void)2627     void createTexture(void)
2628     {
2629         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
2630         int pixelSize                   = m_texFormat.getPixelSize();
2631         int rowLength                   = m_rowLength > 0 ? m_rowLength : m_width;
2632         int rowPitch                    = deAlign32(rowLength * pixelSize, m_alignment);
2633         int imageHeight                 = m_imageHeight > 0 ? m_imageHeight : m_height;
2634         int slicePitch                  = imageHeight * rowPitch;
2635         uint32_t tex                    = 0;
2636         uint32_t buf                    = 0;
2637         vector<uint8_t> data;
2638 
2639         DE_ASSERT(m_numLevels == 1);
2640 
2641         // Fill data with grid.
2642         data.resize(slicePitch * (m_depth + m_skipImages) + m_offset);
2643         {
2644             Vec4 cScale = m_texFormatInfo.valueMax - m_texFormatInfo.valueMin;
2645             Vec4 cBias  = m_texFormatInfo.valueMin;
2646             Vec4 colorA = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
2647             Vec4 colorB = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias;
2648 
2649             tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_depth, rowPitch, slicePitch,
2650                                                      &data[0] + m_skipImages * slicePitch + m_skipRows * rowPitch +
2651                                                          m_skipPixels * pixelSize + m_offset),
2652                               4, colorA, colorB);
2653         }
2654 
2655         glGenBuffers(1, &buf);
2656         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
2657         glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
2658 
2659         glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, m_imageHeight);
2660         glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
2661         glPixelStorei(GL_UNPACK_SKIP_IMAGES, m_skipImages);
2662         glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
2663         glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
2664         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
2665 
2666         glGenTextures(1, &tex);
2667         glBindTexture(GL_TEXTURE_3D, tex);
2668         glTexImage3D(GL_TEXTURE_3D, 0, m_internalFormat, m_width, m_height, m_depth, 0, transferFmt.format,
2669                      transferFmt.dataType, (const void *)(uintptr_t)m_offset);
2670     }
2671 
2672     uint32_t m_internalFormat;
2673     int m_imageHeight;
2674     int m_rowLength;
2675     int m_skipImages;
2676     int m_skipRows;
2677     int m_skipPixels;
2678     int m_alignment;
2679     int m_offset;
2680 };
2681 
2682 // TexSubImage2D() PBO case.
2683 class TexSubImage2DBufferCase : public Texture2DSpecCase
2684 {
2685 public:
TexSubImage2DBufferCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,int subX,int subY,int subW,int subH,int rowLength,int skipRows,int skipPixels,int alignment,int offset)2686     TexSubImage2DBufferCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
2687                             int height, int subX, int subY, int subW, int subH, int rowLength, int skipRows,
2688                             int skipPixels, int alignment, int offset)
2689         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, 1)
2690         , m_internalFormat(internalFormat)
2691         , m_subX(subX)
2692         , m_subY(subY)
2693         , m_subW(subW)
2694         , m_subH(subH)
2695         , m_rowLength(rowLength)
2696         , m_skipRows(skipRows)
2697         , m_skipPixels(skipPixels)
2698         , m_alignment(alignment)
2699         , m_offset(offset)
2700     {
2701     }
2702 
2703 protected:
createTexture(void)2704     void createTexture(void)
2705     {
2706         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
2707         int pixelSize                   = m_texFormat.getPixelSize();
2708         uint32_t tex                    = 0;
2709         uint32_t buf                    = 0;
2710         vector<uint8_t> data;
2711 
2712         DE_ASSERT(m_numLevels == 1);
2713 
2714         glGenTextures(1, &tex);
2715         glBindTexture(GL_TEXTURE_2D, tex);
2716 
2717         // First fill texture with gradient.
2718         data.resize(deAlign32(m_width * pixelSize, 4) * m_height);
2719         tcu::fillWithComponentGradients(
2720             tcu::PixelBufferAccess(m_texFormat, m_width, m_height, 1, deAlign32(m_width * pixelSize, 4), 0, &data[0]),
2721             m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2722         glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFmt.format, transferFmt.dataType,
2723                      &data[0]);
2724 
2725         // Fill data with grid.
2726         {
2727             int rowLength = m_rowLength > 0 ? m_rowLength : m_subW;
2728             int rowPitch  = deAlign32(rowLength * pixelSize, m_alignment);
2729             int height    = m_subH + m_skipRows;
2730             Vec4 cScale   = m_texFormatInfo.valueMax - m_texFormatInfo.valueMin;
2731             Vec4 cBias    = m_texFormatInfo.valueMin;
2732             Vec4 colorA   = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
2733             Vec4 colorB   = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias;
2734 
2735             data.resize(rowPitch * height + m_offset);
2736             tcu::fillWithGrid(
2737                 tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, 1, rowPitch, 0,
2738                                        &data[0] + m_skipRows * rowPitch + m_skipPixels * pixelSize + m_offset),
2739                 4, colorA, colorB);
2740         }
2741 
2742         glGenBuffers(1, &buf);
2743         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
2744         glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
2745 
2746         glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
2747         glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
2748         glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
2749         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
2750         glTexSubImage2D(GL_TEXTURE_2D, 0, m_subX, m_subY, m_subW, m_subH, transferFmt.format, transferFmt.dataType,
2751                         (const void *)(uintptr_t)m_offset);
2752     }
2753 
2754     uint32_t m_internalFormat;
2755     int m_subX;
2756     int m_subY;
2757     int m_subW;
2758     int m_subH;
2759     int m_rowLength;
2760     int m_skipRows;
2761     int m_skipPixels;
2762     int m_alignment;
2763     int m_offset;
2764 };
2765 
2766 // TexSubImage2D() cubemap PBO case.
2767 class TexSubImageCubeBufferCase : public TextureCubeSpecCase
2768 {
2769 public:
TexSubImageCubeBufferCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int size,int subX,int subY,int subW,int subH,int rowLength,int skipRows,int skipPixels,int alignment,int offset)2770     TexSubImageCubeBufferCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int size,
2771                               int subX, int subY, int subW, int subH, int rowLength, int skipRows, int skipPixels,
2772                               int alignment, int offset)
2773         : TextureCubeSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, 1)
2774         , m_internalFormat(internalFormat)
2775         , m_subX(subX)
2776         , m_subY(subY)
2777         , m_subW(subW)
2778         , m_subH(subH)
2779         , m_rowLength(rowLength)
2780         , m_skipRows(skipRows)
2781         , m_skipPixels(skipPixels)
2782         , m_alignment(alignment)
2783         , m_offset(offset)
2784     {
2785     }
2786 
2787 protected:
createTexture(void)2788     void createTexture(void)
2789     {
2790         de::Random rnd(deStringHash(getName()));
2791         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
2792         int pixelSize                   = m_texFormat.getPixelSize();
2793         uint32_t tex                    = 0;
2794         uint32_t buf                    = 0;
2795         vector<uint8_t> data;
2796 
2797         DE_ASSERT(m_numLevels == 1);
2798 
2799         glGenTextures(1, &tex);
2800         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
2801 
2802         // Fill faces with different gradients.
2803 
2804         data.resize(deAlign32(m_size * pixelSize, 4) * m_size);
2805         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2806 
2807         for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
2808         {
2809             const Vec4 gMin = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2810             const Vec4 gMax = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2811 
2812             tcu::fillWithComponentGradients(
2813                 tcu::PixelBufferAccess(m_texFormat, m_size, m_size, 1, deAlign32(m_size * pixelSize, 4), 0, &data[0]),
2814                 gMin, gMax);
2815 
2816             glTexImage2D(s_cubeMapFaces[face], 0, m_internalFormat, m_size, m_size, 0, transferFmt.format,
2817                          transferFmt.dataType, &data[0]);
2818         }
2819 
2820         // Fill data with grid.
2821         {
2822             int rowLength = m_rowLength > 0 ? m_rowLength : m_subW;
2823             int rowPitch  = deAlign32(rowLength * pixelSize, m_alignment);
2824             int height    = m_subH + m_skipRows;
2825             Vec4 cScale   = m_texFormatInfo.valueMax - m_texFormatInfo.valueMin;
2826             Vec4 cBias    = m_texFormatInfo.valueMin;
2827             Vec4 colorA   = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
2828             Vec4 colorB   = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias;
2829 
2830             data.resize(rowPitch * height + m_offset);
2831             tcu::fillWithGrid(
2832                 tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, 1, rowPitch, 0,
2833                                        &data[0] + m_skipRows * rowPitch + m_skipPixels * pixelSize + m_offset),
2834                 4, colorA, colorB);
2835         }
2836 
2837         glGenBuffers(1, &buf);
2838         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
2839         glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
2840 
2841         glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
2842         glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
2843         glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
2844         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
2845 
2846         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
2847             glTexSubImage2D(s_cubeMapFaces[face], 0, m_subX, m_subY, m_subW, m_subH, transferFmt.format,
2848                             transferFmt.dataType, (const void *)(uintptr_t)m_offset);
2849     }
2850 
2851     uint32_t m_internalFormat;
2852     int m_subX;
2853     int m_subY;
2854     int m_subW;
2855     int m_subH;
2856     int m_rowLength;
2857     int m_skipRows;
2858     int m_skipPixels;
2859     int m_alignment;
2860     int m_offset;
2861 };
2862 
2863 // TexSubImage3D() 2D array PBO case.
2864 class TexSubImage2DArrayBufferCase : public Texture2DArraySpecCase
2865 {
2866 public:
TexSubImage2DArrayBufferCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,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)2867     TexSubImage2DArrayBufferCase(Context &context, const char *name, const char *desc, uint32_t internalFormat,
2868                                  int width, int height, int depth, int subX, int subY, int subZ, int subW, int subH,
2869                                  int subD, int imageHeight, int rowLength, int skipImages, int skipRows, int skipPixels,
2870                                  int alignment, int offset)
2871         : Texture2DArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, 1)
2872         , m_internalFormat(internalFormat)
2873         , m_subX(subX)
2874         , m_subY(subY)
2875         , m_subZ(subZ)
2876         , m_subW(subW)
2877         , m_subH(subH)
2878         , m_subD(subD)
2879         , m_imageHeight(imageHeight)
2880         , m_rowLength(rowLength)
2881         , m_skipImages(skipImages)
2882         , m_skipRows(skipRows)
2883         , m_skipPixels(skipPixels)
2884         , m_alignment(alignment)
2885         , m_offset(offset)
2886     {
2887     }
2888 
2889 protected:
createTexture(void)2890     void createTexture(void)
2891     {
2892         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
2893         int pixelSize                   = m_texFormat.getPixelSize();
2894         uint32_t tex                    = 0;
2895         uint32_t buf                    = 0;
2896         vector<uint8_t> data;
2897 
2898         DE_ASSERT(m_numLevels == 1);
2899 
2900         glGenTextures(1, &tex);
2901         glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
2902 
2903         // Fill with gradient.
2904         {
2905             int rowPitch   = deAlign32(pixelSize * m_width, 4);
2906             int slicePitch = rowPitch * m_height;
2907 
2908             data.resize(slicePitch * m_numLayers);
2909             tcu::fillWithComponentGradients(
2910                 tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_numLayers, rowPitch, slicePitch, &data[0]),
2911                 m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2912         }
2913 
2914         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, m_internalFormat, m_width, m_height, m_numLayers, 0, transferFmt.format,
2915                      transferFmt.dataType, &data[0]);
2916 
2917         // Fill data with grid.
2918         {
2919             int rowLength   = m_rowLength > 0 ? m_rowLength : m_subW;
2920             int rowPitch    = deAlign32(rowLength * pixelSize, m_alignment);
2921             int imageHeight = m_imageHeight > 0 ? m_imageHeight : m_subH;
2922             int slicePitch  = imageHeight * rowPitch;
2923             Vec4 cScale     = m_texFormatInfo.valueMax - m_texFormatInfo.valueMin;
2924             Vec4 cBias      = m_texFormatInfo.valueMin;
2925             Vec4 colorA     = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
2926             Vec4 colorB     = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias;
2927 
2928             data.resize(slicePitch * (m_numLayers + m_skipImages) + m_offset);
2929             tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, m_subD, rowPitch, slicePitch,
2930                                                      &data[0] + m_skipImages * slicePitch + m_skipRows * rowPitch +
2931                                                          m_skipPixels * pixelSize + m_offset),
2932                               4, colorA, colorB);
2933         }
2934 
2935         glGenBuffers(1, &buf);
2936         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
2937         glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
2938 
2939         glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, m_imageHeight);
2940         glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
2941         glPixelStorei(GL_UNPACK_SKIP_IMAGES, m_skipImages);
2942         glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
2943         glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
2944         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
2945         glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, m_subX, m_subY, m_subZ, m_subW, m_subH, m_subD, transferFmt.format,
2946                         transferFmt.dataType, (const void *)(intptr_t)m_offset);
2947     }
2948 
2949     uint32_t m_internalFormat;
2950     int m_subX;
2951     int m_subY;
2952     int m_subZ;
2953     int m_subW;
2954     int m_subH;
2955     int m_subD;
2956     int m_imageHeight;
2957     int m_rowLength;
2958     int m_skipImages;
2959     int m_skipRows;
2960     int m_skipPixels;
2961     int m_alignment;
2962     int m_offset;
2963 };
2964 
2965 // TexSubImage2D() test case for PBO bounds.
2966 class CopyTexFromPBOCase : public Texture2DSpecCase
2967 {
2968 public:
CopyTexFromPBOCase(Context & context,const char * name,const char * desc)2969     CopyTexFromPBOCase(Context &context, const char *name, const char *desc)
2970         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(GL_RGBA8), 4, 4, 1)
2971     {
2972     }
2973 
2974 protected:
createTexture(void)2975     void createTexture(void)
2976     {
2977         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
2978 
2979         const glw::GLuint red   = 0xff0000ff; // alpha, blue, green, red
2980         const glw::GLuint green = 0xff00ff00;
2981         const glw::GLuint blue  = 0xffff0000;
2982         const glw::GLuint black = 0xff000000;
2983 
2984         glw::GLuint texId = 0;
2985         glw::GLuint fboId = 0;
2986         glw::GLuint pboId = 0;
2987 
2988         const uint32_t texWidth      = 4;
2989         const uint32_t texHeight     = 4;
2990         const uint32_t texSubWidth   = 2;
2991         const uint32_t texSubHeight  = 4;
2992         const uint32_t texSubOffsetX = 2;
2993         const uint32_t texSubOffsetY = 0;
2994 
2995         const uint32_t pboRowLength      = 4;
2996         const glw::GLuint pboOffset      = 2;
2997         const glw::GLintptr pboOffsetPtr = pboOffset * sizeof(glw::GLuint);
2998         const uint32_t halfWidth         = pboRowLength / 2;
2999 
3000         bool imageOk = true;
3001 
3002         glw::GLuint tex_data[texHeight][texWidth];
3003         glw::GLuint pixel_data[texHeight][texWidth];
3004         glw::GLuint color_data[texHeight][texWidth];
3005 
3006         // Fill pixel data.
3007         for (uint32_t row = 0; row < texHeight; row++)
3008         {
3009             for (uint32_t column = 0; column < texWidth; column++)
3010             {
3011                 tex_data[row][column] = red;
3012 
3013                 if (column < halfWidth)
3014                     pixel_data[row][column] = blue;
3015                 else
3016                     pixel_data[row][column] = green;
3017 
3018                 color_data[row][column] = black;
3019             }
3020         }
3021 
3022         // Create main texture.
3023         glGenTextures(1, &texId);
3024         GLU_EXPECT_NO_ERROR(glGetError(), "glGenTextures() failed");
3025         glBindTexture(GL_TEXTURE_2D, texId);
3026         GLU_EXPECT_NO_ERROR(glGetError(), "glBindTexture() failed");
3027         glTexImage2D(GL_TEXTURE_2D, 0, transferFmt.format, texWidth, texHeight, 0, transferFmt.format,
3028                      transferFmt.dataType, (void *)tex_data[0]);
3029         GLU_EXPECT_NO_ERROR(glGetError(), "glTexImage2D() failed");
3030 
3031         // Create pixel buffer object.
3032         glGenBuffers(1, &pboId);
3033         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboId);
3034         GLU_EXPECT_NO_ERROR(glGetError(), "glBindBuffer() failed");
3035         glPixelStorei(GL_UNPACK_ROW_LENGTH, pboRowLength);
3036         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3037         GLU_EXPECT_NO_ERROR(glGetError(), "glPixelStorei() failed");
3038         glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(pixel_data), (void *)pixel_data, GL_STREAM_DRAW);
3039 
3040         // The very last pixel of the PBO should be available for TexSubImage.
3041         glTexSubImage2D(GL_TEXTURE_2D, 0, texSubOffsetX, texSubOffsetY, texSubWidth, texSubHeight, transferFmt.format,
3042                         transferFmt.dataType, reinterpret_cast<void *>(pboOffsetPtr));
3043         GLU_EXPECT_NO_ERROR(glGetError(), "glTexSubImage2D() failed");
3044 
3045         // Create a framebuffer.
3046         glGenFramebuffers(1, &fboId);
3047         glBindFramebuffer(GL_FRAMEBUFFER, fboId);
3048         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);
3049         GLU_EXPECT_NO_ERROR(glGetError(), "glFramebufferTexture2D() failed");
3050 
3051         // Read pixels for pixel comparison.
3052         glReadPixels(0, 0, texWidth, texHeight, transferFmt.format, transferFmt.dataType, &color_data);
3053         GLU_EXPECT_NO_ERROR(glGetError(), "glReadPixels() failed");
3054 
3055         // Run pixel to pixel comparison tests to confirm all the stored data is there and correctly aligned.
3056         for (uint32_t row = 0; row < texSubHeight; row++)
3057         {
3058             for (uint32_t column = 0; column < pboOffset; column++)
3059             {
3060                 if (color_data[row][column] != tex_data[row][column])
3061                     imageOk = false;
3062             }
3063         }
3064 
3065         if (!imageOk)
3066             TCU_FAIL("Color data versus texture data comparison failed.");
3067 
3068         for (uint32_t row = texSubOffsetY; row < texSubHeight; row++)
3069         {
3070             for (uint32_t column = 0; column < texSubWidth; column++)
3071             {
3072                 if (color_data[row][column + texSubWidth] != pixel_data[row][column + pboOffset])
3073                     imageOk = false;
3074             }
3075         }
3076 
3077         if (!imageOk)
3078             TCU_FAIL("Color data versus pixel data comparison failed.");
3079 
3080         // Cleanup
3081         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
3082         glDeleteBuffers(1, &pboId);
3083     }
3084 };
3085 
3086 // TexSubImage3D() PBO case.
3087 class TexSubImage3DBufferCase : public Texture3DSpecCase
3088 {
3089 public:
TexSubImage3DBufferCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int width,int height,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)3090     TexSubImage3DBufferCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int width,
3091                             int height, int depth, int subX, int subY, int subZ, int subW, int subH, int subD,
3092                             int imageHeight, int rowLength, int skipImages, int skipRows, int skipPixels, int alignment,
3093                             int offset)
3094         : Texture3DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, 1)
3095         , m_internalFormat(internalFormat)
3096         , m_subX(subX)
3097         , m_subY(subY)
3098         , m_subZ(subZ)
3099         , m_subW(subW)
3100         , m_subH(subH)
3101         , m_subD(subD)
3102         , m_imageHeight(imageHeight)
3103         , m_rowLength(rowLength)
3104         , m_skipImages(skipImages)
3105         , m_skipRows(skipRows)
3106         , m_skipPixels(skipPixels)
3107         , m_alignment(alignment)
3108         , m_offset(offset)
3109     {
3110     }
3111 
3112 protected:
createTexture(void)3113     void createTexture(void)
3114     {
3115         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
3116         int pixelSize                   = m_texFormat.getPixelSize();
3117         uint32_t tex                    = 0;
3118         uint32_t buf                    = 0;
3119         vector<uint8_t> data;
3120 
3121         DE_ASSERT(m_numLevels == 1);
3122 
3123         glGenTextures(1, &tex);
3124         glBindTexture(GL_TEXTURE_3D, tex);
3125 
3126         // Fill with gradient.
3127         {
3128             int rowPitch   = deAlign32(pixelSize * m_width, 4);
3129             int slicePitch = rowPitch * m_height;
3130 
3131             data.resize(slicePitch * m_depth);
3132             tcu::fillWithComponentGradients(
3133                 tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_depth, rowPitch, slicePitch, &data[0]),
3134                 m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
3135         }
3136 
3137         glTexImage3D(GL_TEXTURE_3D, 0, m_internalFormat, m_width, m_height, m_depth, 0, transferFmt.format,
3138                      transferFmt.dataType, &data[0]);
3139 
3140         // Fill data with grid.
3141         {
3142             int rowLength   = m_rowLength > 0 ? m_rowLength : m_subW;
3143             int rowPitch    = deAlign32(rowLength * pixelSize, m_alignment);
3144             int imageHeight = m_imageHeight > 0 ? m_imageHeight : m_subH;
3145             int slicePitch  = imageHeight * rowPitch;
3146             Vec4 cScale     = m_texFormatInfo.valueMax - m_texFormatInfo.valueMin;
3147             Vec4 cBias      = m_texFormatInfo.valueMin;
3148             Vec4 colorA     = Vec4(1.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
3149             Vec4 colorB     = Vec4(0.0f, 1.0f, 0.0f, 1.0f) * cScale + cBias;
3150 
3151             data.resize(slicePitch * (m_depth + m_skipImages) + m_offset);
3152             tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, m_subD, rowPitch, slicePitch,
3153                                                      &data[0] + m_skipImages * slicePitch + m_skipRows * rowPitch +
3154                                                          m_skipPixels * pixelSize + m_offset),
3155                               4, colorA, colorB);
3156         }
3157 
3158         glGenBuffers(1, &buf);
3159         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
3160         glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
3161 
3162         glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, m_imageHeight);
3163         glPixelStorei(GL_UNPACK_ROW_LENGTH, m_rowLength);
3164         glPixelStorei(GL_UNPACK_SKIP_IMAGES, m_skipImages);
3165         glPixelStorei(GL_UNPACK_SKIP_ROWS, m_skipRows);
3166         glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_skipPixels);
3167         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
3168         glTexSubImage3D(GL_TEXTURE_3D, 0, m_subX, m_subY, m_subZ, m_subW, m_subH, m_subD, transferFmt.format,
3169                         transferFmt.dataType, (const void *)(intptr_t)m_offset);
3170     }
3171 
3172     uint32_t m_internalFormat;
3173     int m_subX;
3174     int m_subY;
3175     int m_subZ;
3176     int m_subW;
3177     int m_subH;
3178     int m_subD;
3179     int m_imageHeight;
3180     int m_rowLength;
3181     int m_skipImages;
3182     int m_skipRows;
3183     int m_skipPixels;
3184     int m_alignment;
3185     int m_offset;
3186 };
3187 
3188 // TexImage2D() depth case.
3189 class TexImage2DDepthCase : public Texture2DSpecCase
3190 {
3191 public:
TexImage2DDepthCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int imageWidth,int imageHeight)3192     TexImage2DDepthCase(Context &context, const char *name, const char *desc, uint32_t internalFormat, int imageWidth,
3193                         int imageHeight)
3194         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageWidth, imageHeight,
3195                             maxLevelCount(imageWidth, imageHeight))
3196         , m_internalFormat(internalFormat)
3197     {
3198         // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
3199         m_texFormatInfo.lookupBias  = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
3200         m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
3201     }
3202 
createTexture(void)3203     void createTexture(void)
3204     {
3205         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
3206         uint32_t tex            = 0;
3207         tcu::TextureLevel levelData(glu::mapGLTransferFormat(fmt.format, fmt.dataType));
3208 
3209         glGenTextures(1, &tex);
3210         glBindTexture(GL_TEXTURE_2D, tex);
3211         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3212         GLU_CHECK();
3213 
3214         for (int ndx = 0; ndx < m_numLevels; ndx++)
3215         {
3216             const int levelW = de::max(1, m_width >> ndx);
3217             const int levelH = de::max(1, m_height >> ndx);
3218             const Vec4 gMin  = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3219             const Vec4 gMax  = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3220 
3221             levelData.setSize(levelW, levelH);
3222             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
3223 
3224             glTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, levelW, levelH, 0, fmt.format, fmt.dataType,
3225                          levelData.getAccess().getDataPtr());
3226         }
3227     }
3228 
3229     const uint32_t m_internalFormat;
3230 };
3231 
3232 // TexImage3D() depth case.
3233 class TexImage2DArrayDepthCase : public Texture2DArraySpecCase
3234 {
3235 public:
TexImage2DArrayDepthCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int imageWidth,int imageHeight,int numLayers)3236     TexImage2DArrayDepthCase(Context &context, const char *name, const char *desc, uint32_t internalFormat,
3237                              int imageWidth, int imageHeight, int numLayers)
3238         : Texture2DArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageWidth, imageHeight,
3239                                  numLayers, maxLevelCount(imageWidth, imageHeight))
3240         , m_internalFormat(internalFormat)
3241     {
3242         // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
3243         m_texFormatInfo.lookupBias  = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
3244         m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
3245     }
3246 
createTexture(void)3247     void createTexture(void)
3248     {
3249         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
3250         uint32_t tex            = 0;
3251         tcu::TextureLevel levelData(glu::mapGLTransferFormat(fmt.format, fmt.dataType));
3252 
3253         glGenTextures(1, &tex);
3254         glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
3255         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3256         GLU_CHECK();
3257 
3258         for (int ndx = 0; ndx < m_numLevels; ndx++)
3259         {
3260             const int levelW = de::max(1, m_width >> ndx);
3261             const int levelH = de::max(1, m_height >> ndx);
3262             const Vec4 gMin  = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3263             const Vec4 gMax  = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3264 
3265             levelData.setSize(levelW, levelH, m_numLayers);
3266             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
3267 
3268             glTexImage3D(GL_TEXTURE_2D_ARRAY, ndx, m_internalFormat, levelW, levelH, m_numLayers, 0, fmt.format,
3269                          fmt.dataType, levelData.getAccess().getDataPtr());
3270         }
3271     }
3272 
3273     const uint32_t m_internalFormat;
3274 };
3275 
3276 // TexSubImage2D() depth case.
3277 class TexSubImage2DDepthCase : public Texture2DSpecCase
3278 {
3279 public:
TexSubImage2DDepthCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int imageWidth,int imageHeight)3280     TexSubImage2DDepthCase(Context &context, const char *name, const char *desc, uint32_t internalFormat,
3281                            int imageWidth, int imageHeight)
3282         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageWidth, imageHeight,
3283                             maxLevelCount(imageWidth, imageHeight))
3284         , m_internalFormat(internalFormat)
3285     {
3286         // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
3287         m_texFormatInfo.lookupBias  = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
3288         m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
3289     }
3290 
createTexture(void)3291     void createTexture(void)
3292     {
3293         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
3294         de::Random rnd(deStringHash(getName()));
3295         uint32_t tex = 0;
3296         tcu::TextureLevel levelData(glu::mapGLTransferFormat(fmt.format, fmt.dataType));
3297 
3298         glGenTextures(1, &tex);
3299         glBindTexture(GL_TEXTURE_2D, tex);
3300         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3301         GLU_CHECK();
3302 
3303         // First specify full texture.
3304         for (int ndx = 0; ndx < m_numLevels; ndx++)
3305         {
3306             const int levelW = de::max(1, m_width >> ndx);
3307             const int levelH = de::max(1, m_height >> ndx);
3308             const Vec4 gMin  = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3309             const Vec4 gMax  = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3310 
3311             levelData.setSize(levelW, levelH);
3312             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
3313 
3314             glTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, levelW, levelH, 0, fmt.format, fmt.dataType,
3315                          levelData.getAccess().getDataPtr());
3316         }
3317 
3318         // Re-specify parts of each level.
3319         for (int ndx = 0; ndx < m_numLevels; ndx++)
3320         {
3321             const int levelW = de::max(1, m_width >> ndx);
3322             const int levelH = de::max(1, m_height >> ndx);
3323 
3324             const int w = rnd.getInt(1, levelW);
3325             const int h = rnd.getInt(1, levelH);
3326             const int x = rnd.getInt(0, levelW - w);
3327             const int y = rnd.getInt(0, levelH - h);
3328 
3329             const Vec4 colorA  = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3330             const Vec4 colorB  = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3331             const int cellSize = rnd.getInt(2, 16);
3332 
3333             levelData.setSize(w, h);
3334             tcu::fillWithGrid(levelData.getAccess(), cellSize, colorA, colorB);
3335 
3336             glTexSubImage2D(GL_TEXTURE_2D, ndx, x, y, w, h, fmt.format, fmt.dataType,
3337                             levelData.getAccess().getDataPtr());
3338         }
3339     }
3340 
3341     const uint32_t m_internalFormat;
3342 };
3343 
3344 // TexSubImage3D() depth case.
3345 class TexSubImage2DArrayDepthCase : public Texture2DArraySpecCase
3346 {
3347 public:
TexSubImage2DArrayDepthCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int imageWidth,int imageHeight,int numLayers)3348     TexSubImage2DArrayDepthCase(Context &context, const char *name, const char *desc, uint32_t internalFormat,
3349                                 int imageWidth, int imageHeight, int numLayers)
3350         : Texture2DArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageWidth, imageHeight,
3351                                  numLayers, maxLevelCount(imageWidth, imageHeight))
3352         , m_internalFormat(internalFormat)
3353     {
3354         // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
3355         m_texFormatInfo.lookupBias  = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
3356         m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
3357     }
3358 
createTexture(void)3359     void createTexture(void)
3360     {
3361         glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
3362         de::Random rnd(deStringHash(getName()));
3363         uint32_t tex = 0;
3364         tcu::TextureLevel levelData(glu::mapGLTransferFormat(fmt.format, fmt.dataType));
3365 
3366         glGenTextures(1, &tex);
3367         glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
3368         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3369         GLU_CHECK();
3370 
3371         // First specify full texture.
3372         for (int ndx = 0; ndx < m_numLevels; ndx++)
3373         {
3374             const int levelW = de::max(1, m_width >> ndx);
3375             const int levelH = de::max(1, m_height >> ndx);
3376             const Vec4 gMin  = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3377             const Vec4 gMax  = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3378 
3379             levelData.setSize(levelW, levelH, m_numLayers);
3380             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
3381 
3382             glTexImage3D(GL_TEXTURE_2D_ARRAY, ndx, m_internalFormat, levelW, levelH, m_numLayers, 0, fmt.format,
3383                          fmt.dataType, levelData.getAccess().getDataPtr());
3384         }
3385 
3386         // Re-specify parts of each level.
3387         for (int ndx = 0; ndx < m_numLevels; ndx++)
3388         {
3389             const int levelW = de::max(1, m_width >> ndx);
3390             const int levelH = de::max(1, m_height >> ndx);
3391 
3392             const int w = rnd.getInt(1, levelW);
3393             const int h = rnd.getInt(1, levelH);
3394             const int d = rnd.getInt(1, m_numLayers);
3395             const int x = rnd.getInt(0, levelW - w);
3396             const int y = rnd.getInt(0, levelH - h);
3397             const int z = rnd.getInt(0, m_numLayers - d);
3398 
3399             const Vec4 colorA  = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3400             const Vec4 colorB  = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3401             const int cellSize = rnd.getInt(2, 16);
3402 
3403             levelData.setSize(w, h, d);
3404             tcu::fillWithGrid(levelData.getAccess(), cellSize, colorA, colorB);
3405 
3406             glTexSubImage3D(GL_TEXTURE_2D_ARRAY, ndx, x, y, z, w, h, d, fmt.format, fmt.dataType,
3407                             levelData.getAccess().getDataPtr());
3408         }
3409     }
3410 
3411     const uint32_t m_internalFormat;
3412 };
3413 
3414 // TexImage2D() depth case with pbo.
3415 class TexImage2DDepthBufferCase : public Texture2DSpecCase
3416 {
3417 public:
TexImage2DDepthBufferCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int imageWidth,int imageHeight)3418     TexImage2DDepthBufferCase(Context &context, const char *name, const char *desc, uint32_t internalFormat,
3419                               int imageWidth, int imageHeight)
3420         : Texture2DSpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageWidth, imageHeight, 1)
3421         , m_internalFormat(internalFormat)
3422     {
3423         // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
3424         m_texFormatInfo.lookupBias  = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
3425         m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
3426     }
3427 
createTexture(void)3428     void createTexture(void)
3429     {
3430         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
3431         int pixelSize                   = m_texFormat.getPixelSize();
3432         int rowLength                   = m_width;
3433         int alignment                   = 4;
3434         int rowPitch                    = deAlign32(rowLength * pixelSize, alignment);
3435         int height                      = m_height;
3436         uint32_t buf                    = 0;
3437         uint32_t tex                    = 0;
3438         vector<uint8_t> data;
3439 
3440         DE_ASSERT(m_numLevels == 1);
3441 
3442         // Fill data with gradient
3443         data.resize(rowPitch * height);
3444         {
3445             const Vec4 gMin = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3446             const Vec4 gMax = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3447 
3448             tcu::fillWithComponentGradients(
3449                 tcu::PixelBufferAccess(m_texFormat, m_width, m_height, 1, rowPitch, 0, &data[0]), gMin, gMax);
3450         }
3451 
3452         // Create buffer and upload.
3453         glGenBuffers(1, &buf);
3454         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
3455         glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
3456 
3457         glPixelStorei(GL_UNPACK_ROW_LENGTH, rowLength);
3458         glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
3459         glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
3460         glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
3461 
3462         glGenTextures(1, &tex);
3463         glBindTexture(GL_TEXTURE_2D, tex);
3464         glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFmt.format, transferFmt.dataType,
3465                      DE_NULL);
3466         glDeleteBuffers(1, &buf);
3467     }
3468 
3469     const uint32_t m_internalFormat;
3470 };
3471 
3472 // TexImage3D() depth case with pbo.
3473 class TexImage2DArrayDepthBufferCase : public Texture2DArraySpecCase
3474 {
3475 public:
TexImage2DArrayDepthBufferCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,int imageWidth,int imageHeight,int numLayers)3476     TexImage2DArrayDepthBufferCase(Context &context, const char *name, const char *desc, uint32_t internalFormat,
3477                                    int imageWidth, int imageHeight, int numLayers)
3478         : Texture2DArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageWidth, imageHeight,
3479                                  numLayers, 1)
3480         , m_internalFormat(internalFormat)
3481     {
3482         // we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
3483         m_texFormatInfo.lookupBias  = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
3484         m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
3485     }
3486 
createTexture(void)3487     void createTexture(void)
3488     {
3489         glu::TransferFormat transferFmt = glu::getTransferFormat(m_texFormat);
3490         int pixelSize                   = m_texFormat.getPixelSize();
3491         int rowLength                   = m_width;
3492         int alignment                   = 4;
3493         int rowPitch                    = deAlign32(rowLength * pixelSize, alignment);
3494         int imageHeight                 = m_height;
3495         int slicePitch                  = imageHeight * rowPitch;
3496         uint32_t tex                    = 0;
3497         uint32_t buf                    = 0;
3498         vector<uint8_t> data;
3499 
3500         DE_ASSERT(m_numLevels == 1);
3501 
3502         // Fill data with grid.
3503         data.resize(slicePitch * m_numLayers);
3504         {
3505             const Vec4 gMin = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3506             const Vec4 gMax = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3507 
3508             tcu::fillWithComponentGradients(
3509                 tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_numLayers, rowPitch, slicePitch, &data[0]),
3510                 gMin, gMax);
3511         }
3512 
3513         glGenBuffers(1, &buf);
3514         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
3515         glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
3516 
3517         glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, imageHeight);
3518         glPixelStorei(GL_UNPACK_ROW_LENGTH, rowLength);
3519         glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
3520         glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
3521         glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
3522         glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
3523 
3524         glGenTextures(1, &tex);
3525         glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
3526         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, m_internalFormat, m_width, m_height, m_numLayers, 0, transferFmt.format,
3527                      transferFmt.dataType, DE_NULL);
3528         glDeleteBuffers(1, &buf);
3529     }
3530 
3531     const uint32_t m_internalFormat;
3532 };
3533 
TextureSpecificationTests(Context & context)3534 TextureSpecificationTests::TextureSpecificationTests(Context &context)
3535     : TestCaseGroup(context, "specification", "Texture Specification Tests")
3536 {
3537 }
3538 
~TextureSpecificationTests(void)3539 TextureSpecificationTests::~TextureSpecificationTests(void)
3540 {
3541 }
3542 
init(void)3543 void TextureSpecificationTests::init(void)
3544 {
3545     struct
3546     {
3547         const char *name;
3548         uint32_t format;
3549         uint32_t dataType;
3550     } unsizedFormats[] = {{"alpha_unsigned_byte", GL_ALPHA, GL_UNSIGNED_BYTE},
3551                           {"luminance_unsigned_byte", GL_LUMINANCE, GL_UNSIGNED_BYTE},
3552                           {"luminance_alpha_unsigned_byte", GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE},
3553                           {"rgb_unsigned_short_5_6_5", GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
3554                           {"rgb_unsigned_byte", GL_RGB, GL_UNSIGNED_BYTE},
3555                           {"rgba_unsigned_short_4_4_4_4", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4},
3556                           {"rgba_unsigned_short_5_5_5_1", GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1},
3557                           {"rgba_unsigned_byte", GL_RGBA, GL_UNSIGNED_BYTE}};
3558 
3559     struct
3560     {
3561         const char *name;
3562         uint32_t internalFormat;
3563     } colorFormats[] = {{
3564                             "rgba32f",
3565                             GL_RGBA32F,
3566                         },
3567                         {
3568                             "rgba32i",
3569                             GL_RGBA32I,
3570                         },
3571                         {
3572                             "rgba32ui",
3573                             GL_RGBA32UI,
3574                         },
3575                         {
3576                             "rgba16f",
3577                             GL_RGBA16F,
3578                         },
3579                         {
3580                             "rgba16i",
3581                             GL_RGBA16I,
3582                         },
3583                         {
3584                             "rgba16ui",
3585                             GL_RGBA16UI,
3586                         },
3587                         {
3588                             "rgba8",
3589                             GL_RGBA8,
3590                         },
3591                         {
3592                             "rgba8i",
3593                             GL_RGBA8I,
3594                         },
3595                         {
3596                             "rgba8ui",
3597                             GL_RGBA8UI,
3598                         },
3599                         {
3600                             "srgb8_alpha8",
3601                             GL_SRGB8_ALPHA8,
3602                         },
3603                         {
3604                             "rgb10_a2",
3605                             GL_RGB10_A2,
3606                         },
3607                         {
3608                             "rgb10_a2ui",
3609                             GL_RGB10_A2UI,
3610                         },
3611                         {
3612                             "rgba4",
3613                             GL_RGBA4,
3614                         },
3615                         {
3616                             "rgb5_a1",
3617                             GL_RGB5_A1,
3618                         },
3619                         {
3620                             "rgba8_snorm",
3621                             GL_RGBA8_SNORM,
3622                         },
3623                         {
3624                             "rgb8",
3625                             GL_RGB8,
3626                         },
3627                         {
3628                             "rgb565",
3629                             GL_RGB565,
3630                         },
3631                         {
3632                             "r11f_g11f_b10f",
3633                             GL_R11F_G11F_B10F,
3634                         },
3635                         {
3636                             "rgb32f",
3637                             GL_RGB32F,
3638                         },
3639                         {
3640                             "rgb32i",
3641                             GL_RGB32I,
3642                         },
3643                         {
3644                             "rgb32ui",
3645                             GL_RGB32UI,
3646                         },
3647                         {
3648                             "rgb16f",
3649                             GL_RGB16F,
3650                         },
3651                         {
3652                             "rgb16i",
3653                             GL_RGB16I,
3654                         },
3655                         {
3656                             "rgb16ui",
3657                             GL_RGB16UI,
3658                         },
3659                         {
3660                             "rgb8_snorm",
3661                             GL_RGB8_SNORM,
3662                         },
3663                         {
3664                             "rgb8i",
3665                             GL_RGB8I,
3666                         },
3667                         {
3668                             "rgb8ui",
3669                             GL_RGB8UI,
3670                         },
3671                         {
3672                             "srgb8",
3673                             GL_SRGB8,
3674                         },
3675                         {
3676                             "rgb9_e5",
3677                             GL_RGB9_E5,
3678                         },
3679                         {
3680                             "rg32f",
3681                             GL_RG32F,
3682                         },
3683                         {
3684                             "rg32i",
3685                             GL_RG32I,
3686                         },
3687                         {
3688                             "rg32ui",
3689                             GL_RG32UI,
3690                         },
3691                         {
3692                             "rg16f",
3693                             GL_RG16F,
3694                         },
3695                         {
3696                             "rg16i",
3697                             GL_RG16I,
3698                         },
3699                         {
3700                             "rg16ui",
3701                             GL_RG16UI,
3702                         },
3703                         {
3704                             "rg8",
3705                             GL_RG8,
3706                         },
3707                         {
3708                             "rg8i",
3709                             GL_RG8I,
3710                         },
3711                         {
3712                             "rg8ui",
3713                             GL_RG8UI,
3714                         },
3715                         {
3716                             "rg8_snorm",
3717                             GL_RG8_SNORM,
3718                         },
3719                         {
3720                             "r32f",
3721                             GL_R32F,
3722                         },
3723                         {
3724                             "r32i",
3725                             GL_R32I,
3726                         },
3727                         {
3728                             "r32ui",
3729                             GL_R32UI,
3730                         },
3731                         {
3732                             "r16f",
3733                             GL_R16F,
3734                         },
3735                         {
3736                             "r16i",
3737                             GL_R16I,
3738                         },
3739                         {
3740                             "r16ui",
3741                             GL_R16UI,
3742                         },
3743                         {
3744                             "r8",
3745                             GL_R8,
3746                         },
3747                         {
3748                             "r8i",
3749                             GL_R8I,
3750                         },
3751                         {
3752                             "r8ui",
3753                             GL_R8UI,
3754                         },
3755                         {
3756                             "r8_snorm",
3757                             GL_R8_SNORM,
3758                         }};
3759 
3760     static const struct
3761     {
3762         const char *name;
3763         uint32_t internalFormat;
3764     } depthStencilFormats[] = {// Depth and stencil formats
3765                                {"depth_component32f", GL_DEPTH_COMPONENT32F},
3766                                {"depth_component24", GL_DEPTH_COMPONENT24},
3767                                {"depth_component16", GL_DEPTH_COMPONENT16},
3768                                {"depth32f_stencil8", GL_DEPTH32F_STENCIL8},
3769                                {"depth24_stencil8", GL_DEPTH24_STENCIL8}};
3770 
3771     // Basic TexImage2D usage.
3772     {
3773         tcu::TestCaseGroup *basicTexImageGroup =
3774             new tcu::TestCaseGroup(m_testCtx, "basic_teximage2d", "Basic glTexImage2D() usage");
3775         addChild(basicTexImageGroup);
3776         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
3777         {
3778             const char *fmtName   = colorFormats[formatNdx].name;
3779             uint32_t format       = colorFormats[formatNdx].internalFormat;
3780             const int tex2DWidth  = 64;
3781             const int tex2DHeight = 128;
3782             const int texCubeSize = 64;
3783 
3784             basicTexImageGroup->addChild(new BasicTexImage2DCase(m_context, (string(fmtName) + "_2d").c_str(), "",
3785                                                                  format, tex2DWidth, tex2DHeight));
3786             basicTexImageGroup->addChild(
3787                 new BasicTexImageCubeCase(m_context, (string(fmtName) + "_cube").c_str(), "", format, texCubeSize));
3788         }
3789     }
3790 
3791     // Randomized TexImage2D order.
3792     {
3793         tcu::TestCaseGroup *randomTexImageGroup =
3794             new tcu::TestCaseGroup(m_testCtx, "random_teximage2d", "Randomized glTexImage2D() usage");
3795         addChild(randomTexImageGroup);
3796 
3797         de::Random rnd(9);
3798 
3799         // 2D cases.
3800         for (int ndx = 0; ndx < 10; ndx++)
3801         {
3802             int formatNdx = rnd.getInt(0, DE_LENGTH_OF_ARRAY(colorFormats) - 1);
3803             int width     = 1 << rnd.getInt(2, 8);
3804             int height    = 1 << rnd.getInt(2, 8);
3805 
3806             randomTexImageGroup->addChild(
3807                 new RandomOrderTexImage2DCase(m_context, (string("2d_") + de::toString(ndx)).c_str(), "",
3808                                               colorFormats[formatNdx].internalFormat, width, height));
3809         }
3810 
3811         // Cubemap cases.
3812         for (int ndx = 0; ndx < 10; ndx++)
3813         {
3814             int formatNdx = rnd.getInt(0, DE_LENGTH_OF_ARRAY(colorFormats) - 1);
3815             int size      = 1 << rnd.getInt(2, 8);
3816 
3817             randomTexImageGroup->addChild(
3818                 new RandomOrderTexImageCubeCase(m_context, (string("cube_") + de::toString(ndx)).c_str(), "",
3819                                                 colorFormats[formatNdx].internalFormat, size));
3820         }
3821     }
3822 
3823     // TexImage2D unpack alignment.
3824     {
3825         tcu::TestCaseGroup *alignGroup =
3826             new tcu::TestCaseGroup(m_testCtx, "teximage2d_align", "glTexImage2D() unpack alignment tests");
3827         addChild(alignGroup);
3828 
3829         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_r8_4_8", "", GL_R8, 4, 8, 4, 8));
3830         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_r8_63_1", "", GL_R8, 63, 30, 1, 1));
3831         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_r8_63_2", "", GL_R8, 63, 30, 1, 2));
3832         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_r8_63_4", "", GL_R8, 63, 30, 1, 4));
3833         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_r8_63_8", "", GL_R8, 63, 30, 1, 8));
3834         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgba4_51_1", "", GL_RGBA4, 51, 30, 1, 1));
3835         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgba4_51_2", "", GL_RGBA4, 51, 30, 1, 2));
3836         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgba4_51_4", "", GL_RGBA4, 51, 30, 1, 4));
3837         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgba4_51_8", "", GL_RGBA4, 51, 30, 1, 8));
3838         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgb8_39_1", "", GL_RGB8, 39, 43, 1, 1));
3839         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgb8_39_2", "", GL_RGB8, 39, 43, 1, 2));
3840         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgb8_39_4", "", GL_RGB8, 39, 43, 1, 4));
3841         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgb8_39_8", "", GL_RGB8, 39, 43, 1, 8));
3842         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgba8_47_1", "", GL_RGBA8, 47, 27, 1, 1));
3843         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgba8_47_2", "", GL_RGBA8, 47, 27, 1, 2));
3844         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgba8_47_4", "", GL_RGBA8, 47, 27, 1, 4));
3845         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgba8_47_8", "", GL_RGBA8, 47, 27, 1, 8));
3846 
3847         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_r8_4_8", "", GL_R8, 4, 3, 8));
3848         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_r8_63_1", "", GL_R8, 63, 1, 1));
3849         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_r8_63_2", "", GL_R8, 63, 1, 2));
3850         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_r8_63_4", "", GL_R8, 63, 1, 4));
3851         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_r8_63_8", "", GL_R8, 63, 1, 8));
3852         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgba4_51_1", "", GL_RGBA4, 51, 1, 1));
3853         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgba4_51_2", "", GL_RGBA4, 51, 1, 2));
3854         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgba4_51_4", "", GL_RGBA4, 51, 1, 4));
3855         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgba4_51_8", "", GL_RGBA4, 51, 1, 8));
3856         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgb8_39_1", "", GL_RGB8, 39, 1, 1));
3857         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgb8_39_2", "", GL_RGB8, 39, 1, 2));
3858         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgb8_39_4", "", GL_RGB8, 39, 1, 4));
3859         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgb8_39_8", "", GL_RGB8, 39, 1, 8));
3860         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgba8_47_1", "", GL_RGBA8, 47, 1, 1));
3861         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgba8_47_2", "", GL_RGBA8, 47, 1, 2));
3862         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgba8_47_4", "", GL_RGBA8, 47, 1, 4));
3863         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgba8_47_8", "", GL_RGBA8, 47, 1, 8));
3864     }
3865 
3866     // glTexImage2D() unpack parameter cases.
3867     {
3868         tcu::TestCaseGroup *paramGroup =
3869             new tcu::TestCaseGroup(m_testCtx, "teximage2d_unpack_params", "glTexImage2D() pixel transfer mode cases");
3870         addChild(paramGroup);
3871 
3872         static const struct
3873         {
3874             const char *name;
3875             uint32_t format;
3876             int width;
3877             int height;
3878             int rowLength;
3879             int skipRows;
3880             int skipPixels;
3881             int alignment;
3882         } cases[] = {
3883             {"rgb8_alignment", GL_RGB8, 31, 30, 0, 0, 0, 2},     {"rgb8_row_length", GL_RGB8, 31, 30, 50, 0, 0, 4},
3884             {"rgb8_skip_rows", GL_RGB8, 31, 30, 0, 3, 0, 4},     {"rgb8_skip_pixels", GL_RGB8, 31, 30, 36, 0, 5, 4},
3885             {"r8_complex1", GL_R8, 31, 30, 64, 1, 3, 1},         {"r8_complex2", GL_R8, 31, 30, 64, 1, 3, 2},
3886             {"r8_complex3", GL_R8, 31, 30, 64, 1, 3, 4},         {"r8_complex4", GL_R8, 31, 30, 64, 1, 3, 8},
3887             {"rgba8_complex1", GL_RGBA8, 56, 61, 69, 0, 0, 8},   {"rgba8_complex2", GL_RGBA8, 56, 61, 69, 0, 7, 8},
3888             {"rgba8_complex3", GL_RGBA8, 56, 61, 69, 3, 0, 8},   {"rgba8_complex4", GL_RGBA8, 56, 61, 69, 3, 7, 8},
3889             {"rgba32f_complex", GL_RGBA32F, 19, 10, 27, 1, 7, 8}};
3890 
3891         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
3892             paramGroup->addChild(new TexImage2DParamsCase(
3893                 m_context, cases[ndx].name, "", cases[ndx].format, cases[ndx].width, cases[ndx].height,
3894                 cases[ndx].rowLength, cases[ndx].skipRows, cases[ndx].skipPixels, cases[ndx].alignment));
3895     }
3896 
3897     // glTexImage2D() pbo cases.
3898     {
3899         tcu::TestCaseGroup *pboGroup = new tcu::TestCaseGroup(m_testCtx, "teximage2d_pbo", "glTexImage2D() from PBO");
3900         addChild(pboGroup);
3901 
3902         // Parameter cases
3903         static const struct
3904         {
3905             const char *name;
3906             uint32_t format;
3907             int width;
3908             int height;
3909             int rowLength;
3910             int skipRows;
3911             int skipPixels;
3912             int alignment;
3913             int offset;
3914         } parameterCases[] = {{"rgb8_offset", GL_RGB8, 31, 30, 0, 0, 0, 4, 67},
3915                               {"rgb8_alignment", GL_RGB8, 31, 30, 0, 0, 0, 2, 0},
3916                               {"rgb8_row_length", GL_RGB8, 31, 30, 50, 0, 0, 4, 0},
3917                               {"rgb8_skip_rows", GL_RGB8, 31, 30, 0, 3, 0, 4, 0},
3918                               {"rgb8_skip_pixels", GL_RGB8, 31, 30, 36, 0, 5, 4, 0}};
3919 
3920         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
3921         {
3922             const string fmtName  = colorFormats[formatNdx].name;
3923             const uint32_t format = colorFormats[formatNdx].internalFormat;
3924             const int tex2DWidth  = 65;
3925             const int tex2DHeight = 37;
3926             const int texCubeSize = 64;
3927 
3928             pboGroup->addChild(new TexImage2DBufferCase(m_context, (fmtName + "_2d").c_str(), "", format, tex2DWidth,
3929                                                         tex2DHeight, 0, 0, 0, 4, 0));
3930             pboGroup->addChild(new TexImageCubeBufferCase(m_context, (fmtName + "_cube").c_str(), "", format,
3931                                                           texCubeSize, 0, 0, 0, 4, 0));
3932         }
3933 
3934         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(parameterCases); ndx++)
3935         {
3936             pboGroup->addChild(new TexImage2DBufferCase(m_context, (string(parameterCases[ndx].name) + "_2d").c_str(),
3937                                                         "", parameterCases[ndx].format, parameterCases[ndx].width,
3938                                                         parameterCases[ndx].height, parameterCases[ndx].rowLength,
3939                                                         parameterCases[ndx].skipRows, parameterCases[ndx].skipPixels,
3940                                                         parameterCases[ndx].alignment, parameterCases[ndx].offset));
3941             pboGroup->addChild(new TexImageCubeBufferCase(
3942                 m_context, (string(parameterCases[ndx].name) + "_cube").c_str(), "", parameterCases[ndx].format,
3943                 parameterCases[ndx].width, parameterCases[ndx].rowLength, parameterCases[ndx].skipRows,
3944                 parameterCases[ndx].skipPixels, parameterCases[ndx].alignment, parameterCases[ndx].offset));
3945         }
3946     }
3947 
3948     // glTexImage2D() depth cases.
3949     {
3950         tcu::TestCaseGroup *shadow2dGroup =
3951             new tcu::TestCaseGroup(m_testCtx, "teximage2d_depth", "glTexImage2D() with depth or depth/stencil format");
3952         addChild(shadow2dGroup);
3953 
3954         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
3955         {
3956             const int tex2DWidth  = 64;
3957             const int tex2DHeight = 128;
3958 
3959             shadow2dGroup->addChild(new TexImage2DDepthCase(m_context, depthStencilFormats[ndx].name, "",
3960                                                             depthStencilFormats[ndx].internalFormat, tex2DWidth,
3961                                                             tex2DHeight));
3962         }
3963     }
3964 
3965     // glTexImage2D() depth cases with pbo.
3966     {
3967         tcu::TestCaseGroup *shadow2dGroup = new tcu::TestCaseGroup(
3968             m_testCtx, "teximage2d_depth_pbo", "glTexImage2D() with depth or depth/stencil format with pbo");
3969         addChild(shadow2dGroup);
3970 
3971         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
3972         {
3973             const int tex2DWidth  = 64;
3974             const int tex2DHeight = 128;
3975 
3976             shadow2dGroup->addChild(new TexImage2DDepthBufferCase(m_context, depthStencilFormats[ndx].name, "",
3977                                                                   depthStencilFormats[ndx].internalFormat, tex2DWidth,
3978                                                                   tex2DHeight));
3979         }
3980     }
3981 
3982     // Basic TexSubImage2D usage.
3983     {
3984         tcu::TestCaseGroup *basicTexSubImageGroup =
3985             new tcu::TestCaseGroup(m_testCtx, "basic_texsubimage2d", "Basic glTexSubImage2D() usage");
3986         addChild(basicTexSubImageGroup);
3987         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
3988         {
3989             const char *fmtName   = colorFormats[formatNdx].name;
3990             uint32_t format       = colorFormats[formatNdx].internalFormat;
3991             const int tex2DWidth  = 64;
3992             const int tex2DHeight = 128;
3993             const int texCubeSize = 64;
3994 
3995             basicTexSubImageGroup->addChild(new BasicTexSubImage2DCase(m_context, (string(fmtName) + "_2d").c_str(), "",
3996                                                                        format, tex2DWidth, tex2DHeight));
3997             basicTexSubImageGroup->addChild(
3998                 new BasicTexSubImageCubeCase(m_context, (string(fmtName) + "_cube").c_str(), "", format, texCubeSize));
3999         }
4000     }
4001 
4002     // TexSubImage2D to empty texture.
4003     {
4004         tcu::TestCaseGroup *texSubImageEmptyTexGroup = new tcu::TestCaseGroup(
4005             m_testCtx, "texsubimage2d_empty_tex", "glTexSubImage2D() to texture that has storage but no data");
4006         addChild(texSubImageEmptyTexGroup);
4007         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(unsizedFormats); formatNdx++)
4008         {
4009             const char *fmtName   = unsizedFormats[formatNdx].name;
4010             uint32_t format       = unsizedFormats[formatNdx].format;
4011             uint32_t dataType     = unsizedFormats[formatNdx].dataType;
4012             const int tex2DWidth  = 64;
4013             const int tex2DHeight = 32;
4014             const int texCubeSize = 32;
4015 
4016             texSubImageEmptyTexGroup->addChild(new TexSubImage2DEmptyTexCase(
4017                 m_context, (string(fmtName) + "_2d").c_str(), "", format, dataType, tex2DWidth, tex2DHeight));
4018             texSubImageEmptyTexGroup->addChild(new TexSubImageCubeEmptyTexCase(
4019                 m_context, (string(fmtName) + "_cube").c_str(), "", format, dataType, texCubeSize));
4020         }
4021     }
4022 
4023     // TexSubImage2D alignment cases.
4024     {
4025         tcu::TestCaseGroup *alignGroup =
4026             new tcu::TestCaseGroup(m_testCtx, "texsubimage2d_align", "glTexSubImage2D() unpack alignment tests");
4027         addChild(alignGroup);
4028 
4029         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_r8_1_1", "", GL_R8, 64, 64, 13, 17, 1, 6, 1));
4030         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_r8_1_2", "", GL_R8, 64, 64, 13, 17, 1, 6, 2));
4031         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_r8_1_4", "", GL_R8, 64, 64, 13, 17, 1, 6, 4));
4032         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_r8_1_8", "", GL_R8, 64, 64, 13, 17, 1, 6, 8));
4033         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_r8_63_1", "", GL_R8, 64, 64, 1, 9, 63, 30, 1));
4034         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_r8_63_2", "", GL_R8, 64, 64, 1, 9, 63, 30, 2));
4035         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_r8_63_4", "", GL_R8, 64, 64, 1, 9, 63, 30, 4));
4036         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_r8_63_8", "", GL_R8, 64, 64, 1, 9, 63, 30, 8));
4037         alignGroup->addChild(
4038             new TexSubImage2DAlignCase(m_context, "2d_rgba4_51_1", "", GL_RGBA4, 64, 64, 7, 29, 51, 30, 1));
4039         alignGroup->addChild(
4040             new TexSubImage2DAlignCase(m_context, "2d_rgba4_51_2", "", GL_RGBA4, 64, 64, 7, 29, 51, 30, 2));
4041         alignGroup->addChild(
4042             new TexSubImage2DAlignCase(m_context, "2d_rgba4_51_4", "", GL_RGBA4, 64, 64, 7, 29, 51, 30, 4));
4043         alignGroup->addChild(
4044             new TexSubImage2DAlignCase(m_context, "2d_rgba4_51_8", "", GL_RGBA4, 64, 64, 7, 29, 51, 30, 8));
4045         alignGroup->addChild(
4046             new TexSubImage2DAlignCase(m_context, "2d_rgb8_39_1", "", GL_RGB8, 64, 64, 11, 8, 39, 43, 1));
4047         alignGroup->addChild(
4048             new TexSubImage2DAlignCase(m_context, "2d_rgb8_39_2", "", GL_RGB8, 64, 64, 11, 8, 39, 43, 2));
4049         alignGroup->addChild(
4050             new TexSubImage2DAlignCase(m_context, "2d_rgb8_39_4", "", GL_RGB8, 64, 64, 11, 8, 39, 43, 4));
4051         alignGroup->addChild(
4052             new TexSubImage2DAlignCase(m_context, "2d_rgb8_39_8", "", GL_RGB8, 64, 64, 11, 8, 39, 43, 8));
4053         alignGroup->addChild(
4054             new TexSubImage2DAlignCase(m_context, "2d_rgba8_47_1", "", GL_RGBA8, 64, 64, 10, 1, 47, 27, 1));
4055         alignGroup->addChild(
4056             new TexSubImage2DAlignCase(m_context, "2d_rgba8_47_2", "", GL_RGBA8, 64, 64, 10, 1, 47, 27, 2));
4057         alignGroup->addChild(
4058             new TexSubImage2DAlignCase(m_context, "2d_rgba8_47_4", "", GL_RGBA8, 64, 64, 10, 1, 47, 27, 4));
4059         alignGroup->addChild(
4060             new TexSubImage2DAlignCase(m_context, "2d_rgba8_47_8", "", GL_RGBA8, 64, 64, 10, 1, 47, 27, 8));
4061 
4062         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_r8_1_1", "", GL_R8, 64, 13, 17, 1, 6, 1));
4063         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_r8_1_2", "", GL_R8, 64, 13, 17, 1, 6, 2));
4064         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_r8_1_4", "", GL_R8, 64, 13, 17, 1, 6, 4));
4065         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_r8_1_8", "", GL_R8, 64, 13, 17, 1, 6, 8));
4066         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_r8_63_1", "", GL_R8, 64, 1, 9, 63, 30, 1));
4067         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_r8_63_2", "", GL_R8, 64, 1, 9, 63, 30, 2));
4068         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_r8_63_4", "", GL_R8, 64, 1, 9, 63, 30, 4));
4069         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_r8_63_8", "", GL_R8, 64, 1, 9, 63, 30, 8));
4070         alignGroup->addChild(
4071             new TexSubImageCubeAlignCase(m_context, "cube_rgba4_51_1", "", GL_RGBA4, 64, 7, 29, 51, 30, 1));
4072         alignGroup->addChild(
4073             new TexSubImageCubeAlignCase(m_context, "cube_rgba4_51_2", "", GL_RGBA4, 64, 7, 29, 51, 30, 2));
4074         alignGroup->addChild(
4075             new TexSubImageCubeAlignCase(m_context, "cube_rgba4_51_4", "", GL_RGBA4, 64, 7, 29, 51, 30, 4));
4076         alignGroup->addChild(
4077             new TexSubImageCubeAlignCase(m_context, "cube_rgba4_51_8", "", GL_RGBA4, 64, 7, 29, 51, 30, 8));
4078         alignGroup->addChild(
4079             new TexSubImageCubeAlignCase(m_context, "cube_rgb8_39_1", "", GL_RGB8, 64, 11, 8, 39, 43, 1));
4080         alignGroup->addChild(
4081             new TexSubImageCubeAlignCase(m_context, "cube_rgb8_39_2", "", GL_RGB8, 64, 11, 8, 39, 43, 2));
4082         alignGroup->addChild(
4083             new TexSubImageCubeAlignCase(m_context, "cube_rgb8_39_4", "", GL_RGB8, 64, 11, 8, 39, 43, 4));
4084         alignGroup->addChild(
4085             new TexSubImageCubeAlignCase(m_context, "cube_rgb8_39_8", "", GL_RGB8, 64, 11, 8, 39, 43, 8));
4086         alignGroup->addChild(
4087             new TexSubImageCubeAlignCase(m_context, "cube_rgba8_47_1", "", GL_RGBA8, 64, 10, 1, 47, 27, 1));
4088         alignGroup->addChild(
4089             new TexSubImageCubeAlignCase(m_context, "cube_rgba8_47_2", "", GL_RGBA8, 64, 10, 1, 47, 27, 2));
4090         alignGroup->addChild(
4091             new TexSubImageCubeAlignCase(m_context, "cube_rgba8_47_4", "", GL_RGBA8, 64, 10, 1, 47, 27, 4));
4092         alignGroup->addChild(
4093             new TexSubImageCubeAlignCase(m_context, "cube_rgba8_47_8", "", GL_RGBA8, 64, 10, 1, 47, 27, 8));
4094     }
4095 
4096     // glTexSubImage2D() pixel transfer mode cases.
4097     {
4098         tcu::TestCaseGroup *paramGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage2d_unpack_params",
4099                                                                 "glTexSubImage2D() pixel transfer mode cases");
4100         addChild(paramGroup);
4101 
4102         static const struct
4103         {
4104             const char *name;
4105             uint32_t format;
4106             int width;
4107             int height;
4108             int subX;
4109             int subY;
4110             int subW;
4111             int subH;
4112             int rowLength;
4113             int skipRows;
4114             int skipPixels;
4115             int alignment;
4116         } cases[] = {{"rgb8_alignment", GL_RGB8, 54, 60, 11, 7, 31, 30, 0, 0, 0, 2},
4117                      {"rgb8_row_length", GL_RGB8, 54, 60, 11, 7, 31, 30, 50, 0, 0, 4},
4118                      {"rgb8_skip_rows", GL_RGB8, 54, 60, 11, 7, 31, 30, 0, 3, 0, 4},
4119                      {"rgb8_skip_pixels", GL_RGB8, 54, 60, 11, 7, 31, 30, 36, 0, 5, 4},
4120                      {"r8_complex1", GL_R8, 54, 60, 11, 7, 31, 30, 64, 1, 3, 1},
4121                      {"r8_complex2", GL_R8, 54, 60, 11, 7, 31, 30, 64, 1, 3, 2},
4122                      {"r8_complex3", GL_R8, 54, 60, 11, 7, 31, 30, 64, 1, 3, 4},
4123                      {"r8_complex4", GL_R8, 54, 60, 11, 7, 31, 30, 64, 1, 3, 8},
4124                      {"rgba8_complex1", GL_RGBA8, 92, 84, 13, 19, 56, 61, 69, 0, 0, 8},
4125                      {"rgba8_complex2", GL_RGBA8, 92, 84, 13, 19, 56, 61, 69, 0, 7, 8},
4126                      {"rgba8_complex3", GL_RGBA8, 92, 84, 13, 19, 56, 61, 69, 3, 0, 8},
4127                      {"rgba8_complex4", GL_RGBA8, 92, 84, 13, 19, 56, 61, 69, 3, 7, 8},
4128                      {"rgba32f_complex", GL_RGBA32F, 92, 84, 13, 19, 56, 61, 69, 3, 7, 8}};
4129 
4130         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
4131             paramGroup->addChild(new TexSubImage2DParamsCase(
4132                 m_context, cases[ndx].name, "", cases[ndx].format, cases[ndx].width, cases[ndx].height, cases[ndx].subX,
4133                 cases[ndx].subY, cases[ndx].subW, cases[ndx].subH, cases[ndx].rowLength, cases[ndx].skipRows,
4134                 cases[ndx].skipPixels, cases[ndx].alignment));
4135     }
4136 
4137     // glTexSubImage2D() PBO cases.
4138     {
4139         tcu::TestCaseGroup *pboGroup =
4140             new tcu::TestCaseGroup(m_testCtx, "texsubimage2d_pbo", "glTexSubImage2D() pixel buffer object tests");
4141         addChild(pboGroup);
4142 
4143         static const struct
4144         {
4145             const char *name;
4146             uint32_t format;
4147             int width;
4148             int height;
4149             int subX;
4150             int subY;
4151             int subW;
4152             int subH;
4153             int rowLength;
4154             int skipRows;
4155             int skipPixels;
4156             int alignment;
4157             int offset;
4158         } paramCases[] = {{"rgb8_offset", GL_RGB8, 54, 60, 11, 7, 31, 30, 0, 0, 0, 4, 67},
4159                           {"rgb8_alignment", GL_RGB8, 54, 60, 11, 7, 31, 30, 0, 0, 0, 2, 0},
4160                           {"rgb8_row_length", GL_RGB8, 54, 60, 11, 7, 31, 30, 50, 0, 0, 4, 0},
4161                           {"rgb8_skip_rows", GL_RGB8, 54, 60, 11, 7, 31, 30, 0, 3, 0, 4, 0},
4162                           {"rgb8_skip_pixels", GL_RGB8, 54, 60, 11, 7, 31, 30, 36, 0, 5, 4, 0}};
4163 
4164         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
4165         {
4166             pboGroup->addChild(new TexSubImage2DBufferCase(
4167                 m_context, (std::string(colorFormats[ndx].name) + "_2d").c_str(), "", colorFormats[ndx].internalFormat,
4168                 54, // Width
4169                 60, // Height
4170                 11, // Sub X
4171                 7,  // Sub Y
4172                 31, // Sub W
4173                 30, // Sub H
4174                 0,  // Row len
4175                 0,  // Skip rows
4176                 0,  // Skip pixels
4177                 4,  // Alignment
4178                 0 /* offset */));
4179             pboGroup->addChild(new TexSubImageCubeBufferCase(m_context,
4180                                                              (std::string(colorFormats[ndx].name) + "_cube").c_str(),
4181                                                              "", colorFormats[ndx].internalFormat,
4182                                                              64, // Size
4183                                                              11, // Sub X
4184                                                              7,  // Sub Y
4185                                                              31, // Sub W
4186                                                              30, // Sub H
4187                                                              0,  // Row len
4188                                                              0,  // Skip rows
4189                                                              0,  // Skip pixels
4190                                                              4,  // Alignment
4191                                                              0 /* offset */));
4192         }
4193 
4194         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(paramCases); ndx++)
4195         {
4196             pboGroup->addChild(new TexSubImage2DBufferCase(
4197                 m_context, (std::string(paramCases[ndx].name) + "_2d").c_str(), "", paramCases[ndx].format,
4198                 paramCases[ndx].width, paramCases[ndx].height, paramCases[ndx].subX, paramCases[ndx].subY,
4199                 paramCases[ndx].subW, paramCases[ndx].subH, paramCases[ndx].rowLength, paramCases[ndx].skipRows,
4200                 paramCases[ndx].skipPixels, paramCases[ndx].alignment, paramCases[ndx].offset));
4201             pboGroup->addChild(new TexSubImageCubeBufferCase(
4202                 m_context, (std::string(paramCases[ndx].name) + "_cube").c_str(), "", paramCases[ndx].format,
4203                 paramCases[ndx].width, paramCases[ndx].subX, paramCases[ndx].subY, paramCases[ndx].subW,
4204                 paramCases[ndx].subH, paramCases[ndx].rowLength, paramCases[ndx].skipRows, paramCases[ndx].skipPixels,
4205                 paramCases[ndx].alignment, paramCases[ndx].offset));
4206         }
4207 
4208         // This test makes sure the last bits from the PBO data can be read without errors.
4209         pboGroup->addChild(new CopyTexFromPBOCase(m_context, "pbo_bounds_2d",
4210                                                   "Checks the last bits are read from the PBO without errors"));
4211     }
4212 
4213     // glTexSubImage2D() depth cases.
4214     {
4215         tcu::TestCaseGroup *shadow2dGroup = new tcu::TestCaseGroup(
4216             m_testCtx, "texsubimage2d_depth", "glTexSubImage2D() with depth or depth/stencil format");
4217         addChild(shadow2dGroup);
4218 
4219         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
4220         {
4221             const int tex2DWidth  = 64;
4222             const int tex2DHeight = 32;
4223 
4224             shadow2dGroup->addChild(new TexSubImage2DDepthCase(m_context, depthStencilFormats[ndx].name, "",
4225                                                                depthStencilFormats[ndx].internalFormat, tex2DWidth,
4226                                                                tex2DHeight));
4227         }
4228     }
4229 
4230     // Basic glCopyTexImage2D() cases
4231     {
4232         tcu::TestCaseGroup *copyTexImageGroup =
4233             new tcu::TestCaseGroup(m_testCtx, "basic_copyteximage2d", "Basic glCopyTexImage2D() usage");
4234         addChild(copyTexImageGroup);
4235 
4236         copyTexImageGroup->addChild(new BasicCopyTexImage2DCase(m_context, "2d_alpha", "", GL_ALPHA, 128, 64));
4237         copyTexImageGroup->addChild(new BasicCopyTexImage2DCase(m_context, "2d_luminance", "", GL_LUMINANCE, 128, 64));
4238         copyTexImageGroup->addChild(
4239             new BasicCopyTexImage2DCase(m_context, "2d_luminance_alpha", "", GL_LUMINANCE_ALPHA, 128, 64));
4240         copyTexImageGroup->addChild(new BasicCopyTexImage2DCase(m_context, "2d_rgb", "", GL_RGB, 128, 64));
4241         copyTexImageGroup->addChild(new BasicCopyTexImage2DCase(m_context, "2d_rgba", "", GL_RGBA, 128, 64));
4242 
4243         copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase(m_context, "cube_alpha", "", GL_ALPHA, 64));
4244         copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase(m_context, "cube_luminance", "", GL_LUMINANCE, 64));
4245         copyTexImageGroup->addChild(
4246             new BasicCopyTexImageCubeCase(m_context, "cube_luminance_alpha", "", GL_LUMINANCE_ALPHA, 64));
4247         copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase(m_context, "cube_rgb", "", GL_RGB, 64));
4248         copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase(m_context, "cube_rgba", "", GL_RGBA, 64));
4249     }
4250 
4251     // Basic glCopyTexSubImage2D() cases
4252     {
4253         tcu::TestCaseGroup *copyTexSubImageGroup =
4254             new tcu::TestCaseGroup(m_testCtx, "basic_copytexsubimage2d", "Basic glCopyTexSubImage2D() usage");
4255         addChild(copyTexSubImageGroup);
4256 
4257         copyTexSubImageGroup->addChild(
4258             new BasicCopyTexSubImage2DCase(m_context, "2d_alpha", "", GL_ALPHA, GL_UNSIGNED_BYTE, 128, 64));
4259         copyTexSubImageGroup->addChild(
4260             new BasicCopyTexSubImage2DCase(m_context, "2d_luminance", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 128, 64));
4261         copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase(m_context, "2d_luminance_alpha", "",
4262                                                                       GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 128, 64));
4263         copyTexSubImageGroup->addChild(
4264             new BasicCopyTexSubImage2DCase(m_context, "2d_rgb", "", GL_RGB, GL_UNSIGNED_BYTE, 128, 64));
4265         copyTexSubImageGroup->addChild(
4266             new BasicCopyTexSubImage2DCase(m_context, "2d_rgba", "", GL_RGBA, GL_UNSIGNED_BYTE, 128, 64));
4267 
4268         copyTexSubImageGroup->addChild(
4269             new BasicCopyTexSubImageCubeCase(m_context, "cube_alpha", "", GL_ALPHA, GL_UNSIGNED_BYTE, 64));
4270         copyTexSubImageGroup->addChild(
4271             new BasicCopyTexSubImageCubeCase(m_context, "cube_luminance", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64));
4272         copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase(m_context, "cube_luminance_alpha", "",
4273                                                                         GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 64));
4274         copyTexSubImageGroup->addChild(
4275             new BasicCopyTexSubImageCubeCase(m_context, "cube_rgb", "", GL_RGB, GL_UNSIGNED_BYTE, 64));
4276         copyTexSubImageGroup->addChild(
4277             new BasicCopyTexSubImageCubeCase(m_context, "cube_rgba", "", GL_RGBA, GL_UNSIGNED_BYTE, 64));
4278     }
4279 
4280     // Basic TexImage3D usage.
4281     {
4282         tcu::TestCaseGroup *basicTexImageGroup =
4283             new tcu::TestCaseGroup(m_testCtx, "basic_teximage3d", "Basic glTexImage3D() usage");
4284         addChild(basicTexImageGroup);
4285         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
4286         {
4287             const char *fmtName        = colorFormats[formatNdx].name;
4288             uint32_t format            = colorFormats[formatNdx].internalFormat;
4289             const int tex2DArrayWidth  = 57;
4290             const int tex2DArrayHeight = 44;
4291             const int tex2DArrayLevels = 5;
4292             const int tex3DWidth       = 63;
4293             const int tex3DHeight      = 29;
4294             const int tex3DDepth       = 11;
4295 
4296             basicTexImageGroup->addChild(
4297                 new BasicTexImage2DArrayCase(m_context, (string(fmtName) + "_2d_array").c_str(), "", format,
4298                                              tex2DArrayWidth, tex2DArrayHeight, tex2DArrayLevels));
4299             basicTexImageGroup->addChild(new BasicTexImage3DCase(m_context, (string(fmtName) + "_3d").c_str(), "",
4300                                                                  format, tex3DWidth, tex3DHeight, tex3DDepth));
4301         }
4302     }
4303 
4304     // glTexImage3D() unpack params cases.
4305     {
4306         tcu::TestCaseGroup *paramGroup =
4307             new tcu::TestCaseGroup(m_testCtx, "teximage3d_unpack_params", "glTexImage3D() unpack parameters");
4308         addChild(paramGroup);
4309 
4310         static const struct
4311         {
4312             const char *name;
4313             uint32_t format;
4314             int width;
4315             int height;
4316             int depth;
4317             int imageHeight;
4318             int rowLength;
4319             int skipImages;
4320             int skipRows;
4321             int skipPixels;
4322             int alignment;
4323         } cases[] = {{"rgb8_image_height", GL_RGB8, 23, 19, 8, 26, 0, 0, 0, 0, 4},
4324                      {"rgb8_row_length", GL_RGB8, 23, 19, 8, 0, 27, 0, 0, 0, 4},
4325                      {"rgb8_skip_images", GL_RGB8, 23, 19, 8, 0, 0, 3, 0, 0, 4},
4326                      {"rgb8_skip_rows", GL_RGB8, 23, 19, 8, 22, 0, 0, 3, 0, 4},
4327                      {"rgb8_skip_pixels", GL_RGB8, 23, 19, 8, 0, 25, 0, 0, 2, 4},
4328                      {"r8_complex1", GL_R8, 13, 17, 11, 23, 15, 2, 3, 1, 1},
4329                      {"r8_complex2", GL_R8, 13, 17, 11, 23, 15, 2, 3, 1, 2},
4330                      {"r8_complex3", GL_R8, 13, 17, 11, 23, 15, 2, 3, 1, 4},
4331                      {"r8_complex4", GL_R8, 13, 17, 11, 23, 15, 2, 3, 1, 8},
4332                      {"rgba8_complex1", GL_RGBA8, 11, 20, 8, 25, 14, 0, 0, 0, 8},
4333                      {"rgba8_complex2", GL_RGBA8, 11, 20, 8, 25, 14, 0, 2, 0, 8},
4334                      {"rgba8_complex3", GL_RGBA8, 11, 20, 8, 25, 14, 0, 0, 3, 8},
4335                      {"rgba8_complex4", GL_RGBA8, 11, 20, 8, 25, 14, 0, 2, 3, 8},
4336                      {"rgba32f_complex", GL_RGBA32F, 11, 20, 8, 25, 14, 0, 2, 3, 8}};
4337 
4338         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
4339             paramGroup->addChild(new TexImage3DParamsCase(
4340                 m_context, cases[ndx].name, "", cases[ndx].format, cases[ndx].width, cases[ndx].height,
4341                 cases[ndx].depth, cases[ndx].imageHeight, cases[ndx].rowLength, cases[ndx].skipImages,
4342                 cases[ndx].skipRows, cases[ndx].skipPixels, cases[ndx].alignment));
4343     }
4344 
4345     // glTexImage3D() pbo cases.
4346     {
4347         tcu::TestCaseGroup *pboGroup = new tcu::TestCaseGroup(m_testCtx, "teximage3d_pbo", "glTexImage3D() from PBO");
4348         addChild(pboGroup);
4349 
4350         // Parameter cases
4351         static const struct
4352         {
4353             const char *name;
4354             uint32_t format;
4355             int width;
4356             int height;
4357             int depth;
4358             int imageHeight;
4359             int rowLength;
4360             int skipImages;
4361             int skipRows;
4362             int skipPixels;
4363             int alignment;
4364             int offset;
4365         } parameterCases[] = {{"rgb8_offset", GL_RGB8, 23, 19, 8, 0, 0, 0, 0, 0, 1, 67},
4366                               {"rgb8_alignment", GL_RGB8, 23, 19, 8, 0, 0, 0, 0, 0, 2, 0},
4367                               {"rgb8_image_height", GL_RGB8, 23, 19, 8, 26, 0, 0, 0, 0, 4, 0},
4368                               {"rgb8_row_length", GL_RGB8, 23, 19, 8, 0, 27, 0, 0, 0, 4, 0},
4369                               {"rgb8_skip_images", GL_RGB8, 23, 19, 8, 0, 0, 3, 0, 0, 4, 0},
4370                               {"rgb8_skip_rows", GL_RGB8, 23, 19, 8, 22, 0, 0, 3, 0, 4, 0},
4371                               {"rgb8_skip_pixels", GL_RGB8, 23, 19, 8, 0, 25, 0, 0, 2, 4, 0}};
4372 
4373         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
4374         {
4375             const string fmtName  = colorFormats[formatNdx].name;
4376             const uint32_t format = colorFormats[formatNdx].internalFormat;
4377             const int tex3DWidth  = 11;
4378             const int tex3DHeight = 20;
4379             const int tex3DDepth  = 8;
4380 
4381             pboGroup->addChild(new TexImage2DArrayBufferCase(m_context, (fmtName + "_2d_array").c_str(), "", format,
4382                                                              tex3DWidth, tex3DHeight, tex3DDepth, 0, 0, 0, 0, 0, 4, 0));
4383             pboGroup->addChild(new TexImage3DBufferCase(m_context, (fmtName + "_3d").c_str(), "", format, tex3DWidth,
4384                                                         tex3DHeight, tex3DDepth, 0, 0, 0, 0, 0, 4, 0));
4385         }
4386 
4387         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(parameterCases); ndx++)
4388         {
4389             pboGroup->addChild(new TexImage2DArrayBufferCase(
4390                 m_context, (string(parameterCases[ndx].name) + "_2d_array").c_str(), "", parameterCases[ndx].format,
4391                 parameterCases[ndx].width, parameterCases[ndx].depth, parameterCases[ndx].height,
4392                 parameterCases[ndx].imageHeight, parameterCases[ndx].rowLength, parameterCases[ndx].skipImages,
4393                 parameterCases[ndx].skipRows, parameterCases[ndx].skipPixels, parameterCases[ndx].alignment,
4394                 parameterCases[ndx].offset));
4395             pboGroup->addChild(new TexImage3DBufferCase(
4396                 m_context, (string(parameterCases[ndx].name) + "_3d").c_str(), "", parameterCases[ndx].format,
4397                 parameterCases[ndx].width, parameterCases[ndx].depth, parameterCases[ndx].height,
4398                 parameterCases[ndx].imageHeight, parameterCases[ndx].rowLength, parameterCases[ndx].skipImages,
4399                 parameterCases[ndx].skipRows, parameterCases[ndx].skipPixels, parameterCases[ndx].alignment,
4400                 parameterCases[ndx].offset));
4401         }
4402     }
4403 
4404     // glTexImage3D() depth cases.
4405     {
4406         tcu::TestCaseGroup *shadow3dGroup =
4407             new tcu::TestCaseGroup(m_testCtx, "teximage3d_depth", "glTexImage3D() with depth or depth/stencil format");
4408         addChild(shadow3dGroup);
4409 
4410         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
4411         {
4412             const int tex3DWidth  = 32;
4413             const int tex3DHeight = 64;
4414             const int tex3DDepth  = 8;
4415 
4416             shadow3dGroup->addChild(new TexImage2DArrayDepthCase(
4417                 m_context, (std::string(depthStencilFormats[ndx].name) + "_2d_array").c_str(), "",
4418                 depthStencilFormats[ndx].internalFormat, tex3DWidth, tex3DHeight, tex3DDepth));
4419         }
4420     }
4421 
4422     // glTexImage3D() depth cases with pbo.
4423     {
4424         tcu::TestCaseGroup *shadow3dGroup = new tcu::TestCaseGroup(
4425             m_testCtx, "teximage3d_depth_pbo", "glTexImage3D() with depth or depth/stencil format with pbo");
4426         addChild(shadow3dGroup);
4427 
4428         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
4429         {
4430             const int tex3DWidth  = 32;
4431             const int tex3DHeight = 64;
4432             const int tex3DDepth  = 8;
4433 
4434             shadow3dGroup->addChild(new TexImage2DArrayDepthBufferCase(
4435                 m_context, (std::string(depthStencilFormats[ndx].name) + "_2d_array").c_str(), "",
4436                 depthStencilFormats[ndx].internalFormat, tex3DWidth, tex3DHeight, tex3DDepth));
4437         }
4438     }
4439 
4440     // Basic TexSubImage3D usage.
4441     {
4442         tcu::TestCaseGroup *basicTexSubImageGroup =
4443             new tcu::TestCaseGroup(m_testCtx, "basic_texsubimage3d", "Basic glTexSubImage3D() usage");
4444         addChild(basicTexSubImageGroup);
4445         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
4446         {
4447             const char *fmtName   = colorFormats[formatNdx].name;
4448             uint32_t format       = colorFormats[formatNdx].internalFormat;
4449             const int tex3DWidth  = 32;
4450             const int tex3DHeight = 64;
4451             const int tex3DDepth  = 8;
4452 
4453             basicTexSubImageGroup->addChild(new BasicTexSubImage3DCase(m_context, (string(fmtName) + "_3d").c_str(), "",
4454                                                                        format, tex3DWidth, tex3DHeight, tex3DDepth));
4455         }
4456     }
4457 
4458     // glTexSubImage3D() unpack params cases.
4459     {
4460         tcu::TestCaseGroup *paramGroup =
4461             new tcu::TestCaseGroup(m_testCtx, "texsubimage3d_unpack_params", "glTexSubImage3D() unpack parameters");
4462         addChild(paramGroup);
4463 
4464         static const struct
4465         {
4466             const char *name;
4467             uint32_t format;
4468             int width;
4469             int height;
4470             int depth;
4471             int subX;
4472             int subY;
4473             int subZ;
4474             int subW;
4475             int subH;
4476             int subD;
4477             int imageHeight;
4478             int rowLength;
4479             int skipImages;
4480             int skipRows;
4481             int skipPixels;
4482             int alignment;
4483         } cases[] = {{"rgb8_image_height", GL_RGB8, 26, 25, 10, 1, 2, 1, 23, 19, 8, 26, 0, 0, 0, 0, 4},
4484                      {"rgb8_row_length", GL_RGB8, 26, 25, 10, 1, 2, 1, 23, 19, 8, 0, 27, 0, 0, 0, 4},
4485                      {"rgb8_skip_images", GL_RGB8, 26, 25, 10, 1, 2, 1, 23, 19, 8, 0, 0, 3, 0, 0, 4},
4486                      {"rgb8_skip_rows", GL_RGB8, 26, 25, 10, 1, 2, 1, 23, 19, 8, 22, 0, 0, 3, 0, 4},
4487                      {"rgb8_skip_pixels", GL_RGB8, 26, 25, 10, 1, 2, 1, 23, 19, 8, 0, 25, 0, 0, 2, 4},
4488                      {"r8_complex1", GL_R8, 15, 20, 11, 1, 1, 0, 13, 17, 11, 23, 15, 2, 3, 1, 1},
4489                      {"r8_complex2", GL_R8, 15, 20, 11, 1, 1, 0, 13, 17, 11, 23, 15, 2, 3, 1, 2},
4490                      {"r8_complex3", GL_R8, 15, 20, 11, 1, 1, 0, 13, 17, 11, 23, 15, 2, 3, 1, 4},
4491                      {"r8_complex4", GL_R8, 15, 20, 11, 1, 1, 0, 13, 17, 11, 23, 15, 2, 3, 1, 8},
4492                      {"rgba8_complex1", GL_RGBA8, 15, 25, 10, 0, 5, 1, 11, 20, 8, 25, 14, 0, 0, 0, 8},
4493                      {"rgba8_complex2", GL_RGBA8, 15, 25, 10, 0, 5, 1, 11, 20, 8, 25, 14, 0, 2, 0, 8},
4494                      {"rgba8_complex3", GL_RGBA8, 15, 25, 10, 0, 5, 1, 11, 20, 8, 25, 14, 0, 0, 3, 8},
4495                      {"rgba8_complex4", GL_RGBA8, 15, 25, 10, 0, 5, 1, 11, 20, 8, 25, 14, 0, 2, 3, 8},
4496                      {"rgba32f_complex", GL_RGBA32F, 15, 25, 10, 0, 5, 1, 11, 20, 8, 25, 14, 0, 2, 3, 8}};
4497 
4498         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
4499             paramGroup->addChild(new TexSubImage3DParamsCase(
4500                 m_context, cases[ndx].name, "", cases[ndx].format, cases[ndx].width, cases[ndx].height,
4501                 cases[ndx].depth, cases[ndx].subX, cases[ndx].subY, cases[ndx].subZ, cases[ndx].subW, cases[ndx].subH,
4502                 cases[ndx].subD, cases[ndx].imageHeight, cases[ndx].rowLength, cases[ndx].skipImages,
4503                 cases[ndx].skipRows, cases[ndx].skipPixels, cases[ndx].alignment));
4504     }
4505 
4506     // glTexSubImage3D() PBO cases.
4507     {
4508         tcu::TestCaseGroup *pboGroup =
4509             new tcu::TestCaseGroup(m_testCtx, "texsubimage3d_pbo", "glTexSubImage3D() pixel buffer object tests");
4510         addChild(pboGroup);
4511 
4512         static const struct
4513         {
4514             const char *name;
4515             uint32_t format;
4516             int width;
4517             int height;
4518             int depth;
4519             int subX;
4520             int subY;
4521             int subZ;
4522             int subW;
4523             int subH;
4524             int subD;
4525             int imageHeight;
4526             int rowLength;
4527             int skipImages;
4528             int skipRows;
4529             int skipPixels;
4530             int alignment;
4531             int offset;
4532         } paramCases[] = {{"rgb8_offset", GL_RGB8, 26, 25, 10, 1, 2, 1, 23, 19, 8, 0, 0, 0, 0, 0, 4, 67},
4533                           {"rgb8_image_height", GL_RGB8, 26, 25, 10, 1, 2, 1, 23, 19, 8, 26, 0, 0, 0, 0, 4, 0},
4534                           {"rgb8_row_length", GL_RGB8, 26, 25, 10, 1, 2, 1, 23, 19, 8, 0, 27, 0, 0, 0, 4, 0},
4535                           {"rgb8_skip_images", GL_RGB8, 26, 25, 10, 1, 2, 1, 23, 19, 8, 0, 0, 3, 0, 0, 4, 0},
4536                           {"rgb8_skip_rows", GL_RGB8, 26, 25, 10, 1, 2, 1, 23, 19, 8, 22, 0, 0, 3, 0, 4, 0},
4537                           {"rgb8_skip_pixels", GL_RGB8, 26, 25, 10, 1, 2, 1, 23, 19, 8, 0, 25, 0, 0, 2, 4, 0}};
4538 
4539         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
4540         {
4541             pboGroup->addChild(
4542                 new TexSubImage2DArrayBufferCase(m_context, (std::string(colorFormats[ndx].name) + "_2d_array").c_str(),
4543                                                  "", colorFormats[ndx].internalFormat,
4544                                                  26, // Width
4545                                                  25, // Height
4546                                                  10, // Depth
4547                                                  1,  // Sub X
4548                                                  2,  // Sub Y
4549                                                  0,  // Sub Z
4550                                                  23, // Sub W
4551                                                  19, // Sub H
4552                                                  8,  // Sub D
4553                                                  0,  // Image height
4554                                                  0,  // Row length
4555                                                  0,  // Skip images
4556                                                  0,  // Skip rows
4557                                                  0,  // Skip pixels
4558                                                  4,  // Alignment
4559                                                  0 /* offset */));
4560             pboGroup->addChild(new TexSubImage3DBufferCase(
4561                 m_context, (std::string(colorFormats[ndx].name) + "_3d").c_str(), "", colorFormats[ndx].internalFormat,
4562                 26, // Width
4563                 25, // Height
4564                 10, // Depth
4565                 1,  // Sub X
4566                 2,  // Sub Y
4567                 0,  // Sub Z
4568                 23, // Sub W
4569                 19, // Sub H
4570                 8,  // Sub D
4571                 0,  // Image height
4572                 0,  // Row length
4573                 0,  // Skip images
4574                 0,  // Skip rows
4575                 0,  // Skip pixels
4576                 4,  // Alignment
4577                 0 /* offset */));
4578         }
4579 
4580         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(paramCases); ndx++)
4581         {
4582             pboGroup->addChild(new TexSubImage2DArrayBufferCase(
4583                 m_context, (std::string(paramCases[ndx].name) + "_2d_array").c_str(), "", paramCases[ndx].format,
4584                 paramCases[ndx].width, paramCases[ndx].height, paramCases[ndx].depth, paramCases[ndx].subX,
4585                 paramCases[ndx].subY, paramCases[ndx].subZ, paramCases[ndx].subW, paramCases[ndx].subH,
4586                 paramCases[ndx].subD, paramCases[ndx].imageHeight, paramCases[ndx].rowLength,
4587                 paramCases[ndx].skipImages, paramCases[ndx].skipRows, paramCases[ndx].skipPixels,
4588                 paramCases[ndx].alignment, paramCases[ndx].offset));
4589             pboGroup->addChild(new TexSubImage3DBufferCase(
4590                 m_context, (std::string(paramCases[ndx].name) + "_3d").c_str(), "", paramCases[ndx].format,
4591                 paramCases[ndx].width, paramCases[ndx].height, paramCases[ndx].depth, paramCases[ndx].subX,
4592                 paramCases[ndx].subY, paramCases[ndx].subZ, paramCases[ndx].subW, paramCases[ndx].subH,
4593                 paramCases[ndx].subD, paramCases[ndx].imageHeight, paramCases[ndx].rowLength,
4594                 paramCases[ndx].skipImages, paramCases[ndx].skipRows, paramCases[ndx].skipPixels,
4595                 paramCases[ndx].alignment, paramCases[ndx].offset));
4596         }
4597     }
4598 
4599     // glTexSubImage3D() depth cases.
4600     {
4601         tcu::TestCaseGroup *shadow3dGroup = new tcu::TestCaseGroup(
4602             m_testCtx, "texsubimage3d_depth", "glTexSubImage3D() with depth or depth/stencil format");
4603         addChild(shadow3dGroup);
4604 
4605         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
4606         {
4607             const int tex2DArrayWidth  = 57;
4608             const int tex2DArrayHeight = 44;
4609             const int tex2DArrayLevels = 5;
4610 
4611             shadow3dGroup->addChild(new TexSubImage2DArrayDepthCase(
4612                 m_context, (std::string(depthStencilFormats[ndx].name) + "_2d_array").c_str(), "",
4613                 depthStencilFormats[ndx].internalFormat, tex2DArrayWidth, tex2DArrayHeight, tex2DArrayLevels));
4614         }
4615     }
4616 
4617     // glTexStorage2D() cases.
4618     {
4619         tcu::TestCaseGroup *texStorageGroup =
4620             new tcu::TestCaseGroup(m_testCtx, "texstorage2d", "Basic glTexStorage2D() usage");
4621         addChild(texStorageGroup);
4622 
4623         // All formats.
4624         tcu::TestCaseGroup *formatGroup =
4625             new tcu::TestCaseGroup(m_testCtx, "format", "glTexStorage2D() with all formats");
4626         texStorageGroup->addChild(formatGroup);
4627 
4628         // Color formats.
4629         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
4630         {
4631             const char *fmtName     = colorFormats[formatNdx].name;
4632             uint32_t internalFormat = colorFormats[formatNdx].internalFormat;
4633             const int tex2DWidth    = 117;
4634             const int tex2DHeight   = 97;
4635             int tex2DLevels         = maxLevelCount(tex2DWidth, tex2DHeight);
4636             const int cubeSize      = 57;
4637             int cubeLevels          = maxLevelCount(cubeSize, cubeSize);
4638 
4639             formatGroup->addChild(new BasicTexStorage2DCase(m_context, (string(fmtName) + "_2d").c_str(), "",
4640                                                             internalFormat, tex2DWidth, tex2DHeight, tex2DLevels));
4641             formatGroup->addChild(new BasicTexStorageCubeCase(m_context, (string(fmtName) + "_cube").c_str(), "",
4642                                                               internalFormat, cubeSize, cubeLevels));
4643         }
4644 
4645         // Depth / stencil formats.
4646         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); formatNdx++)
4647         {
4648             const char *fmtName     = depthStencilFormats[formatNdx].name;
4649             uint32_t internalFormat = depthStencilFormats[formatNdx].internalFormat;
4650             const int tex2DWidth    = 117;
4651             const int tex2DHeight   = 97;
4652             int tex2DLevels         = maxLevelCount(tex2DWidth, tex2DHeight);
4653             const int cubeSize      = 57;
4654             int cubeLevels          = maxLevelCount(cubeSize, cubeSize);
4655 
4656             formatGroup->addChild(new BasicTexStorage2DCase(m_context, (string(fmtName) + "_2d").c_str(), "",
4657                                                             internalFormat, tex2DWidth, tex2DHeight, tex2DLevels));
4658             formatGroup->addChild(new BasicTexStorageCubeCase(m_context, (string(fmtName) + "_cube").c_str(), "",
4659                                                               internalFormat, cubeSize, cubeLevels));
4660         }
4661 
4662         // Sizes.
4663         static const struct
4664         {
4665             int width;
4666             int height;
4667             int levels;
4668         } tex2DSizes[] = {//    W    H    L
4669                           {1, 1, 1}, {2, 2, 2}, {64, 32, 7}, {32, 64, 4}, {57, 63, 1}, {57, 63, 2}, {57, 63, 6}};
4670         static const struct
4671         {
4672             int size;
4673             int levels;
4674         } cubeSizes[] = {
4675             //    S    L
4676             {1, 1}, {2, 2}, {57, 1}, {57, 2}, {57, 6}, {64, 4}, {64, 7},
4677         };
4678 
4679         tcu::TestCaseGroup *sizeGroup =
4680             new tcu::TestCaseGroup(m_testCtx, "size", "glTexStorage2D() with various sizes");
4681         texStorageGroup->addChild(sizeGroup);
4682 
4683         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(tex2DSizes); ndx++)
4684         {
4685             const uint32_t format = GL_RGBA8;
4686             int width             = tex2DSizes[ndx].width;
4687             int height            = tex2DSizes[ndx].height;
4688             int levels            = tex2DSizes[ndx].levels;
4689             string name           = string("2d_") + de::toString(width) + "x" + de::toString(height) + "_" +
4690                           de::toString(levels) + "_levels";
4691 
4692             sizeGroup->addChild(new BasicTexStorage2DCase(m_context, name.c_str(), "", format, width, height, levels));
4693         }
4694 
4695         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeSizes); ndx++)
4696         {
4697             const uint32_t format = GL_RGBA8;
4698             int size              = cubeSizes[ndx].size;
4699             int levels            = cubeSizes[ndx].levels;
4700             string name = string("cube_") + de::toString(size) + "x" + de::toString(size) + "_" + de::toString(levels) +
4701                           "_levels";
4702 
4703             sizeGroup->addChild(new BasicTexStorageCubeCase(m_context, name.c_str(), "", format, size, levels));
4704         }
4705     }
4706 
4707     // glTexStorage3D() cases.
4708     {
4709         tcu::TestCaseGroup *texStorageGroup =
4710             new tcu::TestCaseGroup(m_testCtx, "texstorage3d", "Basic glTexStorage3D() usage");
4711         addChild(texStorageGroup);
4712 
4713         // All formats.
4714         tcu::TestCaseGroup *formatGroup =
4715             new tcu::TestCaseGroup(m_testCtx, "format", "glTexStorage3D() with all formats");
4716         texStorageGroup->addChild(formatGroup);
4717 
4718         // Color formats.
4719         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
4720         {
4721             const char *fmtName        = colorFormats[formatNdx].name;
4722             uint32_t internalFormat    = colorFormats[formatNdx].internalFormat;
4723             const int tex2DArrayWidth  = 57;
4724             const int tex2DArrayHeight = 13;
4725             const int tex2DArrayLayers = 7;
4726             int tex2DArrayLevels       = maxLevelCount(tex2DArrayWidth, tex2DArrayHeight);
4727             const int tex3DWidth       = 59;
4728             const int tex3DHeight      = 37;
4729             const int tex3DDepth       = 11;
4730             int tex3DLevels            = maxLevelCount(tex3DWidth, tex3DHeight, tex3DDepth);
4731 
4732             formatGroup->addChild(new BasicTexStorage2DArrayCase(m_context, (string(fmtName) + "_2d_array").c_str(), "",
4733                                                                  internalFormat, tex2DArrayWidth, tex2DArrayHeight,
4734                                                                  tex2DArrayLayers, tex2DArrayLevels));
4735             formatGroup->addChild(new BasicTexStorage3DCase(m_context, (string(fmtName) + "_3d").c_str(), "",
4736                                                             internalFormat, tex3DWidth, tex3DHeight, tex3DDepth,
4737                                                             tex3DLevels));
4738         }
4739 
4740         // Depth/stencil formats (only 2D texture array is supported).
4741         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); formatNdx++)
4742         {
4743             const char *fmtName        = depthStencilFormats[formatNdx].name;
4744             uint32_t internalFormat    = depthStencilFormats[formatNdx].internalFormat;
4745             const int tex2DArrayWidth  = 57;
4746             const int tex2DArrayHeight = 13;
4747             const int tex2DArrayLayers = 7;
4748             int tex2DArrayLevels       = maxLevelCount(tex2DArrayWidth, tex2DArrayHeight);
4749 
4750             formatGroup->addChild(new BasicTexStorage2DArrayCase(m_context, (string(fmtName) + "_2d_array").c_str(), "",
4751                                                                  internalFormat, tex2DArrayWidth, tex2DArrayHeight,
4752                                                                  tex2DArrayLayers, tex2DArrayLevels));
4753         }
4754 
4755         // Sizes.
4756         static const struct
4757         {
4758             int width;
4759             int height;
4760             int layers;
4761             int levels;
4762         } tex2DArraySizes[] = {//    W    H    La    Le
4763                                {1, 1, 1, 1},   {2, 2, 2, 2},   {64, 32, 3, 7}, {32, 64, 3, 4},
4764                                {57, 63, 5, 1}, {57, 63, 5, 2}, {57, 63, 5, 6}};
4765         static const struct
4766         {
4767             int width;
4768             int height;
4769             int depth;
4770             int levels;
4771         } tex3DSizes[] = {//    W    H    D    L
4772                           {1, 1, 1, 1},    {2, 2, 2, 2},    {64, 32, 16, 7}, {32, 64, 16, 4},
4773                           {32, 16, 64, 4}, {57, 63, 11, 1}, {57, 63, 11, 2}, {57, 63, 11, 6}};
4774 
4775         tcu::TestCaseGroup *sizeGroup =
4776             new tcu::TestCaseGroup(m_testCtx, "size", "glTexStorage2D() with various sizes");
4777         texStorageGroup->addChild(sizeGroup);
4778 
4779         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(tex2DArraySizes); ndx++)
4780         {
4781             const uint32_t format = GL_RGBA8;
4782             int width             = tex2DArraySizes[ndx].width;
4783             int height            = tex2DArraySizes[ndx].height;
4784             int layers            = tex2DArraySizes[ndx].layers;
4785             int levels            = tex2DArraySizes[ndx].levels;
4786             string name           = string("2d_array_") + de::toString(width) + "x" + de::toString(height) + "x" +
4787                           de::toString(layers) + "_" + de::toString(levels) + "_levels";
4788 
4789             sizeGroup->addChild(
4790                 new BasicTexStorage2DArrayCase(m_context, name.c_str(), "", format, width, height, layers, levels));
4791         }
4792 
4793         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(tex3DSizes); ndx++)
4794         {
4795             const uint32_t format = GL_RGBA8;
4796             int width             = tex3DSizes[ndx].width;
4797             int height            = tex3DSizes[ndx].height;
4798             int depth             = tex3DSizes[ndx].depth;
4799             int levels            = tex3DSizes[ndx].levels;
4800             string name = string("3d_") + de::toString(width) + "x" + de::toString(height) + "x" + de::toString(depth) +
4801                           "_" + de::toString(levels) + "_levels";
4802 
4803             sizeGroup->addChild(
4804                 new BasicTexStorage3DCase(m_context, name.c_str(), "", format, width, height, depth, levels));
4805         }
4806     }
4807 }
4808 
4809 } // namespace Functional
4810 } // namespace gles3
4811 } // namespace deqp
4812