1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Texture filtering accuracy tests.
22 *//*--------------------------------------------------------------------*/
24 #include "es2aTextureFilteringTests.hpp"
25 #include "glsTextureTestUtil.hpp"
26 #include "gluTexture.hpp"
27 #include "gluStrUtil.hpp"
28 #include "gluTextureUtil.hpp"
29 #include "gluPixelTransfer.hpp"
30 #include "tcuSurfaceAccess.hpp"
31 #include "tcuTestLog.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "deStringUtil.hpp"
35 #include "glwFunctions.hpp"
36 #include "glwEnums.hpp"
52 using namespace gls::TextureTestUtil;
53 using namespace glu::TextureTestUtil;
55 class Texture2DFilteringCase : public tcu::TestCase
58 Texture2DFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height);
59 Texture2DFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames);
60 ~Texture2DFilteringCase (void);
64 IterateResult iterate (void);
67 Texture2DFilteringCase (const Texture2DFilteringCase& other);
68 Texture2DFilteringCase& operator= (const Texture2DFilteringCase& other);
70 glu::RenderContext& m_renderCtx;
71 const glu::ContextInfo& m_renderCtxInfo;
83 std::vector<std::string> m_filenames;
85 std::vector<glu::Texture2D*> m_textures;
86 TextureRenderer m_renderer;
90 Texture2DFilteringCase::Texture2DFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height)
91 : TestCase (testCtx, tcu::NODETYPE_ACCURACY, name, desc)
92 , m_renderCtx (renderCtx)
93 , m_renderCtxInfo (ctxInfo)
94 , m_minFilter (minFilter)
95 , m_magFilter (magFilter)
99 , m_dataType (dataType)
102 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
106 Texture2DFilteringCase::Texture2DFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames)
107 : TestCase (testCtx, tcu::NODETYPE_ACCURACY, name, desc)
108 , m_renderCtx (renderCtx)
109 , m_renderCtxInfo (ctxInfo)
110 , m_minFilter (minFilter)
111 , m_magFilter (magFilter)
115 , m_dataType (GL_NONE)
118 , m_filenames (filenames)
119 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
123 Texture2DFilteringCase::~Texture2DFilteringCase (void)
128 void Texture2DFilteringCase::init (void)
132 if (!m_filenames.empty())
134 m_textures.reserve(1);
135 m_textures.push_back(glu::Texture2D::create(m_renderCtx, m_renderCtxInfo, m_testCtx.getArchive(), (int)m_filenames.size(), m_filenames));
139 // Create 2 textures.
140 m_textures.reserve(2);
141 for (int ndx = 0; ndx < 2; ndx++)
142 m_textures.push_back(new glu::Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height));
144 const bool mipmaps = deIsPowerOfTwo32(m_width) && deIsPowerOfTwo32(m_height);
145 const int numLevels = mipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1;
146 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
147 tcu::Vec4 cBias = fmtInfo.valueMin;
148 tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
150 // Fill first gradient texture.
151 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
153 tcu::Vec4 gMin = tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
154 tcu::Vec4 gMax = tcu::Vec4( 1.0f, 1.0f, 1.0f, 0.0f)*cScale + cBias;
156 m_textures[0]->getRefTexture().allocLevel(levelNdx);
157 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
160 // Fill second with grid texture.
161 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
163 deUint32 step = 0x00ffffff / numLevels;
164 deUint32 rgb = step*levelNdx;
165 deUint32 colorA = 0xff000000 | rgb;
166 deUint32 colorB = 0xff000000 | ~rgb;
168 m_textures[1]->getRefTexture().allocLevel(levelNdx);
169 tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
173 for (std::vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
179 // Clean up to save memory.
180 Texture2DFilteringCase::deinit();
185 void Texture2DFilteringCase::deinit (void)
187 for (std::vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
194 Texture2DFilteringCase::IterateResult Texture2DFilteringCase::iterate (void)
196 const glw::Functions& gl = m_renderCtx.getFunctions();
197 TestLog& log = m_testCtx.getLog();
198 const int defViewportWidth = 256;
199 const int defViewportHeight = 256;
200 RandomViewport viewport (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));
201 tcu::Surface renderedFrame (viewport.width, viewport.height);
202 tcu::Surface referenceFrame (viewport.width, viewport.height);
203 const tcu::TextureFormat& texFmt = m_textures[0]->getRefTexture().getFormat();
204 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
205 ReferenceParams refParams (TEXTURETYPE_2D);
206 vector<float> texCoord;
208 // Accuracy measurements are off unless viewport size is 256x256
209 if (viewport.width < defViewportWidth || viewport.height < defViewportHeight)
210 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
212 // Viewport is divided into 4 sections.
213 int leftWidth = viewport.width / 2;
214 int rightWidth = viewport.width - leftWidth;
215 int bottomHeight = viewport.height / 2;
216 int topHeight = viewport.height - bottomHeight;
221 gl.activeTexture(GL_TEXTURE0);
223 // Bind gradient texture and setup sampler parameters.
224 gl.bindTexture(GL_TEXTURE_2D, m_textures[curTexNdx]->getGLTexture());
225 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS);
226 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT);
227 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter);
228 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_magFilter);
230 // Setup params for reference.
231 refParams.sampler = mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter);
232 refParams.samplerType = getSamplerType(texFmt);
233 refParams.lodMode = LODMODE_EXACT;
234 refParams.colorBias = fmtInfo.lookupBias;
235 refParams.colorScale = fmtInfo.lookupScale;
237 // Bottom left: Minification
239 gl.viewport(viewport.x, viewport.y, leftWidth, bottomHeight);
241 computeQuadTexCoord2D(texCoord, tcu::Vec2(-4.0f, -4.5f), tcu::Vec2(4.0f, 2.5f));
243 m_renderer.renderQuad(0, &texCoord[0], refParams);
244 sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, 0, leftWidth, bottomHeight),
245 m_textures[curTexNdx]->getRefTexture(), &texCoord[0], refParams);
248 // Bottom right: Magnification
250 gl.viewport(viewport.x+leftWidth, viewport.y, rightWidth, bottomHeight);
252 computeQuadTexCoord2D(texCoord, tcu::Vec2(-0.5f, 0.75f), tcu::Vec2(0.25f, 1.25f));
254 m_renderer.renderQuad(0, &texCoord[0], refParams);
255 sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth, 0, rightWidth, bottomHeight),
256 m_textures[curTexNdx]->getRefTexture(), &texCoord[0], refParams);
259 if (m_textures.size() >= 2)
263 // Setup second texture.
264 gl.bindTexture(GL_TEXTURE_2D, m_textures[curTexNdx]->getGLTexture());
265 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS);
266 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT);
267 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter);
268 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_magFilter);
271 // Top left: Minification
272 // \note Minification is chosen so that 0.0 < lod <= 0.5. This way special minification threshold rule will be triggered.
274 gl.viewport(viewport.x, viewport.y+bottomHeight, leftWidth, topHeight);
278 float sRange = ((float)leftWidth * 1.2f) / (float)m_textures[curTexNdx]->getRefTexture().getWidth();
279 float tRange = ((float)topHeight * 1.1f) / (float)m_textures[curTexNdx]->getRefTexture().getHeight();
281 computeQuadTexCoord2D(texCoord, tcu::Vec2(sMin, tMin), tcu::Vec2(sMin+sRange, tMin+tRange));
283 m_renderer.renderQuad(0, &texCoord[0], refParams);
284 sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, bottomHeight, leftWidth, topHeight),
285 m_textures[curTexNdx]->getRefTexture(), &texCoord[0], refParams);
288 // Top right: Magnification
290 gl.viewport(viewport.x+leftWidth, viewport.y+bottomHeight, rightWidth, topHeight);
292 computeQuadTexCoord2D(texCoord, tcu::Vec2(-0.5f, 0.75f), tcu::Vec2(0.25f, 1.25f));
294 m_renderer.renderQuad(0, &texCoord[0], refParams);
295 sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth, bottomHeight, rightWidth, topHeight),
296 m_textures[curTexNdx]->getRefTexture(), &texCoord[0], refParams);
300 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
304 DE_ASSERT(getNodeType() == tcu::NODETYPE_ACCURACY);
306 const int bestScoreDiff = 16;
307 const int worstScoreDiff = 3200;
309 int score = measureAccuracy(log, referenceFrame, renderedFrame, bestScoreDiff, worstScoreDiff);
310 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::toString(score).c_str());
316 class TextureCubeFilteringCase : public tcu::TestCase
319 TextureCubeFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height);
320 TextureCubeFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames);
321 ~TextureCubeFilteringCase (void);
325 IterateResult iterate (void);
328 TextureCubeFilteringCase (const TextureCubeFilteringCase& other);
329 TextureCubeFilteringCase& operator= (const TextureCubeFilteringCase& other);
331 glu::RenderContext& m_renderCtx;
332 const glu::ContextInfo& m_renderCtxInfo;
334 deUint32 m_minFilter;
335 deUint32 m_magFilter;
344 std::vector<std::string> m_filenames;
346 std::vector<glu::TextureCube*> m_textures;
347 TextureRenderer m_renderer;
351 TextureCubeFilteringCase::TextureCubeFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height)
352 : TestCase (testCtx, tcu::NODETYPE_ACCURACY, name, desc)
353 , m_renderCtx (renderCtx)
354 , m_renderCtxInfo (ctxInfo)
355 , m_minFilter (minFilter)
356 , m_magFilter (magFilter)
360 , m_dataType (dataType)
363 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
367 TextureCubeFilteringCase::TextureCubeFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames)
368 : TestCase (testCtx, tcu::NODETYPE_ACCURACY, name, desc)
369 , m_renderCtx (renderCtx)
370 , m_renderCtxInfo (ctxInfo)
371 , m_minFilter (minFilter)
372 , m_magFilter (magFilter)
376 , m_dataType (GL_NONE)
379 , m_filenames (filenames)
380 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
384 TextureCubeFilteringCase::~TextureCubeFilteringCase (void)
389 void TextureCubeFilteringCase::init (void)
393 if (!m_filenames.empty())
395 m_textures.reserve(1);
396 m_textures.push_back(glu::TextureCube::create(m_renderCtx, m_renderCtxInfo, m_testCtx.getArchive(), (int)m_filenames.size() / 6, m_filenames));
400 m_textures.reserve(2);
401 DE_ASSERT(m_width == m_height);
402 for (int ndx = 0; ndx < 2; ndx++)
403 m_textures.push_back(new glu::TextureCube(m_renderCtx, m_format, m_dataType, m_width));
405 const bool mipmaps = deIsPowerOfTwo32(m_width) && deIsPowerOfTwo32(m_height);
406 const int numLevels = mipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1;
407 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
408 tcu::Vec4 cBias = fmtInfo.valueMin;
409 tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
411 // Fill first with gradient texture.
412 static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
414 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
415 { tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
416 { tcu::Vec4(-1.0f, 0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
417 { tcu::Vec4(-1.0f, -1.0f, 0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
418 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
419 { tcu::Vec4( 0.0f, 0.0f, 0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) } // positive z
421 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
423 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
425 m_textures[0]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
426 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias);
430 // Fill second with grid texture.
431 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
433 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
435 deUint32 step = 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
436 deUint32 rgb = step*levelNdx*face;
437 deUint32 colorA = 0xff000000 | rgb;
438 deUint32 colorB = 0xff000000 | ~rgb;
440 m_textures[1]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
441 tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
446 for (std::vector<glu::TextureCube*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
450 catch (const std::exception&)
452 // Clean up to save memory.
453 TextureCubeFilteringCase::deinit();
458 void TextureCubeFilteringCase::deinit (void)
460 for (std::vector<glu::TextureCube*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
467 static void renderFaces (
468 const glw::Functions& gl,
469 const tcu::SurfaceAccess& dstRef,
470 const tcu::TextureCube& refTexture,
471 const ReferenceParams& params,
472 TextureRenderer& renderer,
477 const tcu::Vec2& bottomLeft,
478 const tcu::Vec2& topRight,
479 const tcu::Vec2& texCoordTopRightFactor)
481 DE_ASSERT(width == dstRef.getWidth() && height == dstRef.getHeight());
483 vector<float> texCoord;
485 DE_STATIC_ASSERT(tcu::CUBEFACE_LAST == 6);
486 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
488 bool isRightmost = (face == 2) || (face == 5);
489 bool isTop = face >= 3;
490 int curX = (face % 3) * (width / 3);
491 int curY = (face / 3) * (height / 2);
492 int curW = isRightmost ? (width-curX) : (width / 3);
493 int curH = isTop ? (height-curY) : (height / 2);
495 computeQuadTexCoordCube(texCoord, (tcu::CubeFace)face, bottomLeft, topRight);
498 // Move the top and right edges of the texture coord quad. This is useful when we want a cube edge visible.
499 int texCoordSRow = face == tcu::CUBEFACE_NEGATIVE_X || face == tcu::CUBEFACE_POSITIVE_X ? 2 : 0;
500 int texCoordTRow = face == tcu::CUBEFACE_NEGATIVE_Y || face == tcu::CUBEFACE_POSITIVE_Y ? 2 : 1;
501 texCoord[6 + texCoordSRow] *= texCoordTopRightFactor.x();
502 texCoord[9 + texCoordSRow] *= texCoordTopRightFactor.x();
503 texCoord[3 + texCoordTRow] *= texCoordTopRightFactor.y();
504 texCoord[9 + texCoordTRow] *= texCoordTopRightFactor.y();
507 gl.viewport(x+curX, y+curY, curW, curH);
509 renderer.renderQuad(0, &texCoord[0], params);
511 sampleTexture(tcu::SurfaceAccess(dstRef, curX, curY, curW, curH), refTexture, &texCoord[0], params);
514 GLU_EXPECT_NO_ERROR(gl.getError(), "Post render");
517 TextureCubeFilteringCase::IterateResult TextureCubeFilteringCase::iterate (void)
519 const glw::Functions& gl = m_renderCtx.getFunctions();
520 TestLog& log = m_testCtx.getLog();
521 const int cellSize = 28;
522 const int defViewportWidth = cellSize*6;
523 const int defViewportHeight = cellSize*4;
524 RandomViewport viewport (m_renderCtx.getRenderTarget(), cellSize*6, cellSize*4, deStringHash(getName()));
525 tcu::Surface renderedFrame (viewport.width, viewport.height);
526 tcu::Surface referenceFrame (viewport.width, viewport.height);
527 ReferenceParams sampleParams (TEXTURETYPE_CUBE);
528 const tcu::TextureFormat& texFmt = m_textures[0]->getRefTexture().getFormat();
529 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
531 // Accuracy measurements are off unless viewport size is exactly as expected.
532 if (viewport.width < defViewportWidth || viewport.height < defViewportHeight)
533 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
535 // Viewport is divided into 4 sections.
536 int leftWidth = viewport.width / 2;
537 int rightWidth = viewport.width - leftWidth;
538 int bottomHeight = viewport.height / 2;
539 int topHeight = viewport.height - bottomHeight;
543 // Sampling parameters.
544 sampleParams.sampler = mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter);
545 sampleParams.sampler.seamlessCubeMap = false;
546 sampleParams.samplerType = getSamplerType(texFmt);
547 sampleParams.colorBias = fmtInfo.lookupBias;
548 sampleParams.colorScale = fmtInfo.lookupScale;
549 sampleParams.lodMode = LODMODE_EXACT;
552 gl.activeTexture(GL_TEXTURE0);
554 // Setup gradient texture.
555 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textures[curTexNdx]->getGLTexture());
556 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, m_wrapS);
557 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, m_wrapT);
558 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter);
559 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, m_magFilter);
561 // Bottom left: Minification
563 tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, 0, leftWidth, bottomHeight),
564 m_textures[curTexNdx]->getRefTexture(), sampleParams,
566 viewport.x, viewport.y, leftWidth, bottomHeight,
567 tcu::Vec2(-0.81f, -0.81f),
568 tcu::Vec2( 0.8f, 0.8f),
569 tcu::Vec2(1.0f, 1.0f));
571 // Bottom right: Magnification
573 tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth, 0, rightWidth, bottomHeight),
574 m_textures[curTexNdx]->getRefTexture(), sampleParams,
576 viewport.x+leftWidth, viewport.y, rightWidth, bottomHeight,
577 tcu::Vec2(0.5f, 0.65f), tcu::Vec2(0.8f, 0.8f),
578 tcu::Vec2(1.0f, 1.0f));
580 if (m_textures.size() >= 2)
584 // Setup second texture.
585 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textures[curTexNdx]->getGLTexture());
586 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, m_wrapS);
587 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, m_wrapT);
588 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter);
589 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, m_magFilter);
592 // Top left: Minification
594 tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, bottomHeight, leftWidth, topHeight),
595 m_textures[curTexNdx]->getRefTexture(), sampleParams,
597 viewport.x, viewport.y+bottomHeight, leftWidth, topHeight,
598 tcu::Vec2(-0.81f, -0.81f),
599 tcu::Vec2( 0.8f, 0.8f),
600 tcu::Vec2(1.0f, 1.0f));
602 // Top right: Magnification
604 tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth, bottomHeight, rightWidth, topHeight),
605 m_textures[curTexNdx]->getRefTexture(), sampleParams,
607 viewport.x+leftWidth, viewport.y+bottomHeight, rightWidth, topHeight,
608 tcu::Vec2(0.5f, -0.65f), tcu::Vec2(0.8f, -0.8f),
609 tcu::Vec2(1.0f, 1.0f));
612 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
616 DE_ASSERT(getNodeType() == tcu::NODETYPE_ACCURACY);
618 const int bestScoreDiff = 16;
619 const int worstScoreDiff = 10000;
621 int score = measureAccuracy(log, referenceFrame, renderedFrame, bestScoreDiff, worstScoreDiff);
622 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::toString(score).c_str());
628 TextureFilteringTests::TextureFilteringTests (Context& context)
629 : TestCaseGroup(context, "filter", "Texture Filtering Accuracy Tests")
633 TextureFilteringTests::~TextureFilteringTests (void)
637 void TextureFilteringTests::init (void)
639 tcu::TestCaseGroup* group2D = new tcu::TestCaseGroup(m_testCtx, "2d", "2D Texture Filtering");
640 tcu::TestCaseGroup* groupCube = new tcu::TestCaseGroup(m_testCtx, "cube", "Cube Map Filtering");
650 { "clamp", GL_CLAMP_TO_EDGE },
651 { "repeat", GL_REPEAT },
652 { "mirror", GL_MIRRORED_REPEAT }
661 { "nearest", GL_NEAREST },
662 { "linear", GL_LINEAR },
663 { "nearest_mipmap_nearest", GL_NEAREST_MIPMAP_NEAREST },
664 { "linear_mipmap_nearest", GL_LINEAR_MIPMAP_NEAREST },
665 { "nearest_mipmap_linear", GL_NEAREST_MIPMAP_LINEAR },
666 { "linear_mipmap_linear", GL_LINEAR_MIPMAP_LINEAR }
675 { "nearest", GL_NEAREST },
676 { "linear", GL_LINEAR }
708 { "rgba8888", GL_RGBA, GL_UNSIGNED_BYTE },
709 { "rgba4444", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 }
712 #define FOR_EACH(ITERATOR, ARRAY, BODY) \
713 for (int (ITERATOR) = 0; (ITERATOR) < DE_LENGTH_OF_ARRAY(ARRAY); (ITERATOR)++) \
717 FOR_EACH(minFilter, minFilterModes,
718 FOR_EACH(magFilter, magFilterModes,
719 FOR_EACH(wrapMode, wrapModes,
720 FOR_EACH(format, formats,
721 FOR_EACH(size, sizes2D,
723 bool isMipmap = minFilterModes[minFilter].mode != GL_NEAREST && minFilterModes[minFilter].mode != GL_LINEAR;
724 bool isClamp = wrapModes[wrapMode].mode == GL_CLAMP_TO_EDGE;
725 bool isRepeat = wrapModes[wrapMode].mode == GL_REPEAT;
726 bool isMagNearest = magFilterModes[magFilter].mode == GL_NEAREST;
727 bool isPotSize = deIsPowerOfTwo32(sizes2D[size].width) && deIsPowerOfTwo32(sizes2D[size].height);
729 if ((isMipmap || !isClamp) && !isPotSize)
730 continue; // Not supported.
732 if ((format != 0) && !(!isMipmap || (isRepeat && isMagNearest)))
735 string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name + "_" + formats[format].name;
738 name += string("_") + sizes2D[size].name;
740 group2D->addChild(new Texture2DFilteringCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
742 minFilterModes[minFilter].mode,
743 magFilterModes[magFilter].mode,
744 wrapModes[wrapMode].mode,
745 wrapModes[wrapMode].mode,
746 formats[format].format, formats[format].dataType,
747 sizes2D[size].width, sizes2D[size].height));
751 FOR_EACH(minFilter, minFilterModes,
752 FOR_EACH(magFilter, magFilterModes,
753 FOR_EACH(wrapMode, wrapModes,
754 FOR_EACH(format, formats,
755 FOR_EACH(size, sizesCube,
757 bool isMipmap = minFilterModes[minFilter].mode != GL_NEAREST && minFilterModes[minFilter].mode != GL_LINEAR;
758 bool isClamp = wrapModes[wrapMode].mode == GL_CLAMP_TO_EDGE;
759 bool isRepeat = wrapModes[wrapMode].mode == GL_REPEAT;
760 bool isMagNearest = magFilterModes[magFilter].mode == GL_NEAREST;
761 bool isPotSize = deIsPowerOfTwo32(sizesCube[size].width) && deIsPowerOfTwo32(sizesCube[size].height);
763 if ((isMipmap || !isClamp) && !isPotSize)
764 continue; // Not supported.
766 if (format != 0 && !(!isMipmap || (isRepeat && isMagNearest)))
769 string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name + "_" + formats[format].name;
772 name += string("_") + sizesCube[size].name;
774 groupCube->addChild(new TextureCubeFilteringCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
776 minFilterModes[minFilter].mode,
777 magFilterModes[magFilter].mode,
778 wrapModes[wrapMode].mode,
779 wrapModes[wrapMode].mode,
780 formats[format].format, formats[format].dataType,
781 sizesCube[size].width, sizesCube[size].height));