Merge commit '33ebb838720fdc9d4b75f74ec18e45c22a66c3f6' into merge
[platform/upstream/VK-GL-CTS.git] / modules / gles2 / accuracy / es2aTextureMipmapTests.cpp
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 Mipmapping accuracy tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es2aTextureMipmapTests.hpp"
25 #include "glsTextureTestUtil.hpp"
26 #include "gluTexture.hpp"
27 #include "gluStrUtil.hpp"
28 #include "gluTextureUtil.hpp"
29 #include "gluPixelTransfer.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuTextureUtil.hpp"
32 #include "tcuVector.hpp"
33 #include "tcuMatrix.hpp"
34 #include "tcuMatrixUtil.hpp"
35 #include "deStringUtil.hpp"
36 #include "deRandom.hpp"
37
38 #include "glwEnums.hpp"
39 #include "glwFunctions.hpp"
40
41 namespace deqp
42 {
43 namespace gles2
44 {
45 namespace Accuracy
46 {
47
48 using tcu::TestLog;
49 using std::vector;
50 using std::string;
51 using tcu::Sampler;
52 using tcu::Vec2;
53 using tcu::Mat2;
54 using tcu::Vec4;
55 using tcu::IVec2;
56 using tcu::IVec4;
57 using namespace glu;
58 using namespace gls::TextureTestUtil;
59
60 enum CoordType
61 {
62         COORDTYPE_BASIC,                //!< texCoord = translateScale(position).
63         COORDTYPE_BASIC_BIAS,   //!< Like basic, but with bias values.
64         COORDTYPE_AFFINE,               //!< texCoord = translateScaleRotateShear(position).
65         COORDTYPE_PROJECTED,    //!< Projected coordinates, w != 1
66
67         COORDTYPE_LAST
68 };
69
70 // Texture2DMipmapCase
71
72 class Texture2DMipmapCase : public tcu::TestCase
73 {
74 public:
75
76                                                                 Texture2DMipmapCase                     (tcu::TestContext&                      testCtx,
77                                                                                                                          glu::RenderContext&            renderCtx,
78                                                                                                                          const glu::ContextInfo&        renderCtxInfo,
79                                                                                                                          const char*                            name,
80                                                                                                                          const char*                            desc,
81                                                                                                                          CoordType                                      coordType,
82                                                                                                                          deUint32                                       minFilter,
83                                                                                                                          deUint32                                       wrapS,
84                                                                                                                          deUint32                                       wrapT,
85                                                                                                                          deUint32                                       format,
86                                                                                                                          deUint32                                       dataType,
87                                                                                                                          int                                            width,
88                                                                                                                          int                                            height);
89                                                                 ~Texture2DMipmapCase            (void);
90
91         void                                            init                                            (void);
92         void                                            deinit                                          (void);
93         IterateResult                           iterate                                         (void);
94
95 private:
96                                                                 Texture2DMipmapCase                     (const Texture2DMipmapCase& other);
97         Texture2DMipmapCase&            operator=                                       (const Texture2DMipmapCase& other);
98
99         glu::RenderContext&                     m_renderCtx;
100         const glu::ContextInfo&         m_renderCtxInfo;
101
102         CoordType                                       m_coordType;
103         deUint32                                        m_minFilter;
104         deUint32                                        m_wrapS;
105         deUint32                                        m_wrapT;
106         deUint32                                        m_format;
107         deUint32                                        m_dataType;
108         int                                                     m_width;
109         int                                                     m_height;
110
111         glu::Texture2D*                         m_texture;
112         TextureRenderer                         m_renderer;
113 };
114
115 Texture2DMipmapCase::Texture2DMipmapCase (tcu::TestContext&                     testCtx,
116                                                                                   glu::RenderContext&           renderCtx,
117                                                                                   const glu::ContextInfo&       renderCtxInfo,
118                                                                                   const char*                           name,
119                                                                                   const char*                           desc,
120                                                                                   CoordType                                     coordType,
121                                                                                   deUint32                                      minFilter,
122                                                                                   deUint32                                      wrapS,
123                                                                                   deUint32                                      wrapT,
124                                                                                   deUint32                                      format,
125                                                                                   deUint32                                      dataType,
126                                                                                   int                                           width,
127                                                                                   int                                           height)
128         : TestCase                      (testCtx, tcu::NODETYPE_ACCURACY, name, desc)
129         , m_renderCtx           (renderCtx)
130         , m_renderCtxInfo       (renderCtxInfo)
131         , m_coordType           (coordType)
132         , m_minFilter           (minFilter)
133         , m_wrapS                       (wrapS)
134         , m_wrapT                       (wrapT)
135         , m_format                      (format)
136         , m_dataType            (dataType)
137         , m_width                       (width)
138         , m_height                      (height)
139         , m_texture                     (DE_NULL)
140         , m_renderer            (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES,
141                                                  renderCtxInfo.isFragmentHighPrecisionSupported() ? glu::PRECISION_HIGHP // Use highp if available.
142                                                                                                                                                   : glu::PRECISION_MEDIUMP)
143 {
144 }
145
146 Texture2DMipmapCase::~Texture2DMipmapCase (void)
147 {
148         deinit();
149 }
150
151 void Texture2DMipmapCase::init (void)
152 {
153         if (!m_renderCtxInfo.isFragmentHighPrecisionSupported())
154                 m_testCtx.getLog() << TestLog::Message << "Warning: High precision not supported in fragment shaders." << TestLog::EndMessage;
155
156         m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
157
158         int numLevels = deLog2Floor32(de::max(m_width, m_height))+1;
159
160         // Fill texture with colored grid.
161         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
162         {
163                 deUint32        step            = 0xff / (numLevels-1);
164                 deUint32        inc                     = deClamp32(step*levelNdx, 0x00, 0xff);
165                 deUint32        dec                     = 0xff - inc;
166                 deUint32        rgb                     = (inc << 16) | (dec << 8) | 0xff;
167                 deUint32        color           = 0xff000000 | rgb;
168
169                 m_texture->getRefTexture().allocLevel(levelNdx);
170                 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), toVec4(tcu::RGBA(color)));
171         }
172 }
173
174 void Texture2DMipmapCase::deinit (void)
175 {
176         delete m_texture;
177         m_texture = DE_NULL;
178
179         m_renderer.clear();
180 }
181
182 static void getBasicTexCoord2D (std::vector<float>& dst, int cellNdx)
183 {
184         static const struct
185         {
186                 Vec2 bottomLeft;
187                 Vec2 topRight;
188         } s_basicCoords[] =
189         {
190                 { Vec2(-0.1f,  0.1f), Vec2( 0.8f,  1.0f) },
191                 { Vec2(-0.3f, -0.6f), Vec2( 0.7f,  0.4f) },
192                 { Vec2(-0.3f,  0.6f), Vec2( 0.7f, -0.9f) },
193                 { Vec2(-0.8f,  0.6f), Vec2( 0.7f, -0.9f) },
194
195                 { Vec2(-0.5f, -0.5f), Vec2( 1.5f,  1.5f) },
196                 { Vec2( 1.0f, -1.0f), Vec2(-1.3f,  1.0f) },
197                 { Vec2( 1.2f, -1.0f), Vec2(-1.3f,  1.6f) },
198                 { Vec2( 2.2f, -1.1f), Vec2(-1.3f,  0.8f) },
199
200                 { Vec2(-1.5f,  1.6f), Vec2( 1.7f, -1.4f) },
201                 { Vec2( 2.0f,  1.6f), Vec2( 2.3f, -1.4f) },
202                 { Vec2( 1.3f, -2.6f), Vec2(-2.7f,  2.9f) },
203                 { Vec2(-0.8f, -6.6f), Vec2( 6.0f, -0.9f) },
204
205                 { Vec2( -8.0f,   9.0f), Vec2(  8.3f,  -7.0f) },
206                 { Vec2(-16.0f,  10.0f), Vec2( 18.3f,  24.0f) },
207                 { Vec2( 30.2f,  55.0f), Vec2(-24.3f,  -1.6f) },
208                 { Vec2(-33.2f,  64.1f), Vec2( 32.1f, -64.1f) },
209         };
210
211         DE_ASSERT(de::inBounds(cellNdx, 0, DE_LENGTH_OF_ARRAY(s_basicCoords)));
212
213         const Vec2& bottomLeft  = s_basicCoords[cellNdx].bottomLeft;
214         const Vec2& topRight    = s_basicCoords[cellNdx].topRight;
215
216         computeQuadTexCoord2D(dst, bottomLeft, topRight);
217 }
218
219 static void getAffineTexCoord2D (std::vector<float>& dst, int cellNdx)
220 {
221         // Use basic coords as base.
222         getBasicTexCoord2D(dst, cellNdx);
223
224         // Rotate based on cell index.
225         float           angle           = 2.0f*DE_PI * ((float)cellNdx / 16.0f);
226         tcu::Mat2       rotMatrix       = tcu::rotationMatrix(angle);
227
228         // Second and third row are sheared.
229         float           shearX          = de::inRange(cellNdx, 4, 11) ? (float)(15-cellNdx) / 16.0f : 0.0f;
230         tcu::Mat2       shearMatrix     = tcu::shearMatrix(tcu::Vec2(shearX, 0.0f));
231
232         tcu::Mat2       transform       = rotMatrix * shearMatrix;
233         Vec2            p0                      = transform * Vec2(dst[0], dst[1]);
234         Vec2            p1                      = transform * Vec2(dst[2], dst[3]);
235         Vec2            p2                      = transform * Vec2(dst[4], dst[5]);
236         Vec2            p3                      = transform * Vec2(dst[6], dst[7]);
237
238         dst[0] = p0.x();        dst[1] = p0.y();
239         dst[2] = p1.x();        dst[3] = p1.y();
240         dst[4] = p2.x();        dst[5] = p2.y();
241         dst[6] = p3.x();        dst[7] = p3.y();
242 }
243
244 Texture2DMipmapCase::IterateResult Texture2DMipmapCase::iterate (void)
245 {
246         // Constants.
247         const deUint32                          magFilter                       = GL_NEAREST;
248
249         const glw::Functions&           gl                                      = m_renderCtx.getFunctions();
250         TestLog&                                        log                                     = m_testCtx.getLog();
251
252         const tcu::Texture2D&           refTexture                      = m_texture->getRefTexture();
253         const tcu::TextureFormat&       texFmt                          = refTexture.getFormat();
254         tcu::TextureFormatInfo          fmtInfo                         = tcu::getTextureFormatInfo(texFmt);
255
256         int                                                     texWidth                        = refTexture.getWidth();
257         int                                                     texHeight                       = refTexture.getHeight();
258         int                                                     defViewportWidth        = texWidth*4;
259         int                                                     defViewportHeight       = texHeight*4;
260
261         RandomViewport                          viewport                        (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));
262         ReferenceParams                         sampleParams            (TEXTURETYPE_2D);
263         vector<float>                           texCoord;
264         bool                                            isProjected                     = m_coordType == COORDTYPE_PROJECTED;
265         bool                                            useLodBias                      = m_coordType == COORDTYPE_BASIC_BIAS;
266
267         tcu::Surface                            renderedFrame           (viewport.width, viewport.height);
268
269         // Accuracy cases test against ideal lod computation.
270         tcu::Surface                            idealFrame                      (viewport.width, viewport.height);
271
272         // Viewport is divided into 4x4 grid.
273         int                                                     gridWidth                       = 4;
274         int                                                     gridHeight                      = 4;
275         int                                                     cellWidth                       = viewport.width / gridWidth;
276         int                                                     cellHeight                      = viewport.height / gridHeight;
277
278         // Accuracy measurements are off unless we get the expected viewport size.
279         if (viewport.width < defViewportWidth || viewport.height < defViewportHeight)
280                 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
281
282         // Sampling parameters.
283         sampleParams.sampler            = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter);
284         sampleParams.samplerType        = gls::TextureTestUtil::getSamplerType(m_texture->getRefTexture().getFormat());
285         sampleParams.colorBias          = fmtInfo.lookupBias;
286         sampleParams.colorScale         = fmtInfo.lookupScale;
287         sampleParams.flags                      = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
288
289         // Upload texture data.
290         m_texture->upload();
291
292         // Use unit 0.
293         gl.activeTexture(GL_TEXTURE0);
294
295         // Bind gradient texture and setup sampler parameters.
296         gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
297         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,              m_wrapS);
298         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,              m_wrapT);
299         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,  m_minFilter);
300         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,  magFilter);
301
302         GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
303
304         // Bias values.
305         static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
306
307         // Projection values.
308         static const Vec4 s_projections[] =
309         {
310                 Vec4(1.2f, 1.0f, 0.7f, 1.0f),
311                 Vec4(1.3f, 0.8f, 0.6f, 2.0f),
312                 Vec4(0.8f, 1.0f, 1.7f, 0.6f),
313                 Vec4(1.2f, 1.0f, 1.7f, 1.5f)
314         };
315
316         // Render cells.
317         for (int gridY = 0; gridY < gridHeight; gridY++)
318         {
319                 for (int gridX = 0; gridX < gridWidth; gridX++)
320                 {
321                         int                             curX            = cellWidth*gridX;
322                         int                             curY            = cellHeight*gridY;
323                         int                             curW            = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
324                         int                             curH            = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
325                         int                             cellNdx         = gridY*gridWidth + gridX;
326
327                         // Compute texcoord.
328                         switch (m_coordType)
329                         {
330                                 case COORDTYPE_BASIC_BIAS:      // Fall-through.
331                                 case COORDTYPE_PROJECTED:
332                                 case COORDTYPE_BASIC:           getBasicTexCoord2D      (texCoord, cellNdx);    break;
333                                 case COORDTYPE_AFFINE:          getAffineTexCoord2D     (texCoord, cellNdx);    break;
334                                 default:                                        DE_ASSERT(DE_FALSE);
335                         }
336
337                         if (isProjected)
338                                 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
339
340                         if (useLodBias)
341                                 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
342
343                         // Render with GL.
344                         gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
345                         m_renderer.renderQuad(0, &texCoord[0], sampleParams);
346
347                         // Render reference(s).
348                         {
349                                 SurfaceAccess idealDst(idealFrame, m_renderCtx.getRenderTarget().getPixelFormat(), curX, curY, curW, curH);
350                                 sampleParams.lodMode = LODMODE_EXACT;
351                                 sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], sampleParams);
352                         }
353                 }
354         }
355
356         // Read result.
357         glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
358
359         // Compare and log.
360         {
361                 const int       bestScoreDiff   = (texWidth/16)*(texHeight/16);
362                 const int       worstScoreDiff  = texWidth*texHeight;
363
364                 int score = measureAccuracy(log, idealFrame, renderedFrame, bestScoreDiff, worstScoreDiff);
365                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::toString(score).c_str());
366         }
367
368         return STOP;
369 }
370
371 // TextureCubeMipmapCase
372
373 class TextureCubeMipmapCase : public tcu::TestCase
374 {
375 public:
376
377                                                                 TextureCubeMipmapCase           (tcu::TestContext&                      testCtx,
378                                                                                                                          glu::RenderContext&            renderCtx,
379                                                                                                                          const glu::ContextInfo&        renderCtxInfo,
380                                                                                                                          const char*                            name,
381                                                                                                                          const char*                            desc,
382                                                                                                                          CoordType                                      coordType,
383                                                                                                                          deUint32                                       minFilter,
384                                                                                                                          deUint32                                       wrapS,
385                                                                                                                          deUint32                                       wrapT,
386                                                                                                                          deUint32                                       format,
387                                                                                                                          deUint32                                       dataType,
388                                                                                                                          int                                            size);
389                                                                 ~TextureCubeMipmapCase          (void);
390
391         void                                            init                                            (void);
392         void                                            deinit                                          (void);
393         IterateResult                           iterate                                         (void);
394
395 private:
396                                                                 TextureCubeMipmapCase           (const TextureCubeMipmapCase& other);
397         TextureCubeMipmapCase&          operator=                                       (const TextureCubeMipmapCase& other);
398
399         glu::RenderContext&                     m_renderCtx;
400         const glu::ContextInfo&         m_renderCtxInfo;
401
402         CoordType                                       m_coordType;
403         deUint32                                        m_minFilter;
404         deUint32                                        m_wrapS;
405         deUint32                                        m_wrapT;
406         deUint32                                        m_format;
407         deUint32                                        m_dataType;
408         int                                                     m_size;
409
410         glu::TextureCube*                       m_texture;
411         TextureRenderer                         m_renderer;
412 };
413
414 TextureCubeMipmapCase::TextureCubeMipmapCase (tcu::TestContext&                 testCtx,
415                                                                                           glu::RenderContext&           renderCtx,
416                                                                                           const glu::ContextInfo&       renderCtxInfo,
417                                                                                           const char*                           name,
418                                                                                           const char*                           desc,
419                                                                                           CoordType                                     coordType,
420                                                                                           deUint32                                      minFilter,
421                                                                                           deUint32                                      wrapS,
422                                                                                           deUint32                                      wrapT,
423                                                                                           deUint32                                      format,
424                                                                                           deUint32                                      dataType,
425                                                                                           int                                           size)
426         : TestCase                      (testCtx, tcu::NODETYPE_ACCURACY, name, desc)
427         , m_renderCtx           (renderCtx)
428         , m_renderCtxInfo       (renderCtxInfo)
429         , m_coordType           (coordType)
430         , m_minFilter           (minFilter)
431         , m_wrapS                       (wrapS)
432         , m_wrapT                       (wrapT)
433         , m_format                      (format)
434         , m_dataType            (dataType)
435         , m_size                        (size)
436         , m_texture                     (DE_NULL)
437         , m_renderer            (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES,
438                                                  renderCtxInfo.isFragmentHighPrecisionSupported() ? glu::PRECISION_HIGHP // Use highp if available.
439                                                                                                                                                   : glu::PRECISION_MEDIUMP)
440 {
441 }
442
443 TextureCubeMipmapCase::~TextureCubeMipmapCase (void)
444 {
445         deinit();
446 }
447
448 void TextureCubeMipmapCase::init (void)
449 {
450         if (!m_renderCtxInfo.isFragmentHighPrecisionSupported())
451                 m_testCtx.getLog() << TestLog::Message << "Warning: High precision not supported in fragment shaders." << TestLog::EndMessage;
452
453         m_texture = new TextureCube(m_renderCtx, m_format, m_dataType, m_size);
454
455         int numLevels = deLog2Floor32(m_size)+1;
456
457         // Fill texture with colored grid.
458         for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
459         {
460                 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
461                 {
462                         deUint32        step            = 0xff / (numLevels-1);
463                         deUint32        inc                     = deClamp32(step*levelNdx, 0x00, 0xff);
464                         deUint32        dec                     = 0xff - inc;
465                         deUint32        rgb                     = 0;
466
467                         switch (faceNdx)
468                         {
469                                 case 0: rgb = (inc << 16) | (dec << 8) | 255; break;
470                                 case 1: rgb = (255 << 16) | (inc << 8) | dec; break;
471                                 case 2: rgb = (dec << 16) | (255 << 8) | inc; break;
472                                 case 3: rgb = (dec << 16) | (inc << 8) | 255; break;
473                                 case 4: rgb = (255 << 16) | (dec << 8) | inc; break;
474                                 case 5: rgb = (inc << 16) | (255 << 8) | dec; break;
475                         }
476
477                         deUint32        color           = 0xff000000 | rgb;
478
479                         m_texture->getRefTexture().allocLevel((tcu::CubeFace)faceNdx, levelNdx);
480                         tcu::clear(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), toVec4(tcu::RGBA(color)));
481                 }
482         }
483 }
484
485 void TextureCubeMipmapCase::deinit (void)
486 {
487         delete m_texture;
488         m_texture = DE_NULL;
489
490         m_renderer.clear();
491 }
492
493 static void randomPartition (vector<IVec4>& dst, de::Random& rnd, int x, int y, int width, int height)
494 {
495         const int minWidth      = 8;
496         const int minHeight     = 8;
497
498         bool    partition               = rnd.getFloat() > 0.4f;
499         bool    partitionX              = partition && width > minWidth && rnd.getBool();
500         bool    partitionY              = partition && height > minHeight && !partitionX;
501
502         if (partitionX)
503         {
504                 int split = width/2 + rnd.getInt(-width/4, +width/4);
505                 randomPartition(dst, rnd, x, y, split, height);
506                 randomPartition(dst, rnd, x+split, y, width-split, height);
507         }
508         else if (partitionY)
509         {
510                 int split = height/2 + rnd.getInt(-height/4, +height/4);
511                 randomPartition(dst, rnd, x, y, width, split);
512                 randomPartition(dst, rnd, x, y+split, width, height-split);
513         }
514         else
515                 dst.push_back(IVec4(x, y, width, height));
516 }
517
518 static void computeGridLayout (vector<IVec4>& dst, int width, int height)
519 {
520         de::Random rnd(7);
521         randomPartition(dst, rnd, 0, 0, width, height);
522 }
523
524 TextureCubeMipmapCase::IterateResult TextureCubeMipmapCase::iterate (void)
525 {
526         // Constants.
527         const deUint32                  magFilter                       = GL_NEAREST;
528
529         int                                             texWidth                        = m_texture->getRefTexture().getSize();
530         int                                             texHeight                       = m_texture->getRefTexture().getSize();
531
532         int                                             defViewportWidth        = texWidth*2;
533         int                                             defViewportHeight       = texHeight*2;
534
535         const glw::Functions&   gl                                      = m_renderCtx.getFunctions();
536         TestLog&                                log                                     = m_testCtx.getLog();
537         RandomViewport                  viewport                        (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));
538         tcu::Sampler                    sampler                         = mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter);
539
540         vector<float>                   texCoord;
541
542         bool                                    isProjected                     = m_coordType == COORDTYPE_PROJECTED;
543         bool                                    useLodBias                      = m_coordType == COORDTYPE_BASIC_BIAS;
544
545         tcu::Surface                    renderedFrame           (viewport.width, viewport.height);
546
547         // Accuracy cases test against ideal lod computation.
548         tcu::Surface                    idealFrame                      (viewport.width, viewport.height);
549
550         // Accuracy measurements are off unless we get the expected viewport size.
551         if (viewport.width < defViewportWidth || viewport.height < defViewportHeight)
552                 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
553
554         // Upload texture data.
555         m_texture->upload();
556
557         // Use unit 0.
558         gl.activeTexture(GL_TEXTURE0);
559
560         // Bind gradient texture and setup sampler parameters.
561         gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
562         gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,                m_wrapS);
563         gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,                m_wrapT);
564         gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,    m_minFilter);
565         gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,    magFilter);
566
567         GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
568
569         // Compute grid.
570         vector<IVec4> gridLayout;
571         computeGridLayout(gridLayout, viewport.width, viewport.height);
572
573         // Bias values.
574         static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
575
576         // Projection values \note Less agressive than in 2D case due to smaller quads.
577         static const Vec4 s_projections[] =
578         {
579                 Vec4(1.2f, 1.0f, 0.7f, 1.0f),
580                 Vec4(1.3f, 0.8f, 0.6f, 1.1f),
581                 Vec4(0.8f, 1.0f, 1.2f, 0.8f),
582                 Vec4(1.2f, 1.0f, 1.3f, 0.9f)
583         };
584
585         for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
586         {
587                 int                             curX            = gridLayout[cellNdx].x();
588                 int                             curY            = gridLayout[cellNdx].y();
589                 int                             curW            = gridLayout[cellNdx].z();
590                 int                             curH            = gridLayout[cellNdx].w();
591                 tcu::CubeFace   cubeFace        = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
592                 ReferenceParams params          (TEXTURETYPE_CUBE);
593
594                 params.sampler = sampler;
595
596                 DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported.
597                 computeQuadTexCoordCube(texCoord, cubeFace);
598
599                 if (isProjected)
600                 {
601                         params.flags    |= ReferenceParams::PROJECTED;
602                         params.w                 = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
603                 }
604
605                 if (useLodBias)
606                 {
607                         params.flags    |= ReferenceParams::USE_BIAS;
608                         params.bias              = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
609                 }
610
611                 // Render with GL.
612                 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
613                 m_renderer.renderQuad(0, &texCoord[0], params);
614
615                 // Render reference(s).
616                 {
617                         SurfaceAccess idealDst(idealFrame, m_renderCtx.getRenderTarget().getPixelFormat(), curX, curY, curW, curH);
618                         params.lodMode = LODMODE_EXACT;
619                         sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params);
620                 }
621         }
622
623         // Read result.
624         glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
625
626         // Compare and log.
627         {
628                 const int       bestScoreDiff   = (texWidth/16)*(texHeight/16);
629                 const int       worstScoreDiff  = texWidth*texHeight;
630
631                 int score = measureAccuracy(log, idealFrame, renderedFrame, bestScoreDiff, worstScoreDiff);
632                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::toString(score).c_str());
633         }
634
635         return STOP;
636 }
637
638 TextureMipmapTests::TextureMipmapTests (Context& context)
639         : TestCaseGroup(context, "mipmap", "Mipmapping accuracy tests")
640 {
641 }
642
643 TextureMipmapTests::~TextureMipmapTests (void)
644 {
645 }
646
647 void TextureMipmapTests::init (void)
648 {
649         tcu::TestCaseGroup* group2D             = new tcu::TestCaseGroup(m_testCtx, "2d",       "2D Texture Mipmapping");
650         tcu::TestCaseGroup*     groupCube       = new tcu::TestCaseGroup(m_testCtx, "cube",     "Cube Map Filtering");
651         addChild(group2D);
652         addChild(groupCube);
653
654         static const struct
655         {
656                 const char*             name;
657                 deUint32                mode;
658         } wrapModes[] =
659         {
660                 { "clamp",              GL_CLAMP_TO_EDGE },
661                 { "repeat",             GL_REPEAT },
662                 { "mirror",             GL_MIRRORED_REPEAT }
663         };
664
665         static const struct
666         {
667                 const char*             name;
668                 deUint32                mode;
669         } minFilterModes[] =
670         {
671                 { "nearest_nearest",    GL_NEAREST_MIPMAP_NEAREST       },
672                 { "linear_nearest",             GL_LINEAR_MIPMAP_NEAREST        },
673                 { "nearest_linear",             GL_NEAREST_MIPMAP_LINEAR        },
674                 { "linear_linear",              GL_LINEAR_MIPMAP_LINEAR         }
675         };
676
677         static const struct
678         {
679                 CoordType               type;
680                 const char*             name;
681                 const char*             desc;
682         } coordTypes[] =
683         {
684                 { COORDTYPE_BASIC,              "basic",                "Mipmapping with translated and scaled coordinates" },
685                 { COORDTYPE_AFFINE,             "affine",               "Mipmapping with affine coordinate transform"           },
686                 { COORDTYPE_PROJECTED,  "projected",    "Mipmapping with perspective projection"                        }
687         };
688
689         const int tex2DWidth    = 64;
690         const int tex2DHeight   = 64;
691
692         // 2D cases.
693         for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
694         {
695                 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, coordTypes[coordType].name, coordTypes[coordType].desc);
696                 group2D->addChild(coordTypeGroup);
697
698                 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
699                 {
700                         for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
701                         {
702                                 std::ostringstream name;
703                                 name << minFilterModes[minFilter].name
704                                                 << "_" << wrapModes[wrapMode].name;
705
706                                 coordTypeGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
707                                                                                                                                         name.str().c_str(), "",
708                                                                                                                                         coordTypes[coordType].type,
709                                                                                                                                         minFilterModes[minFilter].mode,
710                                                                                                                                         wrapModes[wrapMode].mode,
711                                                                                                                                         wrapModes[wrapMode].mode,
712                                                                                                                                         GL_RGBA, GL_UNSIGNED_BYTE,
713                                                                                                                                         tex2DWidth, tex2DHeight));
714                         }
715                 }
716         }
717
718         const int cubeMapSize = 64;
719
720         static const struct
721         {
722                 CoordType               type;
723                 const char*             name;
724                 const char*             desc;
725         } cubeCoordTypes[] =
726         {
727                 { COORDTYPE_BASIC,              "basic",                "Mipmapping with translated and scaled coordinates" },
728                 { COORDTYPE_PROJECTED,  "projected",    "Mipmapping with perspective projection"                        }
729         };
730
731         // Cubemap cases.
732         for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++)
733         {
734                 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, cubeCoordTypes[coordType].name, cubeCoordTypes[coordType].desc);
735                 groupCube->addChild(coordTypeGroup);
736
737                 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
738                 {
739                         coordTypeGroup->addChild(new TextureCubeMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
740                                                                                                                            minFilterModes[minFilter].name, "",
741                                                                                                                            cubeCoordTypes[coordType].type,
742                                                                                                                            minFilterModes[minFilter].mode,
743                                                                                                                            GL_CLAMP_TO_EDGE,
744                                                                                                                            GL_CLAMP_TO_EDGE,
745                                                                                                                            GL_RGBA, GL_UNSIGNED_BYTE, cubeMapSize));
746                 }
747         }
748 }
749
750 } // Accuracy
751 } // gles2
752 } // deqp