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