/*-------------------------------------------------------------------------
* drawElements Quality Program Tester Core
* ----------------------------------------
*
* Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief Internal utilities shared between TexLookup and TexCompare verifiers.
*//*--------------------------------------------------------------------*/
#include "tcuTexVerifierUtil.hpp"
#include "tcuFloat.hpp"
namespace tcu
{
namespace TexVerifierUtil
{
float computeFloatingPointError (const float value, const int numAccurateBits)
{
const int numGarbageBits = 23-numAccurateBits;
const deUint32 mask = (1u<<numGarbageBits)-1u;
const int exp = tcu::Float32(value).exponent();
return Float32::construct(+1, exp, (1u<<23) | mask).asFloat() - Float32::construct(+1, exp, 1u<<23).asFloat();
}
float computeFixedPointError (const int numAccurateBits)
{
return computeFloatingPointError(1.0f, numAccurateBits);
}
Vec2 computeNonNormalizedCoordBounds (const bool normalizedCoords, const int dim, const float coord, const int coordBits, const int uvBits)
{
const float coordErr = computeFloatingPointError(coord, coordBits);
const float minN = coord - coordErr;
const float maxN = coord + coordErr;
const float minA = normalizedCoords ? minN*float(dim) : minN;
const float maxA = normalizedCoords ? maxN*float(dim) : maxN;
const float minC = minA - computeFixedPointError(uvBits);
const float maxC = maxA + computeFixedPointError(uvBits);
DE_ASSERT(minC <= maxC);
return Vec2(minC, maxC);
}
void getPossibleCubeFaces (const Vec3& coord, const IVec3& bits, CubeFace* faces, int& numFaces)
{
const float x = coord.x();
const float y = coord.y();
const float z = coord.z();
const float ax = de::abs(x);
const float ay = de::abs(y);
const float az = de::abs(z);
const float ex = computeFloatingPointError(x, bits.x());
const float ey = computeFloatingPointError(y, bits.y());
const float ez = computeFloatingPointError(z, bits.z());
numFaces = 0;
if (ay+ey < ax-ex && az+ez < ax-ex)
{
if (x >= ex) faces[numFaces++] = CUBEFACE_POSITIVE_X;
if (x <= ex) faces[numFaces++] = CUBEFACE_NEGATIVE_X;
}
else if (ax+ex < ay-ey && az+ez < ay-ey)
{
if (y >= ey) faces[numFaces++] = CUBEFACE_POSITIVE_Y;
if (y <= ey) faces[numFaces++] = CUBEFACE_NEGATIVE_Y;
}
else if (ax+ex < az-ez && ay+ey < az-ez)
{
if (z >= ez) faces[numFaces++] = CUBEFACE_POSITIVE_Z;
if (z <= ez) faces[numFaces++] = CUBEFACE_NEGATIVE_Z;
}
else
{
// One or more components are equal (or within error bounds). Allow all faces where major axis is not zero.
if (ax > ex)
{
faces[numFaces++] = CUBEFACE_NEGATIVE_X;
faces[numFaces++] = CUBEFACE_POSITIVE_X;
}
if (ay > ey)
{
faces[numFaces++] = CUBEFACE_NEGATIVE_Y;
faces[numFaces++] = CUBEFACE_POSITIVE_Y;
}
if (az > ez)
{
faces[numFaces++] = CUBEFACE_NEGATIVE_Z;
faces[numFaces++] = CUBEFACE_POSITIVE_Z;
}
}
}
Sampler getUnnormalizedCoordSampler (const Sampler& sampler)
{
Sampler copy = sampler;
copy.normalizedCoords = false;
return copy;
}
static inline int imod (int a, int b)
{
int m = a % b;
return m < 0 ? m + b : m;
}
static inline int mirror (int a)
{
return a >= 0.0f ? a : -(1 + a);
}
int wrap (Sampler::WrapMode mode, int c, int size)
{
switch (mode)
{
// \note CL and GL modes are handled identically here, as verification process accounts for
// accuracy differences caused by different methods (wrapping vs. denormalizing first).
case tcu::Sampler::CLAMP_TO_BORDER:
return deClamp32(c, -1, size);
case tcu::Sampler::CLAMP_TO_EDGE:
return deClamp32(c, 0, size-1);
case tcu::Sampler::REPEAT_GL:
case tcu::Sampler::REPEAT_CL:
return imod(c, size);
case tcu::Sampler::MIRRORED_ONCE:
c = deClamp32(c, -size, size);
// Fall-through
case tcu::Sampler::MIRRORED_REPEAT_GL:
case tcu::Sampler::MIRRORED_REPEAT_CL:
return (size - 1) - mirror(imod(c, 2*size) - size);
default:
DE_ASSERT(DE_FALSE);
return 0;
}
}
} // TexVerifierUtil
} // tcu