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