xref: /aosp_15_r20/external/deqp/modules/gles2/functional/es2fTextureSpecificationTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.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 "es2fTextureSpecificationTests.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuImageCompare.hpp"
32 #include "gluTextureUtil.hpp"
33 #include "sglrContextUtil.hpp"
34 #include "sglrContextWrapper.hpp"
35 #include "sglrGLContext.hpp"
36 #include "sglrReferenceContext.hpp"
37 #include "glsTextureTestUtil.hpp"
38 #include "tcuTextureUtil.hpp"
39 #include "tcuFormatUtil.hpp"
40 #include "tcuVectorUtil.hpp"
41 #include "deRandom.hpp"
42 #include "deStringUtil.hpp"
43 
44 #include "glwEnums.hpp"
45 #include "glwFunctions.hpp"
46 
47 namespace deqp
48 {
49 namespace gles2
50 {
51 namespace Functional
52 {
53 
54 using std::pair;
55 using std::string;
56 using std::vector;
57 using tcu::IVec4;
58 using tcu::TestLog;
59 using tcu::UVec4;
60 using tcu::Vec4;
61 
mapGLUnsizedInternalFormat(uint32_t internalFormat)62 tcu::TextureFormat mapGLUnsizedInternalFormat(uint32_t internalFormat)
63 {
64     using tcu::TextureFormat;
65     switch (internalFormat)
66     {
67     case GL_ALPHA:
68         return TextureFormat(TextureFormat::A, TextureFormat::UNORM_INT8);
69     case GL_LUMINANCE:
70         return TextureFormat(TextureFormat::L, TextureFormat::UNORM_INT8);
71     case GL_LUMINANCE_ALPHA:
72         return TextureFormat(TextureFormat::LA, TextureFormat::UNORM_INT8);
73     case GL_RGB:
74         return TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8);
75     case GL_RGBA:
76         return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
77     default:
78         throw tcu::InternalError(string("Can't map GL unsized internal format (") +
79                                  tcu::toHex(internalFormat).toString() + ") to texture format");
80     }
81 }
82 
83 template <int Size>
84 static tcu::Vector<float, Size> randomVector(de::Random &rnd,
85                                              const tcu::Vector<float, Size> &minVal = tcu::Vector<float, Size>(0.0f),
86                                              const tcu::Vector<float, Size> &maxVal = tcu::Vector<float, Size>(1.0f))
87 {
88     tcu::Vector<float, Size> res;
89     for (int ndx = 0; ndx < Size; ndx++)
90         res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]);
91     return res;
92 }
93 
getPixelFormatCompareDepth(const tcu::PixelFormat & pixelFormat,tcu::TextureFormat textureFormat)94 static tcu::IVec4 getPixelFormatCompareDepth(const tcu::PixelFormat &pixelFormat, tcu::TextureFormat textureFormat)
95 {
96     switch (textureFormat.order)
97     {
98     case tcu::TextureFormat::L:
99     case tcu::TextureFormat::LA:
100         return tcu::IVec4(pixelFormat.redBits, pixelFormat.redBits, pixelFormat.redBits, pixelFormat.alphaBits);
101     default:
102         return tcu::IVec4(pixelFormat.redBits, pixelFormat.greenBits, pixelFormat.blueBits, pixelFormat.alphaBits);
103     }
104 }
105 
computeCompareThreshold(const tcu::PixelFormat & pixelFormat,tcu::TextureFormat textureFormat)106 static tcu::UVec4 computeCompareThreshold(const tcu::PixelFormat &pixelFormat, tcu::TextureFormat textureFormat)
107 {
108     const IVec4 texFormatBits   = tcu::getTextureFormatBitDepth(textureFormat);
109     const IVec4 pixelFormatBits = getPixelFormatCompareDepth(pixelFormat, textureFormat);
110     const IVec4 accurateFmtBits = min(pixelFormatBits, texFormatBits);
111     const IVec4 compareBits     = select(accurateFmtBits, IVec4(8), greaterThan(accurateFmtBits, IVec4(0))) - 1;
112 
113     return (IVec4(1) << (8 - compareBits)).asUint();
114 }
115 
116 class GradientShader : public sglr::ShaderProgram
117 {
118 public:
GradientShader(void)119     GradientShader(void)
120         : ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
121                         << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
122                         << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
123                         << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
124                         << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
125                         << sglr::pdec::VertexSource("attribute highp vec4 a_position;\n"
126                                                     "attribute mediump vec2 a_coord;\n"
127                                                     "varying mediump vec2 v_coord;\n"
128                                                     "void main (void)\n"
129                                                     "{\n"
130                                                     "    gl_Position = a_position;\n"
131                                                     "    v_coord = a_coord;\n"
132                                                     "}\n")
133                         << sglr::pdec::FragmentSource("varying mediump vec2 v_coord;\n"
134                                                       "void main (void)\n"
135                                                       "{\n"
136                                                       "    mediump float x = v_coord.x;\n"
137                                                       "    mediump float y = v_coord.y;\n"
138                                                       "    mediump float f0 = (x + y) * 0.5;\n"
139                                                       "    mediump float f1 = 0.5 + (x - y) * 0.5;\n"
140                                                       "    gl_FragColor = vec4(f0, f1, 1.0-f0, 1.0-f1);\n"
141                                                       "}\n"))
142     {
143     }
144 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const145     void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const
146     {
147         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
148         {
149             rr::VertexPacket &packet = *packets[packetNdx];
150 
151             packet.position   = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
152             packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
153         }
154     }
155 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const156     void shadeFragments(rr::FragmentPacket *packets, const int numPackets,
157                         const rr::FragmentShadingContext &context) const
158     {
159         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
160             for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
161             {
162                 const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
163                 const float x         = coord.x();
164                 const float y         = coord.y();
165                 const float f0        = (x + y) * 0.5f;
166                 const float f1        = 0.5f + (x - y) * 0.5f;
167 
168                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, tcu::Vec4(f0, f1, 1.0f - f0, 1.0f - f1));
169             }
170     }
171 };
172 
173 class Tex2DShader : public sglr::ShaderProgram
174 {
175 public:
Tex2DShader(void)176     Tex2DShader(void)
177         : ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
178                         << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
179                         << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
180                         << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
181                         << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
182                         << sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_2D)
183                         << sglr::pdec::VertexSource("attribute highp vec4 a_position;\n"
184                                                     "attribute mediump vec2 a_coord;\n"
185                                                     "varying mediump vec2 v_coord;\n"
186                                                     "void main (void)\n"
187                                                     "{\n"
188                                                     "    gl_Position = a_position;\n"
189                                                     "    v_coord = a_coord;\n"
190                                                     "}\n")
191                         << sglr::pdec::FragmentSource("uniform sampler2D u_sampler0;\n"
192                                                       "varying mediump vec2 v_coord;\n"
193                                                       "void main (void)\n"
194                                                       "{\n"
195                                                       "    gl_FragColor = texture2D(u_sampler0, v_coord);\n"
196                                                       "}\n"))
197     {
198     }
199 
setUniforms(sglr::Context & ctx,uint32_t program) const200     void setUniforms(sglr::Context &ctx, uint32_t program) const
201     {
202         ctx.useProgram(program);
203         ctx.uniform1i(ctx.getUniformLocation(program, "u_sampler0"), 0);
204     }
205 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const206     void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const
207     {
208         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
209         {
210             rr::VertexPacket &packet = *packets[packetNdx];
211 
212             packet.position   = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
213             packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
214         }
215     }
216 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const217     void shadeFragments(rr::FragmentPacket *packets, const int numPackets,
218                         const rr::FragmentShadingContext &context) const
219     {
220         tcu::Vec2 texCoords[4];
221         tcu::Vec4 colors[4];
222 
223         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
224         {
225             // setup tex coords
226             for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
227             {
228                 const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
229                 texCoords[fragNdx]    = tcu::Vec2(coord.x(), coord.y());
230             }
231 
232             // Sample
233             m_uniforms[0].sampler.tex2D->sample4(colors, texCoords);
234 
235             // Write out
236             for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
237                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, colors[fragNdx]);
238         }
239     }
240 };
241 
242 static const char *s_cubeSwizzles[] = {"vec3(-1, -y, +x)", "vec3(+1, -y, -x)", "vec3(+x, -1, -y)",
243                                        "vec3(+x, +1, +y)", "vec3(-x, -y, -1)", "vec3(+x, -y, +1)"};
244 
245 class TexCubeShader : public sglr::ShaderProgram
246 {
247 public:
TexCubeShader(tcu::CubeFace face)248     TexCubeShader(tcu::CubeFace face)
249         : ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
250                         << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
251                         << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
252                         << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
253                         << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
254                         << sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_CUBE)
255                         << sglr::pdec::VertexSource("attribute highp vec4 a_position;\n"
256                                                     "attribute mediump vec2 a_coord;\n"
257                                                     "varying mediump vec2 v_coord;\n"
258                                                     "void main (void)\n"
259                                                     "{\n"
260                                                     "    gl_Position = a_position;\n"
261                                                     "    v_coord = a_coord;\n"
262                                                     "}\n")
263                         << sglr::pdec::FragmentSource(string("") +
264                                                       "uniform samplerCube u_sampler0;\n"
265                                                       "varying mediump vec2 v_coord;\n"
266                                                       "void main (void)\n"
267                                                       "{\n"
268                                                       "    mediump float x = v_coord.x*2.0 - 1.0;\n"
269                                                       "    mediump float y = v_coord.y*2.0 - 1.0;\n"
270                                                       "    gl_FragColor = textureCube(u_sampler0, " +
271                                                       s_cubeSwizzles[face] +
272                                                       ");\n"
273                                                       "}\n"))
274         , m_face(face)
275     {
276     }
277 
setUniforms(sglr::Context & ctx,uint32_t program) const278     void setUniforms(sglr::Context &ctx, uint32_t program) const
279     {
280         ctx.useProgram(program);
281         ctx.uniform1i(ctx.getUniformLocation(program, "u_sampler0"), 0);
282     }
283 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const284     void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const
285     {
286         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
287         {
288             rr::VertexPacket &packet = *packets[packetNdx];
289 
290             packet.position   = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
291             packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
292         }
293     }
294 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const295     void shadeFragments(rr::FragmentPacket *packets, const int numPackets,
296                         const rr::FragmentShadingContext &context) const
297     {
298         tcu::Vec3 texCoords[4];
299         tcu::Vec4 colors[4];
300 
301         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
302         {
303             // setup tex coords
304             for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
305             {
306                 const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
307                 const float x         = coord.x() * 2.0f - 1.0f;
308                 const float y         = coord.y() * 2.0f - 1.0f;
309 
310                 // Swizzle tex coords
311                 switch (m_face)
312                 {
313                 case tcu::CUBEFACE_NEGATIVE_X:
314                     texCoords[fragNdx] = tcu::Vec3(-1.0f, -y, +x);
315                     break;
316                 case tcu::CUBEFACE_POSITIVE_X:
317                     texCoords[fragNdx] = tcu::Vec3(+1.0f, -y, -x);
318                     break;
319                 case tcu::CUBEFACE_NEGATIVE_Y:
320                     texCoords[fragNdx] = tcu::Vec3(+x, -1.0f, -y);
321                     break;
322                 case tcu::CUBEFACE_POSITIVE_Y:
323                     texCoords[fragNdx] = tcu::Vec3(+x, +1.0f, +y);
324                     break;
325                 case tcu::CUBEFACE_NEGATIVE_Z:
326                     texCoords[fragNdx] = tcu::Vec3(-x, -y, -1.0f);
327                     break;
328                 case tcu::CUBEFACE_POSITIVE_Z:
329                     texCoords[fragNdx] = tcu::Vec3(+x, -y, +1.0f);
330                     break;
331                 default:
332                     DE_ASSERT(false);
333                 }
334             }
335 
336             // Sample
337             m_uniforms[0].sampler.texCube->sample4(colors, texCoords);
338 
339             // Write out
340             for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
341                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, colors[fragNdx]);
342         }
343     }
344 
345 private:
346     tcu::CubeFace m_face;
347 };
348 
349 enum TextureType
350 {
351     TEXTURETYPE_2D = 0,
352     TEXTURETYPE_CUBE,
353 
354     TEXTURETYPE_LAST
355 };
356 
357 enum Flags
358 {
359     MIPMAPS = (1 << 0)
360 };
361 
362 static const uint32_t s_cubeMapFaces[] = {
363     GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
364     GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
365 };
366 
367 class TextureSpecCase : public TestCase, public sglr::ContextWrapper
368 {
369 public:
370     TextureSpecCase(Context &context, const char *name, const char *desc, const TextureType type,
371                     const tcu::TextureFormat format, const uint32_t flags, int width, int height);
372     ~TextureSpecCase(void);
373 
374     IterateResult iterate(void);
375 
376 protected:
377     virtual void createTexture(void) = DE_NULL;
378 
379     const TextureType m_texType;
380     const tcu::TextureFormat m_texFormat;
381     const uint32_t m_flags;
382     const int m_width;
383     const int m_height;
384 
385     bool m_half_float_oes;
386 
387 private:
388     TextureSpecCase(const TextureSpecCase &other);
389     TextureSpecCase &operator=(const TextureSpecCase &other);
390 
391     void verifyTex2D(sglr::GLContext &gles2Context, sglr::ReferenceContext &refContext);
392     void verifyTexCube(sglr::GLContext &gles2Context, sglr::ReferenceContext &refContext);
393 
394     void renderTex2D(tcu::Surface &dst, int width, int height);
395     void renderTexCube(tcu::Surface &dst, int width, int height, tcu::CubeFace face);
396 
397     void readPixels(tcu::Surface &dst, int x, int y, int width, int height);
398 
399     // \todo [2012-03-27 pyry] Renderer should be extended to allow custom attributes, that would clean up this cubemap mess.
400     Tex2DShader m_tex2DShader;
401     TexCubeShader m_texCubeNegXShader;
402     TexCubeShader m_texCubePosXShader;
403     TexCubeShader m_texCubeNegYShader;
404     TexCubeShader m_texCubePosYShader;
405     TexCubeShader m_texCubeNegZShader;
406     TexCubeShader m_texCubePosZShader;
407 };
408 
TextureSpecCase(Context & context,const char * name,const char * desc,const TextureType type,const tcu::TextureFormat format,const uint32_t flags,int width,int height)409 TextureSpecCase::TextureSpecCase(Context &context, const char *name, const char *desc, const TextureType type,
410                                  const tcu::TextureFormat format, const uint32_t flags, int width, int height)
411     : TestCase(context, name, desc)
412     , m_texType(type)
413     , m_texFormat(format)
414     , m_flags(flags)
415     , m_width(width)
416     , m_height(height)
417     , m_texCubeNegXShader(tcu::CUBEFACE_NEGATIVE_X)
418     , m_texCubePosXShader(tcu::CUBEFACE_POSITIVE_X)
419     , m_texCubeNegYShader(tcu::CUBEFACE_NEGATIVE_Y)
420     , m_texCubePosYShader(tcu::CUBEFACE_POSITIVE_Y)
421     , m_texCubeNegZShader(tcu::CUBEFACE_NEGATIVE_Z)
422     , m_texCubePosZShader(tcu::CUBEFACE_POSITIVE_Z)
423 {
424     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
425     m_half_float_oes         = glu::hasExtension(gl, glu::ApiType::es(2, 0), "GL_OES_texture_half_float");
426 }
427 
~TextureSpecCase(void)428 TextureSpecCase::~TextureSpecCase(void)
429 {
430 }
431 
iterate(void)432 TextureSpecCase::IterateResult TextureSpecCase::iterate(void)
433 {
434     glu::RenderContext &renderCtx         = TestCase::m_context.getRenderContext();
435     const tcu::RenderTarget &renderTarget = renderCtx.getRenderTarget();
436     tcu::TestLog &log                     = m_testCtx.getLog();
437 
438     DE_ASSERT(m_width <= 256 && m_height <= 256);
439     if (renderTarget.getWidth() < m_width || renderTarget.getHeight() < m_height)
440         throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
441 
442     // Context size, and viewport for GLES2
443     de::Random rnd(deStringHash(getName()));
444     int width  = deMin32(renderTarget.getWidth(), 256);
445     int height = deMin32(renderTarget.getHeight(), 256);
446     int x      = rnd.getInt(0, renderTarget.getWidth() - width);
447     int y      = rnd.getInt(0, renderTarget.getHeight() - height);
448 
449     // Contexts.
450     sglr::GLContext gles2Context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
451     sglr::ReferenceContextBuffers refBuffers(tcu::PixelFormat(8, 8, 8, renderTarget.getPixelFormat().alphaBits ? 8 : 0),
452                                              0 /* depth */, 0 /* stencil */, width, height);
453     sglr::ReferenceContext refContext(sglr::ReferenceContextLimits(renderCtx), refBuffers.getColorbuffer(),
454                                       refBuffers.getDepthbuffer(), refBuffers.getStencilbuffer());
455 
456     // Clear color buffer.
457     for (int ndx = 0; ndx < 2; ndx++)
458     {
459         setContext(ndx ? (sglr::Context *)&refContext : (sglr::Context *)&gles2Context);
460         glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
461         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
462     }
463 
464     // Construct texture using both GLES2 and reference contexts.
465     for (int ndx = 0; ndx < 2; ndx++)
466     {
467         setContext(ndx ? (sglr::Context *)&refContext : (sglr::Context *)&gles2Context);
468         createTexture();
469         TCU_CHECK(glGetError() == GL_NO_ERROR);
470     }
471 
472     // Setup texture filtering state.
473     for (int ndx = 0; ndx < 2; ndx++)
474     {
475         setContext(ndx ? (sglr::Context *)&refContext : (sglr::Context *)&gles2Context);
476 
477         uint32_t texTarget = m_texType == TEXTURETYPE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP;
478         glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, (m_flags & MIPMAPS) ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST);
479         glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
480         glTexParameteri(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
481         glTexParameteri(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
482     }
483 
484     // Initialize case result to pass.
485     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
486 
487     // Disable logging.
488     gles2Context.enableLogging(0);
489 
490     // Verify results.
491     switch (m_texType)
492     {
493     case TEXTURETYPE_2D:
494         verifyTex2D(gles2Context, refContext);
495         break;
496     case TEXTURETYPE_CUBE:
497         verifyTexCube(gles2Context, refContext);
498         break;
499     default:
500         DE_ASSERT(false);
501     }
502 
503     return STOP;
504 }
505 
verifyTex2D(sglr::GLContext & gles2Context,sglr::ReferenceContext & refContext)506 void TextureSpecCase::verifyTex2D(sglr::GLContext &gles2Context, sglr::ReferenceContext &refContext)
507 {
508     int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
509 
510     DE_ASSERT(m_texType == TEXTURETYPE_2D);
511 
512     for (int levelNdx = 0; levelNdx < 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         if (levelW <= 2 || levelH <= 2)
520             continue; // Don't bother checking.
521 
522         // Render with GLES2
523         setContext(&gles2Context);
524         renderTex2D(result, levelW, levelH);
525 
526         // Render reference.
527         setContext(&refContext);
528         renderTex2D(reference, levelW, levelH);
529 
530         {
531             tcu::UVec4 threshold = computeCompareThreshold(m_context.getRenderTarget().getPixelFormat(), m_texFormat);
532             bool isOk            = tcu::intThresholdCompare(m_testCtx.getLog(), "Result", "Image comparison result",
533                                                             reference.getAccess(), result.getAccess(), threshold,
534                                                  levelNdx == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
535 
536             if (!isOk)
537             {
538                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
539                 break;
540             }
541         }
542     }
543 }
544 
verifyTexCube(sglr::GLContext & gles2Context,sglr::ReferenceContext & refContext)545 void TextureSpecCase::verifyTexCube(sglr::GLContext &gles2Context, sglr::ReferenceContext &refContext)
546 {
547     int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
548 
549     DE_ASSERT(m_texType == TEXTURETYPE_CUBE);
550 
551     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
552     {
553         int levelW = de::max(1, m_width >> levelNdx);
554         int levelH = de::max(1, m_height >> levelNdx);
555         bool isOk  = true;
556 
557         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
558         {
559             tcu::Surface reference;
560             tcu::Surface result;
561 
562             if (levelW <= 2 || levelH <= 2)
563                 continue; // Don't bother checking.
564 
565             // Render with GLES2
566             setContext(&gles2Context);
567             renderTexCube(result, levelW, levelH, (tcu::CubeFace)face);
568 
569             // Render reference.
570             setContext(&refContext);
571             renderTexCube(reference, levelW, levelH, (tcu::CubeFace)face);
572 
573             const float threshold = 0.02f;
574             isOk                  = tcu::fuzzyCompare(m_testCtx.getLog(), "Result",
575                                                       (string("Image comparison result: ") + de::toString((tcu::CubeFace)face)).c_str(),
576                                                       reference, result, threshold,
577                                      levelNdx == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
578 
579             if (!isOk)
580             {
581                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
582                 break;
583             }
584         }
585 
586         if (!isOk)
587             break;
588     }
589 }
590 
renderTex2D(tcu::Surface & dst,int width,int height)591 void TextureSpecCase::renderTex2D(tcu::Surface &dst, int width, int height)
592 {
593     int targetW = getWidth();
594     int targetH = getHeight();
595 
596     float w = (float)width / (float)targetW;
597     float h = (float)height / (float)targetH;
598 
599     uint32_t shaderID = getCurrentContext()->createProgram(&m_tex2DShader);
600 
601     m_tex2DShader.setUniforms(*getCurrentContext(), shaderID);
602     sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f),
603                    tcu::Vec3(-1.0f + w * 2.0f, -1.0f + h * 2.0f, 0.0f));
604 
605     // Read pixels back.
606     readPixels(dst, 0, 0, width, height);
607 }
608 
renderTexCube(tcu::Surface & dst,int width,int height,tcu::CubeFace face)609 void TextureSpecCase::renderTexCube(tcu::Surface &dst, int width, int height, tcu::CubeFace face)
610 {
611     int targetW = getWidth();
612     int targetH = getHeight();
613 
614     float w = (float)width / (float)targetW;
615     float h = (float)height / (float)targetH;
616 
617     TexCubeShader *shaders[] = {&m_texCubeNegXShader, &m_texCubePosXShader, &m_texCubeNegYShader,
618                                 &m_texCubePosYShader, &m_texCubeNegZShader, &m_texCubePosZShader};
619 
620     uint32_t shaderID = getCurrentContext()->createProgram(shaders[face]);
621 
622     shaders[face]->setUniforms(*getCurrentContext(), shaderID);
623     sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f),
624                    tcu::Vec3(-1.0f + w * 2.0f, -1.0f + h * 2.0f, 0.0f));
625 
626     // Read pixels back.
627     readPixels(dst, 0, 0, width, height);
628 }
629 
readPixels(tcu::Surface & dst,int x,int y,int width,int height)630 void TextureSpecCase::readPixels(tcu::Surface &dst, int x, int y, int width, int height)
631 {
632     dst.setSize(width, height);
633     glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, dst.getAccess().getDataPtr());
634 }
635 
636 // Basic TexImage2D() with 2D texture usage
637 class BasicTexImage2DCase : public TextureSpecCase
638 {
639 public:
BasicTexImage2DCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,uint32_t flags,int width,int height)640     BasicTexImage2DCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
641                         uint32_t flags, int width, int height)
642         : TextureSpecCase(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width,
643                           height)
644         , m_format(format)
645         , m_dataType(dataType)
646     {
647     }
648 
649 protected:
createTexture(void)650     void createTexture(void)
651     {
652         tcu::TextureFormat fmt = m_texFormat;
653         int numLevels          = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
654         uint32_t tex           = 0;
655         tcu::TextureLevel levelData(fmt);
656         de::Random rnd(deStringHash(getName()));
657 
658         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
659             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
660 
661         glGenTextures(1, &tex);
662         glBindTexture(GL_TEXTURE_2D, tex);
663         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
664 
665         for (int ndx = 0; ndx < numLevels; ndx++)
666         {
667             int levelW = de::max(1, m_width >> ndx);
668             int levelH = de::max(1, m_height >> ndx);
669             Vec4 gMin  = randomVector<4>(rnd);
670             Vec4 gMax  = randomVector<4>(rnd);
671 
672             levelData.setSize(levelW, levelH);
673             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
674 
675             glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType,
676                          levelData.getAccess().getDataPtr());
677         }
678     }
679 
680     uint32_t m_format;
681     uint32_t m_dataType;
682 };
683 
684 // Basic TexImage2D() with cubemap usage
685 class BasicTexImageCubeCase : public TextureSpecCase
686 {
687 public:
BasicTexImageCubeCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,uint32_t flags,int width,int height)688     BasicTexImageCubeCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
689                           uint32_t flags, int width, int height)
690         : TextureSpecCase(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags,
691                           width, height)
692         , m_format(format)
693         , m_dataType(dataType)
694     {
695     }
696 
697 protected:
createTexture(void)698     void createTexture(void)
699     {
700         tcu::TextureFormat fmt = m_texFormat;
701         int numLevels          = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
702         uint32_t tex           = 0;
703         tcu::TextureLevel levelData(fmt);
704         de::Random rnd(deStringHash(getName()));
705 
706         DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
707 
708         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
709             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
710 
711         glGenTextures(1, &tex);
712         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
713         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
714 
715         for (int ndx = 0; ndx < numLevels; ndx++)
716         {
717             int levelW = de::max(1, m_width >> ndx);
718             int levelH = de::max(1, m_height >> ndx);
719 
720             levelData.setSize(levelW, levelH);
721 
722             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
723             {
724                 Vec4 gMin = randomVector<4>(rnd);
725                 Vec4 gMax = randomVector<4>(rnd);
726 
727                 tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
728 
729                 glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType,
730                              levelData.getAccess().getDataPtr());
731             }
732         }
733     }
734 
735     uint32_t m_format;
736     uint32_t m_dataType;
737 };
738 
739 // Randomized 2D texture specification using TexImage2D
740 class RandomOrderTexImage2DCase : public TextureSpecCase
741 {
742 public:
RandomOrderTexImage2DCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,uint32_t flags,int width,int height)743     RandomOrderTexImage2DCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
744                               uint32_t flags, int width, int height)
745         : TextureSpecCase(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width,
746                           height)
747         , m_format(format)
748         , m_dataType(dataType)
749     {
750     }
751 
752 protected:
createTexture(void)753     void createTexture(void)
754     {
755         tcu::TextureFormat fmt = m_texFormat;
756         int numLevels          = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
757         uint32_t tex           = 0;
758         tcu::TextureLevel levelData(fmt);
759         de::Random rnd(deStringHash(getName()));
760 
761         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
762             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
763 
764         glGenTextures(1, &tex);
765         glBindTexture(GL_TEXTURE_2D, tex);
766         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
767 
768         vector<int> levels(numLevels);
769 
770         for (int i = 0; i < numLevels; i++)
771             levels[i] = i;
772         rnd.shuffle(levels.begin(), levels.end());
773 
774         for (int ndx = 0; ndx < numLevels; ndx++)
775         {
776             int levelNdx = levels[ndx];
777             int levelW   = de::max(1, m_width >> levelNdx);
778             int levelH   = de::max(1, m_height >> levelNdx);
779             Vec4 gMin    = randomVector<4>(rnd);
780             Vec4 gMax    = randomVector<4>(rnd);
781 
782             levelData.setSize(levelW, levelH);
783             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
784 
785             glTexImage2D(GL_TEXTURE_2D, levelNdx, m_format, levelW, levelH, 0, m_format, m_dataType,
786                          levelData.getAccess().getDataPtr());
787         }
788     }
789 
790     uint32_t m_format;
791     uint32_t m_dataType;
792 };
793 
794 // Randomized cubemap texture specification using TexImage2D
795 class RandomOrderTexImageCubeCase : public TextureSpecCase
796 {
797 public:
RandomOrderTexImageCubeCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,uint32_t flags,int width,int height)798     RandomOrderTexImageCubeCase(Context &context, const char *name, const char *desc, uint32_t format,
799                                 uint32_t dataType, uint32_t flags, int width, int height)
800         : TextureSpecCase(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags,
801                           width, height)
802         , m_format(format)
803         , m_dataType(dataType)
804     {
805     }
806 
807 protected:
createTexture(void)808     void createTexture(void)
809     {
810         tcu::TextureFormat fmt = m_texFormat;
811         int numLevels          = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
812         uint32_t tex           = 0;
813         tcu::TextureLevel levelData(fmt);
814         de::Random rnd(deStringHash(getName()));
815 
816         DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
817 
818         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
819             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
820 
821         glGenTextures(1, &tex);
822         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
823         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
824 
825         // Level-face pairs.
826         vector<pair<int, tcu::CubeFace>> images(numLevels * 6);
827 
828         for (int ndx = 0; ndx < numLevels; ndx++)
829             for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
830                 images[ndx * 6 + face] = std::make_pair(ndx, (tcu::CubeFace)face);
831 
832         rnd.shuffle(images.begin(), images.end());
833 
834         for (int ndx = 0; ndx < (int)images.size(); ndx++)
835         {
836             int levelNdx       = images[ndx].first;
837             tcu::CubeFace face = images[ndx].second;
838             int levelW         = de::max(1, m_width >> levelNdx);
839             int levelH         = de::max(1, m_height >> levelNdx);
840             Vec4 gMin          = randomVector<4>(rnd);
841             Vec4 gMax          = randomVector<4>(rnd);
842 
843             levelData.setSize(levelW, levelH);
844             tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
845 
846             glTexImage2D(s_cubeMapFaces[face], levelNdx, m_format, levelW, levelH, 0, m_format, m_dataType,
847                          levelData.getAccess().getDataPtr());
848         }
849     }
850 
851     uint32_t m_format;
852     uint32_t m_dataType;
853 };
854 
getRowPitch(const tcu::TextureFormat & transferFmt,int rowLen,int alignment)855 static inline int getRowPitch(const tcu::TextureFormat &transferFmt, int rowLen, int alignment)
856 {
857     int basePitch = transferFmt.getPixelSize() * rowLen;
858     return alignment * (basePitch / alignment + ((basePitch % alignment) ? 1 : 0));
859 }
860 
861 // TexImage2D() unpack alignment case.
862 class TexImage2DAlignCase : public TextureSpecCase
863 {
864 public:
TexImage2DAlignCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,uint32_t flags,int width,int height,int alignment)865     TexImage2DAlignCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
866                         uint32_t flags, int width, int height, int alignment)
867         : TextureSpecCase(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width,
868                           height)
869         , m_format(format)
870         , m_dataType(dataType)
871         , m_alignment(alignment)
872     {
873     }
874 
875 protected:
createTexture(void)876     void createTexture(void)
877     {
878         tcu::TextureFormat fmt = m_texFormat;
879         int numLevels          = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
880         uint32_t tex           = 0;
881         vector<uint8_t> data;
882 
883         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
884             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
885 
886         glGenTextures(1, &tex);
887         glBindTexture(GL_TEXTURE_2D, tex);
888         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
889 
890         for (int ndx = 0; ndx < numLevels; ndx++)
891         {
892             int levelW = de::max(1, m_width >> ndx);
893             int levelH = de::max(1, m_height >> ndx);
894             Vec4 colorA(1.0f, 0.0f, 0.0f, 1.0f);
895             Vec4 colorB(0.0f, 1.0f, 0.0f, 1.0f);
896             int rowPitch = getRowPitch(fmt, levelW, m_alignment);
897             int cellSize = de::max(1, de::min(levelW >> 2, levelH >> 2));
898 
899             data.resize(rowPitch * levelH);
900             tcu::fillWithGrid(tcu::PixelBufferAccess(fmt, levelW, levelH, 1, rowPitch, 0, &data[0]), cellSize, colorA,
901                               colorB);
902 
903             glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType, &data[0]);
904         }
905     }
906 
907     uint32_t m_format;
908     uint32_t m_dataType;
909     int m_alignment;
910 };
911 
912 // TexImage2D() unpack alignment case.
913 class TexImageCubeAlignCase : public TextureSpecCase
914 {
915 public:
TexImageCubeAlignCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,uint32_t flags,int width,int height,int alignment)916     TexImageCubeAlignCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
917                           uint32_t flags, int width, int height, int alignment)
918         : TextureSpecCase(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags,
919                           width, height)
920         , m_format(format)
921         , m_dataType(dataType)
922         , m_alignment(alignment)
923     {
924     }
925 
926 protected:
createTexture(void)927     void createTexture(void)
928     {
929         tcu::TextureFormat fmt = m_texFormat;
930         int numLevels          = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
931         uint32_t tex           = 0;
932         vector<uint8_t> data;
933 
934         DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
935 
936         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
937             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
938 
939         glGenTextures(1, &tex);
940         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
941         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
942 
943         for (int ndx = 0; ndx < numLevels; ndx++)
944         {
945             int levelW   = de::max(1, m_width >> ndx);
946             int levelH   = de::max(1, m_height >> ndx);
947             int rowPitch = getRowPitch(fmt, levelW, m_alignment);
948             Vec4 colorA(1.0f, 0.0f, 0.0f, 1.0f);
949             Vec4 colorB(0.0f, 1.0f, 0.0f, 1.0f);
950             int cellSize = de::max(1, de::min(levelW >> 2, levelH >> 2));
951 
952             data.resize(rowPitch * levelH);
953             tcu::fillWithGrid(tcu::PixelBufferAccess(fmt, levelW, levelH, 1, rowPitch, 0, &data[0]), cellSize, colorA,
954                               colorB);
955 
956             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
957                 glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType, &data[0]);
958         }
959     }
960 
961     uint32_t m_format;
962     uint32_t m_dataType;
963     int m_alignment;
964 };
965 
966 // Basic TexSubImage2D() with 2D texture usage
967 class BasicTexSubImage2DCase : public TextureSpecCase
968 {
969 public:
BasicTexSubImage2DCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,uint32_t flags,int width,int height)970     BasicTexSubImage2DCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
971                            uint32_t flags, int width, int height)
972         : TextureSpecCase(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width,
973                           height)
974         , m_format(format)
975         , m_dataType(dataType)
976     {
977     }
978 
979 protected:
createTexture(void)980     void createTexture(void)
981     {
982         tcu::TextureFormat fmt = m_texFormat;
983         int numLevels          = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
984         uint32_t tex           = 0;
985         tcu::TextureLevel data(fmt);
986         de::Random rnd(deStringHash(getName()));
987 
988         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
989             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
990 
991         glGenTextures(1, &tex);
992         glBindTexture(GL_TEXTURE_2D, tex);
993         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
994 
995         // First specify full texture.
996         for (int ndx = 0; ndx < numLevels; ndx++)
997         {
998             int levelW = de::max(1, m_width >> ndx);
999             int levelH = de::max(1, m_height >> ndx);
1000             Vec4 gMin  = randomVector<4>(rnd);
1001             Vec4 gMax  = randomVector<4>(rnd);
1002 
1003             data.setSize(levelW, levelH);
1004             tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1005 
1006             glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType,
1007                          data.getAccess().getDataPtr());
1008         }
1009 
1010         // Re-specify parts of each level.
1011         for (int ndx = 0; ndx < numLevels; ndx++)
1012         {
1013             int levelW = de::max(1, m_width >> ndx);
1014             int levelH = de::max(1, m_height >> ndx);
1015 
1016             int w = rnd.getInt(1, levelW);
1017             int h = rnd.getInt(1, levelH);
1018             int x = rnd.getInt(0, levelW - w);
1019             int y = rnd.getInt(0, levelH - h);
1020 
1021             Vec4 colorA  = randomVector<4>(rnd);
1022             Vec4 colorB  = randomVector<4>(rnd);
1023             int cellSize = rnd.getInt(2, 16);
1024 
1025             data.setSize(w, h);
1026             tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
1027 
1028             glTexSubImage2D(GL_TEXTURE_2D, ndx, x, y, w, h, m_format, m_dataType, data.getAccess().getDataPtr());
1029         }
1030     }
1031 
1032     uint32_t m_format;
1033     uint32_t m_dataType;
1034 };
1035 
1036 // Basic TexSubImage2D() with cubemap usage
1037 class BasicTexSubImageCubeCase : public TextureSpecCase
1038 {
1039 public:
BasicTexSubImageCubeCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,uint32_t flags,int width,int height)1040     BasicTexSubImageCubeCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
1041                              uint32_t flags, int width, int height)
1042         : TextureSpecCase(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags,
1043                           width, height)
1044         , m_format(format)
1045         , m_dataType(dataType)
1046     {
1047     }
1048 
1049 protected:
createTexture(void)1050     void createTexture(void)
1051     {
1052         tcu::TextureFormat fmt = m_texFormat;
1053         int numLevels          = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
1054         uint32_t tex           = 0;
1055         tcu::TextureLevel data(fmt);
1056         de::Random rnd(deStringHash(getName()));
1057 
1058         DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
1059 
1060         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
1061             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
1062 
1063         glGenTextures(1, &tex);
1064         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1065         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1066 
1067         for (int ndx = 0; ndx < numLevels; ndx++)
1068         {
1069             int levelW = de::max(1, m_width >> ndx);
1070             int levelH = de::max(1, m_height >> ndx);
1071 
1072             data.setSize(levelW, levelH);
1073 
1074             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1075             {
1076                 Vec4 gMin = randomVector<4>(rnd);
1077                 Vec4 gMax = randomVector<4>(rnd);
1078 
1079                 tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1080 
1081                 glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType,
1082                              data.getAccess().getDataPtr());
1083             }
1084         }
1085 
1086         // Re-specify parts of each face and level.
1087         for (int ndx = 0; ndx < numLevels; ndx++)
1088         {
1089             int levelW = de::max(1, m_width >> ndx);
1090             int levelH = de::max(1, m_height >> ndx);
1091 
1092             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1093             {
1094                 int w = rnd.getInt(1, levelW);
1095                 int h = rnd.getInt(1, levelH);
1096                 int x = rnd.getInt(0, levelW - w);
1097                 int y = rnd.getInt(0, levelH - h);
1098 
1099                 Vec4 colorA  = randomVector<4>(rnd);
1100                 Vec4 colorB  = randomVector<4>(rnd);
1101                 int cellSize = rnd.getInt(2, 16);
1102 
1103                 data.setSize(w, h);
1104                 tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
1105 
1106                 glTexSubImage2D(s_cubeMapFaces[face], ndx, x, y, w, h, m_format, m_dataType,
1107                                 data.getAccess().getDataPtr());
1108             }
1109         }
1110     }
1111 
1112     uint32_t m_format;
1113     uint32_t m_dataType;
1114 };
1115 
1116 // TexSubImage2D() to texture initialized with empty data
1117 class TexSubImage2DEmptyTexCase : public TextureSpecCase
1118 {
1119 public:
TexSubImage2DEmptyTexCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,uint32_t flags,int width,int height)1120     TexSubImage2DEmptyTexCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
1121                               uint32_t flags, int width, int height)
1122         : TextureSpecCase(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width,
1123                           height)
1124         , m_format(format)
1125         , m_dataType(dataType)
1126     {
1127     }
1128 
1129 protected:
createTexture(void)1130     void createTexture(void)
1131     {
1132         tcu::TextureFormat fmt = m_texFormat;
1133         int numLevels          = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
1134         uint32_t tex           = 0;
1135         tcu::TextureLevel data(fmt);
1136         de::Random rnd(deStringHash(getName()));
1137 
1138         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
1139             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
1140 
1141         glGenTextures(1, &tex);
1142         glBindTexture(GL_TEXTURE_2D, tex);
1143         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1144 
1145         // First allocate storage for each level.
1146         for (int ndx = 0; ndx < numLevels; ndx++)
1147         {
1148             int levelW = de::max(1, m_width >> ndx);
1149             int levelH = de::max(1, m_height >> ndx);
1150 
1151             glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType, DE_NULL);
1152         }
1153 
1154         // Specify pixel data to all levels using glTexSubImage2D()
1155         for (int ndx = 0; ndx < numLevels; ndx++)
1156         {
1157             int levelW = de::max(1, m_width >> ndx);
1158             int levelH = de::max(1, m_height >> ndx);
1159             Vec4 gMin  = randomVector<4>(rnd);
1160             Vec4 gMax  = randomVector<4>(rnd);
1161 
1162             data.setSize(levelW, levelH);
1163             tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1164 
1165             glTexSubImage2D(GL_TEXTURE_2D, ndx, 0, 0, levelW, levelH, m_format, m_dataType,
1166                             data.getAccess().getDataPtr());
1167         }
1168     }
1169 
1170     uint32_t m_format;
1171     uint32_t m_dataType;
1172 };
1173 
1174 // TexSubImage2D() to empty cubemap texture
1175 class TexSubImageCubeEmptyTexCase : public TextureSpecCase
1176 {
1177 public:
TexSubImageCubeEmptyTexCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,uint32_t flags,int width,int height)1178     TexSubImageCubeEmptyTexCase(Context &context, const char *name, const char *desc, uint32_t format,
1179                                 uint32_t dataType, uint32_t flags, int width, int height)
1180         : TextureSpecCase(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags,
1181                           width, height)
1182         , m_format(format)
1183         , m_dataType(dataType)
1184     {
1185     }
1186 
1187 protected:
createTexture(void)1188     void createTexture(void)
1189     {
1190         tcu::TextureFormat fmt = m_texFormat;
1191         int numLevels          = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
1192         uint32_t tex           = 0;
1193         tcu::TextureLevel data(fmt);
1194         de::Random rnd(deStringHash(getName()));
1195 
1196         DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
1197 
1198         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
1199             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
1200 
1201         glGenTextures(1, &tex);
1202         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1203         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1204 
1205         // Specify storage for each level.
1206         for (int ndx = 0; ndx < numLevels; ndx++)
1207         {
1208             int levelW = de::max(1, m_width >> ndx);
1209             int levelH = de::max(1, m_height >> ndx);
1210 
1211             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1212                 glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType, DE_NULL);
1213         }
1214 
1215         // Specify data using glTexSubImage2D()
1216         for (int ndx = 0; ndx < numLevels; ndx++)
1217         {
1218             int levelW = de::max(1, m_width >> ndx);
1219             int levelH = de::max(1, m_height >> ndx);
1220 
1221             data.setSize(levelW, levelH);
1222 
1223             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1224             {
1225                 Vec4 gMin = randomVector<4>(rnd);
1226                 Vec4 gMax = randomVector<4>(rnd);
1227 
1228                 tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1229 
1230                 glTexSubImage2D(s_cubeMapFaces[face], ndx, 0, 0, levelW, levelH, m_format, m_dataType,
1231                                 data.getAccess().getDataPtr());
1232             }
1233         }
1234     }
1235 
1236     uint32_t m_format;
1237     uint32_t m_dataType;
1238 };
1239 
1240 // TexSubImage2D() unpack alignment with 2D texture
1241 class TexSubImage2DAlignCase : public TextureSpecCase
1242 {
1243 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)1244     TexSubImage2DAlignCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
1245                            int width, int height, int subX, int subY, int subW, int subH, int alignment)
1246         : TextureSpecCase(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType),
1247                           0 /* Mipmaps are never used */, width, height)
1248         , m_format(format)
1249         , m_dataType(dataType)
1250         , m_subX(subX)
1251         , m_subY(subY)
1252         , m_subW(subW)
1253         , m_subH(subH)
1254         , m_alignment(alignment)
1255     {
1256     }
1257 
1258 protected:
createTexture(void)1259     void createTexture(void)
1260     {
1261         tcu::TextureFormat fmt = m_texFormat;
1262         uint32_t tex           = 0;
1263         vector<uint8_t> data;
1264 
1265         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
1266             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
1267 
1268         glGenTextures(1, &tex);
1269         glBindTexture(GL_TEXTURE_2D, tex);
1270 
1271         // Specify base level.
1272         data.resize(fmt.getPixelSize() * m_width * m_height);
1273         tcu::fillWithComponentGradients(tcu::PixelBufferAccess(fmt, m_width, m_height, 1, &data[0]), Vec4(0.0f),
1274                                         Vec4(1.0f));
1275 
1276         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1277         glTexImage2D(GL_TEXTURE_2D, 0, m_format, m_width, m_height, 0, m_format, m_dataType, &data[0]);
1278 
1279         // Re-specify subrectangle.
1280         int rowPitch = getRowPitch(fmt, m_subW, m_alignment);
1281         data.resize(rowPitch * m_subH);
1282         tcu::fillWithGrid(tcu::PixelBufferAccess(fmt, m_subW, m_subH, 1, rowPitch, 0, &data[0]), 4,
1283                           Vec4(1.0f, 0.0f, 0.0f, 1.0f), Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1284 
1285         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1286         glTexSubImage2D(GL_TEXTURE_2D, 0, m_subX, m_subY, m_subW, m_subH, m_format, m_dataType, &data[0]);
1287     }
1288 
1289     uint32_t m_format;
1290     uint32_t m_dataType;
1291     int m_subX;
1292     int m_subY;
1293     int m_subW;
1294     int m_subH;
1295     int m_alignment;
1296 };
1297 
1298 // TexSubImage2D() unpack alignment with cubemap texture
1299 class TexSubImageCubeAlignCase : public TextureSpecCase
1300 {
1301 public:
TexSubImageCubeAlignCase(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)1302     TexSubImageCubeAlignCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
1303                              int width, int height, int subX, int subY, int subW, int subH, int alignment)
1304         : TextureSpecCase(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType),
1305                           0 /* Mipmaps are never used */, width, height)
1306         , m_format(format)
1307         , m_dataType(dataType)
1308         , m_subX(subX)
1309         , m_subY(subY)
1310         , m_subW(subW)
1311         , m_subH(subH)
1312         , m_alignment(alignment)
1313     {
1314     }
1315 
1316 protected:
createTexture(void)1317     void createTexture(void)
1318     {
1319         tcu::TextureFormat fmt = m_texFormat;
1320         uint32_t tex           = 0;
1321         vector<uint8_t> data;
1322 
1323         DE_ASSERT(m_width == m_height);
1324 
1325         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
1326             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
1327 
1328         glGenTextures(1, &tex);
1329         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1330 
1331         // Specify base level.
1332         data.resize(fmt.getPixelSize() * m_width * m_height);
1333         tcu::fillWithComponentGradients(tcu::PixelBufferAccess(fmt, m_width, m_height, 1, &data[0]), Vec4(0.0f),
1334                                         Vec4(1.0f));
1335 
1336         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1337         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1338             glTexImage2D(s_cubeMapFaces[face], 0, m_format, m_width, m_height, 0, m_format, m_dataType, &data[0]);
1339 
1340         // Re-specify subrectangle.
1341         int rowPitch = getRowPitch(fmt, m_subW, m_alignment);
1342         data.resize(rowPitch * m_subH);
1343         tcu::fillWithGrid(tcu::PixelBufferAccess(fmt, m_subW, m_subH, 1, rowPitch, 0, &data[0]), 4,
1344                           Vec4(1.0f, 0.0f, 0.0f, 1.0f), Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1345 
1346         glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1347         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1348             glTexSubImage2D(s_cubeMapFaces[face], 0, m_subX, m_subY, m_subW, m_subH, m_format, m_dataType, &data[0]);
1349     }
1350 
1351     uint32_t m_format;
1352     uint32_t m_dataType;
1353     int m_subX;
1354     int m_subY;
1355     int m_subW;
1356     int m_subH;
1357     int m_alignment;
1358 };
1359 
1360 // Basic CopyTexImage2D() with 2D texture usage
1361 class BasicCopyTexImage2DCase : public TextureSpecCase
1362 {
1363 public:
BasicCopyTexImage2DCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,uint32_t flags,int width,int height)1364     BasicCopyTexImage2DCase(Context &context, const char *name, const char *desc, uint32_t internalFormat,
1365                             uint32_t flags, int width, int height)
1366         : TextureSpecCase(context, name, desc, TEXTURETYPE_2D, mapGLUnsizedInternalFormat(internalFormat), flags, width,
1367                           height)
1368         , m_internalFormat(internalFormat)
1369     {
1370     }
1371 
1372 protected:
createTexture(void)1373     void createTexture(void)
1374     {
1375         const tcu::RenderTarget &renderTarget = TestCase::m_context.getRenderContext().getRenderTarget();
1376         bool targetHasRGB = renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 &&
1377                             renderTarget.getPixelFormat().blueBits > 0;
1378         bool targetHasAlpha    = renderTarget.getPixelFormat().alphaBits > 0;
1379         tcu::TextureFormat fmt = m_texFormat;
1380         bool texHasRGB         = fmt.order != tcu::TextureFormat::A;
1381         bool texHasAlpha       = fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA ||
1382                            fmt.order == tcu::TextureFormat::A;
1383         int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
1384         uint32_t tex  = 0;
1385         de::Random rnd(deStringHash(getName()));
1386         GradientShader shader;
1387         uint32_t shaderID = getCurrentContext()->createProgram(&shader);
1388 
1389         if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
1390             throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
1391 
1392         // Fill render target with gradient.
1393         sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
1394 
1395         glGenTextures(1, &tex);
1396         glBindTexture(GL_TEXTURE_2D, tex);
1397 
1398         for (int ndx = 0; ndx < numLevels; ndx++)
1399         {
1400             int levelW = de::max(1, m_width >> ndx);
1401             int levelH = de::max(1, m_height >> ndx);
1402             int x      = rnd.getInt(0, getWidth() - levelW);
1403             int y      = rnd.getInt(0, getHeight() - levelH);
1404 
1405             glCopyTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, x, y, levelW, levelH, 0);
1406         }
1407     }
1408 
1409     uint32_t m_internalFormat;
1410 };
1411 
1412 // Basic CopyTexImage2D() with cubemap usage
1413 class BasicCopyTexImageCubeCase : public TextureSpecCase
1414 {
1415 public:
BasicCopyTexImageCubeCase(Context & context,const char * name,const char * desc,uint32_t internalFormat,uint32_t flags,int width,int height)1416     BasicCopyTexImageCubeCase(Context &context, const char *name, const char *desc, uint32_t internalFormat,
1417                               uint32_t flags, int width, int height)
1418         : TextureSpecCase(context, name, desc, TEXTURETYPE_CUBE, mapGLUnsizedInternalFormat(internalFormat), flags,
1419                           width, height)
1420         , m_internalFormat(internalFormat)
1421     {
1422     }
1423 
1424 protected:
createTexture(void)1425     void createTexture(void)
1426     {
1427         const tcu::RenderTarget &renderTarget = TestCase::m_context.getRenderContext().getRenderTarget();
1428         bool targetHasRGB = renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 &&
1429                             renderTarget.getPixelFormat().blueBits > 0;
1430         bool targetHasAlpha    = renderTarget.getPixelFormat().alphaBits > 0;
1431         tcu::TextureFormat fmt = m_texFormat;
1432         bool texHasRGB         = fmt.order != tcu::TextureFormat::A;
1433         bool texHasAlpha       = fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA ||
1434                            fmt.order == tcu::TextureFormat::A;
1435         int numLevels = (m_flags & MIPMAPS) ? deLog2Floor32(m_width) + 1 : 1;
1436         uint32_t tex  = 0;
1437         de::Random rnd(deStringHash(getName()));
1438         GradientShader shader;
1439         uint32_t shaderID = getCurrentContext()->createProgram(&shader);
1440 
1441         DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
1442 
1443         if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
1444             throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
1445 
1446         // Fill render target with gradient.
1447         sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
1448 
1449         glGenTextures(1, &tex);
1450         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1451 
1452         for (int ndx = 0; ndx < numLevels; ndx++)
1453         {
1454             int levelW = de::max(1, m_width >> ndx);
1455             int levelH = de::max(1, m_height >> ndx);
1456 
1457             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1458             {
1459                 int x = rnd.getInt(0, getWidth() - levelW);
1460                 int y = rnd.getInt(0, getHeight() - levelH);
1461 
1462                 glCopyTexImage2D(s_cubeMapFaces[face], ndx, m_internalFormat, x, y, levelW, levelH, 0);
1463             }
1464         }
1465     }
1466 
1467     uint32_t m_internalFormat;
1468 };
1469 
1470 // Basic CopyTexSubImage2D() with 2D texture usage
1471 class BasicCopyTexSubImage2DCase : public TextureSpecCase
1472 {
1473 public:
BasicCopyTexSubImage2DCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,uint32_t flags,int width,int height)1474     BasicCopyTexSubImage2DCase(Context &context, const char *name, const char *desc, uint32_t format, uint32_t dataType,
1475                                uint32_t flags, int width, int height)
1476         : TextureSpecCase(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width,
1477                           height)
1478         , m_format(format)
1479         , m_dataType(dataType)
1480     {
1481     }
1482 
1483 protected:
createTexture(void)1484     void createTexture(void)
1485     {
1486         const tcu::RenderTarget &renderTarget = TestCase::m_context.getRenderContext().getRenderTarget();
1487         bool targetHasRGB = renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 &&
1488                             renderTarget.getPixelFormat().blueBits > 0;
1489         bool targetHasAlpha    = renderTarget.getPixelFormat().alphaBits > 0;
1490         tcu::TextureFormat fmt = m_texFormat;
1491         bool texHasRGB         = fmt.order != tcu::TextureFormat::A;
1492         bool texHasAlpha       = fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA ||
1493                            fmt.order == tcu::TextureFormat::A;
1494         int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
1495         uint32_t tex  = 0;
1496         tcu::TextureLevel data(fmt);
1497         de::Random rnd(deStringHash(getName()));
1498         GradientShader shader;
1499         uint32_t shaderID = getCurrentContext()->createProgram(&shader);
1500 
1501         if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
1502             throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
1503 
1504         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
1505             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
1506 
1507         glGenTextures(1, &tex);
1508         glBindTexture(GL_TEXTURE_2D, tex);
1509         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1510 
1511         // First specify full texture.
1512         for (int ndx = 0; ndx < numLevels; ndx++)
1513         {
1514             int levelW = de::max(1, m_width >> ndx);
1515             int levelH = de::max(1, m_height >> ndx);
1516 
1517             Vec4 colorA  = randomVector<4>(rnd);
1518             Vec4 colorB  = randomVector<4>(rnd);
1519             int cellSize = rnd.getInt(2, 16);
1520 
1521             data.setSize(levelW, levelH);
1522             tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
1523 
1524             glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType,
1525                          data.getAccess().getDataPtr());
1526         }
1527 
1528         // Fill render target with gradient.
1529         sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
1530 
1531         // Re-specify parts of each level.
1532         for (int ndx = 0; ndx < numLevels; ndx++)
1533         {
1534             int levelW = de::max(1, m_width >> ndx);
1535             int levelH = de::max(1, m_height >> ndx);
1536 
1537             int w  = rnd.getInt(1, levelW);
1538             int h  = rnd.getInt(1, levelH);
1539             int xo = rnd.getInt(0, levelW - w);
1540             int yo = rnd.getInt(0, levelH - h);
1541 
1542             int x = rnd.getInt(0, getWidth() - w);
1543             int y = rnd.getInt(0, getHeight() - h);
1544 
1545             glCopyTexSubImage2D(GL_TEXTURE_2D, ndx, xo, yo, x, y, w, h);
1546         }
1547     }
1548 
1549     uint32_t m_format;
1550     uint32_t m_dataType;
1551 };
1552 
1553 // Basic CopyTexSubImage2D() with cubemap usage
1554 class BasicCopyTexSubImageCubeCase : public TextureSpecCase
1555 {
1556 public:
BasicCopyTexSubImageCubeCase(Context & context,const char * name,const char * desc,uint32_t format,uint32_t dataType,uint32_t flags,int width,int height)1557     BasicCopyTexSubImageCubeCase(Context &context, const char *name, const char *desc, uint32_t format,
1558                                  uint32_t dataType, uint32_t flags, int width, int height)
1559         : TextureSpecCase(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags,
1560                           width, height)
1561         , m_format(format)
1562         , m_dataType(dataType)
1563     {
1564     }
1565 
1566 protected:
createTexture(void)1567     void createTexture(void)
1568     {
1569         const tcu::RenderTarget &renderTarget = TestCase::m_context.getRenderContext().getRenderTarget();
1570         bool targetHasRGB = renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 &&
1571                             renderTarget.getPixelFormat().blueBits > 0;
1572         bool targetHasAlpha    = renderTarget.getPixelFormat().alphaBits > 0;
1573         tcu::TextureFormat fmt = m_texFormat;
1574         bool texHasRGB         = fmt.order != tcu::TextureFormat::A;
1575         bool texHasAlpha       = fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA ||
1576                            fmt.order == tcu::TextureFormat::A;
1577         int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height)) + 1 : 1;
1578         uint32_t tex  = 0;
1579         tcu::TextureLevel data(fmt);
1580         de::Random rnd(deStringHash(getName()));
1581         GradientShader shader;
1582         uint32_t shaderID = getCurrentContext()->createProgram(&shader);
1583 
1584         DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
1585 
1586         if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
1587             throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
1588 
1589         if (m_dataType == GL_HALF_FLOAT_OES && !m_half_float_oes)
1590             throw tcu::NotSupportedError("GL_OES_texture_half_float is not supported", "", __FILE__, __LINE__);
1591 
1592         glGenTextures(1, &tex);
1593         glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1594         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1595 
1596         for (int ndx = 0; ndx < numLevels; ndx++)
1597         {
1598             int levelW = de::max(1, m_width >> ndx);
1599             int levelH = de::max(1, m_height >> ndx);
1600 
1601             data.setSize(levelW, levelH);
1602 
1603             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1604             {
1605                 Vec4 colorA  = randomVector<4>(rnd);
1606                 Vec4 colorB  = randomVector<4>(rnd);
1607                 int cellSize = rnd.getInt(2, 16);
1608 
1609                 tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
1610                 glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType,
1611                              data.getAccess().getDataPtr());
1612             }
1613         }
1614 
1615         // Fill render target with gradient.
1616         sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
1617 
1618         // Re-specify parts of each face and level.
1619         for (int ndx = 0; ndx < numLevels; ndx++)
1620         {
1621             int levelW = de::max(1, m_width >> ndx);
1622             int levelH = de::max(1, m_height >> ndx);
1623 
1624             for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1625             {
1626                 int w  = rnd.getInt(1, levelW);
1627                 int h  = rnd.getInt(1, levelH);
1628                 int xo = rnd.getInt(0, levelW - w);
1629                 int yo = rnd.getInt(0, levelH - h);
1630 
1631                 int x = rnd.getInt(0, getWidth() - w);
1632                 int y = rnd.getInt(0, getHeight() - h);
1633 
1634                 glCopyTexSubImage2D(s_cubeMapFaces[face], ndx, xo, yo, x, y, w, h);
1635             }
1636         }
1637     }
1638 
1639     uint32_t m_format;
1640     uint32_t m_dataType;
1641 };
1642 
TextureSpecificationTests(Context & context)1643 TextureSpecificationTests::TextureSpecificationTests(Context &context)
1644     : TestCaseGroup(context, "specification", "Texture Specification Tests")
1645 {
1646 }
1647 
~TextureSpecificationTests(void)1648 TextureSpecificationTests::~TextureSpecificationTests(void)
1649 {
1650 }
1651 
init(void)1652 void TextureSpecificationTests::init(void)
1653 {
1654     struct
1655     {
1656         const char *name;
1657         uint32_t format;
1658         uint32_t dataType;
1659     } texFormats[] = {{"a8", GL_ALPHA, GL_UNSIGNED_BYTE},
1660                       {"l8", GL_LUMINANCE, GL_UNSIGNED_BYTE},
1661                       {"la88", GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE},
1662                       {"rgb565", GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
1663                       {"rgb888", GL_RGB, GL_UNSIGNED_BYTE},
1664                       {"rgba4444", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4},
1665                       {"rgba5551", GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1},
1666                       {"rgba8888", GL_RGBA, GL_UNSIGNED_BYTE},
1667                       {"rgba16f", GL_RGBA, GL_HALF_FLOAT_OES},
1668                       {"rgb16f", GL_RGB, GL_HALF_FLOAT_OES},
1669                       {"la16f", GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES},
1670                       {"l16f", GL_LUMINANCE, GL_HALF_FLOAT_OES},
1671                       {"a16f", GL_ALPHA, GL_HALF_FLOAT_OES}};
1672 
1673     // Basic TexImage2D usage.
1674     {
1675         tcu::TestCaseGroup *basicTexImageGroup =
1676             new tcu::TestCaseGroup(m_testCtx, "basic_teximage2d", "Basic glTexImage2D() usage");
1677         addChild(basicTexImageGroup);
1678         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(texFormats); formatNdx++)
1679         {
1680             const char *fmtName   = texFormats[formatNdx].name;
1681             uint32_t format       = texFormats[formatNdx].format;
1682             uint32_t dataType     = texFormats[formatNdx].dataType;
1683             const int tex2DWidth  = 64;
1684             const int tex2DHeight = 128;
1685             const int texCubeSize = 64;
1686 
1687             basicTexImageGroup->addChild(new BasicTexImage2DCase(m_context, (string(fmtName) + "_2d").c_str(), "",
1688                                                                  format, dataType, MIPMAPS, tex2DWidth, tex2DHeight));
1689             basicTexImageGroup->addChild(new BasicTexImageCubeCase(m_context, (string(fmtName) + "_cube").c_str(), "",
1690                                                                    format, dataType, MIPMAPS, texCubeSize,
1691                                                                    texCubeSize));
1692         }
1693     }
1694 
1695     // Randomized TexImage2D order.
1696     {
1697         tcu::TestCaseGroup *randomTexImageGroup =
1698             new tcu::TestCaseGroup(m_testCtx, "random_teximage2d", "Randomized glTexImage2D() usage");
1699         addChild(randomTexImageGroup);
1700 
1701         de::Random rnd(9);
1702 
1703         // 2D cases.
1704         for (int ndx = 0; ndx < 10; ndx++)
1705         {
1706             int formatNdx = rnd.getInt(0, DE_LENGTH_OF_ARRAY(texFormats) - 1);
1707             int width     = 1 << rnd.getInt(2, 8);
1708             int height    = 1 << rnd.getInt(2, 8);
1709 
1710             randomTexImageGroup->addChild(new RandomOrderTexImage2DCase(
1711                 m_context, (string("2d_") + de::toString(ndx)).c_str(), "", texFormats[formatNdx].format,
1712                 texFormats[formatNdx].dataType, MIPMAPS, width, height));
1713         }
1714 
1715         // Cubemap cases.
1716         for (int ndx = 0; ndx < 10; ndx++)
1717         {
1718             int formatNdx = rnd.getInt(0, DE_LENGTH_OF_ARRAY(texFormats) - 1);
1719             int size      = 1 << rnd.getInt(2, 8);
1720 
1721             randomTexImageGroup->addChild(new RandomOrderTexImageCubeCase(
1722                 m_context, (string("cube_") + de::toString(ndx)).c_str(), "", texFormats[formatNdx].format,
1723                 texFormats[formatNdx].dataType, MIPMAPS, size, size));
1724         }
1725     }
1726 
1727     // TexImage2D unpack alignment.
1728     {
1729         tcu::TestCaseGroup *alignGroup =
1730             new tcu::TestCaseGroup(m_testCtx, "teximage2d_align", "glTexImage2D() unpack alignment tests");
1731         addChild(alignGroup);
1732 
1733         alignGroup->addChild(
1734             new TexImage2DAlignCase(m_context, "2d_l8_4_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, MIPMAPS, 4, 8, 8));
1735         alignGroup->addChild(
1736             new TexImage2DAlignCase(m_context, "2d_l8_63_1", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 30, 1));
1737         alignGroup->addChild(
1738             new TexImage2DAlignCase(m_context, "2d_l8_63_2", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 30, 2));
1739         alignGroup->addChild(
1740             new TexImage2DAlignCase(m_context, "2d_l8_63_4", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 30, 4));
1741         alignGroup->addChild(
1742             new TexImage2DAlignCase(m_context, "2d_l8_63_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 30, 8));
1743         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgba4444_51_1", "", GL_RGBA,
1744                                                      GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 30, 1));
1745         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgba4444_51_2", "", GL_RGBA,
1746                                                      GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 30, 2));
1747         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgba4444_51_4", "", GL_RGBA,
1748                                                      GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 30, 4));
1749         alignGroup->addChild(new TexImage2DAlignCase(m_context, "2d_rgba4444_51_8", "", GL_RGBA,
1750                                                      GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 30, 8));
1751         alignGroup->addChild(
1752             new TexImage2DAlignCase(m_context, "2d_rgb888_39_1", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 43, 1));
1753         alignGroup->addChild(
1754             new TexImage2DAlignCase(m_context, "2d_rgb888_39_2", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 43, 2));
1755         alignGroup->addChild(
1756             new TexImage2DAlignCase(m_context, "2d_rgb888_39_4", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 43, 4));
1757         alignGroup->addChild(
1758             new TexImage2DAlignCase(m_context, "2d_rgb888_39_8", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 43, 8));
1759         alignGroup->addChild(
1760             new TexImage2DAlignCase(m_context, "2d_rgba8888_47_1", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 27, 1));
1761         alignGroup->addChild(
1762             new TexImage2DAlignCase(m_context, "2d_rgba8888_47_2", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 27, 2));
1763         alignGroup->addChild(
1764             new TexImage2DAlignCase(m_context, "2d_rgba8888_47_4", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 27, 4));
1765         alignGroup->addChild(
1766             new TexImage2DAlignCase(m_context, "2d_rgba8888_47_8", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 27, 8));
1767 
1768         alignGroup->addChild(
1769             new TexImageCubeAlignCase(m_context, "cube_l8_4_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, MIPMAPS, 4, 4, 8));
1770         alignGroup->addChild(
1771             new TexImageCubeAlignCase(m_context, "cube_l8_63_1", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 63, 1));
1772         alignGroup->addChild(
1773             new TexImageCubeAlignCase(m_context, "cube_l8_63_2", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 63, 2));
1774         alignGroup->addChild(
1775             new TexImageCubeAlignCase(m_context, "cube_l8_63_4", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 63, 4));
1776         alignGroup->addChild(
1777             new TexImageCubeAlignCase(m_context, "cube_l8_63_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 63, 63, 8));
1778         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgba4444_51_1", "", GL_RGBA,
1779                                                        GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 51, 1));
1780         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgba4444_51_2", "", GL_RGBA,
1781                                                        GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 51, 2));
1782         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgba4444_51_4", "", GL_RGBA,
1783                                                        GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 51, 4));
1784         alignGroup->addChild(new TexImageCubeAlignCase(m_context, "cube_rgba4444_51_8", "", GL_RGBA,
1785                                                        GL_UNSIGNED_SHORT_4_4_4_4, 0, 51, 51, 8));
1786         alignGroup->addChild(
1787             new TexImageCubeAlignCase(m_context, "cube_rgb888_39_1", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 39, 1));
1788         alignGroup->addChild(
1789             new TexImageCubeAlignCase(m_context, "cube_rgb888_39_2", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 39, 2));
1790         alignGroup->addChild(
1791             new TexImageCubeAlignCase(m_context, "cube_rgb888_39_4", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 39, 4));
1792         alignGroup->addChild(
1793             new TexImageCubeAlignCase(m_context, "cube_rgb888_39_8", "", GL_RGB, GL_UNSIGNED_BYTE, 0, 39, 39, 8));
1794         alignGroup->addChild(
1795             new TexImageCubeAlignCase(m_context, "cube_rgba8888_47_1", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 47, 1));
1796         alignGroup->addChild(
1797             new TexImageCubeAlignCase(m_context, "cube_rgba8888_47_2", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 47, 2));
1798         alignGroup->addChild(
1799             new TexImageCubeAlignCase(m_context, "cube_rgba8888_47_4", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 47, 4));
1800         alignGroup->addChild(
1801             new TexImageCubeAlignCase(m_context, "cube_rgba8888_47_8", "", GL_RGBA, GL_UNSIGNED_BYTE, 0, 47, 47, 8));
1802     }
1803 
1804     // Basic TexSubImage2D usage.
1805     {
1806         tcu::TestCaseGroup *basicTexSubImageGroup =
1807             new tcu::TestCaseGroup(m_testCtx, "basic_texsubimage2d", "Basic glTexSubImage2D() usage");
1808         addChild(basicTexSubImageGroup);
1809         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(texFormats); formatNdx++)
1810         {
1811             const char *fmtName   = texFormats[formatNdx].name;
1812             uint32_t format       = texFormats[formatNdx].format;
1813             uint32_t dataType     = texFormats[formatNdx].dataType;
1814             const int tex2DWidth  = 64;
1815             const int tex2DHeight = 128;
1816             const int texCubeSize = 64;
1817 
1818             basicTexSubImageGroup->addChild(new BasicTexSubImage2DCase(
1819                 m_context, (string(fmtName) + "_2d").c_str(), "", format, dataType, MIPMAPS, tex2DWidth, tex2DHeight));
1820             basicTexSubImageGroup->addChild(new BasicTexSubImageCubeCase(m_context, (string(fmtName) + "_cube").c_str(),
1821                                                                          "", format, dataType, MIPMAPS, texCubeSize,
1822                                                                          texCubeSize));
1823         }
1824     }
1825 
1826     // TexSubImage2D to empty texture.
1827     {
1828         tcu::TestCaseGroup *texSubImageEmptyTexGroup = new tcu::TestCaseGroup(
1829             m_testCtx, "texsubimage2d_empty_tex", "glTexSubImage2D() to texture that has storage but no data");
1830         addChild(texSubImageEmptyTexGroup);
1831         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(texFormats); formatNdx++)
1832         {
1833             const char *fmtName   = texFormats[formatNdx].name;
1834             uint32_t format       = texFormats[formatNdx].format;
1835             uint32_t dataType     = texFormats[formatNdx].dataType;
1836             const int tex2DWidth  = 64;
1837             const int tex2DHeight = 32;
1838             const int texCubeSize = 32;
1839 
1840             texSubImageEmptyTexGroup->addChild(new TexSubImage2DEmptyTexCase(
1841                 m_context, (string(fmtName) + "_2d").c_str(), "", format, dataType, MIPMAPS, tex2DWidth, tex2DHeight));
1842             texSubImageEmptyTexGroup->addChild(
1843                 new TexSubImageCubeEmptyTexCase(m_context, (string(fmtName) + "_cube").c_str(), "", format, dataType,
1844                                                 MIPMAPS, texCubeSize, texCubeSize));
1845         }
1846     }
1847 
1848     // TexSubImage2D alignment cases.
1849     {
1850         tcu::TestCaseGroup *alignGroup =
1851             new tcu::TestCaseGroup(m_testCtx, "texsubimage2d_align", "glTexSubImage2D() unpack alignment tests");
1852         addChild(alignGroup);
1853 
1854         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_l8_1_1", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64,
1855                                                         64, 13, 17, 1, 6, 1));
1856         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_l8_1_2", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64,
1857                                                         64, 13, 17, 1, 6, 2));
1858         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_l8_1_4", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64,
1859                                                         64, 13, 17, 1, 6, 4));
1860         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_l8_1_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64,
1861                                                         64, 13, 17, 1, 6, 8));
1862         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_l8_63_1", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64,
1863                                                         64, 1, 9, 63, 30, 1));
1864         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_l8_63_2", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64,
1865                                                         64, 1, 9, 63, 30, 2));
1866         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_l8_63_4", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64,
1867                                                         64, 1, 9, 63, 30, 4));
1868         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_l8_63_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE, 64,
1869                                                         64, 1, 9, 63, 30, 8));
1870         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_rgba4444_51_1", "", GL_RGBA,
1871                                                         GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 1));
1872         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_rgba4444_51_2", "", GL_RGBA,
1873                                                         GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 2));
1874         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_rgba4444_51_4", "", GL_RGBA,
1875                                                         GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 4));
1876         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_rgba4444_51_8", "", GL_RGBA,
1877                                                         GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 8));
1878         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_rgb888_39_1", "", GL_RGB, GL_UNSIGNED_BYTE, 64,
1879                                                         64, 11, 8, 39, 43, 1));
1880         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_rgb888_39_2", "", GL_RGB, GL_UNSIGNED_BYTE, 64,
1881                                                         64, 11, 8, 39, 43, 2));
1882         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_rgb888_39_4", "", GL_RGB, GL_UNSIGNED_BYTE, 64,
1883                                                         64, 11, 8, 39, 43, 4));
1884         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_rgb888_39_8", "", GL_RGB, GL_UNSIGNED_BYTE, 64,
1885                                                         64, 11, 8, 39, 43, 8));
1886         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_rgba8888_47_1", "", GL_RGBA, GL_UNSIGNED_BYTE,
1887                                                         64, 64, 10, 1, 47, 27, 1));
1888         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_rgba8888_47_2", "", GL_RGBA, GL_UNSIGNED_BYTE,
1889                                                         64, 64, 10, 1, 47, 27, 2));
1890         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_rgba8888_47_4", "", GL_RGBA, GL_UNSIGNED_BYTE,
1891                                                         64, 64, 10, 1, 47, 27, 4));
1892         alignGroup->addChild(new TexSubImage2DAlignCase(m_context, "2d_rgba8888_47_8", "", GL_RGBA, GL_UNSIGNED_BYTE,
1893                                                         64, 64, 10, 1, 47, 27, 8));
1894 
1895         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_l8_1_1", "", GL_LUMINANCE, GL_UNSIGNED_BYTE,
1896                                                           64, 64, 13, 17, 1, 6, 1));
1897         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_l8_1_2", "", GL_LUMINANCE, GL_UNSIGNED_BYTE,
1898                                                           64, 64, 13, 17, 1, 6, 2));
1899         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_l8_1_4", "", GL_LUMINANCE, GL_UNSIGNED_BYTE,
1900                                                           64, 64, 13, 17, 1, 6, 4));
1901         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_l8_1_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE,
1902                                                           64, 64, 13, 17, 1, 6, 8));
1903         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_l8_63_1", "", GL_LUMINANCE, GL_UNSIGNED_BYTE,
1904                                                           64, 64, 1, 9, 63, 30, 1));
1905         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_l8_63_2", "", GL_LUMINANCE, GL_UNSIGNED_BYTE,
1906                                                           64, 64, 1, 9, 63, 30, 2));
1907         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_l8_63_4", "", GL_LUMINANCE, GL_UNSIGNED_BYTE,
1908                                                           64, 64, 1, 9, 63, 30, 4));
1909         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_l8_63_8", "", GL_LUMINANCE, GL_UNSIGNED_BYTE,
1910                                                           64, 64, 1, 9, 63, 30, 8));
1911         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_rgba4444_51_1", "", GL_RGBA,
1912                                                           GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 1));
1913         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_rgba4444_51_2", "", GL_RGBA,
1914                                                           GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 2));
1915         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_rgba4444_51_4", "", GL_RGBA,
1916                                                           GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 4));
1917         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_rgba4444_51_8", "", GL_RGBA,
1918                                                           GL_UNSIGNED_SHORT_4_4_4_4, 64, 64, 7, 29, 51, 30, 8));
1919         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_rgb888_39_1", "", GL_RGB, GL_UNSIGNED_BYTE,
1920                                                           64, 64, 11, 8, 39, 43, 1));
1921         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_rgb888_39_2", "", GL_RGB, GL_UNSIGNED_BYTE,
1922                                                           64, 64, 11, 8, 39, 43, 2));
1923         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_rgb888_39_4", "", GL_RGB, GL_UNSIGNED_BYTE,
1924                                                           64, 64, 11, 8, 39, 43, 4));
1925         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_rgb888_39_8", "", GL_RGB, GL_UNSIGNED_BYTE,
1926                                                           64, 64, 11, 8, 39, 43, 8));
1927         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_rgba8888_47_1", "", GL_RGBA,
1928                                                           GL_UNSIGNED_BYTE, 64, 64, 10, 1, 47, 27, 1));
1929         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_rgba8888_47_2", "", GL_RGBA,
1930                                                           GL_UNSIGNED_BYTE, 64, 64, 10, 1, 47, 27, 2));
1931         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_rgba8888_47_4", "", GL_RGBA,
1932                                                           GL_UNSIGNED_BYTE, 64, 64, 10, 1, 47, 27, 4));
1933         alignGroup->addChild(new TexSubImageCubeAlignCase(m_context, "cube_rgba8888_47_8", "", GL_RGBA,
1934                                                           GL_UNSIGNED_BYTE, 64, 64, 10, 1, 47, 27, 8));
1935     }
1936 
1937     // Basic glCopyTexImage2D() cases
1938     {
1939         tcu::TestCaseGroup *copyTexImageGroup =
1940             new tcu::TestCaseGroup(m_testCtx, "basic_copyteximage2d", "Basic glCopyTexImage2D() usage");
1941         addChild(copyTexImageGroup);
1942 
1943         copyTexImageGroup->addChild(new BasicCopyTexImage2DCase(m_context, "2d_alpha", "", GL_ALPHA, MIPMAPS, 128, 64));
1944         copyTexImageGroup->addChild(
1945             new BasicCopyTexImage2DCase(m_context, "2d_luminance", "", GL_LUMINANCE, MIPMAPS, 128, 64));
1946         copyTexImageGroup->addChild(
1947             new BasicCopyTexImage2DCase(m_context, "2d_luminance_alpha", "", GL_LUMINANCE_ALPHA, MIPMAPS, 128, 64));
1948         copyTexImageGroup->addChild(new BasicCopyTexImage2DCase(m_context, "2d_rgb", "", GL_RGB, MIPMAPS, 128, 64));
1949         copyTexImageGroup->addChild(new BasicCopyTexImage2DCase(m_context, "2d_rgba", "", GL_RGBA, MIPMAPS, 128, 64));
1950 
1951         copyTexImageGroup->addChild(
1952             new BasicCopyTexImageCubeCase(m_context, "cube_alpha", "", GL_ALPHA, MIPMAPS, 64, 64));
1953         copyTexImageGroup->addChild(
1954             new BasicCopyTexImageCubeCase(m_context, "cube_luminance", "", GL_LUMINANCE, MIPMAPS, 64, 64));
1955         copyTexImageGroup->addChild(
1956             new BasicCopyTexImageCubeCase(m_context, "cube_luminance_alpha", "", GL_LUMINANCE_ALPHA, MIPMAPS, 64, 64));
1957         copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase(m_context, "cube_rgb", "", GL_RGB, MIPMAPS, 64, 64));
1958         copyTexImageGroup->addChild(
1959             new BasicCopyTexImageCubeCase(m_context, "cube_rgba", "", GL_RGBA, MIPMAPS, 64, 64));
1960     }
1961 
1962     // Basic glCopyTexSubImage2D() cases
1963     {
1964         tcu::TestCaseGroup *copyTexSubImageGroup =
1965             new tcu::TestCaseGroup(m_testCtx, "basic_copytexsubimage2d", "Basic glCopyTexSubImage2D() usage");
1966         addChild(copyTexSubImageGroup);
1967 
1968         copyTexSubImageGroup->addChild(
1969             new BasicCopyTexSubImage2DCase(m_context, "2d_alpha", "", GL_ALPHA, GL_UNSIGNED_BYTE, MIPMAPS, 128, 64));
1970         copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase(m_context, "2d_luminance", "", GL_LUMINANCE,
1971                                                                       GL_UNSIGNED_BYTE, MIPMAPS, 128, 64));
1972         copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase(
1973             m_context, "2d_luminance_alpha", "", GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, MIPMAPS, 128, 64));
1974         copyTexSubImageGroup->addChild(
1975             new BasicCopyTexSubImage2DCase(m_context, "2d_rgb", "", GL_RGB, GL_UNSIGNED_BYTE, MIPMAPS, 128, 64));
1976         copyTexSubImageGroup->addChild(
1977             new BasicCopyTexSubImage2DCase(m_context, "2d_rgba", "", GL_RGBA, GL_UNSIGNED_BYTE, MIPMAPS, 128, 64));
1978 
1979         copyTexSubImageGroup->addChild(
1980             new BasicCopyTexSubImageCubeCase(m_context, "cube_alpha", "", GL_ALPHA, GL_UNSIGNED_BYTE, MIPMAPS, 64, 64));
1981         copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase(m_context, "cube_luminance", "", GL_LUMINANCE,
1982                                                                         GL_UNSIGNED_BYTE, MIPMAPS, 64, 64));
1983         copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase(
1984             m_context, "cube_luminance_alpha", "", GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, MIPMAPS, 64, 64));
1985         copyTexSubImageGroup->addChild(
1986             new BasicCopyTexSubImageCubeCase(m_context, "cube_rgb", "", GL_RGB, GL_UNSIGNED_BYTE, MIPMAPS, 64, 64));
1987         copyTexSubImageGroup->addChild(
1988             new BasicCopyTexSubImageCubeCase(m_context, "cube_rgba", "", GL_RGBA, GL_UNSIGNED_BYTE, MIPMAPS, 64, 64));
1989     }
1990 }
1991 
1992 } // namespace Functional
1993 } // namespace gles2
1994 } // namespace deqp
1995