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