xref: /aosp_15_r20/external/deqp/modules/gles2/functional/es2fTextureWrapTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Texture wrap mode tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es2fTextureWrapTests.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 
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 
36 namespace deqp
37 {
38 namespace gles2
39 {
40 namespace Functional
41 {
42 
43 using std::string;
44 using std::vector;
45 using tcu::Sampler;
46 using tcu::TestLog;
47 using namespace glu;
48 using namespace gls::TextureTestUtil;
49 using namespace glu::TextureTestUtil;
50 
51 enum
52 {
53     VIEWPORT_WIDTH  = 256,
54     VIEWPORT_HEIGHT = 256
55 };
56 
57 class TextureWrapCase : public tcu::TestCase
58 {
59 public:
60     TextureWrapCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx, const glu::ContextInfo &ctxInfo,
61                     const char *name, const char *description, uint32_t format, uint32_t dataType, uint32_t wrapS,
62                     uint32_t wrapT, uint32_t minFilter, uint32_t magFilter, int width, int height,
63                     bool enableRelaxedRef = false);
64     TextureWrapCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx, const glu::ContextInfo &ctxInfo,
65                     const char *name, const char *description, uint32_t wrapS, uint32_t wrapT, uint32_t minFilter,
66                     uint32_t magFilter, const std::vector<std::string> &filenames, bool enableRelaxedRef = false);
67     ~TextureWrapCase(void);
68 
69     void init(void);
70     void deinit(void);
71     IterateResult iterate(void);
72 
73 private:
74     TextureWrapCase(const TextureWrapCase &other);
75     TextureWrapCase &operator=(const TextureWrapCase &other);
76 
77     glu::RenderContext &m_renderCtx;
78     const glu::ContextInfo &m_renderCtxInfo;
79 
80     uint32_t m_format;
81     uint32_t m_dataType;
82     uint32_t m_wrapS;
83     uint32_t m_wrapT;
84     uint32_t m_minFilter;
85     uint32_t m_magFilter;
86 
87     int m_width;
88     int m_height;
89     std::vector<std::string> m_filenames;
90 
91     glu::Texture2D *m_texture;
92     TextureRenderer m_renderer;
93 
94     bool m_enableRelaxedRef;
95 };
96 
TextureWrapCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const glu::ContextInfo & ctxInfo,const char * name,const char * description,uint32_t format,uint32_t dataType,uint32_t wrapS,uint32_t wrapT,uint32_t minFilter,uint32_t magFilter,int width,int height,bool enableRelaxedRef)97 TextureWrapCase::TextureWrapCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx,
98                                  const glu::ContextInfo &ctxInfo, const char *name, const char *description,
99                                  uint32_t format, uint32_t dataType, uint32_t wrapS, uint32_t wrapT, uint32_t minFilter,
100                                  uint32_t magFilter, int width, int height, bool enableRelaxedRef)
101     : TestCase(testCtx, name, description)
102     , m_renderCtx(renderCtx)
103     , m_renderCtxInfo(ctxInfo)
104     , m_format(format)
105     , m_dataType(dataType)
106     , m_wrapS(wrapS)
107     , m_wrapT(wrapT)
108     , m_minFilter(minFilter)
109     , m_magFilter(magFilter)
110     , m_width(width)
111     , m_height(height)
112     , m_texture(DE_NULL)
113     , m_renderer(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
114     , m_enableRelaxedRef(enableRelaxedRef)
115 {
116 }
117 
TextureWrapCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const glu::ContextInfo & ctxInfo,const char * name,const char * description,uint32_t wrapS,uint32_t wrapT,uint32_t minFilter,uint32_t magFilter,const std::vector<std::string> & filenames,bool enableRelaxedRef)118 TextureWrapCase::TextureWrapCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx,
119                                  const glu::ContextInfo &ctxInfo, const char *name, const char *description,
120                                  uint32_t wrapS, uint32_t wrapT, uint32_t minFilter, uint32_t magFilter,
121                                  const std::vector<std::string> &filenames, bool enableRelaxedRef)
122     : TestCase(testCtx, name, description)
123     , m_renderCtx(renderCtx)
124     , m_renderCtxInfo(ctxInfo)
125     , m_format(GL_NONE)
126     , m_dataType(GL_NONE)
127     , m_wrapS(wrapS)
128     , m_wrapT(wrapT)
129     , m_minFilter(minFilter)
130     , m_magFilter(magFilter)
131     , m_width(0)
132     , m_height(0)
133     , m_filenames(filenames)
134     , m_texture(DE_NULL)
135     , m_renderer(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
136     , m_enableRelaxedRef(enableRelaxedRef)
137 {
138 }
139 
~TextureWrapCase(void)140 TextureWrapCase::~TextureWrapCase(void)
141 {
142     deinit();
143 }
144 
init(void)145 void TextureWrapCase::init(void)
146 {
147     if (!m_filenames.empty())
148     {
149         DE_ASSERT(m_width == 0 && m_height == 0 && m_format == GL_NONE && m_dataType == GL_NONE);
150 
151         m_texture = glu::Texture2D::create(m_renderCtx, m_renderCtxInfo, m_testCtx.getArchive(),
152                                            (int)m_filenames.size(), m_filenames);
153         m_width   = m_texture->getRefTexture().getWidth();
154         m_height  = m_texture->getRefTexture().getHeight();
155     }
156     else
157     {
158         m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
159 
160         // Fill level 0.
161         m_texture->getRefTexture().allocLevel(0);
162         if (m_wrapS == GL_REPEAT || m_wrapT == GL_REPEAT)
163         {
164             // If run in repeat mode, use conical style texture to avoid edge sample result have a huge difference when coordinate offset in allow range.
165             tcu::fillWithComponentGradients3(m_texture->getRefTexture().getLevel(0),
166                                              tcu::Vec4(-0.5f, -0.5f, -0.5f, 1.5f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
167         }
168         else
169         {
170             tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(0),
171                                             tcu::Vec4(-0.5f, -0.5f, -0.5f, 1.5f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
172         }
173 
174         m_texture->upload();
175     }
176 }
177 
deinit(void)178 void TextureWrapCase::deinit(void)
179 {
180     delete m_texture;
181     m_texture = DE_NULL;
182 
183     m_renderer.clear();
184 }
185 
iterate(void)186 TextureWrapCase::IterateResult TextureWrapCase::iterate(void)
187 {
188     const glw::Functions &gl = m_renderCtx.getFunctions();
189     TestLog &log             = m_testCtx.getLog();
190     RandomViewport viewport(m_renderCtx.getRenderTarget(), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, deStringHash(getName()));
191     tcu::Surface renderedFrame(viewport.width, viewport.height);
192     tcu::Surface referenceFrame(viewport.width, viewport.height);
193     bool isCompressedTex = !m_filenames.empty();
194     ReferenceParams refParams(TEXTURETYPE_2D);
195     int leftWidth  = viewport.width / 2;
196     int rightWidth = viewport.width - leftWidth;
197     vector<float> texCoord;
198 
199     tcu::RGBA threshold;
200     if (m_texture->getRefTexture().getFormat().type == tcu::TextureFormat::UNORM_SHORT_4444 ||
201         m_texture->getRefTexture().getFormat().type == tcu::TextureFormat::UNSIGNED_SHORT_4444)
202     {
203         threshold = tcu::PixelFormat(4, 4, 4, 4).getColorThreshold() + tcu::RGBA(1, 1, 1, 1);
204     }
205     else
206     {
207         threshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() +
208                     (isCompressedTex ? tcu::RGBA(7, 7, 7, 7) : tcu::RGBA(3, 3, 3, 3));
209     }
210 
211     // Bind to unit 0.
212     gl.activeTexture(GL_TEXTURE0);
213     gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
214 
215     // Setup filtering and wrap modes.
216     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS);
217     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT);
218     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter);
219     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_magFilter);
220 
221     GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
222 
223     // Parameters for reference images.
224     refParams.sampler = mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter);
225     refParams.lodMode = LODMODE_EXACT;
226 
227     // Left: minification
228     {
229         gl.viewport(viewport.x, viewport.y, leftWidth, viewport.height);
230 
231         computeQuadTexCoord2D(texCoord, tcu::Vec2(-1.5f, -3.0f), tcu::Vec2(1.5f, 2.5f));
232 
233         m_renderer.renderQuad(0, &texCoord[0], refParams);
234         glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
235 
236         sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, 0,
237                                          leftWidth, viewport.height),
238                       m_texture->getRefTexture(), &texCoord[0], refParams);
239     }
240 
241     // Right: magnification
242     {
243         gl.viewport(viewport.x + leftWidth, viewport.y, rightWidth, viewport.height);
244 
245         computeQuadTexCoord2D(texCoord, tcu::Vec2(-0.5f, 0.75f), tcu::Vec2(0.25f, 1.25f));
246 
247         m_renderer.renderQuad(0, &texCoord[0], refParams);
248         glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
249 
250         sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth, 0,
251                                          rightWidth, viewport.height),
252                       m_texture->getRefTexture(), &texCoord[0], refParams);
253     }
254 
255     // Compare and log.
256     bool isOk = compareImages(log, referenceFrame, renderedFrame, threshold);
257 
258     if ((isOk == false) && m_enableRelaxedRef && m_renderer.getTexCoordPrecision() != PRECISION_HIGHP)
259     {
260         refParams.float16TexCoord = true;
261         // Left: minification
262         {
263             computeQuadTexCoord2D(texCoord, tcu::Vec2(-1.5f, -3.0f), tcu::Vec2(1.5f, 2.5f));
264             sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, 0,
265                                              leftWidth, viewport.height),
266                           m_texture->getRefTexture(), &texCoord[0], refParams);
267         }
268 
269         // Right: magnification
270         {
271             computeQuadTexCoord2D(texCoord, tcu::Vec2(-0.5f, 0.75f), tcu::Vec2(0.25f, 1.25f));
272             sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth,
273                                              0, rightWidth, viewport.height),
274                           m_texture->getRefTexture(), &texCoord[0], refParams);
275         }
276 
277         isOk |= compareImages(log, referenceFrame, renderedFrame, threshold);
278     }
279 
280     m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
281                             isOk ? "Pass" : "Image comparison failed");
282 
283     return STOP;
284 }
285 
TextureWrapTests(Context & context)286 TextureWrapTests::TextureWrapTests(Context &context) : TestCaseGroup(context, "wrap", "Wrap Mode Tests")
287 {
288 }
289 
~TextureWrapTests(void)290 TextureWrapTests::~TextureWrapTests(void)
291 {
292 }
293 
init(void)294 void TextureWrapTests::init(void)
295 {
296     static const struct
297     {
298         const char *name;
299         uint32_t mode;
300     } wrapModes[] = {{"clamp", GL_CLAMP_TO_EDGE}, {"repeat", GL_REPEAT}, {"mirror", GL_MIRRORED_REPEAT}};
301 
302     static const struct
303     {
304         const char *name;
305         uint32_t mode;
306     } filteringModes[] = {{"nearest", GL_NEAREST}, {"linear", GL_LINEAR}};
307 
308     static const struct
309     {
310         const char *name;
311         int width;
312         int height;
313     } sizes[] = {{"pot", 64, 128}, {"npot", 63, 112}};
314 
315     static const struct
316     {
317         const char *name;
318         uint32_t format;
319         uint32_t dataType;
320     } formats[] = {
321         {"rgba8888", GL_RGBA, GL_UNSIGNED_BYTE},
322         {"rgb888", GL_RGB, GL_UNSIGNED_BYTE},
323         {"rgba4444", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4},
324         {"l8", GL_LUMINANCE, GL_UNSIGNED_BYTE},
325     };
326 
327 #define FOR_EACH(ITERATOR, ARRAY, BODY)                                      \
328     for (int ITERATOR = 0; ITERATOR < DE_LENGTH_OF_ARRAY(ARRAY); ITERATOR++) \
329     BODY
330 
331     FOR_EACH(
332         wrapS, wrapModes,
333         FOR_EACH(
334             wrapT, wrapModes,
335             FOR_EACH(filter, filteringModes,
336                      FOR_EACH(size, sizes, FOR_EACH(format, formats, {
337                                   bool is_clamp_clamp            = (wrapModes[wrapS].mode == GL_CLAMP_TO_EDGE &&
338                                                          wrapModes[wrapT].mode == GL_CLAMP_TO_EDGE);
339                                   bool is_repeat_mirror          = (wrapModes[wrapS].mode == GL_REPEAT &&
340                                                            wrapModes[wrapT].mode == GL_MIRRORED_REPEAT);
341                                   bool enableRelaxedPrecisionRef = wrapModes[wrapS].mode == GL_REPEAT ||
342                                                                    wrapModes[wrapT].mode == GL_REPEAT ||
343                                                                    wrapModes[wrapS].mode == GL_MIRRORED_REPEAT ||
344                                                                    wrapModes[wrapT].mode == GL_MIRRORED_REPEAT;
345 
346                                   if (!is_clamp_clamp && !is_repeat_mirror && format != 0)
347                                       continue; // Use other format varants with clamp_clamp & repeat_mirror pair only.
348 
349                                   if (!is_clamp_clamp &&
350                                       (!deIsPowerOfTwo32(sizes[size].width) || !deIsPowerOfTwo32(sizes[size].height)))
351                                       continue; // Not supported as described in Spec section 3.8.2.
352 
353                                   string name = string("") + wrapModes[wrapS].name + "_" + wrapModes[wrapT].name + "_" +
354                                                 filteringModes[filter].name + "_" + sizes[size].name + "_" +
355                                                 formats[format].name;
356                                   addChild(new TextureWrapCase(
357                                       m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), name.c_str(),
358                                       "", formats[format].format, formats[format].dataType, wrapModes[wrapS].mode,
359                                       wrapModes[wrapT].mode, filteringModes[filter].mode, filteringModes[filter].mode,
360                                       sizes[size].width, sizes[size].height, enableRelaxedPrecisionRef));
361                               })))))
362 
363     // Power-of-two ETC1 texture
364     std::vector<std::string> potFilenames;
365     potFilenames.push_back("data/etc1/photo_helsinki_mip_0.pkm");
366 
367     FOR_EACH(wrapS, wrapModes,
368              FOR_EACH(wrapT, wrapModes, FOR_EACH(filter, filteringModes, {
369                           bool enableRelaxedPrecisionRef = wrapModes[wrapS].mode == GL_REPEAT ||
370                                                            wrapModes[wrapT].mode == GL_REPEAT ||
371                                                            wrapModes[wrapS].mode == GL_MIRRORED_REPEAT ||
372                                                            wrapModes[wrapT].mode == GL_MIRRORED_REPEAT;
373 
374                           string name = string("") + wrapModes[wrapS].name + "_" + wrapModes[wrapT].name + "_" +
375                                         filteringModes[filter].name + "_pot_etc1";
376                           addChild(new TextureWrapCase(
377                               m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), name.c_str(), "",
378                               wrapModes[wrapS].mode, wrapModes[wrapT].mode, filteringModes[filter].mode,
379                               filteringModes[filter].mode, potFilenames, enableRelaxedPrecisionRef));
380                       })))
381 
382     std::vector<std::string> npotFilenames;
383     npotFilenames.push_back("data/etc1/photo_helsinki_113x89.pkm");
384 
385     // NPOT ETC1 texture
386     for (int filter = 0; filter < DE_LENGTH_OF_ARRAY(filteringModes); filter++)
387     {
388         string name = string("clamp_clamp_") + filteringModes[filter].name + "_npot_etc1";
389         addChild(new TextureWrapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), name.c_str(),
390                                      "", GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, filteringModes[filter].mode,
391                                      filteringModes[filter].mode, npotFilenames));
392     }
393 }
394 
395 } // namespace Functional
396 } // namespace gles2
397 } // namespace deqp
398