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