1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
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 Internal utilities shared between TexLookup and TexCompare verifiers.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "tcuTexVerifierUtil.hpp"
25 #include "tcuFloat.hpp"
26 
27 namespace tcu
28 {
29 namespace TexVerifierUtil
30 {
31 
computeFloatingPointError(const float value,const int numAccurateBits)32 float computeFloatingPointError (const float value, const int numAccurateBits)
33 {
34 	DE_ASSERT(numAccurateBits >= 0);
35 	DE_ASSERT(numAccurateBits <= 23);
36 
37 	const int		numGarbageBits	= 23-numAccurateBits;
38 	const deUint32	mask			= (1u<<numGarbageBits)-1u;
39 	const int		exp				= tcu::Float32(value).exponent();
40 
41 	return Float32::construct(+1, exp, (1u<<23) | mask).asFloat() - Float32::construct(+1, exp, 1u<<23).asFloat();
42 }
43 
computeFixedPointError(const int numAccurateBits)44 float computeFixedPointError (const int numAccurateBits)
45 {
46 	return computeFloatingPointError(1.0f, numAccurateBits);
47 }
48 
computeColorBitsError(const int bits,const int numAccurateBits)49 float computeColorBitsError(const int bits, const int numAccurateBits)
50 {
51 	// Color bits error is not a generic function, it just for compute the error value that cannot be accurately shown in integer data format.
52 	//
53 	//		"bits" is color bit width, "numAccurateBits" is the number of accurate bits in color bits, "1 << (bits - numAccurateBits)" is the threshold in integer.
54 	//		"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.
55 	return (float(1 << (bits - numAccurateBits)) + 1.0f / 256.0f) / float((1 << bits) - 1);
56 }
57 
computeNonNormalizedCoordBounds(const bool normalizedCoords,const int dim,const float coord,const int coordBits,const int uvBits)58 Vec2 computeNonNormalizedCoordBounds (const bool normalizedCoords, const int dim, const float coord, const int coordBits, const int uvBits)
59 {
60 	const float		coordErr		= computeFloatingPointError(coord, coordBits);
61 	const float		minN			= coord - coordErr;
62 	const float		maxN			= coord + coordErr;
63 	const float		minA			= normalizedCoords ? minN*float(dim) : minN;
64 	const float		maxA			= normalizedCoords ? maxN*float(dim) : maxN;
65 	const float		minC			= minA - computeFixedPointError(uvBits);
66 	const float		maxC			= maxA + computeFixedPointError(uvBits);
67 
68 	DE_ASSERT(minC <= maxC);
69 
70 	return Vec2(minC, maxC);
71 }
72 
getPossibleCubeFaces(const Vec3 & coord,const IVec3 & bits,CubeFace * faces,int & numFaces)73 void getPossibleCubeFaces (const Vec3& coord, const IVec3& bits, CubeFace* faces, int& numFaces)
74 {
75 	const float	x	= coord.x();
76 	const float	y	= coord.y();
77 	const float	z	= coord.z();
78 	const float ax	= de::abs(x);
79 	const float ay	= de::abs(y);
80 	const float az	= de::abs(z);
81 	const float ex	= computeFloatingPointError(x, bits.x());
82 	const float	ey	= computeFloatingPointError(y, bits.y());
83 	const float ez	= computeFloatingPointError(z, bits.z());
84 
85 	numFaces = 0;
86 
87 	if (ay+ey < ax-ex && az+ez < ax-ex)
88 	{
89 		if (x >= ex) faces[numFaces++] = CUBEFACE_POSITIVE_X;
90 		if (x <= ex) faces[numFaces++] = CUBEFACE_NEGATIVE_X;
91 	}
92 	else if (ax+ex < ay-ey && az+ez < ay-ey)
93 	{
94 		if (y >= ey) faces[numFaces++] = CUBEFACE_POSITIVE_Y;
95 		if (y <= ey) faces[numFaces++] = CUBEFACE_NEGATIVE_Y;
96 	}
97 	else if (ax+ex < az-ez && ay+ey < az-ez)
98 	{
99 		if (z >= ez) faces[numFaces++] = CUBEFACE_POSITIVE_Z;
100 		if (z <= ez) faces[numFaces++] = CUBEFACE_NEGATIVE_Z;
101 	}
102 	else
103 	{
104 		// One or more components are equal (or within error bounds). Allow all faces where major axis is not zero.
105 		if (ax > ex)
106 		{
107 			faces[numFaces++] = CUBEFACE_NEGATIVE_X;
108 			faces[numFaces++] = CUBEFACE_POSITIVE_X;
109 		}
110 
111 		if (ay > ey)
112 		{
113 			faces[numFaces++] = CUBEFACE_NEGATIVE_Y;
114 			faces[numFaces++] = CUBEFACE_POSITIVE_Y;
115 		}
116 
117 		if (az > ez)
118 		{
119 			faces[numFaces++] = CUBEFACE_NEGATIVE_Z;
120 			faces[numFaces++] = CUBEFACE_POSITIVE_Z;
121 		}
122 	}
123 }
124 
getUnnormalizedCoordSampler(const Sampler & sampler)125 Sampler getUnnormalizedCoordSampler (const Sampler& sampler)
126 {
127 	Sampler copy = sampler;
128 	copy.normalizedCoords = false;
129 	return copy;
130 }
131 
imod(int a,int b)132 static inline int imod (int a, int b)
133 {
134 	int m = a % b;
135 	return m < 0 ? m + b : m;
136 }
137 
mirror(int a)138 static inline int mirror (int a)
139 {
140 	return a >= 0 ? a : -(1 + a);
141 }
142 
wrap(Sampler::WrapMode mode,int c,int size)143 int wrap (Sampler::WrapMode mode, int c, int size)
144 {
145 	switch (mode)
146 	{
147 		// \note CL and GL modes are handled identically here, as verification process accounts for
148 		//		 accuracy differences caused by different methods (wrapping vs. denormalizing first).
149 		case tcu::Sampler::CLAMP_TO_BORDER:
150 			return deClamp32(c, -1, size);
151 
152 		case tcu::Sampler::CLAMP_TO_EDGE:
153 			return deClamp32(c, 0, size-1);
154 
155 		case tcu::Sampler::REPEAT_GL:
156 		case tcu::Sampler::REPEAT_CL:
157 			return imod(c, size);
158 
159 		case tcu::Sampler::MIRRORED_ONCE:
160 			c = deClamp32(c, -size, size);
161 			// Fall-through
162 
163 		case tcu::Sampler::MIRRORED_REPEAT_GL:
164 		case tcu::Sampler::MIRRORED_REPEAT_CL:
165 			return (size - 1) - mirror(imod(c, 2*size) - size);
166 
167 		default:
168 			DE_ASSERT(DE_FALSE);
169 			return 0;
170 	}
171 }
172 } // TexVerifierUtil
173 } // tcu
174