Merge "x11: Fix deadlock" into nougat-cts-dev am: 34b869eeea am: b6766f9949 am: 7b1b2...
[platform/upstream/VK-GL-CTS.git] / modules / gles2 / accuracy / es2aTextureFilteringTests.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 Texture filtering accuracy tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es2aTextureFilteringTests.hpp"
25 #include "glsTextureTestUtil.hpp"
26 #include "gluTexture.hpp"
27 #include "gluStrUtil.hpp"
28 #include "gluTextureUtil.hpp"
29 #include "gluPixelTransfer.hpp"
30 #include "tcuSurfaceAccess.hpp"
31 #include "tcuTestLog.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "deStringUtil.hpp"
34
35 #include "glwFunctions.hpp"
36 #include "glwEnums.hpp"
37
38 using std::string;
39
40 namespace deqp
41 {
42 namespace gles2
43 {
44 namespace Accuracy
45 {
46
47 using tcu::TestLog;
48 using std::vector;
49 using std::string;
50 using tcu::Sampler;
51 using namespace glu;
52 using namespace gls::TextureTestUtil;
53 using namespace glu::TextureTestUtil;
54
55 class Texture2DFilteringCase : public tcu::TestCase
56 {
57 public:
58                                                                 Texture2DFilteringCase          (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height);
59                                                                 Texture2DFilteringCase          (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames);
60                                                                 ~Texture2DFilteringCase         (void);
61
62         void                                            init                                            (void);
63         void                                            deinit                                          (void);
64         IterateResult                           iterate                                         (void);
65
66 private:
67                                                                 Texture2DFilteringCase          (const Texture2DFilteringCase& other);
68         Texture2DFilteringCase&         operator=                                       (const Texture2DFilteringCase& other);
69
70         glu::RenderContext&                     m_renderCtx;
71         const glu::ContextInfo&         m_renderCtxInfo;
72
73         deUint32                                        m_minFilter;
74         deUint32                                        m_magFilter;
75         deUint32                                        m_wrapS;
76         deUint32                                        m_wrapT;
77
78         deUint32                                        m_format;
79         deUint32                                        m_dataType;
80         int                                                     m_width;
81         int                                                     m_height;
82
83         std::vector<std::string>        m_filenames;
84
85         std::vector<glu::Texture2D*>    m_textures;
86         TextureRenderer                                 m_renderer;
87 };
88
89
90 Texture2DFilteringCase::Texture2DFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height)
91         : TestCase                      (testCtx, tcu::NODETYPE_ACCURACY, name, desc)
92         , m_renderCtx           (renderCtx)
93         , m_renderCtxInfo       (ctxInfo)
94         , m_minFilter           (minFilter)
95         , m_magFilter           (magFilter)
96         , m_wrapS                       (wrapS)
97         , m_wrapT                       (wrapT)
98         , m_format                      (format)
99         , m_dataType            (dataType)
100         , m_width                       (width)
101         , m_height                      (height)
102         , m_renderer            (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
103 {
104 }
105
106 Texture2DFilteringCase::Texture2DFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames)
107         : TestCase                      (testCtx, tcu::NODETYPE_ACCURACY, name, desc)
108         , m_renderCtx           (renderCtx)
109         , m_renderCtxInfo       (ctxInfo)
110         , m_minFilter           (minFilter)
111         , m_magFilter           (magFilter)
112         , m_wrapS                       (wrapS)
113         , m_wrapT                       (wrapT)
114         , m_format                      (GL_NONE)
115         , m_dataType            (GL_NONE)
116         , m_width                       (0)
117         , m_height                      (0)
118         , m_filenames           (filenames)
119         , m_renderer            (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
120 {
121 }
122
123 Texture2DFilteringCase::~Texture2DFilteringCase (void)
124 {
125         deinit();
126 }
127
128 void Texture2DFilteringCase::init (void)
129 {
130         try
131         {
132                 if (!m_filenames.empty())
133                 {
134                         m_textures.reserve(1);
135                         m_textures.push_back(glu::Texture2D::create(m_renderCtx, m_renderCtxInfo, m_testCtx.getArchive(), (int)m_filenames.size(), m_filenames));
136                 }
137                 else
138                 {
139                         // Create 2 textures.
140                         m_textures.reserve(2);
141                         for (int ndx = 0; ndx < 2; ndx++)
142                                 m_textures.push_back(new glu::Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height));
143
144                         const bool                              mipmaps         = deIsPowerOfTwo32(m_width) && deIsPowerOfTwo32(m_height);
145                         const int                               numLevels       = mipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1;
146                         tcu::TextureFormatInfo  fmtInfo         = tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
147                         tcu::Vec4                               cBias           = fmtInfo.valueMin;
148                         tcu::Vec4                               cScale          = fmtInfo.valueMax-fmtInfo.valueMin;
149
150                         // Fill first gradient texture.
151                         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
152                         {
153                                 tcu::Vec4 gMin = tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
154                                 tcu::Vec4 gMax = tcu::Vec4( 1.0f,  1.0f,  1.0f, 0.0f)*cScale + cBias;
155
156                                 m_textures[0]->getRefTexture().allocLevel(levelNdx);
157                                 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
158                         }
159
160                         // Fill second with grid texture.
161                         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
162                         {
163                                 deUint32        step    = 0x00ffffff / numLevels;
164                                 deUint32        rgb             = step*levelNdx;
165                                 deUint32        colorA  = 0xff000000 | rgb;
166                                 deUint32        colorB  = 0xff000000 | ~rgb;
167
168                                 m_textures[1]->getRefTexture().allocLevel(levelNdx);
169                                 tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
170                         }
171
172                         // Upload.
173                         for (std::vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
174                                 (*i)->upload();
175                 }
176         }
177         catch (...)
178         {
179                 // Clean up to save memory.
180                 Texture2DFilteringCase::deinit();
181                 throw;
182         }
183 }
184
185 void Texture2DFilteringCase::deinit (void)
186 {
187         for (std::vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
188                 delete *i;
189         m_textures.clear();
190
191         m_renderer.clear();
192 }
193
194 Texture2DFilteringCase::IterateResult Texture2DFilteringCase::iterate (void)
195 {
196         const glw::Functions&           gl                                      = m_renderCtx.getFunctions();
197         TestLog&                                        log                                     = m_testCtx.getLog();
198         const int                                       defViewportWidth        = 256;
199         const int                                       defViewportHeight       = 256;
200         RandomViewport                          viewport                        (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));
201         tcu::Surface                            renderedFrame           (viewport.width, viewport.height);
202         tcu::Surface                            referenceFrame          (viewport.width, viewport.height);
203         const tcu::TextureFormat&       texFmt                          = m_textures[0]->getRefTexture().getFormat();
204         tcu::TextureFormatInfo          fmtInfo                         = tcu::getTextureFormatInfo(texFmt);
205         ReferenceParams                         refParams                       (TEXTURETYPE_2D);
206         vector<float>                           texCoord;
207
208         // Accuracy measurements are off unless viewport size is 256x256
209         if (viewport.width < defViewportWidth || viewport.height < defViewportHeight)
210                 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
211
212         // Viewport is divided into 4 sections.
213         int                             leftWidth                       = viewport.width / 2;
214         int                             rightWidth                      = viewport.width - leftWidth;
215         int                             bottomHeight            = viewport.height / 2;
216         int                             topHeight                       = viewport.height - bottomHeight;
217
218         int                             curTexNdx                       = 0;
219
220         // Use unit 0.
221         gl.activeTexture(GL_TEXTURE0);
222
223         // Bind gradient texture and setup sampler parameters.
224         gl.bindTexture(GL_TEXTURE_2D, m_textures[curTexNdx]->getGLTexture());
225         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,              m_wrapS);
226         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,              m_wrapT);
227         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,  m_minFilter);
228         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,  m_magFilter);
229
230         // Setup params for reference.
231         refParams.sampler               = mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter);
232         refParams.samplerType   = getSamplerType(texFmt);
233         refParams.lodMode               = LODMODE_EXACT;
234         refParams.colorBias             = fmtInfo.lookupBias;
235         refParams.colorScale    = fmtInfo.lookupScale;
236
237         // Bottom left: Minification
238         {
239                 gl.viewport(viewport.x, viewport.y, leftWidth, bottomHeight);
240
241                 computeQuadTexCoord2D(texCoord, tcu::Vec2(-4.0f, -4.5f), tcu::Vec2(4.0f, 2.5f));
242
243                 m_renderer.renderQuad(0, &texCoord[0], refParams);
244                 sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, 0, leftWidth, bottomHeight),
245                                           m_textures[curTexNdx]->getRefTexture(), &texCoord[0], refParams);
246         }
247
248         // Bottom right: Magnification
249         {
250                 gl.viewport(viewport.x+leftWidth, viewport.y, rightWidth, bottomHeight);
251
252                 computeQuadTexCoord2D(texCoord, tcu::Vec2(-0.5f, 0.75f), tcu::Vec2(0.25f, 1.25f));
253
254                 m_renderer.renderQuad(0, &texCoord[0], refParams);
255                 sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth, 0, rightWidth, bottomHeight),
256                                           m_textures[curTexNdx]->getRefTexture(), &texCoord[0], refParams);
257         }
258
259         if (m_textures.size() >= 2)
260         {
261                 curTexNdx += 1;
262
263                 // Setup second texture.
264                 gl.bindTexture(GL_TEXTURE_2D, m_textures[curTexNdx]->getGLTexture());
265                 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,              m_wrapS);
266                 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,              m_wrapT);
267                 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,  m_minFilter);
268                 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,  m_magFilter);
269         }
270
271         // Top left: Minification
272         // \note Minification is chosen so that 0.0 < lod <= 0.5. This way special minification threshold rule will be triggered.
273         {
274                 gl.viewport(viewport.x, viewport.y+bottomHeight, leftWidth, topHeight);
275
276                 float   sMin            = -0.5f;
277                 float   tMin            = -0.2f;
278                 float   sRange          = ((float)leftWidth * 1.2f) / (float)m_textures[curTexNdx]->getRefTexture().getWidth();
279                 float   tRange          = ((float)topHeight * 1.1f) / (float)m_textures[curTexNdx]->getRefTexture().getHeight();
280
281                 computeQuadTexCoord2D(texCoord, tcu::Vec2(sMin, tMin), tcu::Vec2(sMin+sRange, tMin+tRange));
282
283                 m_renderer.renderQuad(0, &texCoord[0], refParams);
284                 sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, bottomHeight, leftWidth, topHeight),
285                                           m_textures[curTexNdx]->getRefTexture(), &texCoord[0], refParams);
286         }
287
288         // Top right: Magnification
289         {
290                 gl.viewport(viewport.x+leftWidth, viewport.y+bottomHeight, rightWidth, topHeight);
291
292                 computeQuadTexCoord2D(texCoord, tcu::Vec2(-0.5f, 0.75f), tcu::Vec2(0.25f, 1.25f));
293
294                 m_renderer.renderQuad(0, &texCoord[0], refParams);
295                 sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth, bottomHeight, rightWidth, topHeight),
296                                           m_textures[curTexNdx]->getRefTexture(), &texCoord[0], refParams);
297         }
298
299         // Read result.
300         glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
301
302         // Compare and log.
303         {
304                 DE_ASSERT(getNodeType() == tcu::NODETYPE_ACCURACY);
305
306                 const int       bestScoreDiff   = 16;
307                 const int       worstScoreDiff  = 3200;
308
309                 int score = measureAccuracy(log, referenceFrame, renderedFrame, bestScoreDiff, worstScoreDiff);
310                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::toString(score).c_str());
311         }
312
313         return STOP;
314 }
315
316 class TextureCubeFilteringCase : public tcu::TestCase
317 {
318 public:
319                                                                 TextureCubeFilteringCase        (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height);
320                                                                 TextureCubeFilteringCase        (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames);
321                                                                 ~TextureCubeFilteringCase       (void);
322
323         void                                            init                                            (void);
324         void                                            deinit                                          (void);
325         IterateResult                           iterate                                         (void);
326
327 private:
328                                                                 TextureCubeFilteringCase        (const TextureCubeFilteringCase& other);
329         TextureCubeFilteringCase&       operator=                                       (const TextureCubeFilteringCase& other);
330
331         glu::RenderContext&                     m_renderCtx;
332         const glu::ContextInfo&         m_renderCtxInfo;
333
334         deUint32                                        m_minFilter;
335         deUint32                                        m_magFilter;
336         deUint32                                        m_wrapS;
337         deUint32                                        m_wrapT;
338
339         deUint32                                        m_format;
340         deUint32                                        m_dataType;
341         int                                                     m_width;
342         int                                                     m_height;
343
344         std::vector<std::string>        m_filenames;
345
346         std::vector<glu::TextureCube*>  m_textures;
347         TextureRenderer                                 m_renderer;
348 };
349
350
351 TextureCubeFilteringCase::TextureCubeFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height)
352         : TestCase                                      (testCtx, tcu::NODETYPE_ACCURACY, name, desc)
353         , m_renderCtx                           (renderCtx)
354         , m_renderCtxInfo                       (ctxInfo)
355         , m_minFilter                           (minFilter)
356         , m_magFilter                           (magFilter)
357         , m_wrapS                                       (wrapS)
358         , m_wrapT                                       (wrapT)
359         , m_format                                      (format)
360         , m_dataType                            (dataType)
361         , m_width                                       (width)
362         , m_height                                      (height)
363         , m_renderer                            (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
364 {
365 }
366
367 TextureCubeFilteringCase::TextureCubeFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames)
368         : TestCase                                      (testCtx, tcu::NODETYPE_ACCURACY, name, desc)
369         , m_renderCtx                           (renderCtx)
370         , m_renderCtxInfo                       (ctxInfo)
371         , m_minFilter                           (minFilter)
372         , m_magFilter                           (magFilter)
373         , m_wrapS                                       (wrapS)
374         , m_wrapT                                       (wrapT)
375         , m_format                                      (GL_NONE)
376         , m_dataType                            (GL_NONE)
377         , m_width                                       (0)
378         , m_height                                      (0)
379         , m_filenames                           (filenames)
380         , m_renderer                            (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
381 {
382 }
383
384 TextureCubeFilteringCase::~TextureCubeFilteringCase (void)
385 {
386         deinit();
387 }
388
389 void TextureCubeFilteringCase::init (void)
390 {
391         try
392         {
393                 if (!m_filenames.empty())
394                 {
395                         m_textures.reserve(1);
396                         m_textures.push_back(glu::TextureCube::create(m_renderCtx, m_renderCtxInfo, m_testCtx.getArchive(), (int)m_filenames.size() / 6, m_filenames));
397                 }
398                 else
399                 {
400                         m_textures.reserve(2);
401                         DE_ASSERT(m_width == m_height);
402                         for (int ndx = 0; ndx < 2; ndx++)
403                                 m_textures.push_back(new glu::TextureCube(m_renderCtx, m_format, m_dataType, m_width));
404
405                         const bool                              mipmaps         = deIsPowerOfTwo32(m_width) && deIsPowerOfTwo32(m_height);
406                         const int                               numLevels       = mipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1;
407                         tcu::TextureFormatInfo  fmtInfo         = tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
408                         tcu::Vec4                               cBias           = fmtInfo.valueMin;
409                         tcu::Vec4                               cScale          = fmtInfo.valueMax-fmtInfo.valueMin;
410
411                         // Fill first with gradient texture.
412                         static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
413                         {
414                                 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
415                                 { tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
416                                 { tcu::Vec4(-1.0f,  0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
417                                 { tcu::Vec4(-1.0f, -1.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
418                                 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
419                                 { tcu::Vec4( 0.0f,  0.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }  // positive z
420                         };
421                         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
422                         {
423                                 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
424                                 {
425                                         m_textures[0]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
426                                         tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias);
427                                 }
428                         }
429
430                         // Fill second with grid texture.
431                         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
432                         {
433                                 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
434                                 {
435                                         deUint32        step    = 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
436                                         deUint32        rgb             = step*levelNdx*face;
437                                         deUint32        colorA  = 0xff000000 | rgb;
438                                         deUint32        colorB  = 0xff000000 | ~rgb;
439
440                                         m_textures[1]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
441                                         tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
442                                 }
443                         }
444
445                         // Upload.
446                         for (std::vector<glu::TextureCube*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
447                                 (*i)->upload();
448                 }
449         }
450         catch (const std::exception&)
451         {
452                 // Clean up to save memory.
453                 TextureCubeFilteringCase::deinit();
454                 throw;
455         }
456 }
457
458 void TextureCubeFilteringCase::deinit (void)
459 {
460         for (std::vector<glu::TextureCube*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
461                 delete *i;
462         m_textures.clear();
463
464         m_renderer.clear();
465 }
466
467 static void renderFaces (
468         const glw::Functions&           gl,
469         const tcu::SurfaceAccess&       dstRef,
470         const tcu::TextureCube&         refTexture,
471         const ReferenceParams&          params,
472         TextureRenderer&                        renderer,
473         int                                                     x,
474         int                                                     y,
475         int                                                     width,
476         int                                                     height,
477         const tcu::Vec2&                        bottomLeft,
478         const tcu::Vec2&                        topRight,
479         const tcu::Vec2&                        texCoordTopRightFactor)
480 {
481         DE_ASSERT(width == dstRef.getWidth() && height == dstRef.getHeight());
482
483         vector<float> texCoord;
484
485         DE_STATIC_ASSERT(tcu::CUBEFACE_LAST == 6);
486         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
487         {
488                 bool    isRightmost             = (face == 2) || (face == 5);
489                 bool    isTop                   = face >= 3;
490                 int             curX                    = (face % 3) * (width  / 3);
491                 int             curY                    = (face / 3) * (height / 2);
492                 int             curW                    = isRightmost   ? (width-curX)  : (width        / 3);
493                 int             curH                    = isTop                 ? (height-curY) : (height       / 2);
494
495                 computeQuadTexCoordCube(texCoord, (tcu::CubeFace)face, bottomLeft, topRight);
496
497                 {
498                         // Move the top and right edges of the texture coord quad. This is useful when we want a cube edge visible.
499                         int texCoordSRow = face == tcu::CUBEFACE_NEGATIVE_X || face == tcu::CUBEFACE_POSITIVE_X ? 2 : 0;
500                         int texCoordTRow = face == tcu::CUBEFACE_NEGATIVE_Y || face == tcu::CUBEFACE_POSITIVE_Y ? 2 : 1;
501                         texCoord[6 + texCoordSRow] *= texCoordTopRightFactor.x();
502                         texCoord[9 + texCoordSRow] *= texCoordTopRightFactor.x();
503                         texCoord[3 + texCoordTRow] *= texCoordTopRightFactor.y();
504                         texCoord[9 + texCoordTRow] *= texCoordTopRightFactor.y();
505                 }
506
507                 gl.viewport(x+curX, y+curY, curW, curH);
508
509                 renderer.renderQuad(0, &texCoord[0], params);
510
511                 sampleTexture(tcu::SurfaceAccess(dstRef, curX, curY, curW, curH), refTexture, &texCoord[0], params);
512         }
513
514         GLU_EXPECT_NO_ERROR(gl.getError(), "Post render");
515 }
516
517 TextureCubeFilteringCase::IterateResult TextureCubeFilteringCase::iterate (void)
518 {
519         const glw::Functions&           gl                                      = m_renderCtx.getFunctions();
520         TestLog&                                        log                                     = m_testCtx.getLog();
521         const int                                       cellSize                        = 28;
522         const int                                       defViewportWidth        = cellSize*6;
523         const int                                       defViewportHeight       = cellSize*4;
524         RandomViewport                          viewport                        (m_renderCtx.getRenderTarget(), cellSize*6, cellSize*4, deStringHash(getName()));
525         tcu::Surface                            renderedFrame           (viewport.width, viewport.height);
526         tcu::Surface                            referenceFrame          (viewport.width, viewport.height);
527         ReferenceParams                         sampleParams            (TEXTURETYPE_CUBE);
528         const tcu::TextureFormat&       texFmt                          = m_textures[0]->getRefTexture().getFormat();
529         tcu::TextureFormatInfo          fmtInfo                         = tcu::getTextureFormatInfo(texFmt);
530
531         // Accuracy measurements are off unless viewport size is exactly as expected.
532         if (viewport.width < defViewportWidth || viewport.height < defViewportHeight)
533                 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
534
535         // Viewport is divided into 4 sections.
536         int                             leftWidth                       = viewport.width / 2;
537         int                             rightWidth                      = viewport.width - leftWidth;
538         int                             bottomHeight            = viewport.height / 2;
539         int                             topHeight                       = viewport.height - bottomHeight;
540
541         int                             curTexNdx                       = 0;
542
543         // Sampling parameters.
544         sampleParams.sampler                                    = mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter);
545         sampleParams.sampler.seamlessCubeMap    = false;
546         sampleParams.samplerType                                = getSamplerType(texFmt);
547         sampleParams.colorBias                                  = fmtInfo.lookupBias;
548         sampleParams.colorScale                                 = fmtInfo.lookupScale;
549         sampleParams.lodMode                                    = LODMODE_EXACT;
550
551         // Use unit 0.
552         gl.activeTexture(GL_TEXTURE0);
553
554         // Setup gradient texture.
555         gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textures[curTexNdx]->getGLTexture());
556         gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,                m_wrapS);
557         gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,                m_wrapT);
558         gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,    m_minFilter);
559         gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,    m_magFilter);
560
561         // Bottom left: Minification
562         renderFaces(gl,
563                                 tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, 0, leftWidth, bottomHeight),
564                                 m_textures[curTexNdx]->getRefTexture(), sampleParams,
565                                 m_renderer,
566                                 viewport.x, viewport.y, leftWidth, bottomHeight,
567                                 tcu::Vec2(-0.81f, -0.81f),
568                                 tcu::Vec2( 0.8f,  0.8f),
569                                 tcu::Vec2(1.0f, 1.0f));
570
571         // Bottom right: Magnification
572         renderFaces(gl,
573                                 tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth, 0, rightWidth, bottomHeight),
574                                 m_textures[curTexNdx]->getRefTexture(), sampleParams,
575                                 m_renderer,
576                                 viewport.x+leftWidth, viewport.y, rightWidth, bottomHeight,
577                                 tcu::Vec2(0.5f, 0.65f), tcu::Vec2(0.8f, 0.8f),
578                                 tcu::Vec2(1.0f, 1.0f));
579
580         if (m_textures.size() >= 2)
581         {
582                 curTexNdx += 1;
583
584                 // Setup second texture.
585                 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textures[curTexNdx]->getGLTexture());
586                 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,                m_wrapS);
587                 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,                m_wrapT);
588                 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,    m_minFilter);
589                 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,    m_magFilter);
590         }
591
592         // Top left: Minification
593         renderFaces(gl,
594                                 tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, bottomHeight, leftWidth, topHeight),
595                                 m_textures[curTexNdx]->getRefTexture(), sampleParams,
596                                 m_renderer,
597                                 viewport.x, viewport.y+bottomHeight, leftWidth, topHeight,
598                                 tcu::Vec2(-0.81f, -0.81f),
599                                 tcu::Vec2( 0.8f,  0.8f),
600                                 tcu::Vec2(1.0f, 1.0f));
601
602         // Top right: Magnification
603         renderFaces(gl,
604                                 tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth, bottomHeight, rightWidth, topHeight),
605                                 m_textures[curTexNdx]->getRefTexture(), sampleParams,
606                                 m_renderer,
607                                 viewport.x+leftWidth, viewport.y+bottomHeight, rightWidth, topHeight,
608                                 tcu::Vec2(0.5f, -0.65f), tcu::Vec2(0.8f, -0.8f),
609                                 tcu::Vec2(1.0f, 1.0f));
610
611         // Read result.
612         glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
613
614         // Compare and log.
615         {
616                 DE_ASSERT(getNodeType() == tcu::NODETYPE_ACCURACY);
617
618                 const int       bestScoreDiff   = 16;
619                 const int       worstScoreDiff  = 10000;
620
621                 int score = measureAccuracy(log, referenceFrame, renderedFrame, bestScoreDiff, worstScoreDiff);
622                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::toString(score).c_str());
623         }
624
625         return STOP;
626 }
627
628 TextureFilteringTests::TextureFilteringTests (Context& context)
629         : TestCaseGroup(context, "filter", "Texture Filtering Accuracy Tests")
630 {
631 }
632
633 TextureFilteringTests::~TextureFilteringTests (void)
634 {
635 }
636
637 void TextureFilteringTests::init (void)
638 {
639         tcu::TestCaseGroup* group2D             = new tcu::TestCaseGroup(m_testCtx, "2d",       "2D Texture Filtering");
640         tcu::TestCaseGroup*     groupCube       = new tcu::TestCaseGroup(m_testCtx, "cube",     "Cube Map Filtering");
641         addChild(group2D);
642         addChild(groupCube);
643
644         static const struct
645         {
646                 const char*             name;
647                 deUint32                mode;
648         } wrapModes[] =
649         {
650                 { "clamp",              GL_CLAMP_TO_EDGE },
651                 { "repeat",             GL_REPEAT },
652                 { "mirror",             GL_MIRRORED_REPEAT }
653         };
654
655         static const struct
656         {
657                 const char*             name;
658                 deUint32                mode;
659         } minFilterModes[] =
660         {
661                 { "nearest",                            GL_NEAREST                                      },
662                 { "linear",                                     GL_LINEAR                                       },
663                 { "nearest_mipmap_nearest",     GL_NEAREST_MIPMAP_NEAREST       },
664                 { "linear_mipmap_nearest",      GL_LINEAR_MIPMAP_NEAREST        },
665                 { "nearest_mipmap_linear",      GL_NEAREST_MIPMAP_LINEAR        },
666                 { "linear_mipmap_linear",       GL_LINEAR_MIPMAP_LINEAR         }
667         };
668
669         static const struct
670         {
671                 const char*             name;
672                 deUint32                mode;
673         } magFilterModes[] =
674         {
675                 { "nearest",    GL_NEAREST },
676                 { "linear",             GL_LINEAR }
677         };
678
679         static const struct
680         {
681                 const char*             name;
682                 int                             width;
683                 int                             height;
684         } sizes2D[] =
685         {
686                 { "pot",                32, 64 },
687                 { "npot",               31, 55 }
688         };
689
690         static const struct
691         {
692                 const char*             name;
693                 int                             width;
694                 int                             height;
695         } sizesCube[] =
696         {
697                 { "pot",                64, 64 },
698                 { "npot",               63, 63 }
699         };
700
701         static const struct
702         {
703                 const char*             name;
704                 deUint32                format;
705                 deUint32                dataType;
706         } formats[] =
707         {
708                 { "rgba8888",   GL_RGBA,                        GL_UNSIGNED_BYTE                        },
709                 { "rgba4444",   GL_RGBA,                        GL_UNSIGNED_SHORT_4_4_4_4       }
710         };
711
712 #define FOR_EACH(ITERATOR, ARRAY, BODY) \
713         for (int (ITERATOR) = 0; (ITERATOR) < DE_LENGTH_OF_ARRAY(ARRAY); (ITERATOR)++)  \
714                 BODY
715
716         // 2D cases.
717         FOR_EACH(minFilter,             minFilterModes,
718         FOR_EACH(magFilter,             magFilterModes,
719         FOR_EACH(wrapMode,              wrapModes,
720         FOR_EACH(format,                formats,
721         FOR_EACH(size,                  sizes2D,
722                 {
723                         bool isMipmap           = minFilterModes[minFilter].mode != GL_NEAREST && minFilterModes[minFilter].mode != GL_LINEAR;
724                         bool isClamp            = wrapModes[wrapMode].mode == GL_CLAMP_TO_EDGE;
725                         bool isRepeat           = wrapModes[wrapMode].mode == GL_REPEAT;
726                         bool isMagNearest       = magFilterModes[magFilter].mode == GL_NEAREST;
727                         bool isPotSize          = deIsPowerOfTwo32(sizes2D[size].width) && deIsPowerOfTwo32(sizes2D[size].height);
728
729                         if ((isMipmap || !isClamp) && !isPotSize)
730                                 continue; // Not supported.
731
732                         if ((format != 0) && !(!isMipmap || (isRepeat && isMagNearest)))
733                                 continue; // Skip.
734
735                         string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name + "_" + formats[format].name;
736
737                         if (!isMipmap)
738                                 name += string("_") + sizes2D[size].name;
739
740                         group2D->addChild(new Texture2DFilteringCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
741                                                                                                                  name.c_str(), "",
742                                                                                                                  minFilterModes[minFilter].mode,
743                                                                                                                  magFilterModes[magFilter].mode,
744                                                                                                                  wrapModes[wrapMode].mode,
745                                                                                                                  wrapModes[wrapMode].mode,
746                                                                                                                  formats[format].format, formats[format].dataType,
747                                                                                                                  sizes2D[size].width, sizes2D[size].height));
748                 })))));
749
750         // Cubemap cases.
751         FOR_EACH(minFilter,             minFilterModes,
752         FOR_EACH(magFilter,             magFilterModes,
753         FOR_EACH(wrapMode,              wrapModes,
754         FOR_EACH(format,                formats,
755         FOR_EACH(size,                  sizesCube,
756                 {
757                         bool isMipmap           = minFilterModes[minFilter].mode != GL_NEAREST && minFilterModes[minFilter].mode != GL_LINEAR;
758                         bool isClamp            = wrapModes[wrapMode].mode == GL_CLAMP_TO_EDGE;
759                         bool isRepeat           = wrapModes[wrapMode].mode == GL_REPEAT;
760                         bool isMagNearest       = magFilterModes[magFilter].mode == GL_NEAREST;
761                         bool isPotSize          = deIsPowerOfTwo32(sizesCube[size].width) && deIsPowerOfTwo32(sizesCube[size].height);
762
763                         if ((isMipmap || !isClamp) && !isPotSize)
764                                 continue; // Not supported.
765
766                         if (format != 0 && !(!isMipmap || (isRepeat && isMagNearest)))
767                                 continue; // Skip.
768
769                         string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name + "_" + formats[format].name;
770
771                         if (!isMipmap)
772                                 name += string("_") + sizesCube[size].name;
773
774                         groupCube->addChild(new TextureCubeFilteringCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
775                                                                                                                          name.c_str(), "",
776                                                                                                                          minFilterModes[minFilter].mode,
777                                                                                                                          magFilterModes[magFilter].mode,
778                                                                                                                          wrapModes[wrapMode].mode,
779                                                                                                                          wrapModes[wrapMode].mode,
780                                                                                                                          formats[format].format, formats[format].dataType,
781                                                                                                                          sizesCube[size].width, sizesCube[size].height));
782                 })))));
783 }
784
785 } // Accuracy
786 } // gles2
787 } // deqp