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