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 tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3fTextureMipmapTests.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 "tcuTexLookupVerifier.hpp"
34 #include "tcuVectorUtil.hpp"
35 #include "deStringUtil.hpp"
36 #include "deRandom.hpp"
37 #include "deString.h"
38 #include "glwFunctions.hpp"
39 #include "glwEnums.hpp"
40
41 using std::vector;
42 using std::string;
43 using namespace deqp::gls;
44
45 namespace deqp
46 {
47 namespace gles3
48 {
49 namespace Functional
50 {
51
52 using std::string;
53 using std::vector;
54 using tcu::TestLog;
55 using tcu::Vec2;
56 using tcu::Vec3;
57 using tcu::Vec4;
58 using tcu::IVec4;
59 using namespace gls::TextureTestUtil;
60
getMinLodForCell(int cellNdx)61 static float getMinLodForCell (int cellNdx)
62 {
63 static const float s_values[] =
64 {
65 1.0f,
66 3.5f,
67 2.0f,
68 -2.0f,
69 0.0f,
70 3.0f,
71 10.0f,
72 4.8f,
73 5.8f,
74 5.7f,
75 -1.9f,
76 4.0f,
77 6.5f,
78 7.1f,
79 -1e10,
80 1000.f
81 };
82 return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
83 }
84
getMaxLodForCell(int cellNdx)85 static float getMaxLodForCell (int cellNdx)
86 {
87 static const float s_values[] =
88 {
89 0.0f,
90 0.2f,
91 0.7f,
92 0.4f,
93 1.3f,
94 0.0f,
95 0.5f,
96 1.2f,
97 -2.0f,
98 1.0f,
99 0.1f,
100 0.3f,
101 2.7f,
102 1.2f,
103 10.0f,
104 -1000.f,
105 1e10f
106 };
107 return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
108 }
109
110 enum CoordType
111 {
112 COORDTYPE_BASIC, //!< texCoord = translateScale(position).
113 COORDTYPE_BASIC_BIAS, //!< Like basic, but with bias values.
114 COORDTYPE_AFFINE, //!< texCoord = translateScaleRotateShear(position).
115 COORDTYPE_PROJECTED, //!< Projected coordinates, w != 1
116
117 COORDTYPE_LAST
118 };
119
120 // Texture2DMipmapCase
121
122 class Texture2DMipmapCase : public tcu::TestCase
123 {
124 public:
125
126 Texture2DMipmapCase (tcu::TestContext& testCtx,
127 glu::RenderContext& renderCtx,
128 const glu::ContextInfo& renderCtxInfo,
129 const char* name,
130 const char* desc,
131 CoordType coordType,
132 deUint32 minFilter,
133 deUint32 wrapS,
134 deUint32 wrapT,
135 deUint32 format,
136 deUint32 dataType,
137 int width,
138 int height);
139 ~Texture2DMipmapCase (void);
140
141 void init (void);
142 void deinit (void);
143 IterateResult iterate (void);
144
145 private:
146 Texture2DMipmapCase (const Texture2DMipmapCase& other);
147 Texture2DMipmapCase& operator= (const Texture2DMipmapCase& other);
148
149 glu::RenderContext& m_renderCtx;
150 const glu::ContextInfo& m_renderCtxInfo;
151
152 CoordType m_coordType;
153 deUint32 m_minFilter;
154 deUint32 m_wrapS;
155 deUint32 m_wrapT;
156 deUint32 m_format;
157 deUint32 m_dataType;
158 int m_width;
159 int m_height;
160
161 glu::Texture2D* m_texture;
162 TextureRenderer m_renderer;
163 };
164
Texture2DMipmapCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const glu::ContextInfo & renderCtxInfo,const char * name,const char * desc,CoordType coordType,deUint32 minFilter,deUint32 wrapS,deUint32 wrapT,deUint32 format,deUint32 dataType,int width,int height)165 Texture2DMipmapCase::Texture2DMipmapCase (tcu::TestContext& testCtx,
166 glu::RenderContext& renderCtx,
167 const glu::ContextInfo& renderCtxInfo,
168 const char* name,
169 const char* desc,
170 CoordType coordType,
171 deUint32 minFilter,
172 deUint32 wrapS,
173 deUint32 wrapT,
174 deUint32 format,
175 deUint32 dataType,
176 int width,
177 int height)
178 : TestCase (testCtx, name, desc)
179 , m_renderCtx (renderCtx)
180 , m_renderCtxInfo (renderCtxInfo)
181 , m_coordType (coordType)
182 , m_minFilter (minFilter)
183 , m_wrapS (wrapS)
184 , m_wrapT (wrapT)
185 , m_format (format)
186 , m_dataType (dataType)
187 , m_width (width)
188 , m_height (height)
189 , m_texture (DE_NULL)
190 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
191 {
192 }
193
~Texture2DMipmapCase(void)194 Texture2DMipmapCase::~Texture2DMipmapCase (void)
195 {
196 deinit();
197 }
198
init(void)199 void Texture2DMipmapCase::init (void)
200 {
201 if (m_coordType == COORDTYPE_PROJECTED && m_renderCtx.getRenderTarget().getNumSamples() > 0)
202 throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config");
203
204 m_texture = new glu::Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
205
206 int numLevels = deLog2Floor32(de::max(m_width, m_height))+1;
207
208 // Fill texture with colored grid.
209 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
210 {
211 deUint32 step = 0xff / (numLevels-1);
212 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff);
213 deUint32 dec = 0xff - inc;
214 deUint32 rgb = (inc << 16) | (dec << 8) | 0xff;
215 deUint32 color = 0xff000000 | rgb;
216
217 m_texture->getRefTexture().allocLevel(levelNdx);
218 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), toVec4(tcu::RGBA(color)));
219 }
220 }
221
deinit(void)222 void Texture2DMipmapCase::deinit (void)
223 {
224 delete m_texture;
225 m_texture = DE_NULL;
226
227 m_renderer.clear();
228 }
229
getBasicTexCoord2D(std::vector<float> & dst,int cellNdx)230 static void getBasicTexCoord2D (std::vector<float>& dst, int cellNdx)
231 {
232 static const struct
233 {
234 Vec2 bottomLeft;
235 Vec2 topRight;
236 } s_basicCoords[] =
237 {
238 { Vec2(-0.1f, 0.1f), Vec2( 0.8f, 1.0f) },
239 { Vec2(-0.3f, -0.6f), Vec2( 0.7f, 0.4f) },
240 { Vec2(-0.3f, 0.6f), Vec2( 0.7f, -0.9f) },
241 { Vec2(-0.8f, 0.6f), Vec2( 0.7f, -0.9f) },
242
243 { Vec2(-0.5f, -0.5f), Vec2( 1.5f, 1.5f) },
244 { Vec2( 1.0f, -1.0f), Vec2(-1.3f, 1.0f) },
245 { Vec2( 1.2f, -1.0f), Vec2(-1.3f, 1.6f) },
246 { Vec2( 2.2f, -1.1f), Vec2(-1.3f, 0.8f) },
247
248 { Vec2(-1.5f, 1.6f), Vec2( 1.7f, -1.4f) },
249 { Vec2( 2.0f, 1.6f), Vec2( 2.3f, -1.4f) },
250 { Vec2( 1.3f, -2.6f), Vec2(-2.7f, 2.9f) },
251 { Vec2(-0.8f, -6.6f), Vec2( 6.0f, -0.9f) },
252
253 { Vec2( -8.0f, 9.0f), Vec2( 8.3f, -7.0f) },
254 { Vec2(-16.0f, 10.0f), Vec2( 18.3f, 24.0f) },
255 { Vec2( 30.2f, 55.0f), Vec2(-24.3f, -1.6f) },
256 { Vec2(-33.2f, 64.1f), Vec2( 32.1f, -64.1f) },
257 };
258
259 DE_ASSERT(de::inBounds(cellNdx, 0, DE_LENGTH_OF_ARRAY(s_basicCoords)));
260
261 const Vec2& bottomLeft = s_basicCoords[cellNdx].bottomLeft;
262 const Vec2& topRight = s_basicCoords[cellNdx].topRight;
263
264 computeQuadTexCoord2D(dst, bottomLeft, topRight);
265 }
266
getAffineTexCoord2D(std::vector<float> & dst,int cellNdx)267 static void getAffineTexCoord2D (std::vector<float>& dst, int cellNdx)
268 {
269 // Use basic coords as base.
270 getBasicTexCoord2D(dst, cellNdx);
271
272 // Rotate based on cell index.
273 float angle = 2.0f*DE_PI * ((float)cellNdx / 16.0f);
274 tcu::Mat2 rotMatrix = tcu::rotationMatrix(angle);
275
276 // Second and third row are sheared.
277 float shearX = de::inRange(cellNdx, 4, 11) ? (float)(15-cellNdx) / 16.0f : 0.0f;
278 tcu::Mat2 shearMatrix = tcu::shearMatrix(tcu::Vec2(shearX, 0.0f));
279
280 tcu::Mat2 transform = rotMatrix * shearMatrix;
281 Vec2 p0 = transform * Vec2(dst[0], dst[1]);
282 Vec2 p1 = transform * Vec2(dst[2], dst[3]);
283 Vec2 p2 = transform * Vec2(dst[4], dst[5]);
284 Vec2 p3 = transform * Vec2(dst[6], dst[7]);
285
286 dst[0] = p0.x(); dst[1] = p0.y();
287 dst[2] = p1.x(); dst[3] = p1.y();
288 dst[4] = p2.x(); dst[5] = p2.y();
289 dst[6] = p3.x(); dst[7] = p3.y();
290 }
291
iterate(void)292 Texture2DMipmapCase::IterateResult Texture2DMipmapCase::iterate (void)
293 {
294 const glw::Functions& gl = m_renderCtx.getFunctions();
295
296 const tcu::Texture2D& refTexture = m_texture->getRefTexture();
297
298 const deUint32 magFilter = GL_NEAREST;
299 const int texWidth = refTexture.getWidth();
300 const int texHeight = refTexture.getHeight();
301 const int defViewportWidth = texWidth*4;
302 const int defViewportHeight = texHeight*4;
303
304 const RandomViewport viewport (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));
305 ReferenceParams sampleParams (TEXTURETYPE_2D);
306 vector<float> texCoord;
307
308 const bool isProjected = m_coordType == COORDTYPE_PROJECTED;
309 const bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS;
310
311 tcu::Surface renderedFrame (viewport.width, viewport.height);
312
313 // Viewport is divided into 4x4 grid.
314 int gridWidth = 4;
315 int gridHeight = 4;
316 int cellWidth = viewport.width / gridWidth;
317 int cellHeight = viewport.height / gridHeight;
318
319 // Bail out if rendertarget is too small.
320 if (viewport.width < defViewportWidth/2 || viewport.height < defViewportHeight/2)
321 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
322
323 // Sampling parameters.
324 sampleParams.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter);
325 sampleParams.samplerType = gls::TextureTestUtil::getSamplerType(m_texture->getRefTexture().getFormat());
326 sampleParams.flags = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
327 sampleParams.lodMode = LODMODE_EXACT; // Use ideal lod.
328
329 // Upload texture data.
330 m_texture->upload();
331
332 // Bind gradient texture and setup sampler parameters.
333 gl.bindTexture (GL_TEXTURE_2D, m_texture->getGLTexture());
334 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS);
335 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT);
336 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter);
337 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
338
339 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
340
341 // Bias values.
342 static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
343
344 // Projection values.
345 static const Vec4 s_projections[] =
346 {
347 Vec4(1.2f, 1.0f, 0.7f, 1.0f),
348 Vec4(1.3f, 0.8f, 0.6f, 2.0f),
349 Vec4(0.8f, 1.0f, 1.7f, 0.6f),
350 Vec4(1.2f, 1.0f, 1.7f, 1.5f)
351 };
352
353 // Render cells.
354 for (int gridY = 0; gridY < gridHeight; gridY++)
355 {
356 for (int gridX = 0; gridX < gridWidth; gridX++)
357 {
358 const int curX = cellWidth*gridX;
359 const int curY = cellHeight*gridY;
360 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
361 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
362 const int cellNdx = gridY*gridWidth + gridX;
363
364 // Compute texcoord.
365 switch (m_coordType)
366 {
367 case COORDTYPE_BASIC_BIAS: // Fall-through.
368 case COORDTYPE_PROJECTED:
369 case COORDTYPE_BASIC: getBasicTexCoord2D (texCoord, cellNdx); break;
370 case COORDTYPE_AFFINE: getAffineTexCoord2D (texCoord, cellNdx); break;
371 default: DE_ASSERT(DE_FALSE);
372 }
373
374 if (isProjected)
375 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
376
377 if (useLodBias)
378 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
379
380 // Render with GL.
381 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
382 m_renderer.renderQuad(0, &texCoord[0], sampleParams);
383 }
384 }
385
386 // Read result.
387 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
388
389 // Compare and log.
390 {
391 const tcu::PixelFormat& pixelFormat = m_renderCtx.getRenderTarget().getPixelFormat();
392 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
393 tcu::Surface referenceFrame (viewport.width, viewport.height);
394 tcu::Surface errorMask (viewport.width, viewport.height);
395 tcu::LookupPrecision lookupPrec;
396 tcu::LodPrecision lodPrec;
397 int numFailedPixels = 0;
398
399 lookupPrec.coordBits = tcu::IVec3(20, 20, 0);
400 lookupPrec.uvwBits = tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
401 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
402 lookupPrec.colorMask = getCompareMask(pixelFormat);
403 lodPrec.derivateBits = 10;
404 lodPrec.lodBits = isProjected ? 6 : 8;
405
406 for (int gridY = 0; gridY < gridHeight; gridY++)
407 {
408 for (int gridX = 0; gridX < gridWidth; gridX++)
409 {
410 const int curX = cellWidth*gridX;
411 const int curY = cellHeight*gridY;
412 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
413 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
414 const int cellNdx = gridY*gridWidth + gridX;
415
416 // Compute texcoord.
417 switch (m_coordType)
418 {
419 case COORDTYPE_BASIC_BIAS: // Fall-through.
420 case COORDTYPE_PROJECTED:
421 case COORDTYPE_BASIC: getBasicTexCoord2D (texCoord, cellNdx); break;
422 case COORDTYPE_AFFINE: getAffineTexCoord2D (texCoord, cellNdx); break;
423 default: DE_ASSERT(DE_FALSE);
424 }
425
426 if (isProjected)
427 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
428
429 if (useLodBias)
430 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
431
432 // Render ideal result
433 sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
434 refTexture, &texCoord[0], sampleParams);
435
436 // Compare this cell
437 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
438 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
439 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
440 m_texture->getRefTexture(), &texCoord[0], sampleParams,
441 lookupPrec, lodPrec, m_testCtx.getWatchDog());
442 }
443 }
444
445 if (numFailedPixels > 0)
446 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
447
448 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
449 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
450
451 if (numFailedPixels > 0)
452 {
453 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
454 << TestLog::Image("ErrorMask", "Error mask", errorMask);
455 }
456
457 m_testCtx.getLog() << TestLog::EndImageSet;
458
459 {
460 const bool isOk = numFailedPixels == 0;
461 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
462 isOk ? "Pass" : "Image verification failed");
463 }
464 }
465
466 return STOP;
467 }
468
469 // TextureCubeMipmapCase
470
471 class TextureCubeMipmapCase : public tcu::TestCase
472 {
473 public:
474
475 TextureCubeMipmapCase (tcu::TestContext& testCtx,
476 glu::RenderContext& renderCtx,
477 const glu::ContextInfo& renderCtxInfo,
478 const char* name,
479 const char* desc,
480 CoordType coordType,
481 deUint32 minFilter,
482 deUint32 wrapS,
483 deUint32 wrapT,
484 deUint32 format,
485 deUint32 dataType,
486 int size);
487 ~TextureCubeMipmapCase (void);
488
489 void init (void);
490 void deinit (void);
491 IterateResult iterate (void);
492
493 private:
494 TextureCubeMipmapCase (const TextureCubeMipmapCase& other);
495 TextureCubeMipmapCase& operator= (const TextureCubeMipmapCase& other);
496
497 glu::RenderContext& m_renderCtx;
498 const glu::ContextInfo& m_renderCtxInfo;
499
500 CoordType m_coordType;
501 deUint32 m_minFilter;
502 deUint32 m_wrapS;
503 deUint32 m_wrapT;
504 deUint32 m_format;
505 deUint32 m_dataType;
506 int m_size;
507
508 glu::TextureCube* m_texture;
509 TextureRenderer m_renderer;
510 };
511
TextureCubeMipmapCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const glu::ContextInfo & renderCtxInfo,const char * name,const char * desc,CoordType coordType,deUint32 minFilter,deUint32 wrapS,deUint32 wrapT,deUint32 format,deUint32 dataType,int size)512 TextureCubeMipmapCase::TextureCubeMipmapCase (tcu::TestContext& testCtx,
513 glu::RenderContext& renderCtx,
514 const glu::ContextInfo& renderCtxInfo,
515 const char* name,
516 const char* desc,
517 CoordType coordType,
518 deUint32 minFilter,
519 deUint32 wrapS,
520 deUint32 wrapT,
521 deUint32 format,
522 deUint32 dataType,
523 int size)
524 : TestCase (testCtx, name, desc)
525 , m_renderCtx (renderCtx)
526 , m_renderCtxInfo (renderCtxInfo)
527 , m_coordType (coordType)
528 , m_minFilter (minFilter)
529 , m_wrapS (wrapS)
530 , m_wrapT (wrapT)
531 , m_format (format)
532 , m_dataType (dataType)
533 , m_size (size)
534 , m_texture (DE_NULL)
535 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
536 {
537 }
538
~TextureCubeMipmapCase(void)539 TextureCubeMipmapCase::~TextureCubeMipmapCase (void)
540 {
541 deinit();
542 }
543
init(void)544 void TextureCubeMipmapCase::init (void)
545 {
546 if (m_coordType == COORDTYPE_PROJECTED && m_renderCtx.getRenderTarget().getNumSamples() > 0)
547 throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config");
548
549 m_texture = new glu::TextureCube(m_renderCtx, m_format, m_dataType, m_size);
550
551 int numLevels = deLog2Floor32(m_size)+1;
552
553 // Fill texture with colored grid.
554 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
555 {
556 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
557 {
558 deUint32 step = 0xff / (numLevels-1);
559 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff);
560 deUint32 dec = 0xff - inc;
561 deUint32 rgb = 0;
562
563 switch (faceNdx)
564 {
565 case 0: rgb = (inc << 16) | (dec << 8) | 255; break;
566 case 1: rgb = (255 << 16) | (inc << 8) | dec; break;
567 case 2: rgb = (dec << 16) | (255 << 8) | inc; break;
568 case 3: rgb = (dec << 16) | (inc << 8) | 255; break;
569 case 4: rgb = (255 << 16) | (dec << 8) | inc; break;
570 case 5: rgb = (inc << 16) | (255 << 8) | dec; break;
571 }
572
573 deUint32 color = 0xff000000 | rgb;
574
575 m_texture->getRefTexture().allocLevel((tcu::CubeFace)faceNdx, levelNdx);
576 tcu::clear(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), toVec4(tcu::RGBA(color)));
577 }
578 }
579 }
580
deinit(void)581 void TextureCubeMipmapCase::deinit (void)
582 {
583 delete m_texture;
584 m_texture = DE_NULL;
585
586 m_renderer.clear();
587 }
588
randomPartition(vector<IVec4> & dst,de::Random & rnd,int x,int y,int width,int height)589 static void randomPartition (vector<IVec4>& dst, de::Random& rnd, int x, int y, int width, int height)
590 {
591 const int minWidth = 8;
592 const int minHeight = 8;
593
594 bool partition = rnd.getFloat() > 0.4f;
595 bool partitionX = partition && width > minWidth && rnd.getBool();
596 bool partitionY = partition && height > minHeight && !partitionX;
597
598 if (partitionX)
599 {
600 int split = width/2 + rnd.getInt(-width/4, +width/4);
601 randomPartition(dst, rnd, x, y, split, height);
602 randomPartition(dst, rnd, x+split, y, width-split, height);
603 }
604 else if (partitionY)
605 {
606 int split = height/2 + rnd.getInt(-height/4, +height/4);
607 randomPartition(dst, rnd, x, y, width, split);
608 randomPartition(dst, rnd, x, y+split, width, height-split);
609 }
610 else
611 dst.push_back(IVec4(x, y, width, height));
612 }
613
computeGridLayout(vector<IVec4> & dst,int width,int height)614 static void computeGridLayout (vector<IVec4>& dst, int width, int height)
615 {
616 de::Random rnd(7);
617 randomPartition(dst, rnd, 0, 0, width, height);
618 }
619
iterate(void)620 TextureCubeMipmapCase::IterateResult TextureCubeMipmapCase::iterate (void)
621 {
622 const deUint32 magFilter = GL_NEAREST;
623 const int texWidth = m_texture->getRefTexture().getSize();
624 const int texHeight = m_texture->getRefTexture().getSize();
625 const int defViewportWidth = texWidth*2;
626 const int defViewportHeight = texHeight*2;
627
628 const glw::Functions& gl = m_renderCtx.getFunctions();
629 const RandomViewport viewport (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));
630
631 const bool isProjected = m_coordType == COORDTYPE_PROJECTED;
632 const bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS;
633
634 vector<float> texCoord;
635 tcu::Surface renderedFrame (viewport.width, viewport.height);
636
637 // Bail out if rendertarget is too small.
638 if (viewport.width < defViewportWidth/2 || viewport.height < defViewportHeight/2)
639 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
640
641 // Upload texture data.
642 m_texture->upload();
643
644 // Bind gradient texture and setup sampler parameters.
645 gl.bindTexture (GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
646 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, m_wrapS);
647 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, m_wrapT);
648 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter);
649 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter);
650
651 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
652
653 // Compute grid.
654 vector<IVec4> gridLayout;
655 computeGridLayout(gridLayout, viewport.width, viewport.height);
656
657 // Bias values.
658 static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
659
660 // Projection values \note Less agressive than in 2D case due to smaller quads.
661 static const Vec4 s_projections[] =
662 {
663 Vec4(1.2f, 1.0f, 0.7f, 1.0f),
664 Vec4(1.3f, 0.8f, 0.6f, 1.1f),
665 Vec4(0.8f, 1.0f, 1.2f, 0.8f),
666 Vec4(1.2f, 1.0f, 1.3f, 0.9f)
667 };
668
669 // Render with GL
670 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
671 {
672 const int curX = gridLayout[cellNdx].x();
673 const int curY = gridLayout[cellNdx].y();
674 const int curW = gridLayout[cellNdx].z();
675 const int curH = gridLayout[cellNdx].w();
676 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
677 RenderParams params (TEXTURETYPE_CUBE);
678
679 DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported.
680 computeQuadTexCoordCube(texCoord, cubeFace);
681
682 if (isProjected)
683 {
684 params.flags |= ReferenceParams::PROJECTED;
685 params.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
686 }
687
688 if (useLodBias)
689 {
690 params.flags |= ReferenceParams::USE_BIAS;
691 params.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
692 }
693
694 // Render with GL.
695 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
696 m_renderer.renderQuad(0, &texCoord[0], params);
697 }
698 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
699
700 // Read result.
701 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
702 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");
703
704 // Render reference and compare
705 {
706 tcu::Surface referenceFrame (viewport.width, viewport.height);
707 tcu::Surface errorMask (viewport.width, viewport.height);
708 int numFailedPixels = 0;
709 ReferenceParams params (TEXTURETYPE_CUBE);
710 tcu::LookupPrecision lookupPrec;
711 tcu::LodPrecision lodPrec;
712
713 // Params for rendering reference
714 params.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter);
715 params.sampler.seamlessCubeMap = true;
716 params.lodMode = LODMODE_EXACT;
717
718 // Comparison parameters
719 lookupPrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
720 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0)));
721 lookupPrec.coordBits = isProjected ? tcu::IVec3(8) : tcu::IVec3(10);
722 lookupPrec.uvwBits = tcu::IVec3(5,5,0);
723 lodPrec.derivateBits = 10;
724 lodPrec.lodBits = isProjected ? 3 : 6;
725
726 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
727 {
728 const int curX = gridLayout[cellNdx].x();
729 const int curY = gridLayout[cellNdx].y();
730 const int curW = gridLayout[cellNdx].z();
731 const int curH = gridLayout[cellNdx].w();
732 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
733
734 DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported.
735 computeQuadTexCoordCube(texCoord, cubeFace);
736
737 if (isProjected)
738 {
739 params.flags |= ReferenceParams::PROJECTED;
740 params.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
741 }
742
743 if (useLodBias)
744 {
745 params.flags |= ReferenceParams::USE_BIAS;
746 params.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
747 }
748
749 // Render ideal reference.
750 {
751 SurfaceAccess idealDst(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), curX, curY, curW, curH);
752 sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params);
753 }
754
755 // Compare this cell
756 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
757 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
758 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
759 m_texture->getRefTexture(), &texCoord[0], params,
760 lookupPrec, lodPrec, m_testCtx.getWatchDog());
761 }
762
763 if (numFailedPixels > 0)
764 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
765
766 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
767 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
768
769 if (numFailedPixels > 0)
770 {
771 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
772 << TestLog::Image("ErrorMask", "Error mask", errorMask);
773 }
774
775 m_testCtx.getLog() << TestLog::EndImageSet;
776
777 {
778 const bool isOk = numFailedPixels == 0;
779 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
780 isOk ? "Pass" : "Image verification failed");
781 }
782 }
783
784 return STOP;
785 }
786
787 // Texture2DGenMipmapCase
788
789 class Texture2DGenMipmapCase : public tcu::TestCase
790 {
791 public:
792
793 Texture2DGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int width, int height);
794 ~Texture2DGenMipmapCase (void);
795
796 void init (void);
797 void deinit (void);
798 IterateResult iterate (void);
799
800 private:
801 Texture2DGenMipmapCase (const Texture2DGenMipmapCase& other);
802 Texture2DGenMipmapCase& operator= (const Texture2DGenMipmapCase& other);
803
804 glu::RenderContext& m_renderCtx;
805
806 deUint32 m_format;
807 deUint32 m_dataType;
808 deUint32 m_hint;
809 int m_width;
810 int m_height;
811
812 glu::Texture2D* m_texture;
813 TextureRenderer m_renderer;
814 };
815
Texture2DGenMipmapCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,deUint32 format,deUint32 dataType,deUint32 hint,int width,int height)816 Texture2DGenMipmapCase::Texture2DGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int width, int height)
817 : TestCase (testCtx, name, desc)
818 , m_renderCtx (renderCtx)
819 , m_format (format)
820 , m_dataType (dataType)
821 , m_hint (hint)
822 , m_width (width)
823 , m_height (height)
824 , m_texture (DE_NULL)
825 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
826 {
827 }
828
~Texture2DGenMipmapCase(void)829 Texture2DGenMipmapCase::~Texture2DGenMipmapCase (void)
830 {
831 deinit();
832 }
833
init(void)834 void Texture2DGenMipmapCase::init (void)
835 {
836 DE_ASSERT(!m_texture);
837 m_texture = new glu::Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
838 }
839
deinit(void)840 void Texture2DGenMipmapCase::deinit (void)
841 {
842 delete m_texture;
843 m_texture = DE_NULL;
844
845 m_renderer.clear();
846 }
847
iterate(void)848 Texture2DGenMipmapCase::IterateResult Texture2DGenMipmapCase::iterate (void)
849 {
850 const glw::Functions& gl = m_renderCtx.getFunctions();
851
852 const deUint32 minFilter = GL_NEAREST_MIPMAP_NEAREST;
853 const deUint32 magFilter = GL_NEAREST;
854 const deUint32 wrapS = GL_CLAMP_TO_EDGE;
855 const deUint32 wrapT = GL_CLAMP_TO_EDGE;
856
857 const int numLevels = deLog2Floor32(de::max(m_width, m_height))+1;
858
859 tcu::Texture2D resultTexture (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), m_texture->getRefTexture().getWidth(), m_texture->getRefTexture().getHeight());
860
861 vector<float> texCoord;
862
863 // Initialize texture level 0 with colored grid.
864 m_texture->getRefTexture().allocLevel(0);
865 tcu::fillWithGrid(m_texture->getRefTexture().getLevel(0), 8, tcu::Vec4(1.0f, 0.5f, 0.0f, 0.5f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
866
867 // Upload data and setup params.
868 m_texture->upload();
869
870 gl.bindTexture (GL_TEXTURE_2D, m_texture->getGLTexture());
871 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
872 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
873 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
874 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
875 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
876
877 // Generate mipmap.
878 gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint);
879 gl.generateMipmap(GL_TEXTURE_2D);
880 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()");
881
882 // Use (0, 0) -> (1, 1) texture coordinates.
883 computeQuadTexCoord2D(texCoord, Vec2(0.0f, 0.0f), Vec2(1.0f, 1.0f));
884
885 // Fetch resulting texture by rendering.
886 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
887 {
888 const int levelWidth = de::max(1, m_width >> levelNdx);
889 const int levelHeight = de::max(1, m_height >> levelNdx);
890 const RandomViewport viewport (m_renderCtx.getRenderTarget(), levelWidth, levelHeight, deStringHash(getName()) + levelNdx);
891
892 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
893 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_2D);
894
895 resultTexture.allocLevel(levelNdx);
896 glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevel(levelNdx));
897 }
898
899 // Compare results
900 {
901 const IVec4 framebufferBits = max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0));
902 const IVec4 formatBits = tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
903 const tcu::BVec4 formatMask = greaterThan(formatBits, IVec4(0));
904 const IVec4 cmpBits = select(min(framebufferBits, formatBits), framebufferBits, formatMask);
905 GenMipmapPrecision comparePrec;
906
907 comparePrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
908 comparePrec.colorThreshold = tcu::computeFixedPointThreshold(cmpBits);
909 comparePrec.filterBits = tcu::IVec3(4, 4, 0);
910
911 const qpTestResult compareResult = compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec);
912
913 m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS ? "Pass" :
914 compareResult == QP_TEST_RESULT_QUALITY_WARNING ? "Low-quality method used" :
915 compareResult == QP_TEST_RESULT_FAIL ? "Image comparison failed" : "");
916 }
917
918 return STOP;
919 }
920
921 // TextureCubeGenMipmapCase
922
923 class TextureCubeGenMipmapCase : public tcu::TestCase
924 {
925 public:
926
927 TextureCubeGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int size);
928 ~TextureCubeGenMipmapCase (void);
929
930 void init (void);
931 void deinit (void);
932 IterateResult iterate (void);
933
934 private:
935 TextureCubeGenMipmapCase (const TextureCubeGenMipmapCase& other);
936 TextureCubeGenMipmapCase& operator= (const TextureCubeGenMipmapCase& other);
937
938 glu::RenderContext& m_renderCtx;
939
940 deUint32 m_format;
941 deUint32 m_dataType;
942 deUint32 m_hint;
943 int m_size;
944
945 glu::TextureCube* m_texture;
946 TextureRenderer m_renderer;
947 };
948
TextureCubeGenMipmapCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,deUint32 format,deUint32 dataType,deUint32 hint,int size)949 TextureCubeGenMipmapCase::TextureCubeGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int size)
950 : TestCase (testCtx, name, desc)
951 , m_renderCtx (renderCtx)
952 , m_format (format)
953 , m_dataType (dataType)
954 , m_hint (hint)
955 , m_size (size)
956 , m_texture (DE_NULL)
957 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
958 {
959 }
960
~TextureCubeGenMipmapCase(void)961 TextureCubeGenMipmapCase::~TextureCubeGenMipmapCase (void)
962 {
963 deinit();
964 }
965
init(void)966 void TextureCubeGenMipmapCase::init (void)
967 {
968 if (m_renderCtx.getRenderTarget().getWidth() < 3*m_size || m_renderCtx.getRenderTarget().getHeight() < 2*m_size)
969 throw tcu::NotSupportedError("Render target size must be at least (" + de::toString(3*m_size) + ", " + de::toString(2*m_size) + ")");
970
971 DE_ASSERT(!m_texture);
972 m_texture = new glu::TextureCube(m_renderCtx, m_format, m_dataType, m_size);
973 }
974
deinit(void)975 void TextureCubeGenMipmapCase::deinit (void)
976 {
977 delete m_texture;
978 m_texture = DE_NULL;
979
980 m_renderer.clear();
981 }
982
iterate(void)983 TextureCubeGenMipmapCase::IterateResult TextureCubeGenMipmapCase::iterate (void)
984 {
985 const glw::Functions& gl = m_renderCtx.getFunctions();
986
987 const deUint32 minFilter = GL_NEAREST_MIPMAP_NEAREST;
988 const deUint32 magFilter = GL_NEAREST;
989 const deUint32 wrapS = GL_CLAMP_TO_EDGE;
990 const deUint32 wrapT = GL_CLAMP_TO_EDGE;
991
992 tcu::TextureCube resultTexture (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), m_size);
993
994 const int numLevels = deLog2Floor32(m_size)+1;
995 vector<float> texCoord;
996
997 // Initialize texture level 0 with colored grid.
998 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
999 {
1000 Vec4 ca, cb; // Grid colors.
1001
1002 switch (face)
1003 {
1004 case 0: ca = Vec4(1.0f, 0.3f, 0.0f, 0.7f); cb = Vec4(0.0f, 0.0f, 1.0f, 1.0f); break;
1005 case 1: ca = Vec4(0.0f, 1.0f, 0.5f, 0.5f); cb = Vec4(1.0f, 0.0f, 0.0f, 1.0f); break;
1006 case 2: ca = Vec4(0.7f, 0.0f, 1.0f, 0.3f); cb = Vec4(0.0f, 1.0f, 0.0f, 1.0f); break;
1007 case 3: ca = Vec4(0.0f, 0.3f, 1.0f, 1.0f); cb = Vec4(1.0f, 0.0f, 0.0f, 0.7f); break;
1008 case 4: ca = Vec4(1.0f, 0.0f, 0.5f, 1.0f); cb = Vec4(0.0f, 1.0f, 0.0f, 0.5f); break;
1009 case 5: ca = Vec4(0.7f, 1.0f, 0.0f, 1.0f); cb = Vec4(0.0f, 0.0f, 1.0f, 0.3f); break;
1010 }
1011
1012 m_texture->getRefTexture().allocLevel((tcu::CubeFace)face, 0);
1013 fillWithGrid(m_texture->getRefTexture().getLevelFace(0, (tcu::CubeFace)face), 8, ca, cb);
1014 }
1015
1016 // Upload data and setup params.
1017 m_texture->upload();
1018
1019 gl.bindTexture (GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
1020 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrapS);
1021 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrapT);
1022 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, minFilter);
1023 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter);
1024 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
1025
1026 // Generate mipmap.
1027 gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint);
1028 gl.generateMipmap(GL_TEXTURE_CUBE_MAP);
1029 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()");
1030
1031 // Render all levels.
1032 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1033 {
1034 const int levelWidth = de::max(1, m_size >> levelNdx);
1035 const int levelHeight = de::max(1, m_size >> levelNdx);
1036
1037 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1038 {
1039 const RandomViewport viewport (m_renderCtx.getRenderTarget(), levelWidth*3, levelHeight*2, deStringHash(getName()) ^ deInt32Hash(levelNdx + faceNdx));
1040 const tcu::CubeFace face = tcu::CubeFace(faceNdx);
1041
1042 computeQuadTexCoordCube(texCoord, face);
1043
1044 gl.viewport(viewport.x, viewport.y, levelWidth, levelHeight);
1045 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_CUBE);
1046
1047 resultTexture.allocLevel(face, levelNdx);
1048 glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevelFace(levelNdx, face));
1049 }
1050 }
1051
1052 // Compare results
1053 {
1054 const IVec4 framebufferBits = max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0));
1055 const IVec4 formatBits = tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
1056 const tcu::BVec4 formatMask = greaterThan(formatBits, IVec4(0));
1057 const IVec4 cmpBits = select(min(framebufferBits, formatBits), framebufferBits, formatMask);
1058 GenMipmapPrecision comparePrec;
1059
1060 comparePrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
1061 comparePrec.colorThreshold = tcu::computeFixedPointThreshold(cmpBits);
1062 comparePrec.filterBits = tcu::IVec3(4, 4, 0);
1063
1064 const qpTestResult compareResult = compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec);
1065
1066 m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS ? "Pass" :
1067 compareResult == QP_TEST_RESULT_QUALITY_WARNING ? "Low-quality method used" :
1068 compareResult == QP_TEST_RESULT_FAIL ? "Image comparison failed" : "");
1069 }
1070
1071 return STOP;
1072 }
1073
1074 // Texture3DMipmapCase
1075
1076 class Texture3DMipmapCase : public TestCase
1077 {
1078 public:
1079
1080 Texture3DMipmapCase (Context& context,
1081 const char* name,
1082 const char* desc,
1083 CoordType coordType,
1084 deUint32 minFilter,
1085 deUint32 wrapS,
1086 deUint32 wrapT,
1087 deUint32 wrapR,
1088 deUint32 format,
1089 int width,
1090 int height,
1091 int depth);
1092 ~Texture3DMipmapCase (void);
1093
1094 void init (void);
1095 void deinit (void);
1096 IterateResult iterate (void);
1097
1098 private:
1099 Texture3DMipmapCase (const Texture3DMipmapCase& other);
1100 Texture3DMipmapCase& operator= (const Texture3DMipmapCase& other);
1101
1102 CoordType m_coordType;
1103 deUint32 m_minFilter;
1104 deUint32 m_wrapS;
1105 deUint32 m_wrapT;
1106 deUint32 m_wrapR;
1107 deUint32 m_internalFormat;
1108 int m_width;
1109 int m_height;
1110 int m_depth;
1111
1112 glu::Texture3D* m_texture;
1113 TextureTestUtil::TextureRenderer m_renderer;
1114 };
1115
Texture3DMipmapCase(Context & context,const char * name,const char * desc,CoordType coordType,deUint32 minFilter,deUint32 wrapS,deUint32 wrapT,deUint32 wrapR,deUint32 format,int width,int height,int depth)1116 Texture3DMipmapCase::Texture3DMipmapCase (Context& context, const char* name, const char* desc, CoordType coordType, deUint32 minFilter, deUint32 wrapS, deUint32 wrapT, deUint32 wrapR, deUint32 format, int width, int height, int depth)
1117 : TestCase (context, name, desc)
1118 , m_coordType (coordType)
1119 , m_minFilter (minFilter)
1120 , m_wrapS (wrapS)
1121 , m_wrapT (wrapT)
1122 , m_wrapR (wrapR)
1123 , m_internalFormat (format)
1124 , m_width (width)
1125 , m_height (height)
1126 , m_depth (depth)
1127 , m_texture (DE_NULL)
1128 , m_renderer (context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
1129 {
1130 }
1131
~Texture3DMipmapCase(void)1132 Texture3DMipmapCase::~Texture3DMipmapCase (void)
1133 {
1134 Texture3DMipmapCase::deinit();
1135 }
1136
init(void)1137 void Texture3DMipmapCase::init (void)
1138 {
1139 const tcu::TextureFormat& texFmt = glu::mapGLInternalFormat(m_internalFormat);
1140 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
1141 const tcu::Vec4& cScale = fmtInfo.lookupScale;
1142 const tcu::Vec4& cBias = fmtInfo.lookupBias;
1143 int numLevels = deLog2Floor32(de::max(de::max(m_width, m_height), m_depth))+1;
1144
1145 if (m_coordType == COORDTYPE_PROJECTED && m_context.getRenderTarget().getNumSamples() > 0)
1146 throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config");
1147
1148 m_texture = new glu::Texture3D(m_context.getRenderContext(), m_internalFormat, m_width, m_height, m_depth);
1149
1150 // Fill texture with colored grid.
1151 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1152 {
1153 deUint32 step = 0xff / (numLevels-1);
1154 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff);
1155 deUint32 dec = 0xff - inc;
1156 deUint32 rgb = (0xff << 16) | (dec << 8) | inc;
1157 deUint32 color = 0xff000000 | rgb;
1158
1159 m_texture->getRefTexture().allocLevel(levelNdx);
1160 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), tcu::RGBA(color).toVec()*cScale + cBias);
1161 }
1162
1163 m_texture->upload();
1164 }
1165
deinit(void)1166 void Texture3DMipmapCase::deinit (void)
1167 {
1168 delete m_texture;
1169 m_texture = DE_NULL;
1170
1171 m_renderer.clear();
1172 }
1173
getBasicTexCoord3D(std::vector<float> & dst,int cellNdx)1174 static void getBasicTexCoord3D (std::vector<float>& dst, int cellNdx)
1175 {
1176 static const struct
1177 {
1178 float sScale;
1179 float sBias;
1180 float tScale;
1181 float tBias;
1182 float rScale;
1183 float rBias;
1184 } s_params[] =
1185 {
1186 // sScale sBias tScale tBias rScale rBias
1187 { 0.9f, -0.1f, 0.7f, 0.3f, 0.8f, 0.9f },
1188 { 1.2f, -0.1f, 1.1f, 0.3f, 1.0f, 0.9f },
1189 { 1.5f, 0.7f, 0.9f, -0.3f, 1.1f, 0.1f },
1190 { 1.2f, 0.7f, -2.3f, -0.3f, 1.1f, 0.2f },
1191 { 1.1f, 0.8f, -1.3f, -0.3f, 2.9f, 0.9f },
1192 { 3.4f, 0.8f, 4.0f, 0.0f, -3.3f, -1.0f },
1193 { -3.4f, -0.1f, -4.0f, 0.0f, -5.1f, 1.0f },
1194 { -4.0f, -0.1f, 3.4f, 0.1f, 5.7f, 0.0f },
1195 { -5.6f, 0.0f, 0.5f, 1.2f, 3.9f, 4.0f },
1196 { 5.0f, -2.0f, 3.1f, 1.2f, 5.1f, 0.2f },
1197 { 2.5f, -2.0f, 6.3f, 3.0f, 5.1f, 0.2f },
1198 { -8.3f, 0.0f, 7.1f, 3.0f, 2.0f, 0.2f },
1199 { 3.8f, 0.0f, 9.7f, 1.0f, 7.0f, 0.7f },
1200 { 13.3f, 0.0f, 7.1f, 3.0f, 2.0f, 0.2f },
1201 { 16.0f, 8.0f, 12.7f, 1.0f, 17.1f, 0.7f },
1202 { 15.3f, 0.0f, 20.1f, 3.0f, 33.0f, 3.2f }
1203 };
1204
1205 float sScale = s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].sScale;
1206 float sBias = s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].sBias;
1207 float tScale = s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].tScale;
1208 float tBias = s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].tBias;
1209 float rScale = s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].rScale;
1210 float rBias = s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].rBias;
1211
1212 dst.resize(3*4);
1213
1214 dst[0] = sBias; dst[ 1] = tBias; dst[ 2] = rBias;
1215 dst[3] = sBias; dst[ 4] = tBias+tScale; dst[ 5] = rBias+rScale*0.5f;
1216 dst[6] = sBias+sScale; dst[ 7] = tBias; dst[ 8] = rBias+rScale*0.5f;
1217 dst[9] = sBias+sScale; dst[10] = tBias+tScale; dst[11] = rBias+rScale;
1218 }
1219
getAffineTexCoord3D(std::vector<float> & dst,int cellNdx)1220 static void getAffineTexCoord3D (std::vector<float>& dst, int cellNdx)
1221 {
1222 // Use basic coords as base.
1223 getBasicTexCoord3D(dst, cellNdx);
1224
1225 // Rotate based on cell index.
1226 float angleX = 0.0f + 2.0f*DE_PI * ((float)cellNdx / 16.0f);
1227 float angleY = 1.0f + 2.0f*DE_PI * ((float)cellNdx / 32.0f);
1228 tcu::Mat3 rotMatrix = tcu::rotationMatrixX(angleX) * tcu::rotationMatrixY(angleY);
1229
1230 Vec3 p0 = rotMatrix * Vec3(dst[0], dst[ 1], dst[ 2]);
1231 Vec3 p1 = rotMatrix * Vec3(dst[3], dst[ 4], dst[ 5]);
1232 Vec3 p2 = rotMatrix * Vec3(dst[6], dst[ 7], dst[ 8]);
1233 Vec3 p3 = rotMatrix * Vec3(dst[9], dst[10], dst[11]);
1234
1235 dst[0] = p0.x(); dst[ 1] = p0.y(); dst[ 2] = p0.z();
1236 dst[3] = p1.x(); dst[ 4] = p1.y(); dst[ 5] = p1.z();
1237 dst[6] = p2.x(); dst[ 7] = p2.y(); dst[ 8] = p2.z();
1238 dst[9] = p3.x(); dst[10] = p3.y(); dst[11] = p3.z();
1239 }
1240
iterate(void)1241 Texture3DMipmapCase::IterateResult Texture3DMipmapCase::iterate (void)
1242 {
1243 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1244
1245 const tcu::Texture3D& refTexture = m_texture->getRefTexture();
1246 const tcu::TextureFormat& texFmt = refTexture.getFormat();
1247 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
1248 const int texWidth = refTexture.getWidth();
1249 const int texHeight = refTexture.getHeight();
1250 const deUint32 magFilter = GL_NEAREST;
1251
1252 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
1253 const RandomViewport viewport (renderTarget, texWidth*4, texHeight*4, deStringHash(getName()));
1254
1255 const bool isProjected = m_coordType == COORDTYPE_PROJECTED;
1256 const bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS;
1257
1258 // Viewport is divided into 4x4 grid.
1259 const int gridWidth = 4;
1260 const int gridHeight = 4;
1261 const int cellWidth = viewport.width / gridWidth;
1262 const int cellHeight = viewport.height / gridHeight;
1263
1264 ReferenceParams sampleParams (TEXTURETYPE_3D);
1265
1266 tcu::Surface renderedFrame (viewport.width, viewport.height);
1267 vector<float> texCoord;
1268
1269 // Sampling parameters.
1270 sampleParams.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_wrapR, m_minFilter, magFilter);
1271 sampleParams.samplerType = gls::TextureTestUtil::getSamplerType(texFmt);
1272 sampleParams.colorBias = fmtInfo.lookupBias;
1273 sampleParams.colorScale = fmtInfo.lookupScale;
1274 sampleParams.flags = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
1275
1276 // Bind texture and setup sampler parameters.
1277 gl.bindTexture (GL_TEXTURE_3D, m_texture->getGLTexture());
1278 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, m_wrapS);
1279 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, m_wrapT);
1280 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, m_wrapR);
1281 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, m_minFilter);
1282 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, magFilter);
1283
1284 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
1285
1286 // Bias values.
1287 static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
1288
1289 // Projection values.
1290 static const Vec4 s_projections[] =
1291 {
1292 Vec4(1.2f, 1.0f, 0.7f, 1.0f),
1293 Vec4(1.3f, 0.8f, 0.6f, 2.0f),
1294 Vec4(0.8f, 1.0f, 1.7f, 0.6f),
1295 Vec4(1.2f, 1.0f, 1.7f, 1.5f)
1296 };
1297
1298 // Render cells.
1299 for (int gridY = 0; gridY < gridHeight; gridY++)
1300 {
1301 for (int gridX = 0; gridX < gridWidth; gridX++)
1302 {
1303 const int curX = cellWidth*gridX;
1304 const int curY = cellHeight*gridY;
1305 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
1306 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
1307 const int cellNdx = gridY*gridWidth + gridX;
1308
1309 // Compute texcoord.
1310 switch (m_coordType)
1311 {
1312 case COORDTYPE_BASIC_BIAS: // Fall-through.
1313 case COORDTYPE_PROJECTED:
1314 case COORDTYPE_BASIC: getBasicTexCoord3D (texCoord, cellNdx); break;
1315 case COORDTYPE_AFFINE: getAffineTexCoord3D (texCoord, cellNdx); break;
1316 default: DE_ASSERT(DE_FALSE);
1317 }
1318
1319 // Set projection.
1320 if (isProjected)
1321 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
1322
1323 // Set LOD bias.
1324 if (useLodBias)
1325 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
1326
1327 // Render with GL.
1328 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
1329 m_renderer.renderQuad(0, &texCoord[0], sampleParams);
1330 }
1331 }
1332
1333 // Read result.
1334 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess());
1335
1336 // Compare and log
1337 {
1338 const tcu::PixelFormat& pixelFormat = m_context.getRenderTarget().getPixelFormat();
1339 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
1340 tcu::Surface referenceFrame (viewport.width, viewport.height);
1341 tcu::Surface errorMask (viewport.width, viewport.height);
1342 tcu::LookupPrecision lookupPrec;
1343 tcu::LodPrecision lodPrec;
1344 int numFailedPixels = 0;
1345
1346 lookupPrec.coordBits = tcu::IVec3(20, 20, 20);
1347 lookupPrec.uvwBits = tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
1348 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
1349 lookupPrec.colorMask = getCompareMask(pixelFormat);
1350 lodPrec.derivateBits = 10;
1351 lodPrec.lodBits = isProjected ? 6 : 8;
1352
1353 for (int gridY = 0; gridY < gridHeight; gridY++)
1354 {
1355 for (int gridX = 0; gridX < gridWidth; gridX++)
1356 {
1357 const int curX = cellWidth*gridX;
1358 const int curY = cellHeight*gridY;
1359 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
1360 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
1361 const int cellNdx = gridY*gridWidth + gridX;
1362
1363 switch (m_coordType)
1364 {
1365 case COORDTYPE_BASIC_BIAS: // Fall-through.
1366 case COORDTYPE_PROJECTED:
1367 case COORDTYPE_BASIC: getBasicTexCoord3D (texCoord, cellNdx); break;
1368 case COORDTYPE_AFFINE: getAffineTexCoord3D (texCoord, cellNdx); break;
1369 default: DE_ASSERT(DE_FALSE);
1370 }
1371
1372 if (isProjected)
1373 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
1374
1375 if (useLodBias)
1376 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
1377
1378 // Render ideal result
1379 sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
1380 refTexture, &texCoord[0], sampleParams);
1381
1382 // Compare this cell
1383 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1384 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1385 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
1386 m_texture->getRefTexture(), &texCoord[0], sampleParams,
1387 lookupPrec, lodPrec, m_testCtx.getWatchDog());
1388 }
1389 }
1390
1391 if (numFailedPixels > 0)
1392 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1393
1394 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
1395 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
1396
1397 if (numFailedPixels > 0)
1398 {
1399 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1400 << TestLog::Image("ErrorMask", "Error mask", errorMask);
1401 }
1402
1403 m_testCtx.getLog() << TestLog::EndImageSet;
1404
1405 {
1406 const bool isOk = numFailedPixels == 0;
1407 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1408 isOk ? "Pass" : "Image verification failed");
1409 }
1410 }
1411
1412 return STOP;
1413 }
1414
1415 // Texture2DLodControlCase + test cases
1416
1417 class Texture2DLodControlCase : public TestCase
1418 {
1419 public:
1420
1421 Texture2DLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter);
1422 ~Texture2DLodControlCase (void);
1423
1424 void init (void);
1425 void deinit (void);
1426 IterateResult iterate (void);
1427
1428 protected:
1429 virtual void setTextureParams (int cellNdx) = DE_NULL;
1430 virtual void getReferenceParams (ReferenceParams& params, int cellNdx) = DE_NULL;
1431
1432 const int m_texWidth;
1433 const int m_texHeight;
1434
1435 private:
1436 Texture2DLodControlCase (const Texture2DLodControlCase& other);
1437 Texture2DLodControlCase& operator= (const Texture2DLodControlCase& other);
1438
1439 deUint32 m_minFilter;
1440
1441 glu::Texture2D* m_texture;
1442 TextureTestUtil::TextureRenderer m_renderer;
1443 };
1444
Texture2DLodControlCase(Context & context,const char * name,const char * desc,deUint32 minFilter)1445 Texture2DLodControlCase::Texture2DLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
1446 : TestCase (context, name, desc)
1447 , m_texWidth (64)
1448 , m_texHeight (64)
1449 , m_minFilter (minFilter)
1450 , m_texture (DE_NULL)
1451 , m_renderer (context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
1452 {
1453 }
1454
~Texture2DLodControlCase(void)1455 Texture2DLodControlCase::~Texture2DLodControlCase (void)
1456 {
1457 Texture2DLodControlCase::deinit();
1458 }
1459
init(void)1460 void Texture2DLodControlCase::init (void)
1461 {
1462 const deUint32 format = GL_RGBA8;
1463 int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;
1464
1465 m_texture = new glu::Texture2D(m_context.getRenderContext(), format, m_texWidth, m_texHeight);
1466
1467 // Fill texture with colored grid.
1468 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1469 {
1470 deUint32 step = 0xff / (numLevels-1);
1471 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff);
1472 deUint32 dec = 0xff - inc;
1473 deUint32 rgb = (inc << 16) | (dec << 8) | 0xff;
1474 deUint32 color = 0xff000000 | rgb;
1475
1476 m_texture->getRefTexture().allocLevel(levelNdx);
1477 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), tcu::RGBA(color).toVec());
1478 }
1479 }
1480
deinit(void)1481 void Texture2DLodControlCase::deinit (void)
1482 {
1483 delete m_texture;
1484 m_texture = DE_NULL;
1485
1486 m_renderer.clear();
1487 }
1488
iterate(void)1489 Texture2DLodControlCase::IterateResult Texture2DLodControlCase::iterate (void)
1490 {
1491 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1492
1493 const deUint32 wrapS = GL_REPEAT;
1494 const deUint32 wrapT = GL_REPEAT;
1495 const deUint32 magFilter = GL_NEAREST;
1496
1497 const tcu::Texture2D& refTexture = m_texture->getRefTexture();
1498 const int texWidth = refTexture.getWidth();
1499 const int texHeight = refTexture.getHeight();
1500
1501 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
1502 const RandomViewport viewport (renderTarget, texWidth*4, texHeight*4, deStringHash(getName()));
1503
1504 ReferenceParams sampleParams (gls::TextureTestUtil::TEXTURETYPE_2D, glu::mapGLSampler(wrapS, wrapT, m_minFilter, magFilter));
1505 vector<float> texCoord;
1506 tcu::Surface renderedFrame (viewport.width, viewport.height);
1507
1508 // Viewport is divided into 4x4 grid.
1509 const int gridWidth = 4;
1510 const int gridHeight = 4;
1511 const int cellWidth = viewport.width / gridWidth;
1512 const int cellHeight = viewport.height / gridHeight;
1513
1514 // Upload texture data.
1515 m_texture->upload();
1516
1517 // Bind gradient texture and setup sampler parameters.
1518 gl.bindTexture (GL_TEXTURE_2D, m_texture->getGLTexture());
1519 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
1520 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
1521 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter);
1522 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
1523
1524 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
1525
1526 // Render cells.
1527 for (int gridY = 0; gridY < gridHeight; gridY++)
1528 {
1529 for (int gridX = 0; gridX < gridWidth; gridX++)
1530 {
1531 int curX = cellWidth*gridX;
1532 int curY = cellHeight*gridY;
1533 int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
1534 int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
1535 int cellNdx = gridY*gridWidth + gridX;
1536
1537 // Compute texcoord.
1538 getBasicTexCoord2D(texCoord, cellNdx);
1539
1540 // Render with GL.
1541 setTextureParams(cellNdx);
1542 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
1543 m_renderer.renderQuad(0, &texCoord[0], sampleParams);
1544 }
1545 }
1546
1547 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess());
1548 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");
1549
1550 // Compare and log.
1551 {
1552 const tcu::PixelFormat& pixelFormat = m_context.getRenderTarget().getPixelFormat();
1553 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
1554 tcu::Surface referenceFrame (viewport.width, viewport.height);
1555 tcu::Surface errorMask (viewport.width, viewport.height);
1556 tcu::LookupPrecision lookupPrec;
1557 tcu::LodPrecision lodPrec;
1558 int numFailedPixels = 0;
1559
1560 lookupPrec.coordBits = tcu::IVec3(20, 20, 0);
1561 lookupPrec.uvwBits = tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
1562 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
1563 lookupPrec.colorMask = getCompareMask(pixelFormat);
1564 lodPrec.derivateBits = 10;
1565 lodPrec.lodBits = 8;
1566
1567 for (int gridY = 0; gridY < gridHeight; gridY++)
1568 {
1569 for (int gridX = 0; gridX < gridWidth; gridX++)
1570 {
1571 const int curX = cellWidth*gridX;
1572 const int curY = cellHeight*gridY;
1573 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
1574 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
1575 const int cellNdx = gridY*gridWidth + gridX;
1576
1577 getBasicTexCoord2D(texCoord, cellNdx);
1578 getReferenceParams(sampleParams, cellNdx);
1579
1580 // Render ideal result
1581 sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
1582 refTexture, &texCoord[0], sampleParams);
1583
1584 // Compare this cell
1585 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1586 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1587 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
1588 m_texture->getRefTexture(), &texCoord[0], sampleParams,
1589 lookupPrec, lodPrec, m_testCtx.getWatchDog());
1590 }
1591 }
1592
1593 if (numFailedPixels > 0)
1594 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1595
1596 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
1597 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
1598
1599 if (numFailedPixels > 0)
1600 {
1601 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1602 << TestLog::Image("ErrorMask", "Error mask", errorMask);
1603 }
1604
1605 m_testCtx.getLog() << TestLog::EndImageSet;
1606
1607 {
1608 const bool isOk = numFailedPixels == 0;
1609 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1610 isOk ? "Pass" : "Image verification failed");
1611 }
1612 }
1613
1614 return STOP;
1615 }
1616
1617 class Texture2DMinLodCase : public Texture2DLodControlCase
1618 {
1619 public:
Texture2DMinLodCase(Context & context,const char * name,const char * desc,deUint32 minFilter)1620 Texture2DMinLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
1621 : Texture2DLodControlCase(context, name, desc, minFilter)
1622 {
1623 }
1624
1625 protected:
setTextureParams(int cellNdx)1626 void setTextureParams (int cellNdx)
1627 {
1628 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1629 gl.texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, getMinLodForCell(cellNdx));
1630 }
1631
getReferenceParams(ReferenceParams & params,int cellNdx)1632 void getReferenceParams (ReferenceParams& params, int cellNdx)
1633 {
1634 params.minLod = getMinLodForCell(cellNdx);
1635 }
1636 };
1637
1638 class Texture2DMaxLodCase : public Texture2DLodControlCase
1639 {
1640 public:
Texture2DMaxLodCase(Context & context,const char * name,const char * desc,deUint32 minFilter)1641 Texture2DMaxLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
1642 : Texture2DLodControlCase(context, name, desc, minFilter)
1643 {
1644 }
1645
1646 protected:
setTextureParams(int cellNdx)1647 void setTextureParams (int cellNdx)
1648 {
1649 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1650 gl.texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, getMaxLodForCell(cellNdx));
1651 }
1652
getReferenceParams(ReferenceParams & params,int cellNdx)1653 void getReferenceParams (ReferenceParams& params, int cellNdx)
1654 {
1655 params.maxLod = getMaxLodForCell(cellNdx);
1656 }
1657 };
1658
1659 class Texture2DBaseLevelCase : public Texture2DLodControlCase
1660 {
1661 public:
Texture2DBaseLevelCase(Context & context,const char * name,const char * desc,deUint32 minFilter)1662 Texture2DBaseLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
1663 : Texture2DLodControlCase(context, name, desc, minFilter)
1664 {
1665 }
1666
1667 protected:
getBaseLevel(int cellNdx) const1668 int getBaseLevel (int cellNdx) const
1669 {
1670 const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;
1671 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0xac2f274a) % numLevels;
1672
1673 return baseLevel;
1674 }
1675
setTextureParams(int cellNdx)1676 void setTextureParams (int cellNdx)
1677 {
1678 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1679 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, getBaseLevel(cellNdx));
1680 }
1681
getReferenceParams(ReferenceParams & params,int cellNdx)1682 void getReferenceParams (ReferenceParams& params, int cellNdx)
1683 {
1684 params.baseLevel = getBaseLevel(cellNdx);
1685 }
1686 };
1687
1688 class Texture2DMaxLevelCase : public Texture2DLodControlCase
1689 {
1690 public:
Texture2DMaxLevelCase(Context & context,const char * name,const char * desc,deUint32 minFilter)1691 Texture2DMaxLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
1692 : Texture2DLodControlCase(context, name, desc, minFilter)
1693 {
1694 }
1695
1696 protected:
getMaxLevel(int cellNdx) const1697 int getMaxLevel (int cellNdx) const
1698 {
1699 const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;
1700 const int maxLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x82cfa4e) % numLevels;
1701
1702 return maxLevel;
1703 }
1704
setTextureParams(int cellNdx)1705 void setTextureParams (int cellNdx)
1706 {
1707 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1708 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, getMaxLevel(cellNdx));
1709 }
1710
getReferenceParams(ReferenceParams & params,int cellNdx)1711 void getReferenceParams (ReferenceParams& params, int cellNdx)
1712 {
1713 params.maxLevel = getMaxLevel(cellNdx);
1714 }
1715 };
1716
1717 // TextureCubeLodControlCase + test cases
1718
1719 class TextureCubeLodControlCase : public TestCase
1720 {
1721 public:
1722
1723 TextureCubeLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter);
1724 ~TextureCubeLodControlCase (void);
1725
1726 void init (void);
1727 void deinit (void);
1728 IterateResult iterate (void);
1729
1730 protected:
1731 virtual void setTextureParams (int cellNdx) = DE_NULL;
1732 virtual void getReferenceParams (ReferenceParams& params, int cellNdx) = DE_NULL;
1733
1734 const int m_texSize;
1735
1736 private:
1737 TextureCubeLodControlCase (const TextureCubeLodControlCase& other);
1738 TextureCubeLodControlCase& operator= (const TextureCubeLodControlCase& other);
1739
1740 deUint32 m_minFilter;
1741
1742 glu::TextureCube* m_texture;
1743 TextureTestUtil::TextureRenderer m_renderer;
1744 };
1745
TextureCubeLodControlCase(Context & context,const char * name,const char * desc,deUint32 minFilter)1746 TextureCubeLodControlCase::TextureCubeLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
1747 : TestCase (context, name, desc)
1748 , m_texSize (64)
1749 , m_minFilter (minFilter)
1750 , m_texture (DE_NULL)
1751 , m_renderer (context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
1752 {
1753 }
1754
~TextureCubeLodControlCase(void)1755 TextureCubeLodControlCase::~TextureCubeLodControlCase (void)
1756 {
1757 deinit();
1758 }
1759
init(void)1760 void TextureCubeLodControlCase::init (void)
1761 {
1762 const deUint32 format = GL_RGBA8;
1763 const int numLevels = deLog2Floor32(m_texSize)+1;
1764
1765 m_texture = new glu::TextureCube(m_context.getRenderContext(), format, m_texSize);
1766
1767 // Fill texture with colored grid.
1768 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1769 {
1770 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1771 {
1772 deUint32 step = 0xff / (numLevels-1);
1773 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff);
1774 deUint32 dec = 0xff - inc;
1775 deUint32 rgb = 0;
1776
1777 switch (faceNdx)
1778 {
1779 case 0: rgb = (inc << 16) | (dec << 8) | 255; break;
1780 case 1: rgb = (255 << 16) | (inc << 8) | dec; break;
1781 case 2: rgb = (dec << 16) | (255 << 8) | inc; break;
1782 case 3: rgb = (dec << 16) | (inc << 8) | 255; break;
1783 case 4: rgb = (255 << 16) | (dec << 8) | inc; break;
1784 case 5: rgb = (inc << 16) | (255 << 8) | dec; break;
1785 }
1786
1787 deUint32 color = 0xff000000 | rgb;
1788
1789 m_texture->getRefTexture().allocLevel((tcu::CubeFace)faceNdx, levelNdx);
1790 tcu::clear(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), tcu::RGBA(color).toVec());
1791 }
1792 }
1793 }
1794
deinit(void)1795 void TextureCubeLodControlCase::deinit (void)
1796 {
1797 delete m_texture;
1798 m_texture = DE_NULL;
1799
1800 m_renderer.clear();
1801 }
1802
iterate(void)1803 TextureCubeLodControlCase::IterateResult TextureCubeLodControlCase::iterate (void)
1804 {
1805 const deUint32 wrapS = GL_CLAMP_TO_EDGE;
1806 const deUint32 wrapT = GL_CLAMP_TO_EDGE;
1807 const deUint32 magFilter = GL_NEAREST;
1808
1809 const int texWidth = m_texture->getRefTexture().getSize();
1810 const int texHeight = m_texture->getRefTexture().getSize();
1811
1812 const int defViewportWidth = texWidth*2;
1813 const int defViewportHeight = texHeight*2;
1814
1815 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1816 const RandomViewport viewport (m_context.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));
1817
1818 vector<float> texCoord;
1819
1820 tcu::Surface renderedFrame (viewport.width, viewport.height);
1821
1822 // Upload texture data.
1823 m_texture->upload();
1824
1825 // Bind gradient texture and setup sampler parameters.
1826 gl.bindTexture (GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
1827 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrapS);
1828 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrapT);
1829 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter);
1830 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter);
1831
1832 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
1833
1834 // Compute grid.
1835 vector<tcu::IVec4> gridLayout;
1836 computeGridLayout(gridLayout, viewport.width, viewport.height);
1837
1838 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
1839 {
1840 const int curX = gridLayout[cellNdx].x();
1841 const int curY = gridLayout[cellNdx].y();
1842 const int curW = gridLayout[cellNdx].z();
1843 const int curH = gridLayout[cellNdx].w();
1844 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
1845 RenderParams params (TEXTURETYPE_CUBE);
1846
1847 TextureTestUtil::computeQuadTexCoordCube(texCoord, cubeFace);
1848
1849 setTextureParams(cellNdx);
1850
1851 // Render with GL.
1852 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
1853 m_renderer.renderQuad(0, &texCoord[0], params);
1854 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
1855 }
1856
1857 // Read result.
1858 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess());
1859 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");
1860
1861 // Render reference and compare
1862 {
1863 tcu::Surface referenceFrame (viewport.width, viewport.height);
1864 tcu::Surface errorMask (viewport.width, viewport.height);
1865 int numFailedPixels = 0;
1866 ReferenceParams params (TEXTURETYPE_CUBE);
1867 tcu::LookupPrecision lookupPrec;
1868 tcu::LodPrecision lodPrec;
1869
1870 // Params for rendering reference
1871 params.sampler = glu::mapGLSampler(wrapS, wrapT, m_minFilter, magFilter);
1872 params.sampler.seamlessCubeMap = true;
1873 params.lodMode = LODMODE_EXACT;
1874
1875 // Comparison parameters
1876 lookupPrec.colorMask = getCompareMask(m_context.getRenderTarget().getPixelFormat());
1877 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(m_context.getRenderTarget().getPixelFormat())-2, IVec4(0)));
1878 lookupPrec.coordBits = tcu::IVec3(10);
1879 lookupPrec.uvwBits = tcu::IVec3(5,5,0);
1880 lodPrec.derivateBits = 10;
1881 lodPrec.lodBits = 6;
1882
1883 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
1884 {
1885 const int curX = gridLayout[cellNdx].x();
1886 const int curY = gridLayout[cellNdx].y();
1887 const int curW = gridLayout[cellNdx].z();
1888 const int curH = gridLayout[cellNdx].w();
1889 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
1890
1891 computeQuadTexCoordCube(texCoord, cubeFace);
1892 getReferenceParams(params, cellNdx);
1893
1894 // Render ideal reference.
1895 {
1896 SurfaceAccess idealDst(referenceFrame, m_context.getRenderTarget().getPixelFormat(), curX, curY, curW, curH);
1897 sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params);
1898 }
1899
1900 // Compare this cell
1901 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1902 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1903 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
1904 m_texture->getRefTexture(), &texCoord[0], params,
1905 lookupPrec, lodPrec, m_testCtx.getWatchDog());
1906 }
1907
1908 if (numFailedPixels > 0)
1909 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1910
1911 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
1912 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
1913
1914 if (numFailedPixels > 0)
1915 {
1916 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1917 << TestLog::Image("ErrorMask", "Error mask", errorMask);
1918 }
1919
1920 m_testCtx.getLog() << TestLog::EndImageSet;
1921
1922 {
1923 const bool isOk = numFailedPixels == 0;
1924 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1925 isOk ? "Pass" : "Image verification failed");
1926 }
1927 }
1928
1929 return STOP;
1930 }
1931
1932 class TextureCubeMinLodCase : public TextureCubeLodControlCase
1933 {
1934 public:
TextureCubeMinLodCase(Context & context,const char * name,const char * desc,deUint32 minFilter)1935 TextureCubeMinLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
1936 : TextureCubeLodControlCase(context, name, desc, minFilter)
1937 {
1938 }
1939
1940 protected:
setTextureParams(int cellNdx)1941 void setTextureParams (int cellNdx)
1942 {
1943 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1944 gl.texParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_LOD, getMinLodForCell(cellNdx));
1945 }
1946
getReferenceParams(ReferenceParams & params,int cellNdx)1947 void getReferenceParams (ReferenceParams& params, int cellNdx)
1948 {
1949 params.minLod = getMinLodForCell(cellNdx);
1950 }
1951 };
1952
1953 class TextureCubeMaxLodCase : public TextureCubeLodControlCase
1954 {
1955 public:
TextureCubeMaxLodCase(Context & context,const char * name,const char * desc,deUint32 minFilter)1956 TextureCubeMaxLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
1957 : TextureCubeLodControlCase(context, name, desc, minFilter)
1958 {
1959 }
1960
1961 protected:
setTextureParams(int cellNdx)1962 void setTextureParams (int cellNdx)
1963 {
1964 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1965 gl.texParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LOD, getMaxLodForCell(cellNdx));
1966 }
1967
getReferenceParams(ReferenceParams & params,int cellNdx)1968 void getReferenceParams (ReferenceParams& params, int cellNdx)
1969 {
1970 params.maxLod = getMaxLodForCell(cellNdx);
1971 }
1972 };
1973
1974 class TextureCubeBaseLevelCase : public TextureCubeLodControlCase
1975 {
1976 public:
TextureCubeBaseLevelCase(Context & context,const char * name,const char * desc,deUint32 minFilter)1977 TextureCubeBaseLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
1978 : TextureCubeLodControlCase(context, name, desc, minFilter)
1979 {
1980 }
1981
1982 protected:
getBaseLevel(int cellNdx) const1983 int getBaseLevel (int cellNdx) const
1984 {
1985 const int numLevels = deLog2Floor32(m_texSize)+1;
1986 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x23fae13) % numLevels;
1987
1988 return baseLevel;
1989 }
1990
setTextureParams(int cellNdx)1991 void setTextureParams (int cellNdx)
1992 {
1993 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1994 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, getBaseLevel(cellNdx));
1995 }
1996
getReferenceParams(ReferenceParams & params,int cellNdx)1997 void getReferenceParams (ReferenceParams& params, int cellNdx)
1998 {
1999 params.baseLevel = getBaseLevel(cellNdx);
2000 }
2001 };
2002
2003 class TextureCubeMaxLevelCase : public TextureCubeLodControlCase
2004 {
2005 public:
TextureCubeMaxLevelCase(Context & context,const char * name,const char * desc,deUint32 minFilter)2006 TextureCubeMaxLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
2007 : TextureCubeLodControlCase(context, name, desc, minFilter)
2008 {
2009 }
2010
2011 protected:
getMaxLevel(int cellNdx) const2012 int getMaxLevel (int cellNdx) const
2013 {
2014 const int numLevels = deLog2Floor32(m_texSize)+1;
2015 const int maxLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x974e21) % numLevels;
2016
2017 return maxLevel;
2018 }
2019
setTextureParams(int cellNdx)2020 void setTextureParams (int cellNdx)
2021 {
2022 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2023 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, getMaxLevel(cellNdx));
2024 }
2025
getReferenceParams(ReferenceParams & params,int cellNdx)2026 void getReferenceParams (ReferenceParams& params, int cellNdx)
2027 {
2028 params.maxLevel = getMaxLevel(cellNdx);
2029 }
2030 };
2031
2032 // Texture3DLodControlCase + test cases
2033
2034 class Texture3DLodControlCase : public TestCase
2035 {
2036 public:
2037
2038 Texture3DLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter);
2039 ~Texture3DLodControlCase (void);
2040
2041 void init (void);
2042 void deinit (void);
2043 IterateResult iterate (void);
2044
2045 protected:
2046 virtual void setTextureParams (int cellNdx) = DE_NULL;
2047 virtual void getReferenceParams (ReferenceParams& params, int cellNdx) = DE_NULL;
2048
2049 const int m_texWidth;
2050 const int m_texHeight;
2051 const int m_texDepth;
2052
2053 private:
2054 Texture3DLodControlCase (const Texture3DLodControlCase& other);
2055 Texture3DLodControlCase& operator= (const Texture3DLodControlCase& other);
2056
2057 deUint32 m_minFilter;
2058
2059 glu::Texture3D* m_texture;
2060 TextureTestUtil::TextureRenderer m_renderer;
2061 };
2062
Texture3DLodControlCase(Context & context,const char * name,const char * desc,deUint32 minFilter)2063 Texture3DLodControlCase::Texture3DLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
2064 : TestCase (context, name, desc)
2065 , m_texWidth (32)
2066 , m_texHeight (32)
2067 , m_texDepth (32)
2068 , m_minFilter (minFilter)
2069 , m_texture (DE_NULL)
2070 , m_renderer (context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
2071 {
2072 }
2073
~Texture3DLodControlCase(void)2074 Texture3DLodControlCase::~Texture3DLodControlCase (void)
2075 {
2076 Texture3DLodControlCase::deinit();
2077 }
2078
init(void)2079 void Texture3DLodControlCase::init (void)
2080 {
2081 const deUint32 format = GL_RGBA8;
2082 const tcu::TextureFormat& texFmt = glu::mapGLInternalFormat(format);
2083 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
2084 const tcu::Vec4& cScale = fmtInfo.lookupScale;
2085 const tcu::Vec4& cBias = fmtInfo.lookupBias;
2086 int numLevels = deLog2Floor32(de::max(de::max(m_texWidth, m_texHeight), m_texDepth))+1;
2087
2088 m_texture = new glu::Texture3D(m_context.getRenderContext(), format, m_texWidth, m_texHeight, m_texDepth);
2089
2090 // Fill texture with colored grid.
2091 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
2092 {
2093 deUint32 step = 0xff / (numLevels-1);
2094 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff);
2095 deUint32 dec = 0xff - inc;
2096 deUint32 rgb = (inc << 16) | (dec << 8) | 0xff;
2097 deUint32 color = 0xff000000 | rgb;
2098
2099 m_texture->getRefTexture().allocLevel(levelNdx);
2100 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), tcu::RGBA(color).toVec()*cScale + cBias);
2101 }
2102
2103 m_texture->upload();
2104 }
2105
deinit(void)2106 void Texture3DLodControlCase::deinit (void)
2107 {
2108 delete m_texture;
2109 m_texture = DE_NULL;
2110
2111 m_renderer.clear();
2112 }
2113
iterate(void)2114 Texture3DLodControlCase::IterateResult Texture3DLodControlCase::iterate (void)
2115 {
2116 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2117
2118 const deUint32 wrapS = GL_CLAMP_TO_EDGE;
2119 const deUint32 wrapT = GL_CLAMP_TO_EDGE;
2120 const deUint32 wrapR = GL_CLAMP_TO_EDGE;
2121 const deUint32 magFilter = GL_NEAREST;
2122 const tcu::Texture3D& refTexture = m_texture->getRefTexture();
2123 const tcu::TextureFormat& texFmt = refTexture.getFormat();
2124 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
2125 const int texWidth = refTexture.getWidth();
2126 const int texHeight = refTexture.getHeight();
2127
2128 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
2129 const RandomViewport viewport (renderTarget, texWidth*4, texHeight*4, deStringHash(getName()));
2130
2131 // Viewport is divided into 4x4 grid.
2132 const int gridWidth = 4;
2133 const int gridHeight = 4;
2134 const int cellWidth = viewport.width / gridWidth;
2135 const int cellHeight = viewport.height / gridHeight;
2136
2137 tcu::Surface renderedFrame (viewport.width, viewport.height);
2138 vector<float> texCoord;
2139 ReferenceParams sampleParams (gls::TextureTestUtil::TEXTURETYPE_3D);
2140
2141 // Sampling parameters.
2142 sampleParams.sampler = glu::mapGLSampler(wrapS, wrapT, wrapR, m_minFilter, magFilter);
2143 sampleParams.samplerType = gls::TextureTestUtil::getSamplerType(texFmt);
2144 sampleParams.colorBias = fmtInfo.lookupBias;
2145 sampleParams.colorScale = fmtInfo.lookupScale;
2146
2147 // Bind texture and setup sampler parameters.
2148 gl.bindTexture (GL_TEXTURE_3D, m_texture->getGLTexture());
2149 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, wrapS);
2150 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, wrapT);
2151 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, wrapR);
2152 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, m_minFilter);
2153 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, magFilter);
2154
2155 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
2156
2157 // Render cells.
2158 for (int gridY = 0; gridY < gridHeight; gridY++)
2159 {
2160 for (int gridX = 0; gridX < gridWidth; gridX++)
2161 {
2162 int curX = cellWidth*gridX;
2163 int curY = cellHeight*gridY;
2164 int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
2165 int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
2166 int cellNdx = gridY*gridWidth + gridX;
2167
2168 // Compute texcoord.
2169 getBasicTexCoord3D(texCoord, cellNdx);
2170
2171 setTextureParams(cellNdx);
2172
2173 // Render with GL.
2174 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
2175 m_renderer.renderQuad(0, &texCoord[0], sampleParams);
2176 }
2177 }
2178
2179 // Read result.
2180 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess());
2181
2182 // Compare and log
2183 {
2184 const tcu::PixelFormat& pixelFormat = m_context.getRenderTarget().getPixelFormat();
2185 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
2186 tcu::Surface referenceFrame (viewport.width, viewport.height);
2187 tcu::Surface errorMask (viewport.width, viewport.height);
2188 tcu::LookupPrecision lookupPrec;
2189 tcu::LodPrecision lodPrec;
2190 int numFailedPixels = 0;
2191
2192 lookupPrec.coordBits = tcu::IVec3(20, 20, 20);
2193 lookupPrec.uvwBits = tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
2194 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
2195 lookupPrec.colorMask = getCompareMask(pixelFormat);
2196 lodPrec.derivateBits = 10;
2197 lodPrec.lodBits = 8;
2198
2199 for (int gridY = 0; gridY < gridHeight; gridY++)
2200 {
2201 for (int gridX = 0; gridX < gridWidth; gridX++)
2202 {
2203 const int curX = cellWidth*gridX;
2204 const int curY = cellHeight*gridY;
2205 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
2206 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
2207 const int cellNdx = gridY*gridWidth + gridX;
2208
2209 getBasicTexCoord3D(texCoord, cellNdx);
2210 getReferenceParams(sampleParams, cellNdx);
2211
2212 // Render ideal result
2213 sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
2214 refTexture, &texCoord[0], sampleParams);
2215
2216 // Compare this cell
2217 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
2218 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
2219 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
2220 m_texture->getRefTexture(), &texCoord[0], sampleParams,
2221 lookupPrec, lodPrec, m_testCtx.getWatchDog());
2222 }
2223 }
2224
2225 if (numFailedPixels > 0)
2226 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
2227
2228 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
2229 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
2230
2231 if (numFailedPixels > 0)
2232 {
2233 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
2234 << TestLog::Image("ErrorMask", "Error mask", errorMask);
2235 }
2236
2237 m_testCtx.getLog() << TestLog::EndImageSet;
2238
2239 {
2240 const bool isOk = numFailedPixels == 0;
2241 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
2242 isOk ? "Pass" : "Image verification failed");
2243 }
2244 }
2245
2246 return STOP;
2247 }
2248
2249 class Texture3DMinLodCase : public Texture3DLodControlCase
2250 {
2251 public:
Texture3DMinLodCase(Context & context,const char * name,const char * desc,deUint32 minFilter)2252 Texture3DMinLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
2253 : Texture3DLodControlCase(context, name, desc, minFilter)
2254 {
2255 }
2256
2257 protected:
setTextureParams(int cellNdx)2258 void setTextureParams (int cellNdx)
2259 {
2260 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2261 gl.texParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_LOD, getMinLodForCell(cellNdx));
2262 }
2263
getReferenceParams(ReferenceParams & params,int cellNdx)2264 void getReferenceParams (ReferenceParams& params, int cellNdx)
2265 {
2266 params.minLod = getMinLodForCell(cellNdx);
2267 }
2268 };
2269
2270 class Texture3DMaxLodCase : public Texture3DLodControlCase
2271 {
2272 public:
Texture3DMaxLodCase(Context & context,const char * name,const char * desc,deUint32 minFilter)2273 Texture3DMaxLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
2274 : Texture3DLodControlCase(context, name, desc, minFilter)
2275 {
2276 }
2277
2278 protected:
setTextureParams(int cellNdx)2279 void setTextureParams (int cellNdx)
2280 {
2281 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2282 gl.texParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAX_LOD, getMaxLodForCell(cellNdx));
2283 }
2284
getReferenceParams(ReferenceParams & params,int cellNdx)2285 void getReferenceParams (ReferenceParams& params, int cellNdx)
2286 {
2287 params.maxLod = getMaxLodForCell(cellNdx);
2288 }
2289 };
2290
2291 class Texture3DBaseLevelCase : public Texture3DLodControlCase
2292 {
2293 public:
Texture3DBaseLevelCase(Context & context,const char * name,const char * desc,deUint32 minFilter)2294 Texture3DBaseLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
2295 : Texture3DLodControlCase(context, name, desc, minFilter)
2296 {
2297 }
2298
2299 protected:
getBaseLevel(int cellNdx) const2300 int getBaseLevel (int cellNdx) const
2301 {
2302 const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth)))+1;
2303 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x7347e9) % numLevels;
2304
2305 return baseLevel;
2306 }
2307
setTextureParams(int cellNdx)2308 void setTextureParams (int cellNdx)
2309 {
2310 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2311 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, getBaseLevel(cellNdx));
2312 }
2313
getReferenceParams(ReferenceParams & params,int cellNdx)2314 void getReferenceParams (ReferenceParams& params, int cellNdx)
2315 {
2316 params.baseLevel = getBaseLevel(cellNdx);
2317 }
2318 };
2319
2320 class Texture3DMaxLevelCase : public Texture3DLodControlCase
2321 {
2322 public:
Texture3DMaxLevelCase(Context & context,const char * name,const char * desc,deUint32 minFilter)2323 Texture3DMaxLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
2324 : Texture3DLodControlCase(context, name, desc, minFilter)
2325 {
2326 }
2327
2328 protected:
getMaxLevel(int cellNdx) const2329 int getMaxLevel (int cellNdx) const
2330 {
2331 const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth)))+1;
2332 const int maxLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x9111e7) % numLevels;
2333
2334 return maxLevel;
2335 }
2336
setTextureParams(int cellNdx)2337 void setTextureParams (int cellNdx)
2338 {
2339 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2340 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, getMaxLevel(cellNdx));
2341 }
2342
getReferenceParams(ReferenceParams & params,int cellNdx)2343 void getReferenceParams (ReferenceParams& params, int cellNdx)
2344 {
2345 params.maxLevel = getMaxLevel(cellNdx);
2346 }
2347 };
2348
TextureMipmapTests(Context & context)2349 TextureMipmapTests::TextureMipmapTests (Context& context)
2350 : TestCaseGroup(context, "mipmap", "Mipmapping tests")
2351 {
2352 }
2353
~TextureMipmapTests(void)2354 TextureMipmapTests::~TextureMipmapTests (void)
2355 {
2356 }
2357
init(void)2358 void TextureMipmapTests::init (void)
2359 {
2360 tcu::TestCaseGroup* group2D = new tcu::TestCaseGroup(m_testCtx, "2d", "2D Texture Mipmapping");
2361 tcu::TestCaseGroup* groupCube = new tcu::TestCaseGroup(m_testCtx, "cube", "Cube Map Mipmapping");
2362 tcu::TestCaseGroup* group3D = new tcu::TestCaseGroup(m_testCtx, "3d", "3D Texture Mipmapping");
2363 addChild(group2D);
2364 addChild(groupCube);
2365 addChild(group3D);
2366
2367 static const struct
2368 {
2369 const char* name;
2370 deUint32 mode;
2371 } wrapModes[] =
2372 {
2373 { "clamp", GL_CLAMP_TO_EDGE },
2374 { "repeat", GL_REPEAT },
2375 { "mirror", GL_MIRRORED_REPEAT }
2376 };
2377
2378 static const struct
2379 {
2380 const char* name;
2381 deUint32 mode;
2382 } minFilterModes[] =
2383 {
2384 { "nearest_nearest", GL_NEAREST_MIPMAP_NEAREST },
2385 { "linear_nearest", GL_LINEAR_MIPMAP_NEAREST },
2386 { "nearest_linear", GL_NEAREST_MIPMAP_LINEAR },
2387 { "linear_linear", GL_LINEAR_MIPMAP_LINEAR }
2388 };
2389
2390 static const struct
2391 {
2392 CoordType type;
2393 const char* name;
2394 const char* desc;
2395 } coordTypes[] =
2396 {
2397 { COORDTYPE_BASIC, "basic", "Mipmapping with translated and scaled coordinates" },
2398 { COORDTYPE_AFFINE, "affine", "Mipmapping with affine coordinate transform" },
2399 { COORDTYPE_PROJECTED, "projected", "Mipmapping with perspective projection" }
2400 };
2401
2402 static const struct
2403 {
2404 const char* name;
2405 deUint32 format;
2406 deUint32 dataType;
2407 } formats[] =
2408 {
2409 { "a8", GL_ALPHA, GL_UNSIGNED_BYTE },
2410 { "l8", GL_LUMINANCE, GL_UNSIGNED_BYTE },
2411 { "la88", GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE },
2412 { "rgb565", GL_RGB, GL_UNSIGNED_SHORT_5_6_5 },
2413 { "rgb888", GL_RGB, GL_UNSIGNED_BYTE },
2414 { "rgba4444", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 },
2415 { "rgba5551", GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 },
2416 { "rgba8888", GL_RGBA, GL_UNSIGNED_BYTE }
2417 };
2418
2419 static const struct
2420 {
2421 const char* name;
2422 deUint32 hint;
2423 } genHints[] =
2424 {
2425 { "fastest", GL_FASTEST },
2426 { "nicest", GL_NICEST }
2427 };
2428
2429 static const struct
2430 {
2431 const char* name;
2432 int width;
2433 int height;
2434 } tex2DSizes[] =
2435 {
2436 { DE_NULL, 64, 64 }, // Default.
2437 { "npot", 63, 57 },
2438 { "non_square", 32, 64 }
2439 };
2440
2441 static const struct
2442 {
2443 const char* name;
2444 int width;
2445 int height;
2446 int depth;
2447 } tex3DSizes[] =
2448 {
2449 { DE_NULL, 32, 32, 32 }, // Default.
2450 { "npot", 33, 29, 27 }
2451 };
2452
2453 const int cubeMapSize = 64;
2454
2455 static const struct
2456 {
2457 CoordType type;
2458 const char* name;
2459 const char* desc;
2460 } cubeCoordTypes[] =
2461 {
2462 { COORDTYPE_BASIC, "basic", "Mipmapping with translated and scaled coordinates" },
2463 { COORDTYPE_PROJECTED, "projected", "Mipmapping with perspective projection" },
2464 { COORDTYPE_BASIC_BIAS, "bias", "User-supplied bias value" }
2465 };
2466
2467 // 2D cases.
2468 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
2469 {
2470 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, coordTypes[coordType].name, coordTypes[coordType].desc);
2471 group2D->addChild(coordTypeGroup);
2472
2473 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2474 {
2475 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
2476 {
2477 // Add non_square variants to basic cases only.
2478 int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex2DSizes) : 1;
2479
2480 for (int size = 0; size < sizeEnd; size++)
2481 {
2482 std::ostringstream name;
2483 name << minFilterModes[minFilter].name
2484 << "_" << wrapModes[wrapMode].name;
2485
2486 if (tex2DSizes[size].name)
2487 name << "_" << tex2DSizes[size].name;
2488
2489 coordTypeGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
2490 name.str().c_str(), "",
2491 coordTypes[coordType].type,
2492 minFilterModes[minFilter].mode,
2493 wrapModes[wrapMode].mode,
2494 wrapModes[wrapMode].mode,
2495 GL_RGBA, GL_UNSIGNED_BYTE,
2496 tex2DSizes[size].width, tex2DSizes[size].height));
2497 }
2498 }
2499 }
2500 }
2501
2502 // 2D bias variants.
2503 {
2504 tcu::TestCaseGroup* biasGroup = new tcu::TestCaseGroup(m_testCtx, "bias", "User-supplied bias value");
2505 group2D->addChild(biasGroup);
2506
2507 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2508 biasGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
2509 minFilterModes[minFilter].name, "",
2510 COORDTYPE_BASIC_BIAS,
2511 minFilterModes[minFilter].mode,
2512 GL_REPEAT, GL_REPEAT,
2513 GL_RGBA, GL_UNSIGNED_BYTE,
2514 tex2DSizes[0].width, tex2DSizes[0].height));
2515 }
2516
2517 // 2D mipmap generation variants.
2518 {
2519 tcu::TestCaseGroup* genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests");
2520 group2D->addChild(genMipmapGroup);
2521
2522 for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++)
2523 {
2524 for (int size = 0; size < DE_LENGTH_OF_ARRAY(tex2DSizes); size++)
2525 {
2526 for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++)
2527 {
2528 std::ostringstream name;
2529 name << formats[format].name;
2530
2531 if (tex2DSizes[size].name)
2532 name << "_" << tex2DSizes[size].name;
2533
2534 name << "_" << genHints[hint].name;
2535
2536 genMipmapGroup->addChild(new Texture2DGenMipmapCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "",
2537 formats[format].format, formats[format].dataType, genHints[hint].hint,
2538 tex2DSizes[size].width, tex2DSizes[size].height));
2539 }
2540 }
2541 }
2542 }
2543
2544 // 2D LOD controls.
2545 {
2546 // MIN_LOD
2547 tcu::TestCaseGroup* minLodGroup = new tcu::TestCaseGroup(m_testCtx, "min_lod", "Lod control: min lod");
2548 group2D->addChild(minLodGroup);
2549
2550 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2551 minLodGroup->addChild(new Texture2DMinLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2552
2553 // MAX_LOD
2554 tcu::TestCaseGroup* maxLodGroup = new tcu::TestCaseGroup(m_testCtx, "max_lod", "Lod control: max lod");
2555 group2D->addChild(maxLodGroup);
2556
2557 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2558 maxLodGroup->addChild(new Texture2DMaxLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2559
2560 // BASE_LEVEL
2561 tcu::TestCaseGroup* baseLevelGroup = new tcu::TestCaseGroup(m_testCtx, "base_level", "Base level");
2562 group2D->addChild(baseLevelGroup);
2563
2564 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2565 baseLevelGroup->addChild(new Texture2DBaseLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2566
2567 // MAX_LEVEL
2568 tcu::TestCaseGroup* maxLevelGroup = new tcu::TestCaseGroup(m_testCtx, "max_level", "Max level");
2569 group2D->addChild(maxLevelGroup);
2570
2571 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2572 maxLevelGroup->addChild(new Texture2DMaxLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2573 }
2574
2575 // Cubemap cases.
2576 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++)
2577 {
2578 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, cubeCoordTypes[coordType].name, cubeCoordTypes[coordType].desc);
2579 groupCube->addChild(coordTypeGroup);
2580
2581 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2582 {
2583 coordTypeGroup->addChild(new TextureCubeMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
2584 minFilterModes[minFilter].name, "",
2585 cubeCoordTypes[coordType].type,
2586 minFilterModes[minFilter].mode,
2587 GL_CLAMP_TO_EDGE,
2588 GL_CLAMP_TO_EDGE,
2589 GL_RGBA, GL_UNSIGNED_BYTE, cubeMapSize));
2590 }
2591 }
2592
2593 // Cubemap mipmap generation variants.
2594 {
2595 tcu::TestCaseGroup* genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests");
2596 groupCube->addChild(genMipmapGroup);
2597
2598 for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++)
2599 {
2600 for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++)
2601 {
2602 std::ostringstream name;
2603 name << formats[format].name
2604 << "_" << genHints[hint].name;
2605
2606 genMipmapGroup->addChild(new TextureCubeGenMipmapCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "", formats[format].format, formats[format].dataType, genHints[hint].hint, cubeMapSize));
2607 }
2608 }
2609 }
2610
2611 // Cubemap LOD controls.
2612 {
2613 // MIN_LOD
2614 tcu::TestCaseGroup* minLodGroup = new tcu::TestCaseGroup(m_testCtx, "min_lod", "Lod control: min lod");
2615 groupCube->addChild(minLodGroup);
2616
2617 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2618 minLodGroup->addChild(new TextureCubeMinLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2619
2620 // MAX_LOD
2621 tcu::TestCaseGroup* maxLodGroup = new tcu::TestCaseGroup(m_testCtx, "max_lod", "Lod control: max lod");
2622 groupCube->addChild(maxLodGroup);
2623
2624 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2625 maxLodGroup->addChild(new TextureCubeMaxLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2626
2627 // BASE_LEVEL
2628 tcu::TestCaseGroup* baseLevelGroup = new tcu::TestCaseGroup(m_testCtx, "base_level", "Base level");
2629 groupCube->addChild(baseLevelGroup);
2630
2631 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2632 baseLevelGroup->addChild(new TextureCubeBaseLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2633
2634 // MAX_LEVEL
2635 tcu::TestCaseGroup* maxLevelGroup = new tcu::TestCaseGroup(m_testCtx, "max_level", "Max level");
2636 groupCube->addChild(maxLevelGroup);
2637
2638 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2639 maxLevelGroup->addChild(new TextureCubeMaxLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2640 }
2641
2642 // 3D cases.
2643 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
2644 {
2645 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, coordTypes[coordType].name, coordTypes[coordType].desc);
2646 group3D->addChild(coordTypeGroup);
2647
2648 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2649 {
2650 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
2651 {
2652 // Add other size variants to basic cases only.
2653 int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex3DSizes) : 1;
2654
2655 for (int size = 0; size < sizeEnd; size++)
2656 {
2657 std::ostringstream name;
2658 name << minFilterModes[minFilter].name
2659 << "_" << wrapModes[wrapMode].name;
2660
2661 if (tex3DSizes[size].name)
2662 name << "_" << tex3DSizes[size].name;
2663
2664 coordTypeGroup->addChild(new Texture3DMipmapCase(m_context,
2665 name.str().c_str(), "",
2666 coordTypes[coordType].type,
2667 minFilterModes[minFilter].mode,
2668 wrapModes[wrapMode].mode,
2669 wrapModes[wrapMode].mode,
2670 wrapModes[wrapMode].mode,
2671 GL_RGBA8,
2672 tex3DSizes[size].width, tex3DSizes[size].height, tex3DSizes[size].depth));
2673 }
2674 }
2675 }
2676 }
2677
2678 // 3D bias variants.
2679 {
2680 tcu::TestCaseGroup* biasGroup = new tcu::TestCaseGroup(m_testCtx, "bias", "User-supplied bias value");
2681 group3D->addChild(biasGroup);
2682
2683 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2684 biasGroup->addChild(new Texture3DMipmapCase(m_context,
2685 minFilterModes[minFilter].name, "",
2686 COORDTYPE_BASIC_BIAS,
2687 minFilterModes[minFilter].mode,
2688 GL_REPEAT, GL_REPEAT, GL_REPEAT,
2689 GL_RGBA8,
2690 tex3DSizes[0].width, tex3DSizes[0].height, tex3DSizes[0].depth));
2691 }
2692
2693 // 3D LOD controls.
2694 {
2695 // MIN_LOD
2696 tcu::TestCaseGroup* minLodGroup = new tcu::TestCaseGroup(m_testCtx, "min_lod", "Lod control: min lod");
2697 group3D->addChild(minLodGroup);
2698
2699 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2700 minLodGroup->addChild(new Texture3DMinLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2701
2702 // MAX_LOD
2703 tcu::TestCaseGroup* maxLodGroup = new tcu::TestCaseGroup(m_testCtx, "max_lod", "Lod control: max lod");
2704 group3D->addChild(maxLodGroup);
2705
2706 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2707 maxLodGroup->addChild(new Texture3DMaxLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2708
2709 // BASE_LEVEL
2710 tcu::TestCaseGroup* baseLevelGroup = new tcu::TestCaseGroup(m_testCtx, "base_level", "Base level");
2711 group3D->addChild(baseLevelGroup);
2712
2713 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2714 baseLevelGroup->addChild(new Texture3DBaseLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2715
2716 // MAX_LEVEL
2717 tcu::TestCaseGroup* maxLevelGroup = new tcu::TestCaseGroup(m_testCtx, "max_level", "Max level");
2718 group3D->addChild(maxLevelGroup);
2719
2720 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2721 maxLevelGroup->addChild(new Texture3DMaxLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
2722 }
2723 }
2724
2725 } // Functional
2726 } // gles3
2727 } // deqp
2728