1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * drawElements Quality Program Tester Core 3e5c31af7Sopenharmony_ci * ---------------------------------------- 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci *//*! 20e5c31af7Sopenharmony_ci * \file 21e5c31af7Sopenharmony_ci * \brief Internal utilities shared between TexLookup and TexCompare verifiers. 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "tcuTexVerifierUtil.hpp" 25e5c31af7Sopenharmony_ci#include "tcuFloat.hpp" 26e5c31af7Sopenharmony_ci 27e5c31af7Sopenharmony_cinamespace tcu 28e5c31af7Sopenharmony_ci{ 29e5c31af7Sopenharmony_cinamespace TexVerifierUtil 30e5c31af7Sopenharmony_ci{ 31e5c31af7Sopenharmony_ci 32e5c31af7Sopenharmony_cifloat computeFloatingPointError (const float value, const int numAccurateBits) 33e5c31af7Sopenharmony_ci{ 34e5c31af7Sopenharmony_ci DE_ASSERT(numAccurateBits >= 0); 35e5c31af7Sopenharmony_ci DE_ASSERT(numAccurateBits <= 23); 36e5c31af7Sopenharmony_ci 37e5c31af7Sopenharmony_ci const int numGarbageBits = 23-numAccurateBits; 38e5c31af7Sopenharmony_ci const deUint32 mask = (1u<<numGarbageBits)-1u; 39e5c31af7Sopenharmony_ci const int exp = tcu::Float32(value).exponent(); 40e5c31af7Sopenharmony_ci 41e5c31af7Sopenharmony_ci return Float32::construct(+1, exp, (1u<<23) | mask).asFloat() - Float32::construct(+1, exp, 1u<<23).asFloat(); 42e5c31af7Sopenharmony_ci} 43e5c31af7Sopenharmony_ci 44e5c31af7Sopenharmony_cifloat computeFixedPointError (const int numAccurateBits) 45e5c31af7Sopenharmony_ci{ 46e5c31af7Sopenharmony_ci return computeFloatingPointError(1.0f, numAccurateBits); 47e5c31af7Sopenharmony_ci} 48e5c31af7Sopenharmony_ci 49e5c31af7Sopenharmony_cifloat computeColorBitsError(const int bits, const int numAccurateBits) 50e5c31af7Sopenharmony_ci{ 51e5c31af7Sopenharmony_ci // Color bits error is not a generic function, it just for compute the error value that cannot be accurately shown in integer data format. 52e5c31af7Sopenharmony_ci // 53e5c31af7Sopenharmony_ci // "bits" is color bit width, "numAccurateBits" is the number of accurate bits in color bits, "1 << (bits - numAccurateBits)" is the threshold in integer. 54e5c31af7Sopenharmony_ci // "1.0f / 256.0f" is epsilon value, to make sure the threshold use to calculate in float can be a little bigger than the real value. 55e5c31af7Sopenharmony_ci return (float(1 << (bits - numAccurateBits)) + 1.0f / 256.0f) / float((1 << bits) - 1); 56e5c31af7Sopenharmony_ci} 57e5c31af7Sopenharmony_ci 58e5c31af7Sopenharmony_ciVec2 computeNonNormalizedCoordBounds (const bool normalizedCoords, const int dim, const float coord, const int coordBits, const int uvBits) 59e5c31af7Sopenharmony_ci{ 60e5c31af7Sopenharmony_ci const float coordErr = computeFloatingPointError(coord, coordBits); 61e5c31af7Sopenharmony_ci const float minN = coord - coordErr; 62e5c31af7Sopenharmony_ci const float maxN = coord + coordErr; 63e5c31af7Sopenharmony_ci const float minA = normalizedCoords ? minN*float(dim) : minN; 64e5c31af7Sopenharmony_ci const float maxA = normalizedCoords ? maxN*float(dim) : maxN; 65e5c31af7Sopenharmony_ci const float minC = minA - computeFixedPointError(uvBits); 66e5c31af7Sopenharmony_ci const float maxC = maxA + computeFixedPointError(uvBits); 67e5c31af7Sopenharmony_ci 68e5c31af7Sopenharmony_ci DE_ASSERT(minC <= maxC); 69e5c31af7Sopenharmony_ci 70e5c31af7Sopenharmony_ci return Vec2(minC, maxC); 71e5c31af7Sopenharmony_ci} 72e5c31af7Sopenharmony_ci 73e5c31af7Sopenharmony_civoid getPossibleCubeFaces (const Vec3& coord, const IVec3& bits, CubeFace* faces, int& numFaces) 74e5c31af7Sopenharmony_ci{ 75e5c31af7Sopenharmony_ci const float x = coord.x(); 76e5c31af7Sopenharmony_ci const float y = coord.y(); 77e5c31af7Sopenharmony_ci const float z = coord.z(); 78e5c31af7Sopenharmony_ci const float ax = de::abs(x); 79e5c31af7Sopenharmony_ci const float ay = de::abs(y); 80e5c31af7Sopenharmony_ci const float az = de::abs(z); 81e5c31af7Sopenharmony_ci const float ex = computeFloatingPointError(x, bits.x()); 82e5c31af7Sopenharmony_ci const float ey = computeFloatingPointError(y, bits.y()); 83e5c31af7Sopenharmony_ci const float ez = computeFloatingPointError(z, bits.z()); 84e5c31af7Sopenharmony_ci 85e5c31af7Sopenharmony_ci numFaces = 0; 86e5c31af7Sopenharmony_ci 87e5c31af7Sopenharmony_ci if (ay+ey < ax-ex && az+ez < ax-ex) 88e5c31af7Sopenharmony_ci { 89e5c31af7Sopenharmony_ci if (x >= ex) faces[numFaces++] = CUBEFACE_POSITIVE_X; 90e5c31af7Sopenharmony_ci if (x <= ex) faces[numFaces++] = CUBEFACE_NEGATIVE_X; 91e5c31af7Sopenharmony_ci } 92e5c31af7Sopenharmony_ci else if (ax+ex < ay-ey && az+ez < ay-ey) 93e5c31af7Sopenharmony_ci { 94e5c31af7Sopenharmony_ci if (y >= ey) faces[numFaces++] = CUBEFACE_POSITIVE_Y; 95e5c31af7Sopenharmony_ci if (y <= ey) faces[numFaces++] = CUBEFACE_NEGATIVE_Y; 96e5c31af7Sopenharmony_ci } 97e5c31af7Sopenharmony_ci else if (ax+ex < az-ez && ay+ey < az-ez) 98e5c31af7Sopenharmony_ci { 99e5c31af7Sopenharmony_ci if (z >= ez) faces[numFaces++] = CUBEFACE_POSITIVE_Z; 100e5c31af7Sopenharmony_ci if (z <= ez) faces[numFaces++] = CUBEFACE_NEGATIVE_Z; 101e5c31af7Sopenharmony_ci } 102e5c31af7Sopenharmony_ci else 103e5c31af7Sopenharmony_ci { 104e5c31af7Sopenharmony_ci // One or more components are equal (or within error bounds). Allow all faces where major axis is not zero. 105e5c31af7Sopenharmony_ci if (ax > ex) 106e5c31af7Sopenharmony_ci { 107e5c31af7Sopenharmony_ci faces[numFaces++] = CUBEFACE_NEGATIVE_X; 108e5c31af7Sopenharmony_ci faces[numFaces++] = CUBEFACE_POSITIVE_X; 109e5c31af7Sopenharmony_ci } 110e5c31af7Sopenharmony_ci 111e5c31af7Sopenharmony_ci if (ay > ey) 112e5c31af7Sopenharmony_ci { 113e5c31af7Sopenharmony_ci faces[numFaces++] = CUBEFACE_NEGATIVE_Y; 114e5c31af7Sopenharmony_ci faces[numFaces++] = CUBEFACE_POSITIVE_Y; 115e5c31af7Sopenharmony_ci } 116e5c31af7Sopenharmony_ci 117e5c31af7Sopenharmony_ci if (az > ez) 118e5c31af7Sopenharmony_ci { 119e5c31af7Sopenharmony_ci faces[numFaces++] = CUBEFACE_NEGATIVE_Z; 120e5c31af7Sopenharmony_ci faces[numFaces++] = CUBEFACE_POSITIVE_Z; 121e5c31af7Sopenharmony_ci } 122e5c31af7Sopenharmony_ci } 123e5c31af7Sopenharmony_ci} 124e5c31af7Sopenharmony_ci 125e5c31af7Sopenharmony_ciSampler getUnnormalizedCoordSampler (const Sampler& sampler) 126e5c31af7Sopenharmony_ci{ 127e5c31af7Sopenharmony_ci Sampler copy = sampler; 128e5c31af7Sopenharmony_ci copy.normalizedCoords = false; 129e5c31af7Sopenharmony_ci return copy; 130e5c31af7Sopenharmony_ci} 131e5c31af7Sopenharmony_ci 132e5c31af7Sopenharmony_cistatic inline int imod (int a, int b) 133e5c31af7Sopenharmony_ci{ 134e5c31af7Sopenharmony_ci int m = a % b; 135e5c31af7Sopenharmony_ci return m < 0 ? m + b : m; 136e5c31af7Sopenharmony_ci} 137e5c31af7Sopenharmony_ci 138e5c31af7Sopenharmony_cistatic inline int mirror (int a) 139e5c31af7Sopenharmony_ci{ 140e5c31af7Sopenharmony_ci return a >= 0 ? a : -(1 + a); 141e5c31af7Sopenharmony_ci} 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ciint wrap (Sampler::WrapMode mode, int c, int size) 144e5c31af7Sopenharmony_ci{ 145e5c31af7Sopenharmony_ci switch (mode) 146e5c31af7Sopenharmony_ci { 147e5c31af7Sopenharmony_ci // \note CL and GL modes are handled identically here, as verification process accounts for 148e5c31af7Sopenharmony_ci // accuracy differences caused by different methods (wrapping vs. denormalizing first). 149e5c31af7Sopenharmony_ci case tcu::Sampler::CLAMP_TO_BORDER: 150e5c31af7Sopenharmony_ci return deClamp32(c, -1, size); 151e5c31af7Sopenharmony_ci 152e5c31af7Sopenharmony_ci case tcu::Sampler::CLAMP_TO_EDGE: 153e5c31af7Sopenharmony_ci return deClamp32(c, 0, size-1); 154e5c31af7Sopenharmony_ci 155e5c31af7Sopenharmony_ci case tcu::Sampler::REPEAT_GL: 156e5c31af7Sopenharmony_ci case tcu::Sampler::REPEAT_CL: 157e5c31af7Sopenharmony_ci return imod(c, size); 158e5c31af7Sopenharmony_ci 159e5c31af7Sopenharmony_ci case tcu::Sampler::MIRRORED_ONCE: 160e5c31af7Sopenharmony_ci c = deClamp32(c, -size, size); 161e5c31af7Sopenharmony_ci // Fall-through 162e5c31af7Sopenharmony_ci 163e5c31af7Sopenharmony_ci case tcu::Sampler::MIRRORED_REPEAT_GL: 164e5c31af7Sopenharmony_ci case tcu::Sampler::MIRRORED_REPEAT_CL: 165e5c31af7Sopenharmony_ci return (size - 1) - mirror(imod(c, 2*size) - size); 166e5c31af7Sopenharmony_ci 167e5c31af7Sopenharmony_ci default: 168e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 169e5c31af7Sopenharmony_ci return 0; 170e5c31af7Sopenharmony_ci } 171e5c31af7Sopenharmony_ci} 172e5c31af7Sopenharmony_ci} // TexVerifierUtil 173e5c31af7Sopenharmony_ci} // tcu 174