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 Texture lookup simulator that is capable of verifying generic
22*35238bceSAndroid Build Coastguard Worker * lookup results based on accuracy parameters.
23*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
24*35238bceSAndroid Build Coastguard Worker
25*35238bceSAndroid Build Coastguard Worker #include "tcuTexLookupVerifier.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "tcuTexVerifierUtil.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "tcuVectorUtil.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "tcuTextureUtil.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "deMath.h"
30*35238bceSAndroid Build Coastguard Worker
31*35238bceSAndroid Build Coastguard Worker namespace tcu
32*35238bceSAndroid Build Coastguard Worker {
33*35238bceSAndroid Build Coastguard Worker
34*35238bceSAndroid Build Coastguard Worker using namespace TexVerifierUtil;
35*35238bceSAndroid Build Coastguard Worker
36*35238bceSAndroid Build Coastguard Worker // Generic utilities
37*35238bceSAndroid Build Coastguard Worker
38*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
isSamplerSupported(const Sampler & sampler)39*35238bceSAndroid Build Coastguard Worker static bool isSamplerSupported(const Sampler &sampler)
40*35238bceSAndroid Build Coastguard Worker {
41*35238bceSAndroid Build Coastguard Worker return sampler.compare == Sampler::COMPAREMODE_NONE && isWrapModeSupported(sampler.wrapS) &&
42*35238bceSAndroid Build Coastguard Worker isWrapModeSupported(sampler.wrapT) && isWrapModeSupported(sampler.wrapR);
43*35238bceSAndroid Build Coastguard Worker }
44*35238bceSAndroid Build Coastguard Worker #endif // DE_DEBUG
45*35238bceSAndroid Build Coastguard Worker
46*35238bceSAndroid Build Coastguard Worker // Color read & compare utilities
47*35238bceSAndroid Build Coastguard Worker
coordsInBounds(const ConstPixelBufferAccess & access,int x,int y,int z)48*35238bceSAndroid Build Coastguard Worker static inline bool coordsInBounds(const ConstPixelBufferAccess &access, int x, int y, int z)
49*35238bceSAndroid Build Coastguard Worker {
50*35238bceSAndroid Build Coastguard Worker return de::inBounds(x, 0, access.getWidth()) && de::inBounds(y, 0, access.getHeight()) &&
51*35238bceSAndroid Build Coastguard Worker de::inBounds(z, 0, access.getDepth());
52*35238bceSAndroid Build Coastguard Worker }
53*35238bceSAndroid Build Coastguard Worker
54*35238bceSAndroid Build Coastguard Worker template <typename ScalarType>
lookup(const ConstPixelBufferAccess & access,const Sampler & sampler,int i,int j,int k)55*35238bceSAndroid Build Coastguard Worker inline Vector<ScalarType, 4> lookup(const ConstPixelBufferAccess &access, const Sampler &sampler, int i, int j, int k)
56*35238bceSAndroid Build Coastguard Worker {
57*35238bceSAndroid Build Coastguard Worker if (coordsInBounds(access, i, j, k))
58*35238bceSAndroid Build Coastguard Worker return access.getPixelT<ScalarType>(i, j, k);
59*35238bceSAndroid Build Coastguard Worker else
60*35238bceSAndroid Build Coastguard Worker return sampleTextureBorder<ScalarType>(access.getFormat(), sampler);
61*35238bceSAndroid Build Coastguard Worker }
62*35238bceSAndroid Build Coastguard Worker
63*35238bceSAndroid Build Coastguard Worker template <>
lookup(const ConstPixelBufferAccess & access,const Sampler & sampler,int i,int j,int k)64*35238bceSAndroid Build Coastguard Worker inline Vector<float, 4> lookup(const ConstPixelBufferAccess &access, const Sampler &sampler, int i, int j, int k)
65*35238bceSAndroid Build Coastguard Worker {
66*35238bceSAndroid Build Coastguard Worker // Specialization for float lookups: sRGB conversion is performed as specified in format.
67*35238bceSAndroid Build Coastguard Worker if (coordsInBounds(access, i, j, k))
68*35238bceSAndroid Build Coastguard Worker {
69*35238bceSAndroid Build Coastguard Worker const Vec4 p = access.getPixel(i, j, k);
70*35238bceSAndroid Build Coastguard Worker return isSRGB(access.getFormat()) ? sRGBToLinear(p) : p;
71*35238bceSAndroid Build Coastguard Worker }
72*35238bceSAndroid Build Coastguard Worker else
73*35238bceSAndroid Build Coastguard Worker return sampleTextureBorder<float>(access.getFormat(), sampler);
74*35238bceSAndroid Build Coastguard Worker }
75*35238bceSAndroid Build Coastguard Worker
isColorValid(const LookupPrecision & prec,const Vec4 & ref,const Vec4 & result)76*35238bceSAndroid Build Coastguard Worker static inline bool isColorValid(const LookupPrecision &prec, const Vec4 &ref, const Vec4 &result)
77*35238bceSAndroid Build Coastguard Worker {
78*35238bceSAndroid Build Coastguard Worker const Vec4 diff = abs(ref - result);
79*35238bceSAndroid Build Coastguard Worker return boolAll(logicalOr(lessThanEqual(diff, prec.colorThreshold), logicalNot(prec.colorMask)));
80*35238bceSAndroid Build Coastguard Worker }
81*35238bceSAndroid Build Coastguard Worker
isColorValid(const IntLookupPrecision & prec,const IVec4 & ref,const IVec4 & result)82*35238bceSAndroid Build Coastguard Worker static inline bool isColorValid(const IntLookupPrecision &prec, const IVec4 &ref, const IVec4 &result)
83*35238bceSAndroid Build Coastguard Worker {
84*35238bceSAndroid Build Coastguard Worker return boolAll(
85*35238bceSAndroid Build Coastguard Worker logicalOr(lessThanEqual(absDiff(ref, result).asUint(), prec.colorThreshold), logicalNot(prec.colorMask)));
86*35238bceSAndroid Build Coastguard Worker }
87*35238bceSAndroid Build Coastguard Worker
isColorValid(const IntLookupPrecision & prec,const UVec4 & ref,const UVec4 & result)88*35238bceSAndroid Build Coastguard Worker static inline bool isColorValid(const IntLookupPrecision &prec, const UVec4 &ref, const UVec4 &result)
89*35238bceSAndroid Build Coastguard Worker {
90*35238bceSAndroid Build Coastguard Worker return boolAll(logicalOr(lessThanEqual(absDiff(ref, result), prec.colorThreshold), logicalNot(prec.colorMask)));
91*35238bceSAndroid Build Coastguard Worker }
92*35238bceSAndroid Build Coastguard Worker
93*35238bceSAndroid Build Coastguard Worker struct ColorQuad
94*35238bceSAndroid Build Coastguard Worker {
95*35238bceSAndroid Build Coastguard Worker Vec4 p00; //!< (0, 0)
96*35238bceSAndroid Build Coastguard Worker Vec4 p01; //!< (1, 0)
97*35238bceSAndroid Build Coastguard Worker Vec4 p10; //!< (0, 1)
98*35238bceSAndroid Build Coastguard Worker Vec4 p11; //!< (1, 1)
99*35238bceSAndroid Build Coastguard Worker };
100*35238bceSAndroid Build Coastguard Worker
lookupQuad(ColorQuad & dst,const ConstPixelBufferAccess & level,const Sampler & sampler,int x0,int x1,int y0,int y1,int z)101*35238bceSAndroid Build Coastguard Worker static void lookupQuad(ColorQuad &dst, const ConstPixelBufferAccess &level, const Sampler &sampler, int x0, int x1,
102*35238bceSAndroid Build Coastguard Worker int y0, int y1, int z)
103*35238bceSAndroid Build Coastguard Worker {
104*35238bceSAndroid Build Coastguard Worker dst.p00 = lookup<float>(level, sampler, x0, y0, z);
105*35238bceSAndroid Build Coastguard Worker dst.p10 = lookup<float>(level, sampler, x1, y0, z);
106*35238bceSAndroid Build Coastguard Worker dst.p01 = lookup<float>(level, sampler, x0, y1, z);
107*35238bceSAndroid Build Coastguard Worker dst.p11 = lookup<float>(level, sampler, x1, y1, z);
108*35238bceSAndroid Build Coastguard Worker }
109*35238bceSAndroid Build Coastguard Worker
110*35238bceSAndroid Build Coastguard Worker struct ColorLine
111*35238bceSAndroid Build Coastguard Worker {
112*35238bceSAndroid Build Coastguard Worker Vec4 p0; //!< 0
113*35238bceSAndroid Build Coastguard Worker Vec4 p1; //!< 1
114*35238bceSAndroid Build Coastguard Worker };
115*35238bceSAndroid Build Coastguard Worker
lookupLine(ColorLine & dst,const ConstPixelBufferAccess & level,const Sampler & sampler,int x0,int x1,int y)116*35238bceSAndroid Build Coastguard Worker static void lookupLine(ColorLine &dst, const ConstPixelBufferAccess &level, const Sampler &sampler, int x0, int x1,
117*35238bceSAndroid Build Coastguard Worker int y)
118*35238bceSAndroid Build Coastguard Worker {
119*35238bceSAndroid Build Coastguard Worker dst.p0 = lookup<float>(level, sampler, x0, y, 0);
120*35238bceSAndroid Build Coastguard Worker dst.p1 = lookup<float>(level, sampler, x1, y, 0);
121*35238bceSAndroid Build Coastguard Worker }
122*35238bceSAndroid Build Coastguard Worker
123*35238bceSAndroid Build Coastguard Worker template <typename T, int Size>
minComp(const Vector<T,Size> & vec)124*35238bceSAndroid Build Coastguard Worker static T minComp(const Vector<T, Size> &vec)
125*35238bceSAndroid Build Coastguard Worker {
126*35238bceSAndroid Build Coastguard Worker T minVal = vec[0];
127*35238bceSAndroid Build Coastguard Worker for (int ndx = 1; ndx < Size; ndx++)
128*35238bceSAndroid Build Coastguard Worker minVal = de::min(minVal, vec[ndx]);
129*35238bceSAndroid Build Coastguard Worker return minVal;
130*35238bceSAndroid Build Coastguard Worker }
131*35238bceSAndroid Build Coastguard Worker
132*35238bceSAndroid Build Coastguard Worker template <typename T, int Size>
maxComp(const Vector<T,Size> & vec)133*35238bceSAndroid Build Coastguard Worker static T maxComp(const Vector<T, Size> &vec)
134*35238bceSAndroid Build Coastguard Worker {
135*35238bceSAndroid Build Coastguard Worker T maxVal = vec[0];
136*35238bceSAndroid Build Coastguard Worker for (int ndx = 1; ndx < Size; ndx++)
137*35238bceSAndroid Build Coastguard Worker maxVal = de::max(maxVal, vec[ndx]);
138*35238bceSAndroid Build Coastguard Worker return maxVal;
139*35238bceSAndroid Build Coastguard Worker }
140*35238bceSAndroid Build Coastguard Worker
computeBilinearSearchStepFromFloatLine(const LookupPrecision & prec,const ColorLine & line)141*35238bceSAndroid Build Coastguard Worker static float computeBilinearSearchStepFromFloatLine(const LookupPrecision &prec, const ColorLine &line)
142*35238bceSAndroid Build Coastguard Worker {
143*35238bceSAndroid Build Coastguard Worker DE_ASSERT(boolAll(greaterThan(prec.colorThreshold, Vec4(0.0f))));
144*35238bceSAndroid Build Coastguard Worker
145*35238bceSAndroid Build Coastguard Worker const int maxSteps = 1 << 16;
146*35238bceSAndroid Build Coastguard Worker const Vec4 d = abs(line.p1 - line.p0);
147*35238bceSAndroid Build Coastguard Worker const Vec4 stepCount = d / prec.colorThreshold;
148*35238bceSAndroid Build Coastguard Worker const Vec4 minStep = 1.0f / (stepCount + 1.0f);
149*35238bceSAndroid Build Coastguard Worker const float step = de::max(minComp(minStep), 1.0f / float(maxSteps));
150*35238bceSAndroid Build Coastguard Worker
151*35238bceSAndroid Build Coastguard Worker return step;
152*35238bceSAndroid Build Coastguard Worker }
153*35238bceSAndroid Build Coastguard Worker
computeBilinearSearchStepFromFloatQuad(const LookupPrecision & prec,const ColorQuad & quad)154*35238bceSAndroid Build Coastguard Worker static float computeBilinearSearchStepFromFloatQuad(const LookupPrecision &prec, const ColorQuad &quad)
155*35238bceSAndroid Build Coastguard Worker {
156*35238bceSAndroid Build Coastguard Worker DE_ASSERT(boolAll(greaterThan(prec.colorThreshold, Vec4(0.0f))));
157*35238bceSAndroid Build Coastguard Worker
158*35238bceSAndroid Build Coastguard Worker const int maxSteps = 1 << 16;
159*35238bceSAndroid Build Coastguard Worker const Vec4 d0 = abs(quad.p10 - quad.p00);
160*35238bceSAndroid Build Coastguard Worker const Vec4 d1 = abs(quad.p01 - quad.p00);
161*35238bceSAndroid Build Coastguard Worker const Vec4 d2 = abs(quad.p11 - quad.p10);
162*35238bceSAndroid Build Coastguard Worker const Vec4 d3 = abs(quad.p11 - quad.p01);
163*35238bceSAndroid Build Coastguard Worker const Vec4 maxD = max(d0, max(d1, max(d2, d3)));
164*35238bceSAndroid Build Coastguard Worker const Vec4 stepCount = maxD / prec.colorThreshold;
165*35238bceSAndroid Build Coastguard Worker const Vec4 minStep = 1.0f / (stepCount + 1.0f);
166*35238bceSAndroid Build Coastguard Worker const float step = de::max(minComp(minStep), 1.0f / float(maxSteps));
167*35238bceSAndroid Build Coastguard Worker
168*35238bceSAndroid Build Coastguard Worker return step;
169*35238bceSAndroid Build Coastguard Worker }
170*35238bceSAndroid Build Coastguard Worker
computeBilinearSearchStepForUnorm(const LookupPrecision & prec)171*35238bceSAndroid Build Coastguard Worker static float computeBilinearSearchStepForUnorm(const LookupPrecision &prec)
172*35238bceSAndroid Build Coastguard Worker {
173*35238bceSAndroid Build Coastguard Worker DE_ASSERT(boolAll(greaterThan(prec.colorThreshold, Vec4(0.0f))));
174*35238bceSAndroid Build Coastguard Worker
175*35238bceSAndroid Build Coastguard Worker const Vec4 stepCount = 1.0f / prec.colorThreshold;
176*35238bceSAndroid Build Coastguard Worker const Vec4 minStep = 1.0f / (stepCount + 1.0f);
177*35238bceSAndroid Build Coastguard Worker const float step = minComp(minStep);
178*35238bceSAndroid Build Coastguard Worker
179*35238bceSAndroid Build Coastguard Worker return step;
180*35238bceSAndroid Build Coastguard Worker }
181*35238bceSAndroid Build Coastguard Worker
computeBilinearSearchStepForSnorm(const LookupPrecision & prec)182*35238bceSAndroid Build Coastguard Worker static float computeBilinearSearchStepForSnorm(const LookupPrecision &prec)
183*35238bceSAndroid Build Coastguard Worker {
184*35238bceSAndroid Build Coastguard Worker DE_ASSERT(boolAll(greaterThan(prec.colorThreshold, Vec4(0.0f))));
185*35238bceSAndroid Build Coastguard Worker
186*35238bceSAndroid Build Coastguard Worker const Vec4 stepCount = 2.0f / prec.colorThreshold;
187*35238bceSAndroid Build Coastguard Worker const Vec4 minStep = 1.0f / (stepCount + 1.0f);
188*35238bceSAndroid Build Coastguard Worker const float step = minComp(minStep);
189*35238bceSAndroid Build Coastguard Worker
190*35238bceSAndroid Build Coastguard Worker return step;
191*35238bceSAndroid Build Coastguard Worker }
192*35238bceSAndroid Build Coastguard Worker
min(const ColorLine & line)193*35238bceSAndroid Build Coastguard Worker static inline Vec4 min(const ColorLine &line)
194*35238bceSAndroid Build Coastguard Worker {
195*35238bceSAndroid Build Coastguard Worker return min(line.p0, line.p1);
196*35238bceSAndroid Build Coastguard Worker }
197*35238bceSAndroid Build Coastguard Worker
max(const ColorLine & line)198*35238bceSAndroid Build Coastguard Worker static inline Vec4 max(const ColorLine &line)
199*35238bceSAndroid Build Coastguard Worker {
200*35238bceSAndroid Build Coastguard Worker return max(line.p0, line.p1);
201*35238bceSAndroid Build Coastguard Worker }
202*35238bceSAndroid Build Coastguard Worker
min(const ColorQuad & quad)203*35238bceSAndroid Build Coastguard Worker static inline Vec4 min(const ColorQuad &quad)
204*35238bceSAndroid Build Coastguard Worker {
205*35238bceSAndroid Build Coastguard Worker return min(quad.p00, min(quad.p10, min(quad.p01, quad.p11)));
206*35238bceSAndroid Build Coastguard Worker }
207*35238bceSAndroid Build Coastguard Worker
max(const ColorQuad & quad)208*35238bceSAndroid Build Coastguard Worker static inline Vec4 max(const ColorQuad &quad)
209*35238bceSAndroid Build Coastguard Worker {
210*35238bceSAndroid Build Coastguard Worker return max(quad.p00, max(quad.p10, max(quad.p01, quad.p11)));
211*35238bceSAndroid Build Coastguard Worker }
212*35238bceSAndroid Build Coastguard Worker
isInColorBounds(const LookupPrecision & prec,const ColorQuad & quad,const Vec4 & result)213*35238bceSAndroid Build Coastguard Worker static bool isInColorBounds(const LookupPrecision &prec, const ColorQuad &quad, const Vec4 &result)
214*35238bceSAndroid Build Coastguard Worker {
215*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 minVal = min(quad) - prec.colorThreshold;
216*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 maxVal = max(quad) + prec.colorThreshold;
217*35238bceSAndroid Build Coastguard Worker return boolAll(logicalOr(logicalAnd(greaterThanEqual(result, minVal), lessThanEqual(result, maxVal)),
218*35238bceSAndroid Build Coastguard Worker logicalNot(prec.colorMask)));
219*35238bceSAndroid Build Coastguard Worker }
220*35238bceSAndroid Build Coastguard Worker
isInColorBounds(const LookupPrecision & prec,const ColorQuad & quad0,const ColorQuad & quad1,const Vec4 & result)221*35238bceSAndroid Build Coastguard Worker static bool isInColorBounds(const LookupPrecision &prec, const ColorQuad &quad0, const ColorQuad &quad1,
222*35238bceSAndroid Build Coastguard Worker const Vec4 &result)
223*35238bceSAndroid Build Coastguard Worker {
224*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 minVal = min(min(quad0), min(quad1)) - prec.colorThreshold;
225*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 maxVal = max(max(quad0), max(quad1)) + prec.colorThreshold;
226*35238bceSAndroid Build Coastguard Worker return boolAll(logicalOr(logicalAnd(greaterThanEqual(result, minVal), lessThanEqual(result, maxVal)),
227*35238bceSAndroid Build Coastguard Worker logicalNot(prec.colorMask)));
228*35238bceSAndroid Build Coastguard Worker }
229*35238bceSAndroid Build Coastguard Worker
isInColorBounds(const LookupPrecision & prec,const ColorLine & line0,const ColorLine & line1,const Vec4 & result)230*35238bceSAndroid Build Coastguard Worker static bool isInColorBounds(const LookupPrecision &prec, const ColorLine &line0, const ColorLine &line1,
231*35238bceSAndroid Build Coastguard Worker const Vec4 &result)
232*35238bceSAndroid Build Coastguard Worker {
233*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 minVal = min(min(line0), min(line1)) - prec.colorThreshold;
234*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 maxVal = max(max(line0), max(line1)) + prec.colorThreshold;
235*35238bceSAndroid Build Coastguard Worker return boolAll(logicalOr(logicalAnd(greaterThanEqual(result, minVal), lessThanEqual(result, maxVal)),
236*35238bceSAndroid Build Coastguard Worker logicalNot(prec.colorMask)));
237*35238bceSAndroid Build Coastguard Worker }
238*35238bceSAndroid Build Coastguard Worker
isInColorBounds(const LookupPrecision & prec,const ColorQuad & quad00,const ColorQuad & quad01,const ColorQuad & quad10,const ColorQuad & quad11,const Vec4 & result)239*35238bceSAndroid Build Coastguard Worker static bool isInColorBounds(const LookupPrecision &prec, const ColorQuad &quad00, const ColorQuad &quad01,
240*35238bceSAndroid Build Coastguard Worker const ColorQuad &quad10, const ColorQuad &quad11, const Vec4 &result)
241*35238bceSAndroid Build Coastguard Worker {
242*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 minVal = min(min(quad00), min(min(quad01), min(min(quad10), min(quad11)))) - prec.colorThreshold;
243*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 maxVal = max(max(quad00), max(max(quad01), max(max(quad10), max(quad11)))) + prec.colorThreshold;
244*35238bceSAndroid Build Coastguard Worker return boolAll(logicalOr(logicalAnd(greaterThanEqual(result, minVal), lessThanEqual(result, maxVal)),
245*35238bceSAndroid Build Coastguard Worker logicalNot(prec.colorMask)));
246*35238bceSAndroid Build Coastguard Worker }
247*35238bceSAndroid Build Coastguard Worker
248*35238bceSAndroid Build Coastguard Worker // Range search utilities
249*35238bceSAndroid Build Coastguard Worker
isLinearRangeValid(const LookupPrecision & prec,const Vec4 & c0,const Vec4 & c1,const Vec2 & fBounds,const Vec4 & result)250*35238bceSAndroid Build Coastguard Worker static bool isLinearRangeValid(const LookupPrecision &prec, const Vec4 &c0, const Vec4 &c1, const Vec2 &fBounds,
251*35238bceSAndroid Build Coastguard Worker const Vec4 &result)
252*35238bceSAndroid Build Coastguard Worker {
253*35238bceSAndroid Build Coastguard Worker // This is basically line segment - AABB test. Valid interpolation line is checked
254*35238bceSAndroid Build Coastguard Worker // against result AABB constructed by applying threshold.
255*35238bceSAndroid Build Coastguard Worker
256*35238bceSAndroid Build Coastguard Worker const Vec4 i0 = c0 * (1.0f - fBounds[0]) + c1 * fBounds[0];
257*35238bceSAndroid Build Coastguard Worker const Vec4 i1 = c0 * (1.0f - fBounds[1]) + c1 * fBounds[1];
258*35238bceSAndroid Build Coastguard Worker const Vec4 rMin = result - prec.colorThreshold;
259*35238bceSAndroid Build Coastguard Worker const Vec4 rMax = result + prec.colorThreshold;
260*35238bceSAndroid Build Coastguard Worker bool allIntersect = true;
261*35238bceSAndroid Build Coastguard Worker
262*35238bceSAndroid Build Coastguard Worker // Algorithm: For each component check whether segment endpoints are inside, or intersect with slab.
263*35238bceSAndroid Build Coastguard Worker // If all intersect or are inside, line segment intersects the whole 4D AABB.
264*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < 4; compNdx++)
265*35238bceSAndroid Build Coastguard Worker {
266*35238bceSAndroid Build Coastguard Worker if (!prec.colorMask[compNdx])
267*35238bceSAndroid Build Coastguard Worker continue;
268*35238bceSAndroid Build Coastguard Worker
269*35238bceSAndroid Build Coastguard Worker // Signs for both bounds: false = left, true = right.
270*35238bceSAndroid Build Coastguard Worker const bool sMin0 = i0[compNdx] >= rMin[compNdx];
271*35238bceSAndroid Build Coastguard Worker const bool sMin1 = i1[compNdx] >= rMin[compNdx];
272*35238bceSAndroid Build Coastguard Worker const bool sMax0 = i0[compNdx] > rMax[compNdx];
273*35238bceSAndroid Build Coastguard Worker const bool sMax1 = i1[compNdx] > rMax[compNdx];
274*35238bceSAndroid Build Coastguard Worker
275*35238bceSAndroid Build Coastguard Worker // If all signs are equal, line segment is outside bounds.
276*35238bceSAndroid Build Coastguard Worker if (sMin0 == sMin1 && sMin1 == sMax0 && sMax0 == sMax1)
277*35238bceSAndroid Build Coastguard Worker {
278*35238bceSAndroid Build Coastguard Worker allIntersect = false;
279*35238bceSAndroid Build Coastguard Worker break;
280*35238bceSAndroid Build Coastguard Worker }
281*35238bceSAndroid Build Coastguard Worker }
282*35238bceSAndroid Build Coastguard Worker
283*35238bceSAndroid Build Coastguard Worker return allIntersect;
284*35238bceSAndroid Build Coastguard Worker }
285*35238bceSAndroid Build Coastguard Worker
isBilinearRangeValid(const LookupPrecision & prec,const ColorQuad & quad,const Vec2 & xBounds,const Vec2 & yBounds,const float searchStep,const Vec4 & result)286*35238bceSAndroid Build Coastguard Worker static bool isBilinearRangeValid(const LookupPrecision &prec, const ColorQuad &quad, const Vec2 &xBounds,
287*35238bceSAndroid Build Coastguard Worker const Vec2 &yBounds, const float searchStep, const Vec4 &result)
288*35238bceSAndroid Build Coastguard Worker {
289*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds.x() <= xBounds.y());
290*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds.x() <= yBounds.y());
291*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds.x() + searchStep > xBounds.x()); // step is not effectively 0
292*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds.y() + searchStep > xBounds.y());
293*35238bceSAndroid Build Coastguard Worker
294*35238bceSAndroid Build Coastguard Worker if (!isInColorBounds(prec, quad, result))
295*35238bceSAndroid Build Coastguard Worker return false;
296*35238bceSAndroid Build Coastguard Worker
297*35238bceSAndroid Build Coastguard Worker for (float x = xBounds.x(); x < xBounds.y() + searchStep; x += searchStep)
298*35238bceSAndroid Build Coastguard Worker {
299*35238bceSAndroid Build Coastguard Worker const float a = de::min(x, xBounds.y());
300*35238bceSAndroid Build Coastguard Worker const Vec4 c0 = quad.p00 * (1.0f - a) + quad.p10 * a;
301*35238bceSAndroid Build Coastguard Worker const Vec4 c1 = quad.p01 * (1.0f - a) + quad.p11 * a;
302*35238bceSAndroid Build Coastguard Worker
303*35238bceSAndroid Build Coastguard Worker if (isLinearRangeValid(prec, c0, c1, yBounds, result))
304*35238bceSAndroid Build Coastguard Worker return true;
305*35238bceSAndroid Build Coastguard Worker }
306*35238bceSAndroid Build Coastguard Worker
307*35238bceSAndroid Build Coastguard Worker return false;
308*35238bceSAndroid Build Coastguard Worker }
309*35238bceSAndroid Build Coastguard Worker
isTrilinearRangeValid(const LookupPrecision & prec,const ColorQuad & quad0,const ColorQuad & quad1,const Vec2 & xBounds,const Vec2 & yBounds,const Vec2 & zBounds,const float searchStep,const Vec4 & result)310*35238bceSAndroid Build Coastguard Worker static bool isTrilinearRangeValid(const LookupPrecision &prec, const ColorQuad &quad0, const ColorQuad &quad1,
311*35238bceSAndroid Build Coastguard Worker const Vec2 &xBounds, const Vec2 &yBounds, const Vec2 &zBounds, const float searchStep,
312*35238bceSAndroid Build Coastguard Worker const Vec4 &result)
313*35238bceSAndroid Build Coastguard Worker {
314*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds.x() <= xBounds.y());
315*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds.x() <= yBounds.y());
316*35238bceSAndroid Build Coastguard Worker DE_ASSERT(zBounds.x() <= zBounds.y());
317*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds.x() + searchStep > xBounds.x()); // step is not effectively 0
318*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds.y() + searchStep > xBounds.y());
319*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds.x() + searchStep > yBounds.x());
320*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds.y() + searchStep > yBounds.y());
321*35238bceSAndroid Build Coastguard Worker
322*35238bceSAndroid Build Coastguard Worker if (!isInColorBounds(prec, quad0, quad1, result))
323*35238bceSAndroid Build Coastguard Worker return false;
324*35238bceSAndroid Build Coastguard Worker
325*35238bceSAndroid Build Coastguard Worker for (float x = xBounds.x(); x < xBounds.y() + searchStep; x += searchStep)
326*35238bceSAndroid Build Coastguard Worker {
327*35238bceSAndroid Build Coastguard Worker for (float y = yBounds.x(); y < yBounds.y() + searchStep; y += searchStep)
328*35238bceSAndroid Build Coastguard Worker {
329*35238bceSAndroid Build Coastguard Worker const float a = de::min(x, xBounds.y());
330*35238bceSAndroid Build Coastguard Worker const float b = de::min(y, yBounds.y());
331*35238bceSAndroid Build Coastguard Worker const Vec4 c0 = quad0.p00 * (1.0f - a) * (1.0f - b) + quad0.p10 * a * (1.0f - b) +
332*35238bceSAndroid Build Coastguard Worker quad0.p01 * (1.0f - a) * b + quad0.p11 * a * b;
333*35238bceSAndroid Build Coastguard Worker const Vec4 c1 = quad1.p00 * (1.0f - a) * (1.0f - b) + quad1.p10 * a * (1.0f - b) +
334*35238bceSAndroid Build Coastguard Worker quad1.p01 * (1.0f - a) * b + quad1.p11 * a * b;
335*35238bceSAndroid Build Coastguard Worker
336*35238bceSAndroid Build Coastguard Worker if (isLinearRangeValid(prec, c0, c1, zBounds, result))
337*35238bceSAndroid Build Coastguard Worker return true;
338*35238bceSAndroid Build Coastguard Worker }
339*35238bceSAndroid Build Coastguard Worker }
340*35238bceSAndroid Build Coastguard Worker
341*35238bceSAndroid Build Coastguard Worker return false;
342*35238bceSAndroid Build Coastguard Worker }
343*35238bceSAndroid Build Coastguard Worker
isReductionValid(const LookupPrecision & prec,const Vec4 & c0,const Vec4 & c1,tcu::Sampler::ReductionMode reductionMode,const Vec4 & result)344*35238bceSAndroid Build Coastguard Worker static bool isReductionValid(const LookupPrecision &prec, const Vec4 &c0, const Vec4 &c1,
345*35238bceSAndroid Build Coastguard Worker tcu::Sampler::ReductionMode reductionMode, const Vec4 &result)
346*35238bceSAndroid Build Coastguard Worker {
347*35238bceSAndroid Build Coastguard Worker DE_ASSERT(reductionMode == tcu::Sampler::MIN || reductionMode == tcu::Sampler::MAX);
348*35238bceSAndroid Build Coastguard Worker
349*35238bceSAndroid Build Coastguard Worker const Vec4 color = (reductionMode == tcu::Sampler::MIN ? tcu::min(c0, c1) : tcu::max(c0, c1));
350*35238bceSAndroid Build Coastguard Worker
351*35238bceSAndroid Build Coastguard Worker return isColorValid(prec, color, result);
352*35238bceSAndroid Build Coastguard Worker }
353*35238bceSAndroid Build Coastguard Worker
isReductionValid(const LookupPrecision & prec,const ColorQuad & quad,tcu::Sampler::ReductionMode reductionMode,const Vec4 & result)354*35238bceSAndroid Build Coastguard Worker static bool isReductionValid(const LookupPrecision &prec, const ColorQuad &quad,
355*35238bceSAndroid Build Coastguard Worker tcu::Sampler::ReductionMode reductionMode, const Vec4 &result)
356*35238bceSAndroid Build Coastguard Worker {
357*35238bceSAndroid Build Coastguard Worker DE_ASSERT(reductionMode == tcu::Sampler::MIN || reductionMode == tcu::Sampler::MAX);
358*35238bceSAndroid Build Coastguard Worker
359*35238bceSAndroid Build Coastguard Worker const Vec4 c0 = (reductionMode == tcu::Sampler::MIN ? tcu::min(quad.p00, quad.p01) : tcu::max(quad.p00, quad.p01));
360*35238bceSAndroid Build Coastguard Worker const Vec4 c1 = (reductionMode == tcu::Sampler::MIN ? tcu::min(quad.p10, quad.p11) : tcu::max(quad.p10, quad.p11));
361*35238bceSAndroid Build Coastguard Worker
362*35238bceSAndroid Build Coastguard Worker return isReductionValid(prec, c0, c1, reductionMode, result);
363*35238bceSAndroid Build Coastguard Worker }
364*35238bceSAndroid Build Coastguard Worker
isReductionValid(const LookupPrecision & prec,const ColorQuad & quad0,const ColorQuad & quad1,tcu::Sampler::ReductionMode reductionMode,const Vec4 & result)365*35238bceSAndroid Build Coastguard Worker static bool isReductionValid(const LookupPrecision &prec, const ColorQuad &quad0, const ColorQuad &quad1,
366*35238bceSAndroid Build Coastguard Worker tcu::Sampler::ReductionMode reductionMode, const Vec4 &result)
367*35238bceSAndroid Build Coastguard Worker {
368*35238bceSAndroid Build Coastguard Worker DE_ASSERT(reductionMode == tcu::Sampler::MIN || reductionMode == tcu::Sampler::MAX);
369*35238bceSAndroid Build Coastguard Worker
370*35238bceSAndroid Build Coastguard Worker const ColorQuad quad = {
371*35238bceSAndroid Build Coastguard Worker reductionMode == tcu::Sampler::MIN ? tcu::min(quad0.p00, quad1.p00) : tcu::max(quad0.p00, quad1.p00), // p00
372*35238bceSAndroid Build Coastguard Worker reductionMode == tcu::Sampler::MIN ? tcu::min(quad0.p01, quad1.p01) : tcu::max(quad0.p01, quad1.p01), // p01
373*35238bceSAndroid Build Coastguard Worker reductionMode == tcu::Sampler::MIN ? tcu::min(quad0.p10, quad1.p10) : tcu::max(quad0.p10, quad1.p10), // p10
374*35238bceSAndroid Build Coastguard Worker reductionMode == tcu::Sampler::MIN ? tcu::min(quad0.p11, quad1.p11) : tcu::max(quad0.p11, quad1.p11), // p11
375*35238bceSAndroid Build Coastguard Worker };
376*35238bceSAndroid Build Coastguard Worker
377*35238bceSAndroid Build Coastguard Worker return isReductionValid(prec, quad, reductionMode, result);
378*35238bceSAndroid Build Coastguard Worker }
379*35238bceSAndroid Build Coastguard Worker
is1DTrilinearFilterResultValid(const LookupPrecision & prec,const ColorLine & line0,const ColorLine & line1,const Vec2 & xBounds0,const Vec2 & xBounds1,const Vec2 & zBounds,const float searchStep,const Vec4 & result)380*35238bceSAndroid Build Coastguard Worker static bool is1DTrilinearFilterResultValid(const LookupPrecision &prec, const ColorLine &line0, const ColorLine &line1,
381*35238bceSAndroid Build Coastguard Worker const Vec2 &xBounds0, const Vec2 &xBounds1, const Vec2 &zBounds,
382*35238bceSAndroid Build Coastguard Worker const float searchStep, const Vec4 &result)
383*35238bceSAndroid Build Coastguard Worker {
384*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds0.x() <= xBounds0.y());
385*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds1.x() <= xBounds1.y());
386*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds0.x() + searchStep > xBounds0.x()); // step is not effectively 0
387*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds0.y() + searchStep > xBounds0.y());
388*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds1.x() + searchStep > xBounds1.x());
389*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds1.y() + searchStep > xBounds1.y());
390*35238bceSAndroid Build Coastguard Worker
391*35238bceSAndroid Build Coastguard Worker if (!isInColorBounds(prec, line0, line1, result))
392*35238bceSAndroid Build Coastguard Worker return false;
393*35238bceSAndroid Build Coastguard Worker
394*35238bceSAndroid Build Coastguard Worker for (float x0 = xBounds0.x(); x0 < xBounds0.y() + searchStep; x0 += searchStep)
395*35238bceSAndroid Build Coastguard Worker {
396*35238bceSAndroid Build Coastguard Worker const float a0 = de::min(x0, xBounds0.y());
397*35238bceSAndroid Build Coastguard Worker const Vec4 c0 = line0.p0 * (1.0f - a0) + line0.p1 * a0;
398*35238bceSAndroid Build Coastguard Worker
399*35238bceSAndroid Build Coastguard Worker for (float x1 = xBounds1.x(); x1 <= xBounds1.y(); x1 += searchStep)
400*35238bceSAndroid Build Coastguard Worker {
401*35238bceSAndroid Build Coastguard Worker const float a1 = de::min(x1, xBounds1.y());
402*35238bceSAndroid Build Coastguard Worker const Vec4 c1 = line1.p0 * (1.0f - a1) + line1.p1 * a1;
403*35238bceSAndroid Build Coastguard Worker
404*35238bceSAndroid Build Coastguard Worker if (isLinearRangeValid(prec, c0, c1, zBounds, result))
405*35238bceSAndroid Build Coastguard Worker return true;
406*35238bceSAndroid Build Coastguard Worker }
407*35238bceSAndroid Build Coastguard Worker }
408*35238bceSAndroid Build Coastguard Worker
409*35238bceSAndroid Build Coastguard Worker return false;
410*35238bceSAndroid Build Coastguard Worker }
411*35238bceSAndroid Build Coastguard Worker
is2DTrilinearFilterResultValid(const LookupPrecision & prec,const ColorQuad & quad0,const ColorQuad & quad1,const Vec2 & xBounds0,const Vec2 & yBounds0,const Vec2 & xBounds1,const Vec2 & yBounds1,const Vec2 & zBounds,const float searchStep,const Vec4 & result)412*35238bceSAndroid Build Coastguard Worker static bool is2DTrilinearFilterResultValid(const LookupPrecision &prec, const ColorQuad &quad0, const ColorQuad &quad1,
413*35238bceSAndroid Build Coastguard Worker const Vec2 &xBounds0, const Vec2 &yBounds0, const Vec2 &xBounds1,
414*35238bceSAndroid Build Coastguard Worker const Vec2 &yBounds1, const Vec2 &zBounds, const float searchStep,
415*35238bceSAndroid Build Coastguard Worker const Vec4 &result)
416*35238bceSAndroid Build Coastguard Worker {
417*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds0.x() <= xBounds0.y());
418*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds0.x() <= yBounds0.y());
419*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds1.x() <= xBounds1.y());
420*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds1.x() <= yBounds1.y());
421*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds0.x() + searchStep > xBounds0.x()); // step is not effectively 0
422*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds0.y() + searchStep > xBounds0.y());
423*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds0.x() + searchStep > yBounds0.x());
424*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds0.y() + searchStep > yBounds0.y());
425*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds1.x() + searchStep > xBounds1.x());
426*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds1.y() + searchStep > xBounds1.y());
427*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds1.x() + searchStep > yBounds1.x());
428*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds1.y() + searchStep > yBounds1.y());
429*35238bceSAndroid Build Coastguard Worker
430*35238bceSAndroid Build Coastguard Worker if (!isInColorBounds(prec, quad0, quad1, result))
431*35238bceSAndroid Build Coastguard Worker return false;
432*35238bceSAndroid Build Coastguard Worker
433*35238bceSAndroid Build Coastguard Worker for (float x0 = xBounds0.x(); x0 < xBounds0.y() + searchStep; x0 += searchStep)
434*35238bceSAndroid Build Coastguard Worker {
435*35238bceSAndroid Build Coastguard Worker for (float y0 = yBounds0.x(); y0 < yBounds0.y() + searchStep; y0 += searchStep)
436*35238bceSAndroid Build Coastguard Worker {
437*35238bceSAndroid Build Coastguard Worker const float a0 = de::min(x0, xBounds0.y());
438*35238bceSAndroid Build Coastguard Worker const float b0 = de::min(y0, yBounds0.y());
439*35238bceSAndroid Build Coastguard Worker const Vec4 c0 = quad0.p00 * (1.0f - a0) * (1.0f - b0) + quad0.p10 * a0 * (1.0f - b0) +
440*35238bceSAndroid Build Coastguard Worker quad0.p01 * (1.0f - a0) * b0 + quad0.p11 * a0 * b0;
441*35238bceSAndroid Build Coastguard Worker
442*35238bceSAndroid Build Coastguard Worker for (float x1 = xBounds1.x(); x1 <= xBounds1.y(); x1 += searchStep)
443*35238bceSAndroid Build Coastguard Worker {
444*35238bceSAndroid Build Coastguard Worker for (float y1 = yBounds1.x(); y1 <= yBounds1.y(); y1 += searchStep)
445*35238bceSAndroid Build Coastguard Worker {
446*35238bceSAndroid Build Coastguard Worker const float a1 = de::min(x1, xBounds1.y());
447*35238bceSAndroid Build Coastguard Worker const float b1 = de::min(y1, yBounds1.y());
448*35238bceSAndroid Build Coastguard Worker const Vec4 c1 = quad1.p00 * (1.0f - a1) * (1.0f - b1) + quad1.p10 * a1 * (1.0f - b1) +
449*35238bceSAndroid Build Coastguard Worker quad1.p01 * (1.0f - a1) * b1 + quad1.p11 * a1 * b1;
450*35238bceSAndroid Build Coastguard Worker
451*35238bceSAndroid Build Coastguard Worker if (isLinearRangeValid(prec, c0, c1, zBounds, result))
452*35238bceSAndroid Build Coastguard Worker return true;
453*35238bceSAndroid Build Coastguard Worker }
454*35238bceSAndroid Build Coastguard Worker }
455*35238bceSAndroid Build Coastguard Worker }
456*35238bceSAndroid Build Coastguard Worker }
457*35238bceSAndroid Build Coastguard Worker
458*35238bceSAndroid Build Coastguard Worker return false;
459*35238bceSAndroid Build Coastguard Worker }
460*35238bceSAndroid Build Coastguard Worker
is3DTrilinearFilterResultValid(const LookupPrecision & prec,const ColorQuad & quad00,const ColorQuad & quad01,const ColorQuad & quad10,const ColorQuad & quad11,const Vec2 & xBounds0,const Vec2 & yBounds0,const Vec2 & zBounds0,const Vec2 & xBounds1,const Vec2 & yBounds1,const Vec2 & zBounds1,const Vec2 & wBounds,const float searchStep,const Vec4 & result)461*35238bceSAndroid Build Coastguard Worker static bool is3DTrilinearFilterResultValid(const LookupPrecision &prec, const ColorQuad &quad00,
462*35238bceSAndroid Build Coastguard Worker const ColorQuad &quad01, const ColorQuad &quad10, const ColorQuad &quad11,
463*35238bceSAndroid Build Coastguard Worker const Vec2 &xBounds0, const Vec2 &yBounds0, const Vec2 &zBounds0,
464*35238bceSAndroid Build Coastguard Worker const Vec2 &xBounds1, const Vec2 &yBounds1, const Vec2 &zBounds1,
465*35238bceSAndroid Build Coastguard Worker const Vec2 &wBounds, const float searchStep, const Vec4 &result)
466*35238bceSAndroid Build Coastguard Worker {
467*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds0.x() <= xBounds0.y());
468*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds0.x() <= yBounds0.y());
469*35238bceSAndroid Build Coastguard Worker DE_ASSERT(zBounds0.x() <= zBounds0.y());
470*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds1.x() <= xBounds1.y());
471*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds1.x() <= yBounds1.y());
472*35238bceSAndroid Build Coastguard Worker DE_ASSERT(zBounds1.x() <= zBounds1.y());
473*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds0.x() + searchStep > xBounds0.x()); // step is not effectively 0
474*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds0.y() + searchStep > xBounds0.y());
475*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds0.x() + searchStep > yBounds0.x());
476*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds0.y() + searchStep > yBounds0.y());
477*35238bceSAndroid Build Coastguard Worker DE_ASSERT(zBounds0.x() + searchStep > zBounds0.x());
478*35238bceSAndroid Build Coastguard Worker DE_ASSERT(zBounds0.y() + searchStep > zBounds0.y());
479*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds1.x() + searchStep > xBounds1.x());
480*35238bceSAndroid Build Coastguard Worker DE_ASSERT(xBounds1.y() + searchStep > xBounds1.y());
481*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds1.x() + searchStep > yBounds1.x());
482*35238bceSAndroid Build Coastguard Worker DE_ASSERT(yBounds1.y() + searchStep > yBounds1.y());
483*35238bceSAndroid Build Coastguard Worker DE_ASSERT(zBounds1.x() + searchStep > zBounds1.x());
484*35238bceSAndroid Build Coastguard Worker DE_ASSERT(zBounds1.y() + searchStep > zBounds1.y());
485*35238bceSAndroid Build Coastguard Worker
486*35238bceSAndroid Build Coastguard Worker if (!isInColorBounds(prec, quad00, quad01, quad10, quad11, result))
487*35238bceSAndroid Build Coastguard Worker return false;
488*35238bceSAndroid Build Coastguard Worker
489*35238bceSAndroid Build Coastguard Worker for (float x0 = xBounds0.x(); x0 < xBounds0.y() + searchStep; x0 += searchStep)
490*35238bceSAndroid Build Coastguard Worker {
491*35238bceSAndroid Build Coastguard Worker for (float y0 = yBounds0.x(); y0 < yBounds0.y() + searchStep; y0 += searchStep)
492*35238bceSAndroid Build Coastguard Worker {
493*35238bceSAndroid Build Coastguard Worker const float a0 = de::min(x0, xBounds0.y());
494*35238bceSAndroid Build Coastguard Worker const float b0 = de::min(y0, yBounds0.y());
495*35238bceSAndroid Build Coastguard Worker const Vec4 c00 = quad00.p00 * (1.0f - a0) * (1.0f - b0) + quad00.p10 * a0 * (1.0f - b0) +
496*35238bceSAndroid Build Coastguard Worker quad00.p01 * (1.0f - a0) * b0 + quad00.p11 * a0 * b0;
497*35238bceSAndroid Build Coastguard Worker const Vec4 c01 = quad01.p00 * (1.0f - a0) * (1.0f - b0) + quad01.p10 * a0 * (1.0f - b0) +
498*35238bceSAndroid Build Coastguard Worker quad01.p01 * (1.0f - a0) * b0 + quad01.p11 * a0 * b0;
499*35238bceSAndroid Build Coastguard Worker
500*35238bceSAndroid Build Coastguard Worker for (float z0 = zBounds0.x(); z0 < zBounds0.y() + searchStep; z0 += searchStep)
501*35238bceSAndroid Build Coastguard Worker {
502*35238bceSAndroid Build Coastguard Worker const float c0 = de::min(z0, zBounds0.y());
503*35238bceSAndroid Build Coastguard Worker const Vec4 cz0 = c00 * (1.0f - c0) + c01 * c0;
504*35238bceSAndroid Build Coastguard Worker
505*35238bceSAndroid Build Coastguard Worker for (float x1 = xBounds1.x(); x1 < xBounds1.y() + searchStep; x1 += searchStep)
506*35238bceSAndroid Build Coastguard Worker {
507*35238bceSAndroid Build Coastguard Worker for (float y1 = yBounds1.x(); y1 < yBounds1.y() + searchStep; y1 += searchStep)
508*35238bceSAndroid Build Coastguard Worker {
509*35238bceSAndroid Build Coastguard Worker const float a1 = de::min(x1, xBounds1.y());
510*35238bceSAndroid Build Coastguard Worker const float b1 = de::min(y1, yBounds1.y());
511*35238bceSAndroid Build Coastguard Worker const Vec4 c10 = quad10.p00 * (1.0f - a1) * (1.0f - b1) + quad10.p10 * a1 * (1.0f - b1) +
512*35238bceSAndroid Build Coastguard Worker quad10.p01 * (1.0f - a1) * b1 + quad10.p11 * a1 * b1;
513*35238bceSAndroid Build Coastguard Worker const Vec4 c11 = quad11.p00 * (1.0f - a1) * (1.0f - b1) + quad11.p10 * a1 * (1.0f - b1) +
514*35238bceSAndroid Build Coastguard Worker quad11.p01 * (1.0f - a1) * b1 + quad11.p11 * a1 * b1;
515*35238bceSAndroid Build Coastguard Worker
516*35238bceSAndroid Build Coastguard Worker for (float z1 = zBounds1.x(); z1 < zBounds1.y() + searchStep; z1 += searchStep)
517*35238bceSAndroid Build Coastguard Worker {
518*35238bceSAndroid Build Coastguard Worker const float c1 = de::min(z1, zBounds1.y());
519*35238bceSAndroid Build Coastguard Worker const Vec4 cz1 = c10 * (1.0f - c1) + c11 * c1;
520*35238bceSAndroid Build Coastguard Worker
521*35238bceSAndroid Build Coastguard Worker if (isLinearRangeValid(prec, cz0, cz1, wBounds, result))
522*35238bceSAndroid Build Coastguard Worker return true;
523*35238bceSAndroid Build Coastguard Worker }
524*35238bceSAndroid Build Coastguard Worker }
525*35238bceSAndroid Build Coastguard Worker }
526*35238bceSAndroid Build Coastguard Worker }
527*35238bceSAndroid Build Coastguard Worker }
528*35238bceSAndroid Build Coastguard Worker }
529*35238bceSAndroid Build Coastguard Worker
530*35238bceSAndroid Build Coastguard Worker return false;
531*35238bceSAndroid Build Coastguard Worker }
532*35238bceSAndroid Build Coastguard Worker
533*35238bceSAndroid Build Coastguard Worker template <typename PrecType, typename ScalarType>
isNearestSampleResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const PrecType & prec,const float coordX,const int coordY,const Vector<ScalarType,4> & result)534*35238bceSAndroid Build Coastguard Worker static bool isNearestSampleResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
535*35238bceSAndroid Build Coastguard Worker const PrecType &prec, const float coordX, const int coordY,
536*35238bceSAndroid Build Coastguard Worker const Vector<ScalarType, 4> &result)
537*35238bceSAndroid Build Coastguard Worker {
538*35238bceSAndroid Build Coastguard Worker DE_ASSERT(level.getDepth() == 1);
539*35238bceSAndroid Build Coastguard Worker
540*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coordX,
541*35238bceSAndroid Build Coastguard Worker prec.coordBits.x(), prec.uvwBits.x());
542*35238bceSAndroid Build Coastguard Worker
543*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x());
544*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y());
545*35238bceSAndroid Build Coastguard Worker
546*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
547*35238bceSAndroid Build Coastguard Worker {
548*35238bceSAndroid Build Coastguard Worker const int x = wrap(sampler.wrapS, i, level.getWidth());
549*35238bceSAndroid Build Coastguard Worker const Vector<ScalarType, 4> color = lookup<ScalarType>(level, sampler, x, coordY, 0);
550*35238bceSAndroid Build Coastguard Worker
551*35238bceSAndroid Build Coastguard Worker if (isColorValid(prec, color, result))
552*35238bceSAndroid Build Coastguard Worker return true;
553*35238bceSAndroid Build Coastguard Worker }
554*35238bceSAndroid Build Coastguard Worker
555*35238bceSAndroid Build Coastguard Worker return false;
556*35238bceSAndroid Build Coastguard Worker }
557*35238bceSAndroid Build Coastguard Worker
558*35238bceSAndroid Build Coastguard Worker template <typename PrecType, typename ScalarType>
isNearestSampleResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const PrecType & prec,const Vec2 & coord,const int coordZ,const Vector<ScalarType,4> & result)559*35238bceSAndroid Build Coastguard Worker static bool isNearestSampleResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
560*35238bceSAndroid Build Coastguard Worker const PrecType &prec, const Vec2 &coord, const int coordZ,
561*35238bceSAndroid Build Coastguard Worker const Vector<ScalarType, 4> &result)
562*35238bceSAndroid Build Coastguard Worker {
563*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord.x(),
564*35238bceSAndroid Build Coastguard Worker prec.coordBits.x(), prec.uvwBits.x());
565*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord.y(),
566*35238bceSAndroid Build Coastguard Worker prec.coordBits.y(), prec.uvwBits.y());
567*35238bceSAndroid Build Coastguard Worker
568*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
569*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x());
570*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y());
571*35238bceSAndroid Build Coastguard Worker const int minJ = deFloorFloatToInt32(vBounds.x());
572*35238bceSAndroid Build Coastguard Worker const int maxJ = deFloorFloatToInt32(vBounds.y());
573*35238bceSAndroid Build Coastguard Worker
574*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.
575*35238bceSAndroid Build Coastguard Worker
576*35238bceSAndroid Build Coastguard Worker for (int j = minJ; j <= maxJ; j++)
577*35238bceSAndroid Build Coastguard Worker {
578*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
579*35238bceSAndroid Build Coastguard Worker {
580*35238bceSAndroid Build Coastguard Worker const int x = wrap(sampler.wrapS, i, level.getWidth());
581*35238bceSAndroid Build Coastguard Worker const int y = wrap(sampler.wrapT, j, level.getHeight());
582*35238bceSAndroid Build Coastguard Worker const Vector<ScalarType, 4> color = lookup<ScalarType>(level, sampler, x, y, coordZ);
583*35238bceSAndroid Build Coastguard Worker
584*35238bceSAndroid Build Coastguard Worker if (isColorValid(prec, color, result))
585*35238bceSAndroid Build Coastguard Worker return true;
586*35238bceSAndroid Build Coastguard Worker }
587*35238bceSAndroid Build Coastguard Worker }
588*35238bceSAndroid Build Coastguard Worker
589*35238bceSAndroid Build Coastguard Worker return false;
590*35238bceSAndroid Build Coastguard Worker }
591*35238bceSAndroid Build Coastguard Worker
592*35238bceSAndroid Build Coastguard Worker template <typename PrecType, typename ScalarType>
isNearestSampleResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const PrecType & prec,const Vec3 & coord,const Vector<ScalarType,4> & result)593*35238bceSAndroid Build Coastguard Worker static bool isNearestSampleResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
594*35238bceSAndroid Build Coastguard Worker const PrecType &prec, const Vec3 &coord, const Vector<ScalarType, 4> &result)
595*35238bceSAndroid Build Coastguard Worker {
596*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord.x(),
597*35238bceSAndroid Build Coastguard Worker prec.coordBits.x(), prec.uvwBits.x());
598*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord.y(),
599*35238bceSAndroid Build Coastguard Worker prec.coordBits.y(), prec.uvwBits.y());
600*35238bceSAndroid Build Coastguard Worker const Vec2 wBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getDepth(), coord.z(),
601*35238bceSAndroid Build Coastguard Worker prec.coordBits.z(), prec.uvwBits.z());
602*35238bceSAndroid Build Coastguard Worker
603*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
604*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x());
605*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y());
606*35238bceSAndroid Build Coastguard Worker const int minJ = deFloorFloatToInt32(vBounds.x());
607*35238bceSAndroid Build Coastguard Worker const int maxJ = deFloorFloatToInt32(vBounds.y());
608*35238bceSAndroid Build Coastguard Worker const int minK = deFloorFloatToInt32(wBounds.x());
609*35238bceSAndroid Build Coastguard Worker const int maxK = deFloorFloatToInt32(wBounds.y());
610*35238bceSAndroid Build Coastguard Worker
611*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.
612*35238bceSAndroid Build Coastguard Worker
613*35238bceSAndroid Build Coastguard Worker for (int k = minK; k <= maxK; k++)
614*35238bceSAndroid Build Coastguard Worker {
615*35238bceSAndroid Build Coastguard Worker for (int j = minJ; j <= maxJ; j++)
616*35238bceSAndroid Build Coastguard Worker {
617*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
618*35238bceSAndroid Build Coastguard Worker {
619*35238bceSAndroid Build Coastguard Worker const int x = wrap(sampler.wrapS, i, level.getWidth());
620*35238bceSAndroid Build Coastguard Worker const int y = wrap(sampler.wrapT, j, level.getHeight());
621*35238bceSAndroid Build Coastguard Worker const int z = wrap(sampler.wrapR, k, level.getDepth());
622*35238bceSAndroid Build Coastguard Worker const Vector<ScalarType, 4> color = lookup<ScalarType>(level, sampler, x, y, z);
623*35238bceSAndroid Build Coastguard Worker
624*35238bceSAndroid Build Coastguard Worker if (isColorValid(prec, color, result))
625*35238bceSAndroid Build Coastguard Worker return true;
626*35238bceSAndroid Build Coastguard Worker }
627*35238bceSAndroid Build Coastguard Worker }
628*35238bceSAndroid Build Coastguard Worker }
629*35238bceSAndroid Build Coastguard Worker
630*35238bceSAndroid Build Coastguard Worker return false;
631*35238bceSAndroid Build Coastguard Worker }
632*35238bceSAndroid Build Coastguard Worker
isLinearSampleResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const LookupPrecision & prec,const float coordX,const int coordY,const Vec4 & result)633*35238bceSAndroid Build Coastguard Worker bool isLinearSampleResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler, const LookupPrecision &prec,
634*35238bceSAndroid Build Coastguard Worker const float coordX, const int coordY, const Vec4 &result)
635*35238bceSAndroid Build Coastguard Worker {
636*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coordX,
637*35238bceSAndroid Build Coastguard Worker prec.coordBits.x(), prec.uvwBits.x());
638*35238bceSAndroid Build Coastguard Worker
639*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x() - 0.5f);
640*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y() - 0.5f);
641*35238bceSAndroid Build Coastguard Worker
642*35238bceSAndroid Build Coastguard Worker const int w = level.getWidth();
643*35238bceSAndroid Build Coastguard Worker
644*35238bceSAndroid Build Coastguard Worker const TextureFormat format = level.getFormat();
645*35238bceSAndroid Build Coastguard Worker const TextureChannelClass texClass = getTextureChannelClass(format.type);
646*35238bceSAndroid Build Coastguard Worker
647*35238bceSAndroid Build Coastguard Worker DE_ASSERT(texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
648*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || texClass == TEXTURECHANNELCLASS_FLOATING_POINT ||
649*35238bceSAndroid Build Coastguard Worker sampler.reductionMode != Sampler::WEIGHTED_AVERAGE);
650*35238bceSAndroid Build Coastguard Worker
651*35238bceSAndroid Build Coastguard Worker DE_UNREF(texClass);
652*35238bceSAndroid Build Coastguard Worker DE_UNREF(format);
653*35238bceSAndroid Build Coastguard Worker
654*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
655*35238bceSAndroid Build Coastguard Worker {
656*35238bceSAndroid Build Coastguard Worker // Wrapped coordinates
657*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i, w);
658*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i + 1, w);
659*35238bceSAndroid Build Coastguard Worker
660*35238bceSAndroid Build Coastguard Worker // Bounds for filtering factors
661*35238bceSAndroid Build Coastguard Worker const float minA = de::clamp((uBounds.x() - 0.5f) - float(i), 0.0f, 1.0f);
662*35238bceSAndroid Build Coastguard Worker const float maxA = de::clamp((uBounds.y() - 0.5f) - float(i), 0.0f, 1.0f);
663*35238bceSAndroid Build Coastguard Worker
664*35238bceSAndroid Build Coastguard Worker const Vec4 colorA = lookup<float>(level, sampler, x0, coordY, 0);
665*35238bceSAndroid Build Coastguard Worker const Vec4 colorB = lookup<float>(level, sampler, x1, coordY, 0);
666*35238bceSAndroid Build Coastguard Worker
667*35238bceSAndroid Build Coastguard Worker if (sampler.reductionMode == Sampler::WEIGHTED_AVERAGE)
668*35238bceSAndroid Build Coastguard Worker {
669*35238bceSAndroid Build Coastguard Worker if (isLinearRangeValid(prec, colorA, colorB, Vec2(minA, maxA), result))
670*35238bceSAndroid Build Coastguard Worker return true;
671*35238bceSAndroid Build Coastguard Worker }
672*35238bceSAndroid Build Coastguard Worker else
673*35238bceSAndroid Build Coastguard Worker {
674*35238bceSAndroid Build Coastguard Worker if (isReductionValid(prec, colorA, colorB, sampler.reductionMode, result))
675*35238bceSAndroid Build Coastguard Worker return true;
676*35238bceSAndroid Build Coastguard Worker }
677*35238bceSAndroid Build Coastguard Worker }
678*35238bceSAndroid Build Coastguard Worker
679*35238bceSAndroid Build Coastguard Worker return false;
680*35238bceSAndroid Build Coastguard Worker }
681*35238bceSAndroid Build Coastguard Worker
isLinearSampleResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const LookupPrecision & prec,const Vec2 & coord,const int coordZ,const Vec4 & result)682*35238bceSAndroid Build Coastguard Worker bool isLinearSampleResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler, const LookupPrecision &prec,
683*35238bceSAndroid Build Coastguard Worker const Vec2 &coord, const int coordZ, const Vec4 &result)
684*35238bceSAndroid Build Coastguard Worker {
685*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord.x(),
686*35238bceSAndroid Build Coastguard Worker prec.coordBits.x(), prec.uvwBits.x());
687*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord.y(),
688*35238bceSAndroid Build Coastguard Worker prec.coordBits.y(), prec.uvwBits.y());
689*35238bceSAndroid Build Coastguard Worker
690*35238bceSAndroid Build Coastguard Worker // Integer coordinate bounds for (x0,y0) - without wrap mode
691*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x() - 0.5f);
692*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y() - 0.5f);
693*35238bceSAndroid Build Coastguard Worker const int minJ = deFloorFloatToInt32(vBounds.x() - 0.5f);
694*35238bceSAndroid Build Coastguard Worker const int maxJ = deFloorFloatToInt32(vBounds.y() - 0.5f);
695*35238bceSAndroid Build Coastguard Worker
696*35238bceSAndroid Build Coastguard Worker const int w = level.getWidth();
697*35238bceSAndroid Build Coastguard Worker const int h = level.getHeight();
698*35238bceSAndroid Build Coastguard Worker
699*35238bceSAndroid Build Coastguard Worker const TextureChannelClass texClass = getTextureChannelClass(level.getFormat().type);
700*35238bceSAndroid Build Coastguard Worker float searchStep = texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ?
701*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForUnorm(prec) :
702*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ?
703*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForSnorm(prec) :
704*35238bceSAndroid Build Coastguard Worker 0.0f; // Step is computed for floating-point quads based on texel values.
705*35238bceSAndroid Build Coastguard Worker
706*35238bceSAndroid Build Coastguard Worker DE_ASSERT(texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
707*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || texClass == TEXTURECHANNELCLASS_FLOATING_POINT ||
708*35238bceSAndroid Build Coastguard Worker sampler.reductionMode != Sampler::WEIGHTED_AVERAGE);
709*35238bceSAndroid Build Coastguard Worker
710*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.
711*35238bceSAndroid Build Coastguard Worker
712*35238bceSAndroid Build Coastguard Worker for (int j = minJ; j <= maxJ; j++)
713*35238bceSAndroid Build Coastguard Worker {
714*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
715*35238bceSAndroid Build Coastguard Worker {
716*35238bceSAndroid Build Coastguard Worker // Wrapped coordinates
717*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i, w);
718*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i + 1, w);
719*35238bceSAndroid Build Coastguard Worker const int y0 = wrap(sampler.wrapT, j, h);
720*35238bceSAndroid Build Coastguard Worker const int y1 = wrap(sampler.wrapT, j + 1, h);
721*35238bceSAndroid Build Coastguard Worker
722*35238bceSAndroid Build Coastguard Worker // Bounds for filtering factors
723*35238bceSAndroid Build Coastguard Worker const float minA = de::clamp((uBounds.x() - 0.5f) - float(i), 0.0f, 1.0f);
724*35238bceSAndroid Build Coastguard Worker const float maxA = de::clamp((uBounds.y() - 0.5f) - float(i), 0.0f, 1.0f);
725*35238bceSAndroid Build Coastguard Worker const float minB = de::clamp((vBounds.x() - 0.5f) - float(j), 0.0f, 1.0f);
726*35238bceSAndroid Build Coastguard Worker const float maxB = de::clamp((vBounds.y() - 0.5f) - float(j), 0.0f, 1.0f);
727*35238bceSAndroid Build Coastguard Worker
728*35238bceSAndroid Build Coastguard Worker ColorQuad quad;
729*35238bceSAndroid Build Coastguard Worker lookupQuad(quad, level, sampler, x0, x1, y0, y1, coordZ);
730*35238bceSAndroid Build Coastguard Worker
731*35238bceSAndroid Build Coastguard Worker if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
732*35238bceSAndroid Build Coastguard Worker searchStep = computeBilinearSearchStepFromFloatQuad(prec, quad);
733*35238bceSAndroid Build Coastguard Worker
734*35238bceSAndroid Build Coastguard Worker if (sampler.reductionMode == Sampler::WEIGHTED_AVERAGE)
735*35238bceSAndroid Build Coastguard Worker {
736*35238bceSAndroid Build Coastguard Worker if (isBilinearRangeValid(prec, quad, Vec2(minA, maxA), Vec2(minB, maxB), searchStep, result))
737*35238bceSAndroid Build Coastguard Worker return true;
738*35238bceSAndroid Build Coastguard Worker }
739*35238bceSAndroid Build Coastguard Worker else
740*35238bceSAndroid Build Coastguard Worker {
741*35238bceSAndroid Build Coastguard Worker if (isReductionValid(prec, quad, sampler.reductionMode, result))
742*35238bceSAndroid Build Coastguard Worker return true;
743*35238bceSAndroid Build Coastguard Worker }
744*35238bceSAndroid Build Coastguard Worker }
745*35238bceSAndroid Build Coastguard Worker }
746*35238bceSAndroid Build Coastguard Worker
747*35238bceSAndroid Build Coastguard Worker return false;
748*35238bceSAndroid Build Coastguard Worker }
749*35238bceSAndroid Build Coastguard Worker
isLinearSampleResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const LookupPrecision & prec,const Vec3 & coord,const Vec4 & result)750*35238bceSAndroid Build Coastguard Worker static bool isLinearSampleResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
751*35238bceSAndroid Build Coastguard Worker const LookupPrecision &prec, const Vec3 &coord, const Vec4 &result)
752*35238bceSAndroid Build Coastguard Worker {
753*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord.x(),
754*35238bceSAndroid Build Coastguard Worker prec.coordBits.x(), prec.uvwBits.x());
755*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord.y(),
756*35238bceSAndroid Build Coastguard Worker prec.coordBits.y(), prec.uvwBits.y());
757*35238bceSAndroid Build Coastguard Worker const Vec2 wBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getDepth(), coord.z(),
758*35238bceSAndroid Build Coastguard Worker prec.coordBits.z(), prec.uvwBits.z());
759*35238bceSAndroid Build Coastguard Worker
760*35238bceSAndroid Build Coastguard Worker // Integer coordinate bounds for (x0,y0) - without wrap mode
761*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x() - 0.5f);
762*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y() - 0.5f);
763*35238bceSAndroid Build Coastguard Worker const int minJ = deFloorFloatToInt32(vBounds.x() - 0.5f);
764*35238bceSAndroid Build Coastguard Worker const int maxJ = deFloorFloatToInt32(vBounds.y() - 0.5f);
765*35238bceSAndroid Build Coastguard Worker const int minK = deFloorFloatToInt32(wBounds.x() - 0.5f);
766*35238bceSAndroid Build Coastguard Worker const int maxK = deFloorFloatToInt32(wBounds.y() - 0.5f);
767*35238bceSAndroid Build Coastguard Worker
768*35238bceSAndroid Build Coastguard Worker const int w = level.getWidth();
769*35238bceSAndroid Build Coastguard Worker const int h = level.getHeight();
770*35238bceSAndroid Build Coastguard Worker const int d = level.getDepth();
771*35238bceSAndroid Build Coastguard Worker
772*35238bceSAndroid Build Coastguard Worker const TextureChannelClass texClass = getTextureChannelClass(level.getFormat().type);
773*35238bceSAndroid Build Coastguard Worker float searchStep = texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ?
774*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForUnorm(prec) :
775*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ?
776*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForSnorm(prec) :
777*35238bceSAndroid Build Coastguard Worker 0.0f; // Step is computed for floating-point quads based on texel values.
778*35238bceSAndroid Build Coastguard Worker
779*35238bceSAndroid Build Coastguard Worker DE_ASSERT(texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
780*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || texClass == TEXTURECHANNELCLASS_FLOATING_POINT ||
781*35238bceSAndroid Build Coastguard Worker sampler.reductionMode != Sampler::WEIGHTED_AVERAGE);
782*35238bceSAndroid Build Coastguard Worker
783*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.
784*35238bceSAndroid Build Coastguard Worker
785*35238bceSAndroid Build Coastguard Worker for (int k = minK; k <= maxK; k++)
786*35238bceSAndroid Build Coastguard Worker {
787*35238bceSAndroid Build Coastguard Worker for (int j = minJ; j <= maxJ; j++)
788*35238bceSAndroid Build Coastguard Worker {
789*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
790*35238bceSAndroid Build Coastguard Worker {
791*35238bceSAndroid Build Coastguard Worker // Wrapped coordinates
792*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i, w);
793*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i + 1, w);
794*35238bceSAndroid Build Coastguard Worker const int y0 = wrap(sampler.wrapT, j, h);
795*35238bceSAndroid Build Coastguard Worker const int y1 = wrap(sampler.wrapT, j + 1, h);
796*35238bceSAndroid Build Coastguard Worker const int z0 = wrap(sampler.wrapR, k, d);
797*35238bceSAndroid Build Coastguard Worker const int z1 = wrap(sampler.wrapR, k + 1, d);
798*35238bceSAndroid Build Coastguard Worker
799*35238bceSAndroid Build Coastguard Worker // Bounds for filtering factors
800*35238bceSAndroid Build Coastguard Worker const float minA = de::clamp((uBounds.x() - 0.5f) - float(i), 0.0f, 1.0f);
801*35238bceSAndroid Build Coastguard Worker const float maxA = de::clamp((uBounds.y() - 0.5f) - float(i), 0.0f, 1.0f);
802*35238bceSAndroid Build Coastguard Worker const float minB = de::clamp((vBounds.x() - 0.5f) - float(j), 0.0f, 1.0f);
803*35238bceSAndroid Build Coastguard Worker const float maxB = de::clamp((vBounds.y() - 0.5f) - float(j), 0.0f, 1.0f);
804*35238bceSAndroid Build Coastguard Worker const float minC = de::clamp((wBounds.x() - 0.5f) - float(k), 0.0f, 1.0f);
805*35238bceSAndroid Build Coastguard Worker const float maxC = de::clamp((wBounds.y() - 0.5f) - float(k), 0.0f, 1.0f);
806*35238bceSAndroid Build Coastguard Worker
807*35238bceSAndroid Build Coastguard Worker ColorQuad quad0, quad1;
808*35238bceSAndroid Build Coastguard Worker lookupQuad(quad0, level, sampler, x0, x1, y0, y1, z0);
809*35238bceSAndroid Build Coastguard Worker lookupQuad(quad1, level, sampler, x0, x1, y0, y1, z1);
810*35238bceSAndroid Build Coastguard Worker
811*35238bceSAndroid Build Coastguard Worker if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
812*35238bceSAndroid Build Coastguard Worker searchStep = de::min(computeBilinearSearchStepFromFloatQuad(prec, quad0),
813*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepFromFloatQuad(prec, quad1));
814*35238bceSAndroid Build Coastguard Worker
815*35238bceSAndroid Build Coastguard Worker if (sampler.reductionMode == Sampler::WEIGHTED_AVERAGE)
816*35238bceSAndroid Build Coastguard Worker {
817*35238bceSAndroid Build Coastguard Worker if (isTrilinearRangeValid(prec, quad0, quad1, Vec2(minA, maxA), Vec2(minB, maxB), Vec2(minC, maxC),
818*35238bceSAndroid Build Coastguard Worker searchStep, result))
819*35238bceSAndroid Build Coastguard Worker return true;
820*35238bceSAndroid Build Coastguard Worker }
821*35238bceSAndroid Build Coastguard Worker else
822*35238bceSAndroid Build Coastguard Worker {
823*35238bceSAndroid Build Coastguard Worker if (isReductionValid(prec, quad0, quad1, sampler.reductionMode, result))
824*35238bceSAndroid Build Coastguard Worker return true;
825*35238bceSAndroid Build Coastguard Worker }
826*35238bceSAndroid Build Coastguard Worker }
827*35238bceSAndroid Build Coastguard Worker }
828*35238bceSAndroid Build Coastguard Worker }
829*35238bceSAndroid Build Coastguard Worker
830*35238bceSAndroid Build Coastguard Worker return false;
831*35238bceSAndroid Build Coastguard Worker }
832*35238bceSAndroid Build Coastguard Worker
isNearestMipmapLinearSampleResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const LookupPrecision & prec,const float coord,const int coordY,const Vec2 & fBounds,const Vec4 & result)833*35238bceSAndroid Build Coastguard Worker static bool isNearestMipmapLinearSampleResultValid(const ConstPixelBufferAccess &level0,
834*35238bceSAndroid Build Coastguard Worker const ConstPixelBufferAccess &level1, const Sampler &sampler,
835*35238bceSAndroid Build Coastguard Worker const LookupPrecision &prec, const float coord, const int coordY,
836*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const Vec4 &result)
837*35238bceSAndroid Build Coastguard Worker {
838*35238bceSAndroid Build Coastguard Worker const int w0 = level0.getWidth();
839*35238bceSAndroid Build Coastguard Worker const int w1 = level1.getWidth();
840*35238bceSAndroid Build Coastguard Worker
841*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds0 =
842*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord, prec.coordBits.x(), prec.uvwBits.x());
843*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds1 =
844*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord, prec.coordBits.x(), prec.uvwBits.x());
845*35238bceSAndroid Build Coastguard Worker
846*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
847*35238bceSAndroid Build Coastguard Worker const int minI0 = deFloorFloatToInt32(uBounds0.x());
848*35238bceSAndroid Build Coastguard Worker const int maxI0 = deFloorFloatToInt32(uBounds0.y());
849*35238bceSAndroid Build Coastguard Worker const int minI1 = deFloorFloatToInt32(uBounds1.x());
850*35238bceSAndroid Build Coastguard Worker const int maxI1 = deFloorFloatToInt32(uBounds1.y());
851*35238bceSAndroid Build Coastguard Worker
852*35238bceSAndroid Build Coastguard Worker for (int i0 = minI0; i0 <= maxI0; i0++)
853*35238bceSAndroid Build Coastguard Worker {
854*35238bceSAndroid Build Coastguard Worker for (int i1 = minI1; i1 <= maxI1; i1++)
855*35238bceSAndroid Build Coastguard Worker {
856*35238bceSAndroid Build Coastguard Worker const Vec4 c0 = lookup<float>(level0, sampler, wrap(sampler.wrapS, i0, w0), coordY, 0);
857*35238bceSAndroid Build Coastguard Worker const Vec4 c1 = lookup<float>(level1, sampler, wrap(sampler.wrapS, i1, w1), coordY, 0);
858*35238bceSAndroid Build Coastguard Worker
859*35238bceSAndroid Build Coastguard Worker if (isLinearRangeValid(prec, c0, c1, fBounds, result))
860*35238bceSAndroid Build Coastguard Worker return true;
861*35238bceSAndroid Build Coastguard Worker }
862*35238bceSAndroid Build Coastguard Worker }
863*35238bceSAndroid Build Coastguard Worker
864*35238bceSAndroid Build Coastguard Worker return false;
865*35238bceSAndroid Build Coastguard Worker }
866*35238bceSAndroid Build Coastguard Worker
isNearestMipmapLinearSampleResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const LookupPrecision & prec,const Vec2 & coord,const int coordZ,const Vec2 & fBounds,const Vec4 & result)867*35238bceSAndroid Build Coastguard Worker static bool isNearestMipmapLinearSampleResultValid(const ConstPixelBufferAccess &level0,
868*35238bceSAndroid Build Coastguard Worker const ConstPixelBufferAccess &level1, const Sampler &sampler,
869*35238bceSAndroid Build Coastguard Worker const LookupPrecision &prec, const Vec2 &coord, const int coordZ,
870*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const Vec4 &result)
871*35238bceSAndroid Build Coastguard Worker {
872*35238bceSAndroid Build Coastguard Worker const int w0 = level0.getWidth();
873*35238bceSAndroid Build Coastguard Worker const int w1 = level1.getWidth();
874*35238bceSAndroid Build Coastguard Worker const int h0 = level0.getHeight();
875*35238bceSAndroid Build Coastguard Worker const int h1 = level1.getHeight();
876*35238bceSAndroid Build Coastguard Worker
877*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds0 =
878*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
879*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds1 =
880*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
881*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds0 =
882*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0, coord.y(), prec.coordBits.y(), prec.uvwBits.y());
883*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds1 =
884*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1, coord.y(), prec.coordBits.y(), prec.uvwBits.y());
885*35238bceSAndroid Build Coastguard Worker
886*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
887*35238bceSAndroid Build Coastguard Worker const int minI0 = deFloorFloatToInt32(uBounds0.x());
888*35238bceSAndroid Build Coastguard Worker const int maxI0 = deFloorFloatToInt32(uBounds0.y());
889*35238bceSAndroid Build Coastguard Worker const int minI1 = deFloorFloatToInt32(uBounds1.x());
890*35238bceSAndroid Build Coastguard Worker const int maxI1 = deFloorFloatToInt32(uBounds1.y());
891*35238bceSAndroid Build Coastguard Worker const int minJ0 = deFloorFloatToInt32(vBounds0.x());
892*35238bceSAndroid Build Coastguard Worker const int maxJ0 = deFloorFloatToInt32(vBounds0.y());
893*35238bceSAndroid Build Coastguard Worker const int minJ1 = deFloorFloatToInt32(vBounds1.x());
894*35238bceSAndroid Build Coastguard Worker const int maxJ1 = deFloorFloatToInt32(vBounds1.y());
895*35238bceSAndroid Build Coastguard Worker
896*35238bceSAndroid Build Coastguard Worker for (int j0 = minJ0; j0 <= maxJ0; j0++)
897*35238bceSAndroid Build Coastguard Worker {
898*35238bceSAndroid Build Coastguard Worker for (int i0 = minI0; i0 <= maxI0; i0++)
899*35238bceSAndroid Build Coastguard Worker {
900*35238bceSAndroid Build Coastguard Worker for (int j1 = minJ1; j1 <= maxJ1; j1++)
901*35238bceSAndroid Build Coastguard Worker {
902*35238bceSAndroid Build Coastguard Worker for (int i1 = minI1; i1 <= maxI1; i1++)
903*35238bceSAndroid Build Coastguard Worker {
904*35238bceSAndroid Build Coastguard Worker const Vec4 c0 = lookup<float>(level0, sampler, wrap(sampler.wrapS, i0, w0),
905*35238bceSAndroid Build Coastguard Worker wrap(sampler.wrapT, j0, h0), coordZ);
906*35238bceSAndroid Build Coastguard Worker const Vec4 c1 = lookup<float>(level1, sampler, wrap(sampler.wrapS, i1, w1),
907*35238bceSAndroid Build Coastguard Worker wrap(sampler.wrapT, j1, h1), coordZ);
908*35238bceSAndroid Build Coastguard Worker
909*35238bceSAndroid Build Coastguard Worker if (isLinearRangeValid(prec, c0, c1, fBounds, result))
910*35238bceSAndroid Build Coastguard Worker return true;
911*35238bceSAndroid Build Coastguard Worker }
912*35238bceSAndroid Build Coastguard Worker }
913*35238bceSAndroid Build Coastguard Worker }
914*35238bceSAndroid Build Coastguard Worker }
915*35238bceSAndroid Build Coastguard Worker
916*35238bceSAndroid Build Coastguard Worker return false;
917*35238bceSAndroid Build Coastguard Worker }
918*35238bceSAndroid Build Coastguard Worker
isNearestMipmapLinearSampleResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const LookupPrecision & prec,const Vec3 & coord,const Vec2 & fBounds,const Vec4 & result)919*35238bceSAndroid Build Coastguard Worker static bool isNearestMipmapLinearSampleResultValid(const ConstPixelBufferAccess &level0,
920*35238bceSAndroid Build Coastguard Worker const ConstPixelBufferAccess &level1, const Sampler &sampler,
921*35238bceSAndroid Build Coastguard Worker const LookupPrecision &prec, const Vec3 &coord, const Vec2 &fBounds,
922*35238bceSAndroid Build Coastguard Worker const Vec4 &result)
923*35238bceSAndroid Build Coastguard Worker {
924*35238bceSAndroid Build Coastguard Worker const int w0 = level0.getWidth();
925*35238bceSAndroid Build Coastguard Worker const int w1 = level1.getWidth();
926*35238bceSAndroid Build Coastguard Worker const int h0 = level0.getHeight();
927*35238bceSAndroid Build Coastguard Worker const int h1 = level1.getHeight();
928*35238bceSAndroid Build Coastguard Worker const int d0 = level0.getDepth();
929*35238bceSAndroid Build Coastguard Worker const int d1 = level1.getDepth();
930*35238bceSAndroid Build Coastguard Worker
931*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds0 =
932*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
933*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds1 =
934*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
935*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds0 =
936*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0, coord.y(), prec.coordBits.y(), prec.uvwBits.y());
937*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds1 =
938*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1, coord.y(), prec.coordBits.y(), prec.uvwBits.y());
939*35238bceSAndroid Build Coastguard Worker const Vec2 wBounds0 =
940*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, d0, coord.z(), prec.coordBits.z(), prec.uvwBits.z());
941*35238bceSAndroid Build Coastguard Worker const Vec2 wBounds1 =
942*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, d1, coord.z(), prec.coordBits.z(), prec.uvwBits.z());
943*35238bceSAndroid Build Coastguard Worker
944*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
945*35238bceSAndroid Build Coastguard Worker const int minI0 = deFloorFloatToInt32(uBounds0.x());
946*35238bceSAndroid Build Coastguard Worker const int maxI0 = deFloorFloatToInt32(uBounds0.y());
947*35238bceSAndroid Build Coastguard Worker const int minI1 = deFloorFloatToInt32(uBounds1.x());
948*35238bceSAndroid Build Coastguard Worker const int maxI1 = deFloorFloatToInt32(uBounds1.y());
949*35238bceSAndroid Build Coastguard Worker const int minJ0 = deFloorFloatToInt32(vBounds0.x());
950*35238bceSAndroid Build Coastguard Worker const int maxJ0 = deFloorFloatToInt32(vBounds0.y());
951*35238bceSAndroid Build Coastguard Worker const int minJ1 = deFloorFloatToInt32(vBounds1.x());
952*35238bceSAndroid Build Coastguard Worker const int maxJ1 = deFloorFloatToInt32(vBounds1.y());
953*35238bceSAndroid Build Coastguard Worker const int minK0 = deFloorFloatToInt32(wBounds0.x());
954*35238bceSAndroid Build Coastguard Worker const int maxK0 = deFloorFloatToInt32(wBounds0.y());
955*35238bceSAndroid Build Coastguard Worker const int minK1 = deFloorFloatToInt32(wBounds1.x());
956*35238bceSAndroid Build Coastguard Worker const int maxK1 = deFloorFloatToInt32(wBounds1.y());
957*35238bceSAndroid Build Coastguard Worker
958*35238bceSAndroid Build Coastguard Worker for (int k0 = minK0; k0 <= maxK0; k0++)
959*35238bceSAndroid Build Coastguard Worker {
960*35238bceSAndroid Build Coastguard Worker for (int j0 = minJ0; j0 <= maxJ0; j0++)
961*35238bceSAndroid Build Coastguard Worker {
962*35238bceSAndroid Build Coastguard Worker for (int i0 = minI0; i0 <= maxI0; i0++)
963*35238bceSAndroid Build Coastguard Worker {
964*35238bceSAndroid Build Coastguard Worker for (int k1 = minK1; k1 <= maxK1; k1++)
965*35238bceSAndroid Build Coastguard Worker {
966*35238bceSAndroid Build Coastguard Worker for (int j1 = minJ1; j1 <= maxJ1; j1++)
967*35238bceSAndroid Build Coastguard Worker {
968*35238bceSAndroid Build Coastguard Worker for (int i1 = minI1; i1 <= maxI1; i1++)
969*35238bceSAndroid Build Coastguard Worker {
970*35238bceSAndroid Build Coastguard Worker const Vec4 c0 = lookup<float>(level0, sampler, wrap(sampler.wrapS, i0, w0),
971*35238bceSAndroid Build Coastguard Worker wrap(sampler.wrapT, j0, h0), wrap(sampler.wrapR, k0, d0));
972*35238bceSAndroid Build Coastguard Worker const Vec4 c1 = lookup<float>(level1, sampler, wrap(sampler.wrapS, i1, w1),
973*35238bceSAndroid Build Coastguard Worker wrap(sampler.wrapT, j1, h1), wrap(sampler.wrapR, k1, d1));
974*35238bceSAndroid Build Coastguard Worker
975*35238bceSAndroid Build Coastguard Worker if (isLinearRangeValid(prec, c0, c1, fBounds, result))
976*35238bceSAndroid Build Coastguard Worker return true;
977*35238bceSAndroid Build Coastguard Worker }
978*35238bceSAndroid Build Coastguard Worker }
979*35238bceSAndroid Build Coastguard Worker }
980*35238bceSAndroid Build Coastguard Worker }
981*35238bceSAndroid Build Coastguard Worker }
982*35238bceSAndroid Build Coastguard Worker }
983*35238bceSAndroid Build Coastguard Worker
984*35238bceSAndroid Build Coastguard Worker return false;
985*35238bceSAndroid Build Coastguard Worker }
986*35238bceSAndroid Build Coastguard Worker
isLinearMipmapLinearSampleResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const LookupPrecision & prec,const float coordX,const int coordY,const Vec2 & fBounds,const Vec4 & result)987*35238bceSAndroid Build Coastguard Worker static bool isLinearMipmapLinearSampleResultValid(const ConstPixelBufferAccess &level0,
988*35238bceSAndroid Build Coastguard Worker const ConstPixelBufferAccess &level1, const Sampler &sampler,
989*35238bceSAndroid Build Coastguard Worker const LookupPrecision &prec, const float coordX, const int coordY,
990*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const Vec4 &result)
991*35238bceSAndroid Build Coastguard Worker {
992*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
993*35238bceSAndroid Build Coastguard Worker // Right now this allows pairing any two valid bilinear quads.
994*35238bceSAndroid Build Coastguard Worker
995*35238bceSAndroid Build Coastguard Worker const int w0 = level0.getWidth();
996*35238bceSAndroid Build Coastguard Worker const int w1 = level1.getWidth();
997*35238bceSAndroid Build Coastguard Worker
998*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds0 =
999*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coordX, prec.coordBits.x(), prec.uvwBits.x());
1000*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds1 =
1001*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coordX, prec.coordBits.x(), prec.uvwBits.x());
1002*35238bceSAndroid Build Coastguard Worker
1003*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
1004*35238bceSAndroid Build Coastguard Worker const int minI0 = deFloorFloatToInt32(uBounds0.x() - 0.5f);
1005*35238bceSAndroid Build Coastguard Worker const int maxI0 = deFloorFloatToInt32(uBounds0.y() - 0.5f);
1006*35238bceSAndroid Build Coastguard Worker const int minI1 = deFloorFloatToInt32(uBounds1.x() - 0.5f);
1007*35238bceSAndroid Build Coastguard Worker const int maxI1 = deFloorFloatToInt32(uBounds1.y() - 0.5f);
1008*35238bceSAndroid Build Coastguard Worker
1009*35238bceSAndroid Build Coastguard Worker const TextureChannelClass texClass = getTextureChannelClass(level0.getFormat().type);
1010*35238bceSAndroid Build Coastguard Worker const float cSearchStep = texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ?
1011*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForUnorm(prec) :
1012*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ?
1013*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForSnorm(prec) :
1014*35238bceSAndroid Build Coastguard Worker 0.0f; // Step is computed for floating-point quads based on texel values.
1015*35238bceSAndroid Build Coastguard Worker
1016*35238bceSAndroid Build Coastguard Worker DE_ASSERT(texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
1017*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || texClass == TEXTURECHANNELCLASS_FLOATING_POINT ||
1018*35238bceSAndroid Build Coastguard Worker sampler.reductionMode != Sampler::WEIGHTED_AVERAGE);
1019*35238bceSAndroid Build Coastguard Worker
1020*35238bceSAndroid Build Coastguard Worker for (int i0 = minI0; i0 <= maxI0; i0++)
1021*35238bceSAndroid Build Coastguard Worker {
1022*35238bceSAndroid Build Coastguard Worker ColorLine line0;
1023*35238bceSAndroid Build Coastguard Worker float searchStep0;
1024*35238bceSAndroid Build Coastguard Worker
1025*35238bceSAndroid Build Coastguard Worker {
1026*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i0, w0);
1027*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i0 + 1, w0);
1028*35238bceSAndroid Build Coastguard Worker lookupLine(line0, level0, sampler, x0, x1, coordY);
1029*35238bceSAndroid Build Coastguard Worker
1030*35238bceSAndroid Build Coastguard Worker if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
1031*35238bceSAndroid Build Coastguard Worker searchStep0 = computeBilinearSearchStepFromFloatLine(prec, line0);
1032*35238bceSAndroid Build Coastguard Worker else
1033*35238bceSAndroid Build Coastguard Worker searchStep0 = cSearchStep;
1034*35238bceSAndroid Build Coastguard Worker }
1035*35238bceSAndroid Build Coastguard Worker
1036*35238bceSAndroid Build Coastguard Worker const float minA0 = de::clamp((uBounds0.x() - 0.5f) - float(i0), 0.0f, 1.0f);
1037*35238bceSAndroid Build Coastguard Worker const float maxA0 = de::clamp((uBounds0.y() - 0.5f) - float(i0), 0.0f, 1.0f);
1038*35238bceSAndroid Build Coastguard Worker
1039*35238bceSAndroid Build Coastguard Worker for (int i1 = minI1; i1 <= maxI1; i1++)
1040*35238bceSAndroid Build Coastguard Worker {
1041*35238bceSAndroid Build Coastguard Worker ColorLine line1;
1042*35238bceSAndroid Build Coastguard Worker float searchStep1;
1043*35238bceSAndroid Build Coastguard Worker
1044*35238bceSAndroid Build Coastguard Worker {
1045*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i1, w1);
1046*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i1 + 1, w1);
1047*35238bceSAndroid Build Coastguard Worker lookupLine(line1, level1, sampler, x0, x1, coordY);
1048*35238bceSAndroid Build Coastguard Worker
1049*35238bceSAndroid Build Coastguard Worker if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
1050*35238bceSAndroid Build Coastguard Worker searchStep1 = computeBilinearSearchStepFromFloatLine(prec, line1);
1051*35238bceSAndroid Build Coastguard Worker else
1052*35238bceSAndroid Build Coastguard Worker searchStep1 = cSearchStep;
1053*35238bceSAndroid Build Coastguard Worker }
1054*35238bceSAndroid Build Coastguard Worker
1055*35238bceSAndroid Build Coastguard Worker const float minA1 = de::clamp((uBounds1.x() - 0.5f) - float(i1), 0.0f, 1.0f);
1056*35238bceSAndroid Build Coastguard Worker const float maxA1 = de::clamp((uBounds1.y() - 0.5f) - float(i1), 0.0f, 1.0f);
1057*35238bceSAndroid Build Coastguard Worker
1058*35238bceSAndroid Build Coastguard Worker if (is1DTrilinearFilterResultValid(prec, line0, line1, Vec2(minA0, maxA0), Vec2(minA1, maxA1), fBounds,
1059*35238bceSAndroid Build Coastguard Worker de::min(searchStep0, searchStep1), result))
1060*35238bceSAndroid Build Coastguard Worker return true;
1061*35238bceSAndroid Build Coastguard Worker }
1062*35238bceSAndroid Build Coastguard Worker }
1063*35238bceSAndroid Build Coastguard Worker
1064*35238bceSAndroid Build Coastguard Worker return false;
1065*35238bceSAndroid Build Coastguard Worker }
1066*35238bceSAndroid Build Coastguard Worker
isLinearMipmapLinearSampleResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const LookupPrecision & prec,const Vec2 & coord,const int coordZ,const Vec2 & fBounds,const Vec4 & result)1067*35238bceSAndroid Build Coastguard Worker static bool isLinearMipmapLinearSampleResultValid(const ConstPixelBufferAccess &level0,
1068*35238bceSAndroid Build Coastguard Worker const ConstPixelBufferAccess &level1, const Sampler &sampler,
1069*35238bceSAndroid Build Coastguard Worker const LookupPrecision &prec, const Vec2 &coord, const int coordZ,
1070*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const Vec4 &result)
1071*35238bceSAndroid Build Coastguard Worker {
1072*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
1073*35238bceSAndroid Build Coastguard Worker // Right now this allows pairing any two valid bilinear quads.
1074*35238bceSAndroid Build Coastguard Worker
1075*35238bceSAndroid Build Coastguard Worker const int w0 = level0.getWidth();
1076*35238bceSAndroid Build Coastguard Worker const int w1 = level1.getWidth();
1077*35238bceSAndroid Build Coastguard Worker const int h0 = level0.getHeight();
1078*35238bceSAndroid Build Coastguard Worker const int h1 = level1.getHeight();
1079*35238bceSAndroid Build Coastguard Worker
1080*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds0 =
1081*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
1082*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds1 =
1083*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
1084*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds0 =
1085*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0, coord.y(), prec.coordBits.y(), prec.uvwBits.y());
1086*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds1 =
1087*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1, coord.y(), prec.coordBits.y(), prec.uvwBits.y());
1088*35238bceSAndroid Build Coastguard Worker
1089*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
1090*35238bceSAndroid Build Coastguard Worker const int minI0 = deFloorFloatToInt32(uBounds0.x() - 0.5f);
1091*35238bceSAndroid Build Coastguard Worker const int maxI0 = deFloorFloatToInt32(uBounds0.y() - 0.5f);
1092*35238bceSAndroid Build Coastguard Worker const int minI1 = deFloorFloatToInt32(uBounds1.x() - 0.5f);
1093*35238bceSAndroid Build Coastguard Worker const int maxI1 = deFloorFloatToInt32(uBounds1.y() - 0.5f);
1094*35238bceSAndroid Build Coastguard Worker const int minJ0 = deFloorFloatToInt32(vBounds0.x() - 0.5f);
1095*35238bceSAndroid Build Coastguard Worker const int maxJ0 = deFloorFloatToInt32(vBounds0.y() - 0.5f);
1096*35238bceSAndroid Build Coastguard Worker const int minJ1 = deFloorFloatToInt32(vBounds1.x() - 0.5f);
1097*35238bceSAndroid Build Coastguard Worker const int maxJ1 = deFloorFloatToInt32(vBounds1.y() - 0.5f);
1098*35238bceSAndroid Build Coastguard Worker
1099*35238bceSAndroid Build Coastguard Worker const TextureChannelClass texClass = getTextureChannelClass(level0.getFormat().type);
1100*35238bceSAndroid Build Coastguard Worker const float cSearchStep = texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ?
1101*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForUnorm(prec) :
1102*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ?
1103*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForSnorm(prec) :
1104*35238bceSAndroid Build Coastguard Worker 0.0f; // Step is computed for floating-point quads based on texel values.
1105*35238bceSAndroid Build Coastguard Worker
1106*35238bceSAndroid Build Coastguard Worker DE_ASSERT(texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
1107*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || texClass == TEXTURECHANNELCLASS_FLOATING_POINT ||
1108*35238bceSAndroid Build Coastguard Worker sampler.reductionMode != Sampler::WEIGHTED_AVERAGE);
1109*35238bceSAndroid Build Coastguard Worker
1110*35238bceSAndroid Build Coastguard Worker for (int j0 = minJ0; j0 <= maxJ0; j0++)
1111*35238bceSAndroid Build Coastguard Worker {
1112*35238bceSAndroid Build Coastguard Worker for (int i0 = minI0; i0 <= maxI0; i0++)
1113*35238bceSAndroid Build Coastguard Worker {
1114*35238bceSAndroid Build Coastguard Worker ColorQuad quad0;
1115*35238bceSAndroid Build Coastguard Worker float searchStep0;
1116*35238bceSAndroid Build Coastguard Worker
1117*35238bceSAndroid Build Coastguard Worker {
1118*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i0, w0);
1119*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i0 + 1, w0);
1120*35238bceSAndroid Build Coastguard Worker const int y0 = wrap(sampler.wrapT, j0, h0);
1121*35238bceSAndroid Build Coastguard Worker const int y1 = wrap(sampler.wrapT, j0 + 1, h0);
1122*35238bceSAndroid Build Coastguard Worker lookupQuad(quad0, level0, sampler, x0, x1, y0, y1, coordZ);
1123*35238bceSAndroid Build Coastguard Worker
1124*35238bceSAndroid Build Coastguard Worker if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
1125*35238bceSAndroid Build Coastguard Worker searchStep0 = computeBilinearSearchStepFromFloatQuad(prec, quad0);
1126*35238bceSAndroid Build Coastguard Worker else
1127*35238bceSAndroid Build Coastguard Worker searchStep0 = cSearchStep;
1128*35238bceSAndroid Build Coastguard Worker }
1129*35238bceSAndroid Build Coastguard Worker
1130*35238bceSAndroid Build Coastguard Worker const float minA0 = de::clamp((uBounds0.x() - 0.5f) - float(i0), 0.0f, 1.0f);
1131*35238bceSAndroid Build Coastguard Worker const float maxA0 = de::clamp((uBounds0.y() - 0.5f) - float(i0), 0.0f, 1.0f);
1132*35238bceSAndroid Build Coastguard Worker const float minB0 = de::clamp((vBounds0.x() - 0.5f) - float(j0), 0.0f, 1.0f);
1133*35238bceSAndroid Build Coastguard Worker const float maxB0 = de::clamp((vBounds0.y() - 0.5f) - float(j0), 0.0f, 1.0f);
1134*35238bceSAndroid Build Coastguard Worker
1135*35238bceSAndroid Build Coastguard Worker for (int j1 = minJ1; j1 <= maxJ1; j1++)
1136*35238bceSAndroid Build Coastguard Worker {
1137*35238bceSAndroid Build Coastguard Worker for (int i1 = minI1; i1 <= maxI1; i1++)
1138*35238bceSAndroid Build Coastguard Worker {
1139*35238bceSAndroid Build Coastguard Worker ColorQuad quad1;
1140*35238bceSAndroid Build Coastguard Worker float searchStep1;
1141*35238bceSAndroid Build Coastguard Worker
1142*35238bceSAndroid Build Coastguard Worker {
1143*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i1, w1);
1144*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i1 + 1, w1);
1145*35238bceSAndroid Build Coastguard Worker const int y0 = wrap(sampler.wrapT, j1, h1);
1146*35238bceSAndroid Build Coastguard Worker const int y1 = wrap(sampler.wrapT, j1 + 1, h1);
1147*35238bceSAndroid Build Coastguard Worker lookupQuad(quad1, level1, sampler, x0, x1, y0, y1, coordZ);
1148*35238bceSAndroid Build Coastguard Worker
1149*35238bceSAndroid Build Coastguard Worker if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
1150*35238bceSAndroid Build Coastguard Worker searchStep1 = computeBilinearSearchStepFromFloatQuad(prec, quad1);
1151*35238bceSAndroid Build Coastguard Worker else
1152*35238bceSAndroid Build Coastguard Worker searchStep1 = cSearchStep;
1153*35238bceSAndroid Build Coastguard Worker }
1154*35238bceSAndroid Build Coastguard Worker
1155*35238bceSAndroid Build Coastguard Worker const float minA1 = de::clamp((uBounds1.x() - 0.5f) - float(i1), 0.0f, 1.0f);
1156*35238bceSAndroid Build Coastguard Worker const float maxA1 = de::clamp((uBounds1.y() - 0.5f) - float(i1), 0.0f, 1.0f);
1157*35238bceSAndroid Build Coastguard Worker const float minB1 = de::clamp((vBounds1.x() - 0.5f) - float(j1), 0.0f, 1.0f);
1158*35238bceSAndroid Build Coastguard Worker const float maxB1 = de::clamp((vBounds1.y() - 0.5f) - float(j1), 0.0f, 1.0f);
1159*35238bceSAndroid Build Coastguard Worker
1160*35238bceSAndroid Build Coastguard Worker if (is2DTrilinearFilterResultValid(prec, quad0, quad1, Vec2(minA0, maxA0), Vec2(minB0, maxB0),
1161*35238bceSAndroid Build Coastguard Worker Vec2(minA1, maxA1), Vec2(minB1, maxB1), fBounds,
1162*35238bceSAndroid Build Coastguard Worker de::min(searchStep0, searchStep1), result))
1163*35238bceSAndroid Build Coastguard Worker return true;
1164*35238bceSAndroid Build Coastguard Worker }
1165*35238bceSAndroid Build Coastguard Worker }
1166*35238bceSAndroid Build Coastguard Worker }
1167*35238bceSAndroid Build Coastguard Worker }
1168*35238bceSAndroid Build Coastguard Worker
1169*35238bceSAndroid Build Coastguard Worker return false;
1170*35238bceSAndroid Build Coastguard Worker }
1171*35238bceSAndroid Build Coastguard Worker
isLinearMipmapLinearSampleResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const LookupPrecision & prec,const Vec3 & coord,const Vec2 & fBounds,const Vec4 & result)1172*35238bceSAndroid Build Coastguard Worker static bool isLinearMipmapLinearSampleResultValid(const ConstPixelBufferAccess &level0,
1173*35238bceSAndroid Build Coastguard Worker const ConstPixelBufferAccess &level1, const Sampler &sampler,
1174*35238bceSAndroid Build Coastguard Worker const LookupPrecision &prec, const Vec3 &coord, const Vec2 &fBounds,
1175*35238bceSAndroid Build Coastguard Worker const Vec4 &result)
1176*35238bceSAndroid Build Coastguard Worker {
1177*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
1178*35238bceSAndroid Build Coastguard Worker // Right now this allows pairing any two valid bilinear quads.
1179*35238bceSAndroid Build Coastguard Worker
1180*35238bceSAndroid Build Coastguard Worker const int w0 = level0.getWidth();
1181*35238bceSAndroid Build Coastguard Worker const int w1 = level1.getWidth();
1182*35238bceSAndroid Build Coastguard Worker const int h0 = level0.getHeight();
1183*35238bceSAndroid Build Coastguard Worker const int h1 = level1.getHeight();
1184*35238bceSAndroid Build Coastguard Worker const int d0 = level0.getDepth();
1185*35238bceSAndroid Build Coastguard Worker const int d1 = level1.getDepth();
1186*35238bceSAndroid Build Coastguard Worker
1187*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds0 =
1188*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
1189*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds1 =
1190*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1, coord.x(), prec.coordBits.x(), prec.uvwBits.x());
1191*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds0 =
1192*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0, coord.y(), prec.coordBits.y(), prec.uvwBits.y());
1193*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds1 =
1194*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1, coord.y(), prec.coordBits.y(), prec.uvwBits.y());
1195*35238bceSAndroid Build Coastguard Worker const Vec2 wBounds0 =
1196*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, d0, coord.z(), prec.coordBits.z(), prec.uvwBits.z());
1197*35238bceSAndroid Build Coastguard Worker const Vec2 wBounds1 =
1198*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, d1, coord.z(), prec.coordBits.z(), prec.uvwBits.z());
1199*35238bceSAndroid Build Coastguard Worker
1200*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
1201*35238bceSAndroid Build Coastguard Worker const int minI0 = deFloorFloatToInt32(uBounds0.x() - 0.5f);
1202*35238bceSAndroid Build Coastguard Worker const int maxI0 = deFloorFloatToInt32(uBounds0.y() - 0.5f);
1203*35238bceSAndroid Build Coastguard Worker const int minI1 = deFloorFloatToInt32(uBounds1.x() - 0.5f);
1204*35238bceSAndroid Build Coastguard Worker const int maxI1 = deFloorFloatToInt32(uBounds1.y() - 0.5f);
1205*35238bceSAndroid Build Coastguard Worker const int minJ0 = deFloorFloatToInt32(vBounds0.x() - 0.5f);
1206*35238bceSAndroid Build Coastguard Worker const int maxJ0 = deFloorFloatToInt32(vBounds0.y() - 0.5f);
1207*35238bceSAndroid Build Coastguard Worker const int minJ1 = deFloorFloatToInt32(vBounds1.x() - 0.5f);
1208*35238bceSAndroid Build Coastguard Worker const int maxJ1 = deFloorFloatToInt32(vBounds1.y() - 0.5f);
1209*35238bceSAndroid Build Coastguard Worker const int minK0 = deFloorFloatToInt32(wBounds0.x() - 0.5f);
1210*35238bceSAndroid Build Coastguard Worker const int maxK0 = deFloorFloatToInt32(wBounds0.y() - 0.5f);
1211*35238bceSAndroid Build Coastguard Worker const int minK1 = deFloorFloatToInt32(wBounds1.x() - 0.5f);
1212*35238bceSAndroid Build Coastguard Worker const int maxK1 = deFloorFloatToInt32(wBounds1.y() - 0.5f);
1213*35238bceSAndroid Build Coastguard Worker
1214*35238bceSAndroid Build Coastguard Worker const TextureChannelClass texClass = getTextureChannelClass(level0.getFormat().type);
1215*35238bceSAndroid Build Coastguard Worker const float cSearchStep = texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ?
1216*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForUnorm(prec) :
1217*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ?
1218*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForSnorm(prec) :
1219*35238bceSAndroid Build Coastguard Worker 0.0f; // Step is computed for floating-point quads based on texel values.
1220*35238bceSAndroid Build Coastguard Worker
1221*35238bceSAndroid Build Coastguard Worker DE_ASSERT(texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
1222*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || texClass == TEXTURECHANNELCLASS_FLOATING_POINT ||
1223*35238bceSAndroid Build Coastguard Worker sampler.reductionMode != Sampler::WEIGHTED_AVERAGE);
1224*35238bceSAndroid Build Coastguard Worker
1225*35238bceSAndroid Build Coastguard Worker for (int k0 = minK0; k0 <= maxK0; k0++)
1226*35238bceSAndroid Build Coastguard Worker {
1227*35238bceSAndroid Build Coastguard Worker for (int j0 = minJ0; j0 <= maxJ0; j0++)
1228*35238bceSAndroid Build Coastguard Worker {
1229*35238bceSAndroid Build Coastguard Worker for (int i0 = minI0; i0 <= maxI0; i0++)
1230*35238bceSAndroid Build Coastguard Worker {
1231*35238bceSAndroid Build Coastguard Worker ColorQuad quad00, quad01;
1232*35238bceSAndroid Build Coastguard Worker float searchStep0;
1233*35238bceSAndroid Build Coastguard Worker
1234*35238bceSAndroid Build Coastguard Worker {
1235*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i0, w0);
1236*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i0 + 1, w0);
1237*35238bceSAndroid Build Coastguard Worker const int y0 = wrap(sampler.wrapT, j0, h0);
1238*35238bceSAndroid Build Coastguard Worker const int y1 = wrap(sampler.wrapT, j0 + 1, h0);
1239*35238bceSAndroid Build Coastguard Worker const int z0 = wrap(sampler.wrapR, k0, d0);
1240*35238bceSAndroid Build Coastguard Worker const int z1 = wrap(sampler.wrapR, k0 + 1, d0);
1241*35238bceSAndroid Build Coastguard Worker lookupQuad(quad00, level0, sampler, x0, x1, y0, y1, z0);
1242*35238bceSAndroid Build Coastguard Worker lookupQuad(quad01, level0, sampler, x0, x1, y0, y1, z1);
1243*35238bceSAndroid Build Coastguard Worker
1244*35238bceSAndroid Build Coastguard Worker if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
1245*35238bceSAndroid Build Coastguard Worker searchStep0 = de::min(computeBilinearSearchStepFromFloatQuad(prec, quad00),
1246*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepFromFloatQuad(prec, quad01));
1247*35238bceSAndroid Build Coastguard Worker else
1248*35238bceSAndroid Build Coastguard Worker searchStep0 = cSearchStep;
1249*35238bceSAndroid Build Coastguard Worker }
1250*35238bceSAndroid Build Coastguard Worker
1251*35238bceSAndroid Build Coastguard Worker const float minA0 = de::clamp((uBounds0.x() - 0.5f) - float(i0), 0.0f, 1.0f);
1252*35238bceSAndroid Build Coastguard Worker const float maxA0 = de::clamp((uBounds0.y() - 0.5f) - float(i0), 0.0f, 1.0f);
1253*35238bceSAndroid Build Coastguard Worker const float minB0 = de::clamp((vBounds0.x() - 0.5f) - float(j0), 0.0f, 1.0f);
1254*35238bceSAndroid Build Coastguard Worker const float maxB0 = de::clamp((vBounds0.y() - 0.5f) - float(j0), 0.0f, 1.0f);
1255*35238bceSAndroid Build Coastguard Worker const float minC0 = de::clamp((wBounds0.x() - 0.5f) - float(k0), 0.0f, 1.0f);
1256*35238bceSAndroid Build Coastguard Worker const float maxC0 = de::clamp((wBounds0.y() - 0.5f) - float(k0), 0.0f, 1.0f);
1257*35238bceSAndroid Build Coastguard Worker
1258*35238bceSAndroid Build Coastguard Worker for (int k1 = minK1; k1 <= maxK1; k1++)
1259*35238bceSAndroid Build Coastguard Worker {
1260*35238bceSAndroid Build Coastguard Worker for (int j1 = minJ1; j1 <= maxJ1; j1++)
1261*35238bceSAndroid Build Coastguard Worker {
1262*35238bceSAndroid Build Coastguard Worker for (int i1 = minI1; i1 <= maxI1; i1++)
1263*35238bceSAndroid Build Coastguard Worker {
1264*35238bceSAndroid Build Coastguard Worker ColorQuad quad10, quad11;
1265*35238bceSAndroid Build Coastguard Worker float searchStep1;
1266*35238bceSAndroid Build Coastguard Worker
1267*35238bceSAndroid Build Coastguard Worker {
1268*35238bceSAndroid Build Coastguard Worker const int x0 = wrap(sampler.wrapS, i1, w1);
1269*35238bceSAndroid Build Coastguard Worker const int x1 = wrap(sampler.wrapS, i1 + 1, w1);
1270*35238bceSAndroid Build Coastguard Worker const int y0 = wrap(sampler.wrapT, j1, h1);
1271*35238bceSAndroid Build Coastguard Worker const int y1 = wrap(sampler.wrapT, j1 + 1, h1);
1272*35238bceSAndroid Build Coastguard Worker const int z0 = wrap(sampler.wrapR, k1, d1);
1273*35238bceSAndroid Build Coastguard Worker const int z1 = wrap(sampler.wrapR, k1 + 1, d1);
1274*35238bceSAndroid Build Coastguard Worker lookupQuad(quad10, level1, sampler, x0, x1, y0, y1, z0);
1275*35238bceSAndroid Build Coastguard Worker lookupQuad(quad11, level1, sampler, x0, x1, y0, y1, z1);
1276*35238bceSAndroid Build Coastguard Worker
1277*35238bceSAndroid Build Coastguard Worker if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
1278*35238bceSAndroid Build Coastguard Worker searchStep1 = de::min(computeBilinearSearchStepFromFloatQuad(prec, quad10),
1279*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepFromFloatQuad(prec, quad11));
1280*35238bceSAndroid Build Coastguard Worker else
1281*35238bceSAndroid Build Coastguard Worker searchStep1 = cSearchStep;
1282*35238bceSAndroid Build Coastguard Worker }
1283*35238bceSAndroid Build Coastguard Worker
1284*35238bceSAndroid Build Coastguard Worker const float minA1 = de::clamp((uBounds1.x() - 0.5f) - float(i1), 0.0f, 1.0f);
1285*35238bceSAndroid Build Coastguard Worker const float maxA1 = de::clamp((uBounds1.y() - 0.5f) - float(i1), 0.0f, 1.0f);
1286*35238bceSAndroid Build Coastguard Worker const float minB1 = de::clamp((vBounds1.x() - 0.5f) - float(j1), 0.0f, 1.0f);
1287*35238bceSAndroid Build Coastguard Worker const float maxB1 = de::clamp((vBounds1.y() - 0.5f) - float(j1), 0.0f, 1.0f);
1288*35238bceSAndroid Build Coastguard Worker const float minC1 = de::clamp((wBounds1.x() - 0.5f) - float(k1), 0.0f, 1.0f);
1289*35238bceSAndroid Build Coastguard Worker const float maxC1 = de::clamp((wBounds1.y() - 0.5f) - float(k1), 0.0f, 1.0f);
1290*35238bceSAndroid Build Coastguard Worker
1291*35238bceSAndroid Build Coastguard Worker if (is3DTrilinearFilterResultValid(
1292*35238bceSAndroid Build Coastguard Worker prec, quad00, quad01, quad10, quad11, Vec2(minA0, maxA0), Vec2(minB0, maxB0),
1293*35238bceSAndroid Build Coastguard Worker Vec2(minC0, maxC0), Vec2(minA1, maxA1), Vec2(minB1, maxB1), Vec2(minC1, maxC1),
1294*35238bceSAndroid Build Coastguard Worker fBounds, de::min(searchStep0, searchStep1), result))
1295*35238bceSAndroid Build Coastguard Worker return true;
1296*35238bceSAndroid Build Coastguard Worker }
1297*35238bceSAndroid Build Coastguard Worker }
1298*35238bceSAndroid Build Coastguard Worker }
1299*35238bceSAndroid Build Coastguard Worker }
1300*35238bceSAndroid Build Coastguard Worker }
1301*35238bceSAndroid Build Coastguard Worker }
1302*35238bceSAndroid Build Coastguard Worker
1303*35238bceSAndroid Build Coastguard Worker return false;
1304*35238bceSAndroid Build Coastguard Worker }
1305*35238bceSAndroid Build Coastguard Worker
isLevelSampleResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const Sampler::FilterMode filterMode,const LookupPrecision & prec,const float coordX,const int coordY,const Vec4 & result)1306*35238bceSAndroid Build Coastguard Worker static bool isLevelSampleResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
1307*35238bceSAndroid Build Coastguard Worker const Sampler::FilterMode filterMode, const LookupPrecision &prec,
1308*35238bceSAndroid Build Coastguard Worker const float coordX, const int coordY, const Vec4 &result)
1309*35238bceSAndroid Build Coastguard Worker {
1310*35238bceSAndroid Build Coastguard Worker if (filterMode == Sampler::LINEAR)
1311*35238bceSAndroid Build Coastguard Worker return isLinearSampleResultValid(level, sampler, prec, coordX, coordY, result);
1312*35238bceSAndroid Build Coastguard Worker else
1313*35238bceSAndroid Build Coastguard Worker return isNearestSampleResultValid(level, sampler, prec, coordX, coordY, result);
1314*35238bceSAndroid Build Coastguard Worker }
1315*35238bceSAndroid Build Coastguard Worker
isLevelSampleResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const Sampler::FilterMode filterMode,const LookupPrecision & prec,const Vec2 & coord,const int coordZ,const Vec4 & result)1316*35238bceSAndroid Build Coastguard Worker static bool isLevelSampleResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
1317*35238bceSAndroid Build Coastguard Worker const Sampler::FilterMode filterMode, const LookupPrecision &prec,
1318*35238bceSAndroid Build Coastguard Worker const Vec2 &coord, const int coordZ, const Vec4 &result)
1319*35238bceSAndroid Build Coastguard Worker {
1320*35238bceSAndroid Build Coastguard Worker if (filterMode == Sampler::LINEAR)
1321*35238bceSAndroid Build Coastguard Worker return isLinearSampleResultValid(level, sampler, prec, coord, coordZ, result);
1322*35238bceSAndroid Build Coastguard Worker else
1323*35238bceSAndroid Build Coastguard Worker return isNearestSampleResultValid(level, sampler, prec, coord, coordZ, result);
1324*35238bceSAndroid Build Coastguard Worker }
1325*35238bceSAndroid Build Coastguard Worker
isMipmapLinearSampleResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const Sampler::FilterMode levelFilter,const LookupPrecision & prec,const float coordX,const int coordY,const Vec2 & fBounds,const Vec4 & result)1326*35238bceSAndroid Build Coastguard Worker static bool isMipmapLinearSampleResultValid(const ConstPixelBufferAccess &level0, const ConstPixelBufferAccess &level1,
1327*35238bceSAndroid Build Coastguard Worker const Sampler &sampler, const Sampler::FilterMode levelFilter,
1328*35238bceSAndroid Build Coastguard Worker const LookupPrecision &prec, const float coordX, const int coordY,
1329*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const Vec4 &result)
1330*35238bceSAndroid Build Coastguard Worker {
1331*35238bceSAndroid Build Coastguard Worker if (levelFilter == Sampler::LINEAR)
1332*35238bceSAndroid Build Coastguard Worker return isLinearMipmapLinearSampleResultValid(level0, level1, sampler, prec, coordX, coordY, fBounds, result);
1333*35238bceSAndroid Build Coastguard Worker else
1334*35238bceSAndroid Build Coastguard Worker return isNearestMipmapLinearSampleResultValid(level0, level1, sampler, prec, coordX, coordY, fBounds, result);
1335*35238bceSAndroid Build Coastguard Worker }
1336*35238bceSAndroid Build Coastguard Worker
isMipmapLinearSampleResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const Sampler::FilterMode levelFilter,const LookupPrecision & prec,const Vec2 & coord,const int coordZ,const Vec2 & fBounds,const Vec4 & result)1337*35238bceSAndroid Build Coastguard Worker static bool isMipmapLinearSampleResultValid(const ConstPixelBufferAccess &level0, const ConstPixelBufferAccess &level1,
1338*35238bceSAndroid Build Coastguard Worker const Sampler &sampler, const Sampler::FilterMode levelFilter,
1339*35238bceSAndroid Build Coastguard Worker const LookupPrecision &prec, const Vec2 &coord, const int coordZ,
1340*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const Vec4 &result)
1341*35238bceSAndroid Build Coastguard Worker {
1342*35238bceSAndroid Build Coastguard Worker if (levelFilter == Sampler::LINEAR)
1343*35238bceSAndroid Build Coastguard Worker return isLinearMipmapLinearSampleResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds, result);
1344*35238bceSAndroid Build Coastguard Worker else
1345*35238bceSAndroid Build Coastguard Worker return isNearestMipmapLinearSampleResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds, result);
1346*35238bceSAndroid Build Coastguard Worker }
1347*35238bceSAndroid Build Coastguard Worker
isLookupResultValid(const Texture2DView & texture,const Sampler & sampler,const LookupPrecision & prec,const Vec2 & coord,const Vec2 & lodBounds,const Vec4 & result)1348*35238bceSAndroid Build Coastguard Worker bool isLookupResultValid(const Texture2DView &texture, const Sampler &sampler, const LookupPrecision &prec,
1349*35238bceSAndroid Build Coastguard Worker const Vec2 &coord, const Vec2 &lodBounds, const Vec4 &result)
1350*35238bceSAndroid Build Coastguard Worker {
1351*35238bceSAndroid Build Coastguard Worker const float minLod = lodBounds.x();
1352*35238bceSAndroid Build Coastguard Worker const float maxLod = lodBounds.y();
1353*35238bceSAndroid Build Coastguard Worker const bool canBeMagnified = minLod <= sampler.lodThreshold;
1354*35238bceSAndroid Build Coastguard Worker const bool canBeMinified = maxLod > sampler.lodThreshold;
1355*35238bceSAndroid Build Coastguard Worker
1356*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
1357*35238bceSAndroid Build Coastguard Worker
1358*35238bceSAndroid Build Coastguard Worker if (canBeMagnified)
1359*35238bceSAndroid Build Coastguard Worker {
1360*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, 0, result))
1361*35238bceSAndroid Build Coastguard Worker return true;
1362*35238bceSAndroid Build Coastguard Worker }
1363*35238bceSAndroid Build Coastguard Worker
1364*35238bceSAndroid Build Coastguard Worker if (canBeMinified)
1365*35238bceSAndroid Build Coastguard Worker {
1366*35238bceSAndroid Build Coastguard Worker const bool isNearestMipmap = isNearestMipmapFilter(sampler.minFilter);
1367*35238bceSAndroid Build Coastguard Worker const bool isLinearMipmap = isLinearMipmapFilter(sampler.minFilter);
1368*35238bceSAndroid Build Coastguard Worker const int minTexLevel = 0;
1369*35238bceSAndroid Build Coastguard Worker const int maxTexLevel = texture.getNumLevels() - 1;
1370*35238bceSAndroid Build Coastguard Worker
1371*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minTexLevel <= maxTexLevel);
1372*35238bceSAndroid Build Coastguard Worker
1373*35238bceSAndroid Build Coastguard Worker if (isLinearMipmap && minTexLevel < maxTexLevel)
1374*35238bceSAndroid Build Coastguard Worker {
1375*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel - 1);
1376*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel - 1);
1377*35238bceSAndroid Build Coastguard Worker
1378*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1379*35238bceSAndroid Build Coastguard Worker
1380*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1381*35238bceSAndroid Build Coastguard Worker {
1382*35238bceSAndroid Build Coastguard Worker const float minF = de::clamp(minLod - float(level), 0.0f, 1.0f);
1383*35238bceSAndroid Build Coastguard Worker const float maxF = de::clamp(maxLod - float(level), 0.0f, 1.0f);
1384*35238bceSAndroid Build Coastguard Worker
1385*35238bceSAndroid Build Coastguard Worker if (isMipmapLinearSampleResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler,
1386*35238bceSAndroid Build Coastguard Worker getLevelFilter(sampler.minFilter), prec, coord, 0, Vec2(minF, maxF),
1387*35238bceSAndroid Build Coastguard Worker result))
1388*35238bceSAndroid Build Coastguard Worker return true;
1389*35238bceSAndroid Build Coastguard Worker }
1390*35238bceSAndroid Build Coastguard Worker }
1391*35238bceSAndroid Build Coastguard Worker else if (isNearestMipmap)
1392*35238bceSAndroid Build Coastguard Worker {
1393*35238bceSAndroid Build Coastguard Worker // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
1394*35238bceSAndroid Build Coastguard Worker // decision to allow floor(lod + 0.5) as well.
1395*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatCeil(minLod + 0.5f) - 1, minTexLevel, maxTexLevel);
1396*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod + 0.5f), minTexLevel, maxTexLevel);
1397*35238bceSAndroid Build Coastguard Worker
1398*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1399*35238bceSAndroid Build Coastguard Worker
1400*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1401*35238bceSAndroid Build Coastguard Worker {
1402*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter), prec,
1403*35238bceSAndroid Build Coastguard Worker coord, 0, result))
1404*35238bceSAndroid Build Coastguard Worker return true;
1405*35238bceSAndroid Build Coastguard Worker }
1406*35238bceSAndroid Build Coastguard Worker }
1407*35238bceSAndroid Build Coastguard Worker else
1408*35238bceSAndroid Build Coastguard Worker {
1409*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, 0, result))
1410*35238bceSAndroid Build Coastguard Worker return true;
1411*35238bceSAndroid Build Coastguard Worker }
1412*35238bceSAndroid Build Coastguard Worker }
1413*35238bceSAndroid Build Coastguard Worker
1414*35238bceSAndroid Build Coastguard Worker return false;
1415*35238bceSAndroid Build Coastguard Worker }
1416*35238bceSAndroid Build Coastguard Worker
isLookupResultValid(const Texture1DView & texture,const Sampler & sampler,const LookupPrecision & prec,const float coord,const Vec2 & lodBounds,const Vec4 & result)1417*35238bceSAndroid Build Coastguard Worker bool isLookupResultValid(const Texture1DView &texture, const Sampler &sampler, const LookupPrecision &prec,
1418*35238bceSAndroid Build Coastguard Worker const float coord, const Vec2 &lodBounds, const Vec4 &result)
1419*35238bceSAndroid Build Coastguard Worker {
1420*35238bceSAndroid Build Coastguard Worker const float minLod = lodBounds.x();
1421*35238bceSAndroid Build Coastguard Worker const float maxLod = lodBounds.y();
1422*35238bceSAndroid Build Coastguard Worker const bool canBeMagnified = minLod <= sampler.lodThreshold;
1423*35238bceSAndroid Build Coastguard Worker const bool canBeMinified = maxLod > sampler.lodThreshold;
1424*35238bceSAndroid Build Coastguard Worker
1425*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
1426*35238bceSAndroid Build Coastguard Worker
1427*35238bceSAndroid Build Coastguard Worker if (canBeMagnified)
1428*35238bceSAndroid Build Coastguard Worker {
1429*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, 0, result))
1430*35238bceSAndroid Build Coastguard Worker return true;
1431*35238bceSAndroid Build Coastguard Worker }
1432*35238bceSAndroid Build Coastguard Worker
1433*35238bceSAndroid Build Coastguard Worker if (canBeMinified)
1434*35238bceSAndroid Build Coastguard Worker {
1435*35238bceSAndroid Build Coastguard Worker const bool isNearestMipmap = isNearestMipmapFilter(sampler.minFilter);
1436*35238bceSAndroid Build Coastguard Worker const bool isLinearMipmap = isLinearMipmapFilter(sampler.minFilter);
1437*35238bceSAndroid Build Coastguard Worker const int minTexLevel = 0;
1438*35238bceSAndroid Build Coastguard Worker const int maxTexLevel = texture.getNumLevels() - 1;
1439*35238bceSAndroid Build Coastguard Worker
1440*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minTexLevel <= maxTexLevel);
1441*35238bceSAndroid Build Coastguard Worker
1442*35238bceSAndroid Build Coastguard Worker if (isLinearMipmap && minTexLevel < maxTexLevel)
1443*35238bceSAndroid Build Coastguard Worker {
1444*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel - 1);
1445*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel - 1);
1446*35238bceSAndroid Build Coastguard Worker
1447*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1448*35238bceSAndroid Build Coastguard Worker
1449*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1450*35238bceSAndroid Build Coastguard Worker {
1451*35238bceSAndroid Build Coastguard Worker const float minF = de::clamp(minLod - float(level), 0.0f, 1.0f);
1452*35238bceSAndroid Build Coastguard Worker const float maxF = de::clamp(maxLod - float(level), 0.0f, 1.0f);
1453*35238bceSAndroid Build Coastguard Worker
1454*35238bceSAndroid Build Coastguard Worker if (isMipmapLinearSampleResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler,
1455*35238bceSAndroid Build Coastguard Worker getLevelFilter(sampler.minFilter), prec, coord, 0, Vec2(minF, maxF),
1456*35238bceSAndroid Build Coastguard Worker result))
1457*35238bceSAndroid Build Coastguard Worker return true;
1458*35238bceSAndroid Build Coastguard Worker }
1459*35238bceSAndroid Build Coastguard Worker }
1460*35238bceSAndroid Build Coastguard Worker else if (isNearestMipmap)
1461*35238bceSAndroid Build Coastguard Worker {
1462*35238bceSAndroid Build Coastguard Worker // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
1463*35238bceSAndroid Build Coastguard Worker // decision to allow floor(lod + 0.5) as well.
1464*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatCeil(minLod + 0.5f) - 1, minTexLevel, maxTexLevel);
1465*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod + 0.5f), minTexLevel, maxTexLevel);
1466*35238bceSAndroid Build Coastguard Worker
1467*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1468*35238bceSAndroid Build Coastguard Worker
1469*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1470*35238bceSAndroid Build Coastguard Worker {
1471*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter), prec,
1472*35238bceSAndroid Build Coastguard Worker coord, 0, result))
1473*35238bceSAndroid Build Coastguard Worker return true;
1474*35238bceSAndroid Build Coastguard Worker }
1475*35238bceSAndroid Build Coastguard Worker }
1476*35238bceSAndroid Build Coastguard Worker else
1477*35238bceSAndroid Build Coastguard Worker {
1478*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, 0, result))
1479*35238bceSAndroid Build Coastguard Worker return true;
1480*35238bceSAndroid Build Coastguard Worker }
1481*35238bceSAndroid Build Coastguard Worker }
1482*35238bceSAndroid Build Coastguard Worker
1483*35238bceSAndroid Build Coastguard Worker return false;
1484*35238bceSAndroid Build Coastguard Worker }
1485*35238bceSAndroid Build Coastguard Worker
isSeamlessLinearSampleResultValid(const ConstPixelBufferAccess (& faces)[CUBEFACE_LAST],const Sampler & sampler,const LookupPrecision & prec,const CubeFaceFloatCoords & coords,const Vec4 & result)1486*35238bceSAndroid Build Coastguard Worker static bool isSeamlessLinearSampleResultValid(const ConstPixelBufferAccess (&faces)[CUBEFACE_LAST],
1487*35238bceSAndroid Build Coastguard Worker const Sampler &sampler, const LookupPrecision &prec,
1488*35238bceSAndroid Build Coastguard Worker const CubeFaceFloatCoords &coords, const Vec4 &result)
1489*35238bceSAndroid Build Coastguard Worker {
1490*35238bceSAndroid Build Coastguard Worker const int size = faces[coords.face].getWidth();
1491*35238bceSAndroid Build Coastguard Worker
1492*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds =
1493*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.s, prec.coordBits.x(), prec.uvwBits.x());
1494*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds =
1495*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.t, prec.coordBits.y(), prec.uvwBits.y());
1496*35238bceSAndroid Build Coastguard Worker
1497*35238bceSAndroid Build Coastguard Worker // Integer coordinate bounds for (x0,y0) - without wrap mode
1498*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x() - 0.5f);
1499*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y() - 0.5f);
1500*35238bceSAndroid Build Coastguard Worker const int minJ = deFloorFloatToInt32(vBounds.x() - 0.5f);
1501*35238bceSAndroid Build Coastguard Worker const int maxJ = deFloorFloatToInt32(vBounds.y() - 0.5f);
1502*35238bceSAndroid Build Coastguard Worker
1503*35238bceSAndroid Build Coastguard Worker const TextureChannelClass texClass = getTextureChannelClass(faces[coords.face].getFormat().type);
1504*35238bceSAndroid Build Coastguard Worker float searchStep = texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ?
1505*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForUnorm(prec) :
1506*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ?
1507*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForSnorm(prec) :
1508*35238bceSAndroid Build Coastguard Worker 0.0f; // Step is computed for floating-point quads based on texel values.
1509*35238bceSAndroid Build Coastguard Worker
1510*35238bceSAndroid Build Coastguard Worker DE_ASSERT(texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
1511*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || texClass == TEXTURECHANNELCLASS_FLOATING_POINT ||
1512*35238bceSAndroid Build Coastguard Worker sampler.reductionMode != Sampler::WEIGHTED_AVERAGE);
1513*35238bceSAndroid Build Coastguard Worker
1514*35238bceSAndroid Build Coastguard Worker for (int j = minJ; j <= maxJ; j++)
1515*35238bceSAndroid Build Coastguard Worker {
1516*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
1517*35238bceSAndroid Build Coastguard Worker {
1518*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c00 =
1519*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i + 0, j + 0)), size);
1520*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c10 =
1521*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i + 1, j + 0)), size);
1522*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c01 =
1523*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i + 0, j + 1)), size);
1524*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c11 =
1525*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i + 1, j + 1)), size);
1526*35238bceSAndroid Build Coastguard Worker
1527*35238bceSAndroid Build Coastguard Worker // If any of samples is out of both edges, implementations can do pretty much anything according to spec.
1528*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
1529*35238bceSAndroid Build Coastguard Worker if (c00.face == CUBEFACE_LAST || c01.face == CUBEFACE_LAST || c10.face == CUBEFACE_LAST ||
1530*35238bceSAndroid Build Coastguard Worker c11.face == CUBEFACE_LAST)
1531*35238bceSAndroid Build Coastguard Worker return true;
1532*35238bceSAndroid Build Coastguard Worker
1533*35238bceSAndroid Build Coastguard Worker // Bounds for filtering factors
1534*35238bceSAndroid Build Coastguard Worker const float minA = de::clamp((uBounds.x() - 0.5f) - float(i), 0.0f, 1.0f);
1535*35238bceSAndroid Build Coastguard Worker const float maxA = de::clamp((uBounds.y() - 0.5f) - float(i), 0.0f, 1.0f);
1536*35238bceSAndroid Build Coastguard Worker const float minB = de::clamp((vBounds.x() - 0.5f) - float(j), 0.0f, 1.0f);
1537*35238bceSAndroid Build Coastguard Worker const float maxB = de::clamp((vBounds.y() - 0.5f) - float(j), 0.0f, 1.0f);
1538*35238bceSAndroid Build Coastguard Worker
1539*35238bceSAndroid Build Coastguard Worker ColorQuad quad;
1540*35238bceSAndroid Build Coastguard Worker quad.p00 = lookup<float>(faces[c00.face], sampler, c00.s, c00.t, 0);
1541*35238bceSAndroid Build Coastguard Worker quad.p10 = lookup<float>(faces[c10.face], sampler, c10.s, c10.t, 0);
1542*35238bceSAndroid Build Coastguard Worker quad.p01 = lookup<float>(faces[c01.face], sampler, c01.s, c01.t, 0);
1543*35238bceSAndroid Build Coastguard Worker quad.p11 = lookup<float>(faces[c11.face], sampler, c11.s, c11.t, 0);
1544*35238bceSAndroid Build Coastguard Worker
1545*35238bceSAndroid Build Coastguard Worker if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
1546*35238bceSAndroid Build Coastguard Worker searchStep = computeBilinearSearchStepFromFloatQuad(prec, quad);
1547*35238bceSAndroid Build Coastguard Worker
1548*35238bceSAndroid Build Coastguard Worker if (sampler.reductionMode == Sampler::WEIGHTED_AVERAGE)
1549*35238bceSAndroid Build Coastguard Worker {
1550*35238bceSAndroid Build Coastguard Worker if (isBilinearRangeValid(prec, quad, Vec2(minA, maxA), Vec2(minB, maxB), searchStep, result))
1551*35238bceSAndroid Build Coastguard Worker return true;
1552*35238bceSAndroid Build Coastguard Worker }
1553*35238bceSAndroid Build Coastguard Worker else
1554*35238bceSAndroid Build Coastguard Worker {
1555*35238bceSAndroid Build Coastguard Worker if (isReductionValid(prec, quad, sampler.reductionMode, result))
1556*35238bceSAndroid Build Coastguard Worker return true;
1557*35238bceSAndroid Build Coastguard Worker }
1558*35238bceSAndroid Build Coastguard Worker }
1559*35238bceSAndroid Build Coastguard Worker }
1560*35238bceSAndroid Build Coastguard Worker
1561*35238bceSAndroid Build Coastguard Worker return false;
1562*35238bceSAndroid Build Coastguard Worker }
1563*35238bceSAndroid Build Coastguard Worker
isSeamplessLinearMipmapLinearSampleResultValid(const ConstPixelBufferAccess (& faces0)[CUBEFACE_LAST],const ConstPixelBufferAccess (& faces1)[CUBEFACE_LAST],const Sampler & sampler,const LookupPrecision & prec,const CubeFaceFloatCoords & coords,const Vec2 & fBounds,const Vec4 & result)1564*35238bceSAndroid Build Coastguard Worker static bool isSeamplessLinearMipmapLinearSampleResultValid(const ConstPixelBufferAccess (&faces0)[CUBEFACE_LAST],
1565*35238bceSAndroid Build Coastguard Worker const ConstPixelBufferAccess (&faces1)[CUBEFACE_LAST],
1566*35238bceSAndroid Build Coastguard Worker const Sampler &sampler, const LookupPrecision &prec,
1567*35238bceSAndroid Build Coastguard Worker const CubeFaceFloatCoords &coords, const Vec2 &fBounds,
1568*35238bceSAndroid Build Coastguard Worker const Vec4 &result)
1569*35238bceSAndroid Build Coastguard Worker {
1570*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
1571*35238bceSAndroid Build Coastguard Worker // Right now this allows pairing any two valid bilinear quads.
1572*35238bceSAndroid Build Coastguard Worker
1573*35238bceSAndroid Build Coastguard Worker const int size0 = faces0[coords.face].getWidth();
1574*35238bceSAndroid Build Coastguard Worker const int size1 = faces1[coords.face].getWidth();
1575*35238bceSAndroid Build Coastguard Worker
1576*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds0 = computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.s, prec.coordBits.x(),
1577*35238bceSAndroid Build Coastguard Worker prec.uvwBits.x());
1578*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds1 = computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.s, prec.coordBits.x(),
1579*35238bceSAndroid Build Coastguard Worker prec.uvwBits.x());
1580*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds0 = computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0, coords.t, prec.coordBits.y(),
1581*35238bceSAndroid Build Coastguard Worker prec.uvwBits.y());
1582*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds1 = computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1, coords.t, prec.coordBits.y(),
1583*35238bceSAndroid Build Coastguard Worker prec.uvwBits.y());
1584*35238bceSAndroid Build Coastguard Worker
1585*35238bceSAndroid Build Coastguard Worker // Integer coordinates - without wrap mode
1586*35238bceSAndroid Build Coastguard Worker const int minI0 = deFloorFloatToInt32(uBounds0.x() - 0.5f);
1587*35238bceSAndroid Build Coastguard Worker const int maxI0 = deFloorFloatToInt32(uBounds0.y() - 0.5f);
1588*35238bceSAndroid Build Coastguard Worker const int minI1 = deFloorFloatToInt32(uBounds1.x() - 0.5f);
1589*35238bceSAndroid Build Coastguard Worker const int maxI1 = deFloorFloatToInt32(uBounds1.y() - 0.5f);
1590*35238bceSAndroid Build Coastguard Worker const int minJ0 = deFloorFloatToInt32(vBounds0.x() - 0.5f);
1591*35238bceSAndroid Build Coastguard Worker const int maxJ0 = deFloorFloatToInt32(vBounds0.y() - 0.5f);
1592*35238bceSAndroid Build Coastguard Worker const int minJ1 = deFloorFloatToInt32(vBounds1.x() - 0.5f);
1593*35238bceSAndroid Build Coastguard Worker const int maxJ1 = deFloorFloatToInt32(vBounds1.y() - 0.5f);
1594*35238bceSAndroid Build Coastguard Worker
1595*35238bceSAndroid Build Coastguard Worker const TextureChannelClass texClass = getTextureChannelClass(faces0[coords.face].getFormat().type);
1596*35238bceSAndroid Build Coastguard Worker const float cSearchStep = texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ?
1597*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForUnorm(prec) :
1598*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ?
1599*35238bceSAndroid Build Coastguard Worker computeBilinearSearchStepForSnorm(prec) :
1600*35238bceSAndroid Build Coastguard Worker 0.0f; // Step is computed for floating-point quads based on texel values.
1601*35238bceSAndroid Build Coastguard Worker
1602*35238bceSAndroid Build Coastguard Worker DE_ASSERT(texClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
1603*35238bceSAndroid Build Coastguard Worker texClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || texClass == TEXTURECHANNELCLASS_FLOATING_POINT ||
1604*35238bceSAndroid Build Coastguard Worker sampler.reductionMode != Sampler::WEIGHTED_AVERAGE);
1605*35238bceSAndroid Build Coastguard Worker
1606*35238bceSAndroid Build Coastguard Worker for (int j0 = minJ0; j0 <= maxJ0; j0++)
1607*35238bceSAndroid Build Coastguard Worker {
1608*35238bceSAndroid Build Coastguard Worker for (int i0 = minI0; i0 <= maxI0; i0++)
1609*35238bceSAndroid Build Coastguard Worker {
1610*35238bceSAndroid Build Coastguard Worker ColorQuad quad0;
1611*35238bceSAndroid Build Coastguard Worker float searchStep0;
1612*35238bceSAndroid Build Coastguard Worker
1613*35238bceSAndroid Build Coastguard Worker {
1614*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c00 =
1615*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0 + 0, j0 + 0)), size0);
1616*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c10 =
1617*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0 + 1, j0 + 0)), size0);
1618*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c01 =
1619*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0 + 0, j0 + 1)), size0);
1620*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c11 =
1621*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0 + 1, j0 + 1)), size0);
1622*35238bceSAndroid Build Coastguard Worker
1623*35238bceSAndroid Build Coastguard Worker // If any of samples is out of both edges, implementations can do pretty much anything according to spec.
1624*35238bceSAndroid Build Coastguard Worker // \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
1625*35238bceSAndroid Build Coastguard Worker if (c00.face == CUBEFACE_LAST || c01.face == CUBEFACE_LAST || c10.face == CUBEFACE_LAST ||
1626*35238bceSAndroid Build Coastguard Worker c11.face == CUBEFACE_LAST)
1627*35238bceSAndroid Build Coastguard Worker return true;
1628*35238bceSAndroid Build Coastguard Worker
1629*35238bceSAndroid Build Coastguard Worker quad0.p00 = lookup<float>(faces0[c00.face], sampler, c00.s, c00.t, 0);
1630*35238bceSAndroid Build Coastguard Worker quad0.p10 = lookup<float>(faces0[c10.face], sampler, c10.s, c10.t, 0);
1631*35238bceSAndroid Build Coastguard Worker quad0.p01 = lookup<float>(faces0[c01.face], sampler, c01.s, c01.t, 0);
1632*35238bceSAndroid Build Coastguard Worker quad0.p11 = lookup<float>(faces0[c11.face], sampler, c11.s, c11.t, 0);
1633*35238bceSAndroid Build Coastguard Worker
1634*35238bceSAndroid Build Coastguard Worker if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
1635*35238bceSAndroid Build Coastguard Worker searchStep0 = computeBilinearSearchStepFromFloatQuad(prec, quad0);
1636*35238bceSAndroid Build Coastguard Worker else
1637*35238bceSAndroid Build Coastguard Worker searchStep0 = cSearchStep;
1638*35238bceSAndroid Build Coastguard Worker }
1639*35238bceSAndroid Build Coastguard Worker
1640*35238bceSAndroid Build Coastguard Worker const float minA0 = de::clamp((uBounds0.x() - 0.5f) - float(i0), 0.0f, 1.0f);
1641*35238bceSAndroid Build Coastguard Worker const float maxA0 = de::clamp((uBounds0.y() - 0.5f) - float(i0), 0.0f, 1.0f);
1642*35238bceSAndroid Build Coastguard Worker const float minB0 = de::clamp((vBounds0.x() - 0.5f) - float(j0), 0.0f, 1.0f);
1643*35238bceSAndroid Build Coastguard Worker const float maxB0 = de::clamp((vBounds0.y() - 0.5f) - float(j0), 0.0f, 1.0f);
1644*35238bceSAndroid Build Coastguard Worker
1645*35238bceSAndroid Build Coastguard Worker for (int j1 = minJ1; j1 <= maxJ1; j1++)
1646*35238bceSAndroid Build Coastguard Worker {
1647*35238bceSAndroid Build Coastguard Worker for (int i1 = minI1; i1 <= maxI1; i1++)
1648*35238bceSAndroid Build Coastguard Worker {
1649*35238bceSAndroid Build Coastguard Worker ColorQuad quad1;
1650*35238bceSAndroid Build Coastguard Worker float searchStep1;
1651*35238bceSAndroid Build Coastguard Worker
1652*35238bceSAndroid Build Coastguard Worker {
1653*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c00 =
1654*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1 + 0, j1 + 0)), size1);
1655*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c10 =
1656*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1 + 1, j1 + 0)), size1);
1657*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c01 =
1658*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1 + 0, j1 + 1)), size1);
1659*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c11 =
1660*35238bceSAndroid Build Coastguard Worker remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1 + 1, j1 + 1)), size1);
1661*35238bceSAndroid Build Coastguard Worker
1662*35238bceSAndroid Build Coastguard Worker if (c00.face == CUBEFACE_LAST || c01.face == CUBEFACE_LAST || c10.face == CUBEFACE_LAST ||
1663*35238bceSAndroid Build Coastguard Worker c11.face == CUBEFACE_LAST)
1664*35238bceSAndroid Build Coastguard Worker return true;
1665*35238bceSAndroid Build Coastguard Worker
1666*35238bceSAndroid Build Coastguard Worker quad1.p00 = lookup<float>(faces1[c00.face], sampler, c00.s, c00.t, 0);
1667*35238bceSAndroid Build Coastguard Worker quad1.p10 = lookup<float>(faces1[c10.face], sampler, c10.s, c10.t, 0);
1668*35238bceSAndroid Build Coastguard Worker quad1.p01 = lookup<float>(faces1[c01.face], sampler, c01.s, c01.t, 0);
1669*35238bceSAndroid Build Coastguard Worker quad1.p11 = lookup<float>(faces1[c11.face], sampler, c11.s, c11.t, 0);
1670*35238bceSAndroid Build Coastguard Worker
1671*35238bceSAndroid Build Coastguard Worker if (texClass == TEXTURECHANNELCLASS_FLOATING_POINT)
1672*35238bceSAndroid Build Coastguard Worker searchStep1 = computeBilinearSearchStepFromFloatQuad(prec, quad1);
1673*35238bceSAndroid Build Coastguard Worker else
1674*35238bceSAndroid Build Coastguard Worker searchStep1 = cSearchStep;
1675*35238bceSAndroid Build Coastguard Worker }
1676*35238bceSAndroid Build Coastguard Worker
1677*35238bceSAndroid Build Coastguard Worker const float minA1 = de::clamp((uBounds1.x() - 0.5f) - float(i1), 0.0f, 1.0f);
1678*35238bceSAndroid Build Coastguard Worker const float maxA1 = de::clamp((uBounds1.y() - 0.5f) - float(i1), 0.0f, 1.0f);
1679*35238bceSAndroid Build Coastguard Worker const float minB1 = de::clamp((vBounds1.x() - 0.5f) - float(j1), 0.0f, 1.0f);
1680*35238bceSAndroid Build Coastguard Worker const float maxB1 = de::clamp((vBounds1.y() - 0.5f) - float(j1), 0.0f, 1.0f);
1681*35238bceSAndroid Build Coastguard Worker
1682*35238bceSAndroid Build Coastguard Worker if (is2DTrilinearFilterResultValid(prec, quad0, quad1, Vec2(minA0, maxA0), Vec2(minB0, maxB0),
1683*35238bceSAndroid Build Coastguard Worker Vec2(minA1, maxA1), Vec2(minB1, maxB1), fBounds,
1684*35238bceSAndroid Build Coastguard Worker de::min(searchStep0, searchStep1), result))
1685*35238bceSAndroid Build Coastguard Worker return true;
1686*35238bceSAndroid Build Coastguard Worker }
1687*35238bceSAndroid Build Coastguard Worker }
1688*35238bceSAndroid Build Coastguard Worker }
1689*35238bceSAndroid Build Coastguard Worker }
1690*35238bceSAndroid Build Coastguard Worker
1691*35238bceSAndroid Build Coastguard Worker return false;
1692*35238bceSAndroid Build Coastguard Worker }
1693*35238bceSAndroid Build Coastguard Worker
isCubeLevelSampleResultValid(const ConstPixelBufferAccess (& level)[CUBEFACE_LAST],const Sampler & sampler,const Sampler::FilterMode filterMode,const LookupPrecision & prec,const CubeFaceFloatCoords & coords,const Vec4 & result)1694*35238bceSAndroid Build Coastguard Worker static bool isCubeLevelSampleResultValid(const ConstPixelBufferAccess (&level)[CUBEFACE_LAST], const Sampler &sampler,
1695*35238bceSAndroid Build Coastguard Worker const Sampler::FilterMode filterMode, const LookupPrecision &prec,
1696*35238bceSAndroid Build Coastguard Worker const CubeFaceFloatCoords &coords, const Vec4 &result)
1697*35238bceSAndroid Build Coastguard Worker {
1698*35238bceSAndroid Build Coastguard Worker if (filterMode == Sampler::LINEAR)
1699*35238bceSAndroid Build Coastguard Worker {
1700*35238bceSAndroid Build Coastguard Worker if (sampler.seamlessCubeMap)
1701*35238bceSAndroid Build Coastguard Worker return isSeamlessLinearSampleResultValid(level, sampler, prec, coords, result);
1702*35238bceSAndroid Build Coastguard Worker else
1703*35238bceSAndroid Build Coastguard Worker return isLinearSampleResultValid(level[coords.face], sampler, prec, Vec2(coords.s, coords.t), 0, result);
1704*35238bceSAndroid Build Coastguard Worker }
1705*35238bceSAndroid Build Coastguard Worker else
1706*35238bceSAndroid Build Coastguard Worker return isNearestSampleResultValid(level[coords.face], sampler, prec, Vec2(coords.s, coords.t), 0, result);
1707*35238bceSAndroid Build Coastguard Worker }
1708*35238bceSAndroid Build Coastguard Worker
isCubeMipmapLinearSampleResultValid(const ConstPixelBufferAccess (& faces0)[CUBEFACE_LAST],const ConstPixelBufferAccess (& faces1)[CUBEFACE_LAST],const Sampler & sampler,const Sampler::FilterMode levelFilter,const LookupPrecision & prec,const CubeFaceFloatCoords & coords,const Vec2 & fBounds,const Vec4 & result)1709*35238bceSAndroid Build Coastguard Worker static bool isCubeMipmapLinearSampleResultValid(const ConstPixelBufferAccess (&faces0)[CUBEFACE_LAST],
1710*35238bceSAndroid Build Coastguard Worker const ConstPixelBufferAccess (&faces1)[CUBEFACE_LAST],
1711*35238bceSAndroid Build Coastguard Worker const Sampler &sampler, const Sampler::FilterMode levelFilter,
1712*35238bceSAndroid Build Coastguard Worker const LookupPrecision &prec, const CubeFaceFloatCoords &coords,
1713*35238bceSAndroid Build Coastguard Worker const Vec2 &fBounds, const Vec4 &result)
1714*35238bceSAndroid Build Coastguard Worker {
1715*35238bceSAndroid Build Coastguard Worker if (levelFilter == Sampler::LINEAR)
1716*35238bceSAndroid Build Coastguard Worker {
1717*35238bceSAndroid Build Coastguard Worker if (sampler.seamlessCubeMap)
1718*35238bceSAndroid Build Coastguard Worker return isSeamplessLinearMipmapLinearSampleResultValid(faces0, faces1, sampler, prec, coords, fBounds,
1719*35238bceSAndroid Build Coastguard Worker result);
1720*35238bceSAndroid Build Coastguard Worker else
1721*35238bceSAndroid Build Coastguard Worker return isLinearMipmapLinearSampleResultValid(faces0[coords.face], faces1[coords.face], sampler, prec,
1722*35238bceSAndroid Build Coastguard Worker Vec2(coords.s, coords.t), 0, fBounds, result);
1723*35238bceSAndroid Build Coastguard Worker }
1724*35238bceSAndroid Build Coastguard Worker else
1725*35238bceSAndroid Build Coastguard Worker return isNearestMipmapLinearSampleResultValid(faces0[coords.face], faces1[coords.face], sampler, prec,
1726*35238bceSAndroid Build Coastguard Worker Vec2(coords.s, coords.t), 0, fBounds, result);
1727*35238bceSAndroid Build Coastguard Worker }
1728*35238bceSAndroid Build Coastguard Worker
getCubeLevelFaces(const TextureCubeView & texture,const int levelNdx,ConstPixelBufferAccess (& out)[CUBEFACE_LAST])1729*35238bceSAndroid Build Coastguard Worker static void getCubeLevelFaces(const TextureCubeView &texture, const int levelNdx,
1730*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess (&out)[CUBEFACE_LAST])
1731*35238bceSAndroid Build Coastguard Worker {
1732*35238bceSAndroid Build Coastguard Worker for (int faceNdx = 0; faceNdx < CUBEFACE_LAST; faceNdx++)
1733*35238bceSAndroid Build Coastguard Worker out[faceNdx] = texture.getLevelFace(levelNdx, (CubeFace)faceNdx);
1734*35238bceSAndroid Build Coastguard Worker }
1735*35238bceSAndroid Build Coastguard Worker
isLookupResultValid(const TextureCubeView & texture,const Sampler & sampler,const LookupPrecision & prec,const Vec3 & coord,const Vec2 & lodBounds,const Vec4 & result)1736*35238bceSAndroid Build Coastguard Worker bool isLookupResultValid(const TextureCubeView &texture, const Sampler &sampler, const LookupPrecision &prec,
1737*35238bceSAndroid Build Coastguard Worker const Vec3 &coord, const Vec2 &lodBounds, const Vec4 &result)
1738*35238bceSAndroid Build Coastguard Worker {
1739*35238bceSAndroid Build Coastguard Worker int numPossibleFaces = 0;
1740*35238bceSAndroid Build Coastguard Worker CubeFace possibleFaces[CUBEFACE_LAST];
1741*35238bceSAndroid Build Coastguard Worker
1742*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
1743*35238bceSAndroid Build Coastguard Worker
1744*35238bceSAndroid Build Coastguard Worker getPossibleCubeFaces(coord, prec.coordBits, &possibleFaces[0], numPossibleFaces);
1745*35238bceSAndroid Build Coastguard Worker
1746*35238bceSAndroid Build Coastguard Worker if (numPossibleFaces == 0)
1747*35238bceSAndroid Build Coastguard Worker return true; // Result is undefined.
1748*35238bceSAndroid Build Coastguard Worker
1749*35238bceSAndroid Build Coastguard Worker for (int tryFaceNdx = 0; tryFaceNdx < numPossibleFaces; tryFaceNdx++)
1750*35238bceSAndroid Build Coastguard Worker {
1751*35238bceSAndroid Build Coastguard Worker const CubeFaceFloatCoords faceCoords(possibleFaces[tryFaceNdx],
1752*35238bceSAndroid Build Coastguard Worker projectToFace(possibleFaces[tryFaceNdx], coord));
1753*35238bceSAndroid Build Coastguard Worker const float minLod = lodBounds.x();
1754*35238bceSAndroid Build Coastguard Worker const float maxLod = lodBounds.y();
1755*35238bceSAndroid Build Coastguard Worker const bool canBeMagnified = minLod <= sampler.lodThreshold;
1756*35238bceSAndroid Build Coastguard Worker const bool canBeMinified = maxLod > sampler.lodThreshold;
1757*35238bceSAndroid Build Coastguard Worker
1758*35238bceSAndroid Build Coastguard Worker if (canBeMagnified)
1759*35238bceSAndroid Build Coastguard Worker {
1760*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess faces[CUBEFACE_LAST];
1761*35238bceSAndroid Build Coastguard Worker getCubeLevelFaces(texture, 0, faces);
1762*35238bceSAndroid Build Coastguard Worker
1763*35238bceSAndroid Build Coastguard Worker if (isCubeLevelSampleResultValid(faces, sampler, sampler.magFilter, prec, faceCoords, result))
1764*35238bceSAndroid Build Coastguard Worker return true;
1765*35238bceSAndroid Build Coastguard Worker }
1766*35238bceSAndroid Build Coastguard Worker
1767*35238bceSAndroid Build Coastguard Worker if (canBeMinified)
1768*35238bceSAndroid Build Coastguard Worker {
1769*35238bceSAndroid Build Coastguard Worker const bool isNearestMipmap = isNearestMipmapFilter(sampler.minFilter);
1770*35238bceSAndroid Build Coastguard Worker const bool isLinearMipmap = isLinearMipmapFilter(sampler.minFilter);
1771*35238bceSAndroid Build Coastguard Worker const int minTexLevel = 0;
1772*35238bceSAndroid Build Coastguard Worker const int maxTexLevel = texture.getNumLevels() - 1;
1773*35238bceSAndroid Build Coastguard Worker
1774*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minTexLevel <= maxTexLevel);
1775*35238bceSAndroid Build Coastguard Worker
1776*35238bceSAndroid Build Coastguard Worker if (isLinearMipmap && minTexLevel < maxTexLevel)
1777*35238bceSAndroid Build Coastguard Worker {
1778*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel - 1);
1779*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel - 1);
1780*35238bceSAndroid Build Coastguard Worker
1781*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1782*35238bceSAndroid Build Coastguard Worker
1783*35238bceSAndroid Build Coastguard Worker for (int levelNdx = minLevel; levelNdx <= maxLevel; levelNdx++)
1784*35238bceSAndroid Build Coastguard Worker {
1785*35238bceSAndroid Build Coastguard Worker const float minF = de::clamp(minLod - float(levelNdx), 0.0f, 1.0f);
1786*35238bceSAndroid Build Coastguard Worker const float maxF = de::clamp(maxLod - float(levelNdx), 0.0f, 1.0f);
1787*35238bceSAndroid Build Coastguard Worker
1788*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess faces0[CUBEFACE_LAST];
1789*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess faces1[CUBEFACE_LAST];
1790*35238bceSAndroid Build Coastguard Worker
1791*35238bceSAndroid Build Coastguard Worker getCubeLevelFaces(texture, levelNdx, faces0);
1792*35238bceSAndroid Build Coastguard Worker getCubeLevelFaces(texture, levelNdx + 1, faces1);
1793*35238bceSAndroid Build Coastguard Worker
1794*35238bceSAndroid Build Coastguard Worker if (isCubeMipmapLinearSampleResultValid(faces0, faces1, sampler, getLevelFilter(sampler.minFilter),
1795*35238bceSAndroid Build Coastguard Worker prec, faceCoords, Vec2(minF, maxF), result))
1796*35238bceSAndroid Build Coastguard Worker return true;
1797*35238bceSAndroid Build Coastguard Worker }
1798*35238bceSAndroid Build Coastguard Worker }
1799*35238bceSAndroid Build Coastguard Worker else if (isNearestMipmap)
1800*35238bceSAndroid Build Coastguard Worker {
1801*35238bceSAndroid Build Coastguard Worker // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
1802*35238bceSAndroid Build Coastguard Worker // decision to allow floor(lod + 0.5) as well.
1803*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatCeil(minLod + 0.5f) - 1, minTexLevel, maxTexLevel);
1804*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod + 0.5f), minTexLevel, maxTexLevel);
1805*35238bceSAndroid Build Coastguard Worker
1806*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1807*35238bceSAndroid Build Coastguard Worker
1808*35238bceSAndroid Build Coastguard Worker for (int levelNdx = minLevel; levelNdx <= maxLevel; levelNdx++)
1809*35238bceSAndroid Build Coastguard Worker {
1810*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess faces[CUBEFACE_LAST];
1811*35238bceSAndroid Build Coastguard Worker getCubeLevelFaces(texture, levelNdx, faces);
1812*35238bceSAndroid Build Coastguard Worker
1813*35238bceSAndroid Build Coastguard Worker if (isCubeLevelSampleResultValid(faces, sampler, getLevelFilter(sampler.minFilter), prec,
1814*35238bceSAndroid Build Coastguard Worker faceCoords, result))
1815*35238bceSAndroid Build Coastguard Worker return true;
1816*35238bceSAndroid Build Coastguard Worker }
1817*35238bceSAndroid Build Coastguard Worker }
1818*35238bceSAndroid Build Coastguard Worker else
1819*35238bceSAndroid Build Coastguard Worker {
1820*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess faces[CUBEFACE_LAST];
1821*35238bceSAndroid Build Coastguard Worker getCubeLevelFaces(texture, 0, faces);
1822*35238bceSAndroid Build Coastguard Worker
1823*35238bceSAndroid Build Coastguard Worker if (isCubeLevelSampleResultValid(faces, sampler, sampler.minFilter, prec, faceCoords, result))
1824*35238bceSAndroid Build Coastguard Worker return true;
1825*35238bceSAndroid Build Coastguard Worker }
1826*35238bceSAndroid Build Coastguard Worker }
1827*35238bceSAndroid Build Coastguard Worker }
1828*35238bceSAndroid Build Coastguard Worker
1829*35238bceSAndroid Build Coastguard Worker return false;
1830*35238bceSAndroid Build Coastguard Worker }
1831*35238bceSAndroid Build Coastguard Worker
computeLayerRange(int numLayers,int numCoordBits,float layerCoord)1832*35238bceSAndroid Build Coastguard Worker static inline IVec2 computeLayerRange(int numLayers, int numCoordBits, float layerCoord)
1833*35238bceSAndroid Build Coastguard Worker {
1834*35238bceSAndroid Build Coastguard Worker const float err = computeFloatingPointError(layerCoord, numCoordBits);
1835*35238bceSAndroid Build Coastguard Worker const int minL = (int)deFloatFloor(layerCoord - err + 0.5f); // Round down
1836*35238bceSAndroid Build Coastguard Worker const int maxL = (int)deFloatCeil(layerCoord + err + 0.5f) - 1; // Round up
1837*35238bceSAndroid Build Coastguard Worker
1838*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minL <= maxL);
1839*35238bceSAndroid Build Coastguard Worker
1840*35238bceSAndroid Build Coastguard Worker return IVec2(de::clamp(minL, 0, numLayers - 1), de::clamp(maxL, 0, numLayers - 1));
1841*35238bceSAndroid Build Coastguard Worker }
1842*35238bceSAndroid Build Coastguard Worker
isLookupResultValid(const Texture1DArrayView & texture,const Sampler & sampler,const LookupPrecision & prec,const Vec2 & coord,const Vec2 & lodBounds,const Vec4 & result)1843*35238bceSAndroid Build Coastguard Worker bool isLookupResultValid(const Texture1DArrayView &texture, const Sampler &sampler, const LookupPrecision &prec,
1844*35238bceSAndroid Build Coastguard Worker const Vec2 &coord, const Vec2 &lodBounds, const Vec4 &result)
1845*35238bceSAndroid Build Coastguard Worker {
1846*35238bceSAndroid Build Coastguard Worker const IVec2 layerRange = computeLayerRange(texture.getNumLayers(), prec.coordBits.y(), coord.y());
1847*35238bceSAndroid Build Coastguard Worker const float coordX = coord.x();
1848*35238bceSAndroid Build Coastguard Worker const float minLod = lodBounds.x();
1849*35238bceSAndroid Build Coastguard Worker const float maxLod = lodBounds.y();
1850*35238bceSAndroid Build Coastguard Worker const bool canBeMagnified = minLod <= sampler.lodThreshold;
1851*35238bceSAndroid Build Coastguard Worker const bool canBeMinified = maxLod > sampler.lodThreshold;
1852*35238bceSAndroid Build Coastguard Worker
1853*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
1854*35238bceSAndroid Build Coastguard Worker
1855*35238bceSAndroid Build Coastguard Worker for (int layer = layerRange.x(); layer <= layerRange.y(); layer++)
1856*35238bceSAndroid Build Coastguard Worker {
1857*35238bceSAndroid Build Coastguard Worker if (canBeMagnified)
1858*35238bceSAndroid Build Coastguard Worker {
1859*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coordX, layer, result))
1860*35238bceSAndroid Build Coastguard Worker return true;
1861*35238bceSAndroid Build Coastguard Worker }
1862*35238bceSAndroid Build Coastguard Worker
1863*35238bceSAndroid Build Coastguard Worker if (canBeMinified)
1864*35238bceSAndroid Build Coastguard Worker {
1865*35238bceSAndroid Build Coastguard Worker const bool isNearestMipmap = isNearestMipmapFilter(sampler.minFilter);
1866*35238bceSAndroid Build Coastguard Worker const bool isLinearMipmap = isLinearMipmapFilter(sampler.minFilter);
1867*35238bceSAndroid Build Coastguard Worker const int minTexLevel = 0;
1868*35238bceSAndroid Build Coastguard Worker const int maxTexLevel = texture.getNumLevels() - 1;
1869*35238bceSAndroid Build Coastguard Worker
1870*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minTexLevel <= maxTexLevel);
1871*35238bceSAndroid Build Coastguard Worker
1872*35238bceSAndroid Build Coastguard Worker if (isLinearMipmap && minTexLevel < maxTexLevel)
1873*35238bceSAndroid Build Coastguard Worker {
1874*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel - 1);
1875*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel - 1);
1876*35238bceSAndroid Build Coastguard Worker
1877*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1878*35238bceSAndroid Build Coastguard Worker
1879*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1880*35238bceSAndroid Build Coastguard Worker {
1881*35238bceSAndroid Build Coastguard Worker const float minF = de::clamp(minLod - float(level), 0.0f, 1.0f);
1882*35238bceSAndroid Build Coastguard Worker const float maxF = de::clamp(maxLod - float(level), 0.0f, 1.0f);
1883*35238bceSAndroid Build Coastguard Worker
1884*35238bceSAndroid Build Coastguard Worker if (isMipmapLinearSampleResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler,
1885*35238bceSAndroid Build Coastguard Worker getLevelFilter(sampler.minFilter), prec, coordX, layer,
1886*35238bceSAndroid Build Coastguard Worker Vec2(minF, maxF), result))
1887*35238bceSAndroid Build Coastguard Worker return true;
1888*35238bceSAndroid Build Coastguard Worker }
1889*35238bceSAndroid Build Coastguard Worker }
1890*35238bceSAndroid Build Coastguard Worker else if (isNearestMipmap)
1891*35238bceSAndroid Build Coastguard Worker {
1892*35238bceSAndroid Build Coastguard Worker // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
1893*35238bceSAndroid Build Coastguard Worker // decision to allow floor(lod + 0.5) as well.
1894*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatCeil(minLod + 0.5f) - 1, minTexLevel, maxTexLevel);
1895*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod + 0.5f), minTexLevel, maxTexLevel);
1896*35238bceSAndroid Build Coastguard Worker
1897*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1898*35238bceSAndroid Build Coastguard Worker
1899*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1900*35238bceSAndroid Build Coastguard Worker {
1901*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter),
1902*35238bceSAndroid Build Coastguard Worker prec, coordX, layer, result))
1903*35238bceSAndroid Build Coastguard Worker return true;
1904*35238bceSAndroid Build Coastguard Worker }
1905*35238bceSAndroid Build Coastguard Worker }
1906*35238bceSAndroid Build Coastguard Worker else
1907*35238bceSAndroid Build Coastguard Worker {
1908*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coordX, layer,
1909*35238bceSAndroid Build Coastguard Worker result))
1910*35238bceSAndroid Build Coastguard Worker return true;
1911*35238bceSAndroid Build Coastguard Worker }
1912*35238bceSAndroid Build Coastguard Worker }
1913*35238bceSAndroid Build Coastguard Worker }
1914*35238bceSAndroid Build Coastguard Worker
1915*35238bceSAndroid Build Coastguard Worker return false;
1916*35238bceSAndroid Build Coastguard Worker }
1917*35238bceSAndroid Build Coastguard Worker
isLookupResultValid(const Texture2DArrayView & texture,const Sampler & sampler,const LookupPrecision & prec,const Vec3 & coord,const Vec2 & lodBounds,const Vec4 & result)1918*35238bceSAndroid Build Coastguard Worker bool isLookupResultValid(const Texture2DArrayView &texture, const Sampler &sampler, const LookupPrecision &prec,
1919*35238bceSAndroid Build Coastguard Worker const Vec3 &coord, const Vec2 &lodBounds, const Vec4 &result)
1920*35238bceSAndroid Build Coastguard Worker {
1921*35238bceSAndroid Build Coastguard Worker const IVec2 layerRange = computeLayerRange(texture.getNumLayers(), prec.coordBits.z(), coord.z());
1922*35238bceSAndroid Build Coastguard Worker const Vec2 coordXY = coord.swizzle(0, 1);
1923*35238bceSAndroid Build Coastguard Worker const float minLod = lodBounds.x();
1924*35238bceSAndroid Build Coastguard Worker const float maxLod = lodBounds.y();
1925*35238bceSAndroid Build Coastguard Worker const bool canBeMagnified = minLod <= sampler.lodThreshold;
1926*35238bceSAndroid Build Coastguard Worker const bool canBeMinified = maxLod > sampler.lodThreshold;
1927*35238bceSAndroid Build Coastguard Worker
1928*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
1929*35238bceSAndroid Build Coastguard Worker
1930*35238bceSAndroid Build Coastguard Worker for (int layer = layerRange.x(); layer <= layerRange.y(); layer++)
1931*35238bceSAndroid Build Coastguard Worker {
1932*35238bceSAndroid Build Coastguard Worker if (canBeMagnified)
1933*35238bceSAndroid Build Coastguard Worker {
1934*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coordXY, layer, result))
1935*35238bceSAndroid Build Coastguard Worker return true;
1936*35238bceSAndroid Build Coastguard Worker }
1937*35238bceSAndroid Build Coastguard Worker
1938*35238bceSAndroid Build Coastguard Worker if (canBeMinified)
1939*35238bceSAndroid Build Coastguard Worker {
1940*35238bceSAndroid Build Coastguard Worker const bool isNearestMipmap = isNearestMipmapFilter(sampler.minFilter);
1941*35238bceSAndroid Build Coastguard Worker const bool isLinearMipmap = isLinearMipmapFilter(sampler.minFilter);
1942*35238bceSAndroid Build Coastguard Worker const int minTexLevel = 0;
1943*35238bceSAndroid Build Coastguard Worker const int maxTexLevel = texture.getNumLevels() - 1;
1944*35238bceSAndroid Build Coastguard Worker
1945*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minTexLevel <= maxTexLevel);
1946*35238bceSAndroid Build Coastguard Worker
1947*35238bceSAndroid Build Coastguard Worker if (isLinearMipmap && minTexLevel < maxTexLevel)
1948*35238bceSAndroid Build Coastguard Worker {
1949*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel - 1);
1950*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel - 1);
1951*35238bceSAndroid Build Coastguard Worker
1952*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1953*35238bceSAndroid Build Coastguard Worker
1954*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1955*35238bceSAndroid Build Coastguard Worker {
1956*35238bceSAndroid Build Coastguard Worker const float minF = de::clamp(minLod - float(level), 0.0f, 1.0f);
1957*35238bceSAndroid Build Coastguard Worker const float maxF = de::clamp(maxLod - float(level), 0.0f, 1.0f);
1958*35238bceSAndroid Build Coastguard Worker
1959*35238bceSAndroid Build Coastguard Worker if (isMipmapLinearSampleResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler,
1960*35238bceSAndroid Build Coastguard Worker getLevelFilter(sampler.minFilter), prec, coordXY, layer,
1961*35238bceSAndroid Build Coastguard Worker Vec2(minF, maxF), result))
1962*35238bceSAndroid Build Coastguard Worker return true;
1963*35238bceSAndroid Build Coastguard Worker }
1964*35238bceSAndroid Build Coastguard Worker }
1965*35238bceSAndroid Build Coastguard Worker else if (isNearestMipmap)
1966*35238bceSAndroid Build Coastguard Worker {
1967*35238bceSAndroid Build Coastguard Worker // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
1968*35238bceSAndroid Build Coastguard Worker // decision to allow floor(lod + 0.5) as well.
1969*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatCeil(minLod + 0.5f) - 1, minTexLevel, maxTexLevel);
1970*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod + 0.5f), minTexLevel, maxTexLevel);
1971*35238bceSAndroid Build Coastguard Worker
1972*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
1973*35238bceSAndroid Build Coastguard Worker
1974*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
1975*35238bceSAndroid Build Coastguard Worker {
1976*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter),
1977*35238bceSAndroid Build Coastguard Worker prec, coordXY, layer, result))
1978*35238bceSAndroid Build Coastguard Worker return true;
1979*35238bceSAndroid Build Coastguard Worker }
1980*35238bceSAndroid Build Coastguard Worker }
1981*35238bceSAndroid Build Coastguard Worker else
1982*35238bceSAndroid Build Coastguard Worker {
1983*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coordXY, layer,
1984*35238bceSAndroid Build Coastguard Worker result))
1985*35238bceSAndroid Build Coastguard Worker return true;
1986*35238bceSAndroid Build Coastguard Worker }
1987*35238bceSAndroid Build Coastguard Worker }
1988*35238bceSAndroid Build Coastguard Worker }
1989*35238bceSAndroid Build Coastguard Worker
1990*35238bceSAndroid Build Coastguard Worker return false;
1991*35238bceSAndroid Build Coastguard Worker }
1992*35238bceSAndroid Build Coastguard Worker
isLevelSampleResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const Sampler::FilterMode filterMode,const LookupPrecision & prec,const Vec3 & coord,const Vec4 & result)1993*35238bceSAndroid Build Coastguard Worker static bool isLevelSampleResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
1994*35238bceSAndroid Build Coastguard Worker const Sampler::FilterMode filterMode, const LookupPrecision &prec,
1995*35238bceSAndroid Build Coastguard Worker const Vec3 &coord, const Vec4 &result)
1996*35238bceSAndroid Build Coastguard Worker {
1997*35238bceSAndroid Build Coastguard Worker if (filterMode == Sampler::LINEAR)
1998*35238bceSAndroid Build Coastguard Worker return isLinearSampleResultValid(level, sampler, prec, coord, result);
1999*35238bceSAndroid Build Coastguard Worker else
2000*35238bceSAndroid Build Coastguard Worker return isNearestSampleResultValid(level, sampler, prec, coord, result);
2001*35238bceSAndroid Build Coastguard Worker }
2002*35238bceSAndroid Build Coastguard Worker
isMipmapLinearSampleResultValid(const ConstPixelBufferAccess & level0,const ConstPixelBufferAccess & level1,const Sampler & sampler,const Sampler::FilterMode levelFilter,const LookupPrecision & prec,const Vec3 & coord,const Vec2 & fBounds,const Vec4 & result)2003*35238bceSAndroid Build Coastguard Worker static bool isMipmapLinearSampleResultValid(const ConstPixelBufferAccess &level0, const ConstPixelBufferAccess &level1,
2004*35238bceSAndroid Build Coastguard Worker const Sampler &sampler, const Sampler::FilterMode levelFilter,
2005*35238bceSAndroid Build Coastguard Worker const LookupPrecision &prec, const Vec3 &coord, const Vec2 &fBounds,
2006*35238bceSAndroid Build Coastguard Worker const Vec4 &result)
2007*35238bceSAndroid Build Coastguard Worker {
2008*35238bceSAndroid Build Coastguard Worker if (levelFilter == Sampler::LINEAR)
2009*35238bceSAndroid Build Coastguard Worker return isLinearMipmapLinearSampleResultValid(level0, level1, sampler, prec, coord, fBounds, result);
2010*35238bceSAndroid Build Coastguard Worker else
2011*35238bceSAndroid Build Coastguard Worker return isNearestMipmapLinearSampleResultValid(level0, level1, sampler, prec, coord, fBounds, result);
2012*35238bceSAndroid Build Coastguard Worker }
2013*35238bceSAndroid Build Coastguard Worker
isLookupResultValid(const Texture3DView & texture,const Sampler & sampler,const LookupPrecision & prec,const Vec3 & coord,const Vec2 & lodBounds,const Vec4 & result)2014*35238bceSAndroid Build Coastguard Worker bool isLookupResultValid(const Texture3DView &texture, const Sampler &sampler, const LookupPrecision &prec,
2015*35238bceSAndroid Build Coastguard Worker const Vec3 &coord, const Vec2 &lodBounds, const Vec4 &result)
2016*35238bceSAndroid Build Coastguard Worker {
2017*35238bceSAndroid Build Coastguard Worker const float minLod = lodBounds.x();
2018*35238bceSAndroid Build Coastguard Worker const float maxLod = lodBounds.y();
2019*35238bceSAndroid Build Coastguard Worker const bool canBeMagnified = minLod <= sampler.lodThreshold;
2020*35238bceSAndroid Build Coastguard Worker const bool canBeMinified = maxLod > sampler.lodThreshold;
2021*35238bceSAndroid Build Coastguard Worker
2022*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
2023*35238bceSAndroid Build Coastguard Worker
2024*35238bceSAndroid Build Coastguard Worker if (canBeMagnified)
2025*35238bceSAndroid Build Coastguard Worker {
2026*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, result))
2027*35238bceSAndroid Build Coastguard Worker return true;
2028*35238bceSAndroid Build Coastguard Worker }
2029*35238bceSAndroid Build Coastguard Worker
2030*35238bceSAndroid Build Coastguard Worker if (canBeMinified)
2031*35238bceSAndroid Build Coastguard Worker {
2032*35238bceSAndroid Build Coastguard Worker const bool isNearestMipmap = isNearestMipmapFilter(sampler.minFilter);
2033*35238bceSAndroid Build Coastguard Worker const bool isLinearMipmap = isLinearMipmapFilter(sampler.minFilter);
2034*35238bceSAndroid Build Coastguard Worker const int minTexLevel = 0;
2035*35238bceSAndroid Build Coastguard Worker const int maxTexLevel = texture.getNumLevels() - 1;
2036*35238bceSAndroid Build Coastguard Worker
2037*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minTexLevel <= maxTexLevel);
2038*35238bceSAndroid Build Coastguard Worker
2039*35238bceSAndroid Build Coastguard Worker if (isLinearMipmap && minTexLevel < maxTexLevel)
2040*35238bceSAndroid Build Coastguard Worker {
2041*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel - 1);
2042*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel - 1);
2043*35238bceSAndroid Build Coastguard Worker
2044*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
2045*35238bceSAndroid Build Coastguard Worker
2046*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
2047*35238bceSAndroid Build Coastguard Worker {
2048*35238bceSAndroid Build Coastguard Worker const float minF = de::clamp(minLod - float(level), 0.0f, 1.0f);
2049*35238bceSAndroid Build Coastguard Worker const float maxF = de::clamp(maxLod - float(level), 0.0f, 1.0f);
2050*35238bceSAndroid Build Coastguard Worker
2051*35238bceSAndroid Build Coastguard Worker if (isMipmapLinearSampleResultValid(texture.getLevel(level), texture.getLevel(level + 1), sampler,
2052*35238bceSAndroid Build Coastguard Worker getLevelFilter(sampler.minFilter), prec, coord, Vec2(minF, maxF),
2053*35238bceSAndroid Build Coastguard Worker result))
2054*35238bceSAndroid Build Coastguard Worker return true;
2055*35238bceSAndroid Build Coastguard Worker }
2056*35238bceSAndroid Build Coastguard Worker }
2057*35238bceSAndroid Build Coastguard Worker else if (isNearestMipmap)
2058*35238bceSAndroid Build Coastguard Worker {
2059*35238bceSAndroid Build Coastguard Worker // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
2060*35238bceSAndroid Build Coastguard Worker // decision to allow floor(lod + 0.5) as well.
2061*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatCeil(minLod + 0.5f) - 1, minTexLevel, maxTexLevel);
2062*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod + 0.5f), minTexLevel, maxTexLevel);
2063*35238bceSAndroid Build Coastguard Worker
2064*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
2065*35238bceSAndroid Build Coastguard Worker
2066*35238bceSAndroid Build Coastguard Worker for (int level = minLevel; level <= maxLevel; level++)
2067*35238bceSAndroid Build Coastguard Worker {
2068*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter), prec,
2069*35238bceSAndroid Build Coastguard Worker coord, result))
2070*35238bceSAndroid Build Coastguard Worker return true;
2071*35238bceSAndroid Build Coastguard Worker }
2072*35238bceSAndroid Build Coastguard Worker }
2073*35238bceSAndroid Build Coastguard Worker else
2074*35238bceSAndroid Build Coastguard Worker {
2075*35238bceSAndroid Build Coastguard Worker if (isLevelSampleResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, result))
2076*35238bceSAndroid Build Coastguard Worker return true;
2077*35238bceSAndroid Build Coastguard Worker }
2078*35238bceSAndroid Build Coastguard Worker }
2079*35238bceSAndroid Build Coastguard Worker
2080*35238bceSAndroid Build Coastguard Worker return false;
2081*35238bceSAndroid Build Coastguard Worker }
2082*35238bceSAndroid Build Coastguard Worker
getCubeArrayLevelFaces(const TextureCubeArrayView & texture,const int levelNdx,const int layerNdx,ConstPixelBufferAccess (& out)[CUBEFACE_LAST])2083*35238bceSAndroid Build Coastguard Worker static void getCubeArrayLevelFaces(const TextureCubeArrayView &texture, const int levelNdx, const int layerNdx,
2084*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess (&out)[CUBEFACE_LAST])
2085*35238bceSAndroid Build Coastguard Worker {
2086*35238bceSAndroid Build Coastguard Worker const ConstPixelBufferAccess &level = texture.getLevel(levelNdx);
2087*35238bceSAndroid Build Coastguard Worker const int layerDepth = layerNdx * 6;
2088*35238bceSAndroid Build Coastguard Worker
2089*35238bceSAndroid Build Coastguard Worker for (int faceNdx = 0; faceNdx < CUBEFACE_LAST; faceNdx++)
2090*35238bceSAndroid Build Coastguard Worker {
2091*35238bceSAndroid Build Coastguard Worker const CubeFace face = (CubeFace)faceNdx;
2092*35238bceSAndroid Build Coastguard Worker out[faceNdx] =
2093*35238bceSAndroid Build Coastguard Worker getSubregion(level, 0, 0, layerDepth + getCubeArrayFaceIndex(face), level.getWidth(), level.getHeight(), 1);
2094*35238bceSAndroid Build Coastguard Worker }
2095*35238bceSAndroid Build Coastguard Worker }
2096*35238bceSAndroid Build Coastguard Worker
isLookupResultValid(const TextureCubeArrayView & texture,const Sampler & sampler,const LookupPrecision & prec,const IVec4 & coordBits,const Vec4 & coord,const Vec2 & lodBounds,const Vec4 & result)2097*35238bceSAndroid Build Coastguard Worker bool isLookupResultValid(const TextureCubeArrayView &texture, const Sampler &sampler, const LookupPrecision &prec,
2098*35238bceSAndroid Build Coastguard Worker const IVec4 &coordBits, const Vec4 &coord, const Vec2 &lodBounds, const Vec4 &result)
2099*35238bceSAndroid Build Coastguard Worker {
2100*35238bceSAndroid Build Coastguard Worker const IVec2 layerRange = computeLayerRange(texture.getNumLayers(), coordBits.w(), coord.w());
2101*35238bceSAndroid Build Coastguard Worker const Vec3 layerCoord = coord.toWidth<3>();
2102*35238bceSAndroid Build Coastguard Worker int numPossibleFaces = 0;
2103*35238bceSAndroid Build Coastguard Worker CubeFace possibleFaces[CUBEFACE_LAST];
2104*35238bceSAndroid Build Coastguard Worker
2105*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSamplerSupported(sampler));
2106*35238bceSAndroid Build Coastguard Worker
2107*35238bceSAndroid Build Coastguard Worker getPossibleCubeFaces(layerCoord, prec.coordBits, &possibleFaces[0], numPossibleFaces);
2108*35238bceSAndroid Build Coastguard Worker
2109*35238bceSAndroid Build Coastguard Worker if (numPossibleFaces == 0)
2110*35238bceSAndroid Build Coastguard Worker return true; // Result is undefined.
2111*35238bceSAndroid Build Coastguard Worker
2112*35238bceSAndroid Build Coastguard Worker for (int layerNdx = layerRange.x(); layerNdx <= layerRange.y(); layerNdx++)
2113*35238bceSAndroid Build Coastguard Worker {
2114*35238bceSAndroid Build Coastguard Worker for (int tryFaceNdx = 0; tryFaceNdx < numPossibleFaces; tryFaceNdx++)
2115*35238bceSAndroid Build Coastguard Worker {
2116*35238bceSAndroid Build Coastguard Worker const CubeFaceFloatCoords faceCoords(possibleFaces[tryFaceNdx],
2117*35238bceSAndroid Build Coastguard Worker projectToFace(possibleFaces[tryFaceNdx], layerCoord));
2118*35238bceSAndroid Build Coastguard Worker const float minLod = lodBounds.x();
2119*35238bceSAndroid Build Coastguard Worker const float maxLod = lodBounds.y();
2120*35238bceSAndroid Build Coastguard Worker const bool canBeMagnified = minLod <= sampler.lodThreshold;
2121*35238bceSAndroid Build Coastguard Worker const bool canBeMinified = maxLod > sampler.lodThreshold;
2122*35238bceSAndroid Build Coastguard Worker
2123*35238bceSAndroid Build Coastguard Worker if (canBeMagnified)
2124*35238bceSAndroid Build Coastguard Worker {
2125*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess faces[CUBEFACE_LAST];
2126*35238bceSAndroid Build Coastguard Worker getCubeArrayLevelFaces(texture, 0, layerNdx, faces);
2127*35238bceSAndroid Build Coastguard Worker
2128*35238bceSAndroid Build Coastguard Worker if (isCubeLevelSampleResultValid(faces, sampler, sampler.magFilter, prec, faceCoords, result))
2129*35238bceSAndroid Build Coastguard Worker return true;
2130*35238bceSAndroid Build Coastguard Worker }
2131*35238bceSAndroid Build Coastguard Worker
2132*35238bceSAndroid Build Coastguard Worker if (canBeMinified)
2133*35238bceSAndroid Build Coastguard Worker {
2134*35238bceSAndroid Build Coastguard Worker const bool isNearestMipmap = isNearestMipmapFilter(sampler.minFilter);
2135*35238bceSAndroid Build Coastguard Worker const bool isLinearMipmap = isLinearMipmapFilter(sampler.minFilter);
2136*35238bceSAndroid Build Coastguard Worker const int minTexLevel = 0;
2137*35238bceSAndroid Build Coastguard Worker const int maxTexLevel = texture.getNumLevels() - 1;
2138*35238bceSAndroid Build Coastguard Worker
2139*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minTexLevel <= maxTexLevel);
2140*35238bceSAndroid Build Coastguard Worker
2141*35238bceSAndroid Build Coastguard Worker if (isLinearMipmap && minTexLevel < maxTexLevel)
2142*35238bceSAndroid Build Coastguard Worker {
2143*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel - 1);
2144*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel - 1);
2145*35238bceSAndroid Build Coastguard Worker
2146*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
2147*35238bceSAndroid Build Coastguard Worker
2148*35238bceSAndroid Build Coastguard Worker for (int levelNdx = minLevel; levelNdx <= maxLevel; levelNdx++)
2149*35238bceSAndroid Build Coastguard Worker {
2150*35238bceSAndroid Build Coastguard Worker const float minF = de::clamp(minLod - float(levelNdx), 0.0f, 1.0f);
2151*35238bceSAndroid Build Coastguard Worker const float maxF = de::clamp(maxLod - float(levelNdx), 0.0f, 1.0f);
2152*35238bceSAndroid Build Coastguard Worker
2153*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess faces0[CUBEFACE_LAST];
2154*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess faces1[CUBEFACE_LAST];
2155*35238bceSAndroid Build Coastguard Worker
2156*35238bceSAndroid Build Coastguard Worker getCubeArrayLevelFaces(texture, levelNdx, layerNdx, faces0);
2157*35238bceSAndroid Build Coastguard Worker getCubeArrayLevelFaces(texture, levelNdx + 1, layerNdx, faces1);
2158*35238bceSAndroid Build Coastguard Worker
2159*35238bceSAndroid Build Coastguard Worker if (isCubeMipmapLinearSampleResultValid(faces0, faces1, sampler,
2160*35238bceSAndroid Build Coastguard Worker getLevelFilter(sampler.minFilter), prec, faceCoords,
2161*35238bceSAndroid Build Coastguard Worker Vec2(minF, maxF), result))
2162*35238bceSAndroid Build Coastguard Worker return true;
2163*35238bceSAndroid Build Coastguard Worker }
2164*35238bceSAndroid Build Coastguard Worker }
2165*35238bceSAndroid Build Coastguard Worker else if (isNearestMipmap)
2166*35238bceSAndroid Build Coastguard Worker {
2167*35238bceSAndroid Build Coastguard Worker // \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
2168*35238bceSAndroid Build Coastguard Worker // decision to allow floor(lod + 0.5) as well.
2169*35238bceSAndroid Build Coastguard Worker const int minLevel = de::clamp((int)deFloatCeil(minLod + 0.5f) - 1, minTexLevel, maxTexLevel);
2170*35238bceSAndroid Build Coastguard Worker const int maxLevel = de::clamp((int)deFloatFloor(maxLod + 0.5f), minTexLevel, maxTexLevel);
2171*35238bceSAndroid Build Coastguard Worker
2172*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLevel <= maxLevel);
2173*35238bceSAndroid Build Coastguard Worker
2174*35238bceSAndroid Build Coastguard Worker for (int levelNdx = minLevel; levelNdx <= maxLevel; levelNdx++)
2175*35238bceSAndroid Build Coastguard Worker {
2176*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess faces[CUBEFACE_LAST];
2177*35238bceSAndroid Build Coastguard Worker getCubeArrayLevelFaces(texture, levelNdx, layerNdx, faces);
2178*35238bceSAndroid Build Coastguard Worker
2179*35238bceSAndroid Build Coastguard Worker if (isCubeLevelSampleResultValid(faces, sampler, getLevelFilter(sampler.minFilter), prec,
2180*35238bceSAndroid Build Coastguard Worker faceCoords, result))
2181*35238bceSAndroid Build Coastguard Worker return true;
2182*35238bceSAndroid Build Coastguard Worker }
2183*35238bceSAndroid Build Coastguard Worker }
2184*35238bceSAndroid Build Coastguard Worker else
2185*35238bceSAndroid Build Coastguard Worker {
2186*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess faces[CUBEFACE_LAST];
2187*35238bceSAndroid Build Coastguard Worker getCubeArrayLevelFaces(texture, 0, layerNdx, faces);
2188*35238bceSAndroid Build Coastguard Worker
2189*35238bceSAndroid Build Coastguard Worker if (isCubeLevelSampleResultValid(faces, sampler, sampler.minFilter, prec, faceCoords, result))
2190*35238bceSAndroid Build Coastguard Worker return true;
2191*35238bceSAndroid Build Coastguard Worker }
2192*35238bceSAndroid Build Coastguard Worker }
2193*35238bceSAndroid Build Coastguard Worker }
2194*35238bceSAndroid Build Coastguard Worker }
2195*35238bceSAndroid Build Coastguard Worker
2196*35238bceSAndroid Build Coastguard Worker return false;
2197*35238bceSAndroid Build Coastguard Worker }
2198*35238bceSAndroid Build Coastguard Worker
computeFixedPointThreshold(const IVec4 & bits)2199*35238bceSAndroid Build Coastguard Worker Vec4 computeFixedPointThreshold(const IVec4 &bits)
2200*35238bceSAndroid Build Coastguard Worker {
2201*35238bceSAndroid Build Coastguard Worker return computeFixedPointError(bits);
2202*35238bceSAndroid Build Coastguard Worker }
2203*35238bceSAndroid Build Coastguard Worker
computeFloatingPointThreshold(const IVec4 & bits,const Vec4 & value)2204*35238bceSAndroid Build Coastguard Worker Vec4 computeFloatingPointThreshold(const IVec4 &bits, const Vec4 &value)
2205*35238bceSAndroid Build Coastguard Worker {
2206*35238bceSAndroid Build Coastguard Worker return computeFloatingPointError(value, bits);
2207*35238bceSAndroid Build Coastguard Worker }
2208*35238bceSAndroid Build Coastguard Worker
computeColorBitsThreshold(const IVec4 & bits,const IVec4 & numAccurateBits)2209*35238bceSAndroid Build Coastguard Worker Vec4 computeColorBitsThreshold(const IVec4 &bits, const IVec4 &numAccurateBits)
2210*35238bceSAndroid Build Coastguard Worker {
2211*35238bceSAndroid Build Coastguard Worker return computeColorBitsError(bits, numAccurateBits);
2212*35238bceSAndroid Build Coastguard Worker }
2213*35238bceSAndroid Build Coastguard Worker
computeLodBoundsFromDerivates(const float dudx,const float dvdx,const float dwdx,const float dudy,const float dvdy,const float dwdy,const LodPrecision & prec)2214*35238bceSAndroid Build Coastguard Worker Vec2 computeLodBoundsFromDerivates(const float dudx, const float dvdx, const float dwdx, const float dudy,
2215*35238bceSAndroid Build Coastguard Worker const float dvdy, const float dwdy, const LodPrecision &prec)
2216*35238bceSAndroid Build Coastguard Worker {
2217*35238bceSAndroid Build Coastguard Worker const float mux = deFloatAbs(dudx);
2218*35238bceSAndroid Build Coastguard Worker const float mvx = deFloatAbs(dvdx);
2219*35238bceSAndroid Build Coastguard Worker const float mwx = deFloatAbs(dwdx);
2220*35238bceSAndroid Build Coastguard Worker const float muy = deFloatAbs(dudy);
2221*35238bceSAndroid Build Coastguard Worker const float mvy = deFloatAbs(dvdy);
2222*35238bceSAndroid Build Coastguard Worker const float mwy = deFloatAbs(dwdy);
2223*35238bceSAndroid Build Coastguard Worker
2224*35238bceSAndroid Build Coastguard Worker // Ideal:
2225*35238bceSAndroid Build Coastguard Worker // px = deFloatSqrt2(mux*mux + mvx*mvx + mwx*mwx);
2226*35238bceSAndroid Build Coastguard Worker // py = deFloatSqrt2(muy*muy + mvy*mvy + mwy*mwy);
2227*35238bceSAndroid Build Coastguard Worker
2228*35238bceSAndroid Build Coastguard Worker // fx, fy estimate lower bounds
2229*35238bceSAndroid Build Coastguard Worker const float fxMin = de::max(de::max(mux, mvx), mwx);
2230*35238bceSAndroid Build Coastguard Worker const float fyMin = de::max(de::max(muy, mvy), mwy);
2231*35238bceSAndroid Build Coastguard Worker
2232*35238bceSAndroid Build Coastguard Worker // fx, fy estimate upper bounds
2233*35238bceSAndroid Build Coastguard Worker const float sqrt2 = deFloatSqrt(2.0f);
2234*35238bceSAndroid Build Coastguard Worker const float fxMax = sqrt2 * (mux + mvx + mwx);
2235*35238bceSAndroid Build Coastguard Worker const float fyMax = sqrt2 * (muy + mvy + mwy);
2236*35238bceSAndroid Build Coastguard Worker
2237*35238bceSAndroid Build Coastguard Worker // p = max(px, py) (isotropic filtering)
2238*35238bceSAndroid Build Coastguard Worker const float pMin = de::max(fxMin, fyMin);
2239*35238bceSAndroid Build Coastguard Worker const float pMax = de::max(fxMax, fyMax);
2240*35238bceSAndroid Build Coastguard Worker
2241*35238bceSAndroid Build Coastguard Worker // error terms
2242*35238bceSAndroid Build Coastguard Worker const float pMinErr = computeFloatingPointError(pMin, prec.derivateBits);
2243*35238bceSAndroid Build Coastguard Worker const float pMaxErr = computeFloatingPointError(pMax, prec.derivateBits);
2244*35238bceSAndroid Build Coastguard Worker
2245*35238bceSAndroid Build Coastguard Worker const float minLod = deFloatLog2(pMin - pMinErr);
2246*35238bceSAndroid Build Coastguard Worker const float maxLod = deFloatLog2(pMax + pMaxErr);
2247*35238bceSAndroid Build Coastguard Worker const float lodErr = computeFixedPointError(prec.lodBits);
2248*35238bceSAndroid Build Coastguard Worker
2249*35238bceSAndroid Build Coastguard Worker DE_ASSERT(minLod <= maxLod);
2250*35238bceSAndroid Build Coastguard Worker return Vec2(minLod - lodErr, maxLod + lodErr);
2251*35238bceSAndroid Build Coastguard Worker }
2252*35238bceSAndroid Build Coastguard Worker
computeLodBoundsFromDerivates(const float dudx,const float dvdx,const float dudy,const float dvdy,const LodPrecision & prec)2253*35238bceSAndroid Build Coastguard Worker Vec2 computeLodBoundsFromDerivates(const float dudx, const float dvdx, const float dudy, const float dvdy,
2254*35238bceSAndroid Build Coastguard Worker const LodPrecision &prec)
2255*35238bceSAndroid Build Coastguard Worker {
2256*35238bceSAndroid Build Coastguard Worker return computeLodBoundsFromDerivates(dudx, dvdx, 0.0f, dudy, dvdy, 0.0f, prec);
2257*35238bceSAndroid Build Coastguard Worker }
2258*35238bceSAndroid Build Coastguard Worker
computeLodBoundsFromDerivates(const float dudx,const float dudy,const LodPrecision & prec)2259*35238bceSAndroid Build Coastguard Worker Vec2 computeLodBoundsFromDerivates(const float dudx, const float dudy, const LodPrecision &prec)
2260*35238bceSAndroid Build Coastguard Worker {
2261*35238bceSAndroid Build Coastguard Worker return computeLodBoundsFromDerivates(dudx, 0.0f, 0.0f, dudy, 0.0f, 0.0f, prec);
2262*35238bceSAndroid Build Coastguard Worker }
2263*35238bceSAndroid Build Coastguard Worker
computeCubeLodBoundsFromDerivates(const Vec3 & coord,const Vec3 & coordDx,const Vec3 & coordDy,const int faceSize,const LodPrecision & prec)2264*35238bceSAndroid Build Coastguard Worker Vec2 computeCubeLodBoundsFromDerivates(const Vec3 &coord, const Vec3 &coordDx, const Vec3 &coordDy, const int faceSize,
2265*35238bceSAndroid Build Coastguard Worker const LodPrecision &prec)
2266*35238bceSAndroid Build Coastguard Worker {
2267*35238bceSAndroid Build Coastguard Worker const bool allowBrokenEdgeDerivate = false;
2268*35238bceSAndroid Build Coastguard Worker const CubeFace face = selectCubeFace(coord);
2269*35238bceSAndroid Build Coastguard Worker int maNdx = 0;
2270*35238bceSAndroid Build Coastguard Worker int sNdx = 0;
2271*35238bceSAndroid Build Coastguard Worker int tNdx = 0;
2272*35238bceSAndroid Build Coastguard Worker
2273*35238bceSAndroid Build Coastguard Worker // \note Derivate signs don't matter when computing lod
2274*35238bceSAndroid Build Coastguard Worker switch (face)
2275*35238bceSAndroid Build Coastguard Worker {
2276*35238bceSAndroid Build Coastguard Worker case CUBEFACE_NEGATIVE_X:
2277*35238bceSAndroid Build Coastguard Worker case CUBEFACE_POSITIVE_X:
2278*35238bceSAndroid Build Coastguard Worker maNdx = 0;
2279*35238bceSAndroid Build Coastguard Worker sNdx = 2;
2280*35238bceSAndroid Build Coastguard Worker tNdx = 1;
2281*35238bceSAndroid Build Coastguard Worker break;
2282*35238bceSAndroid Build Coastguard Worker case CUBEFACE_NEGATIVE_Y:
2283*35238bceSAndroid Build Coastguard Worker case CUBEFACE_POSITIVE_Y:
2284*35238bceSAndroid Build Coastguard Worker maNdx = 1;
2285*35238bceSAndroid Build Coastguard Worker sNdx = 0;
2286*35238bceSAndroid Build Coastguard Worker tNdx = 2;
2287*35238bceSAndroid Build Coastguard Worker break;
2288*35238bceSAndroid Build Coastguard Worker case CUBEFACE_NEGATIVE_Z:
2289*35238bceSAndroid Build Coastguard Worker case CUBEFACE_POSITIVE_Z:
2290*35238bceSAndroid Build Coastguard Worker maNdx = 2;
2291*35238bceSAndroid Build Coastguard Worker sNdx = 0;
2292*35238bceSAndroid Build Coastguard Worker tNdx = 1;
2293*35238bceSAndroid Build Coastguard Worker break;
2294*35238bceSAndroid Build Coastguard Worker default:
2295*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
2296*35238bceSAndroid Build Coastguard Worker }
2297*35238bceSAndroid Build Coastguard Worker
2298*35238bceSAndroid Build Coastguard Worker {
2299*35238bceSAndroid Build Coastguard Worker const float sc = coord[sNdx];
2300*35238bceSAndroid Build Coastguard Worker const float tc = coord[tNdx];
2301*35238bceSAndroid Build Coastguard Worker const float ma = de::abs(coord[maNdx]);
2302*35238bceSAndroid Build Coastguard Worker const float scdx = coordDx[sNdx];
2303*35238bceSAndroid Build Coastguard Worker const float tcdx = coordDx[tNdx];
2304*35238bceSAndroid Build Coastguard Worker const float madx = de::abs(coordDx[maNdx]);
2305*35238bceSAndroid Build Coastguard Worker const float scdy = coordDy[sNdx];
2306*35238bceSAndroid Build Coastguard Worker const float tcdy = coordDy[tNdx];
2307*35238bceSAndroid Build Coastguard Worker const float mady = de::abs(coordDy[maNdx]);
2308*35238bceSAndroid Build Coastguard Worker const float dudx = float(faceSize) * 0.5f * (scdx * ma - sc * madx) / (ma * ma);
2309*35238bceSAndroid Build Coastguard Worker const float dvdx = float(faceSize) * 0.5f * (tcdx * ma - tc * madx) / (ma * ma);
2310*35238bceSAndroid Build Coastguard Worker const float dudy = float(faceSize) * 0.5f * (scdy * ma - sc * mady) / (ma * ma);
2311*35238bceSAndroid Build Coastguard Worker const float dvdy = float(faceSize) * 0.5f * (tcdy * ma - tc * mady) / (ma * ma);
2312*35238bceSAndroid Build Coastguard Worker const Vec2 bounds = computeLodBoundsFromDerivates(dudx, dvdx, dudy, dvdy, prec);
2313*35238bceSAndroid Build Coastguard Worker
2314*35238bceSAndroid Build Coastguard Worker // Implementations may compute derivate from projected (s, t) resulting in incorrect values at edges.
2315*35238bceSAndroid Build Coastguard Worker if (allowBrokenEdgeDerivate)
2316*35238bceSAndroid Build Coastguard Worker {
2317*35238bceSAndroid Build Coastguard Worker const Vec3 dxErr = computeFloatingPointError(coordDx, IVec3(prec.derivateBits));
2318*35238bceSAndroid Build Coastguard Worker const Vec3 dyErr = computeFloatingPointError(coordDy, IVec3(prec.derivateBits));
2319*35238bceSAndroid Build Coastguard Worker const Vec3 xoffs = abs(coordDx) + dxErr;
2320*35238bceSAndroid Build Coastguard Worker const Vec3 yoffs = abs(coordDy) + dyErr;
2321*35238bceSAndroid Build Coastguard Worker
2322*35238bceSAndroid Build Coastguard Worker if (selectCubeFace(coord + xoffs) != face || selectCubeFace(coord - xoffs) != face ||
2323*35238bceSAndroid Build Coastguard Worker selectCubeFace(coord + yoffs) != face || selectCubeFace(coord - yoffs) != face)
2324*35238bceSAndroid Build Coastguard Worker {
2325*35238bceSAndroid Build Coastguard Worker return Vec2(bounds.x(), 1000.0f);
2326*35238bceSAndroid Build Coastguard Worker }
2327*35238bceSAndroid Build Coastguard Worker }
2328*35238bceSAndroid Build Coastguard Worker
2329*35238bceSAndroid Build Coastguard Worker return bounds;
2330*35238bceSAndroid Build Coastguard Worker }
2331*35238bceSAndroid Build Coastguard Worker }
2332*35238bceSAndroid Build Coastguard Worker
clampLodBounds(const Vec2 & lodBounds,const Vec2 & lodMinMax,const LodPrecision & prec)2333*35238bceSAndroid Build Coastguard Worker Vec2 clampLodBounds(const Vec2 &lodBounds, const Vec2 &lodMinMax, const LodPrecision &prec)
2334*35238bceSAndroid Build Coastguard Worker {
2335*35238bceSAndroid Build Coastguard Worker const float lodErr = computeFixedPointError(prec.lodBits);
2336*35238bceSAndroid Build Coastguard Worker const float a = lodMinMax.x();
2337*35238bceSAndroid Build Coastguard Worker const float b = lodMinMax.y();
2338*35238bceSAndroid Build Coastguard Worker return Vec2(de::clamp(lodBounds.x(), a - lodErr, b - lodErr), de::clamp(lodBounds.y(), a + lodErr, b + lodErr));
2339*35238bceSAndroid Build Coastguard Worker }
2340*35238bceSAndroid Build Coastguard Worker
isLevel1DLookupResultValid(const ConstPixelBufferAccess & access,const Sampler & sampler,TexLookupScaleMode scaleMode,const LookupPrecision & prec,const float coordX,const int coordY,const Vec4 & result)2341*35238bceSAndroid Build Coastguard Worker bool isLevel1DLookupResultValid(const ConstPixelBufferAccess &access, const Sampler &sampler,
2342*35238bceSAndroid Build Coastguard Worker TexLookupScaleMode scaleMode, const LookupPrecision &prec, const float coordX,
2343*35238bceSAndroid Build Coastguard Worker const int coordY, const Vec4 &result)
2344*35238bceSAndroid Build Coastguard Worker {
2345*35238bceSAndroid Build Coastguard Worker const Sampler::FilterMode filterMode =
2346*35238bceSAndroid Build Coastguard Worker scaleMode == TEX_LOOKUP_SCALE_MAGNIFY ? sampler.magFilter : sampler.minFilter;
2347*35238bceSAndroid Build Coastguard Worker return isLevelSampleResultValid(access, sampler, filterMode, prec, coordX, coordY, result);
2348*35238bceSAndroid Build Coastguard Worker }
2349*35238bceSAndroid Build Coastguard Worker
isLevel1DLookupResultValid(const ConstPixelBufferAccess & access,const Sampler & sampler,TexLookupScaleMode scaleMode,const IntLookupPrecision & prec,const float coordX,const int coordY,const IVec4 & result)2350*35238bceSAndroid Build Coastguard Worker bool isLevel1DLookupResultValid(const ConstPixelBufferAccess &access, const Sampler &sampler,
2351*35238bceSAndroid Build Coastguard Worker TexLookupScaleMode scaleMode, const IntLookupPrecision &prec, const float coordX,
2352*35238bceSAndroid Build Coastguard Worker const int coordY, const IVec4 &result)
2353*35238bceSAndroid Build Coastguard Worker {
2354*35238bceSAndroid Build Coastguard Worker DE_ASSERT(sampler.minFilter == Sampler::NEAREST && sampler.magFilter == Sampler::NEAREST);
2355*35238bceSAndroid Build Coastguard Worker DE_UNREF(scaleMode);
2356*35238bceSAndroid Build Coastguard Worker return isNearestSampleResultValid(access, sampler, prec, coordX, coordY, result);
2357*35238bceSAndroid Build Coastguard Worker }
2358*35238bceSAndroid Build Coastguard Worker
isLevel1DLookupResultValid(const ConstPixelBufferAccess & access,const Sampler & sampler,TexLookupScaleMode scaleMode,const IntLookupPrecision & prec,const float coordX,const int coordY,const UVec4 & result)2359*35238bceSAndroid Build Coastguard Worker bool isLevel1DLookupResultValid(const ConstPixelBufferAccess &access, const Sampler &sampler,
2360*35238bceSAndroid Build Coastguard Worker TexLookupScaleMode scaleMode, const IntLookupPrecision &prec, const float coordX,
2361*35238bceSAndroid Build Coastguard Worker const int coordY, const UVec4 &result)
2362*35238bceSAndroid Build Coastguard Worker {
2363*35238bceSAndroid Build Coastguard Worker DE_ASSERT(sampler.minFilter == Sampler::NEAREST && sampler.magFilter == Sampler::NEAREST);
2364*35238bceSAndroid Build Coastguard Worker DE_UNREF(scaleMode);
2365*35238bceSAndroid Build Coastguard Worker return isNearestSampleResultValid(access, sampler, prec, coordX, coordY, result);
2366*35238bceSAndroid Build Coastguard Worker }
2367*35238bceSAndroid Build Coastguard Worker
isLevel2DLookupResultValid(const ConstPixelBufferAccess & access,const Sampler & sampler,TexLookupScaleMode scaleMode,const LookupPrecision & prec,const Vec2 & coord,const int coordZ,const Vec4 & result)2368*35238bceSAndroid Build Coastguard Worker bool isLevel2DLookupResultValid(const ConstPixelBufferAccess &access, const Sampler &sampler,
2369*35238bceSAndroid Build Coastguard Worker TexLookupScaleMode scaleMode, const LookupPrecision &prec, const Vec2 &coord,
2370*35238bceSAndroid Build Coastguard Worker const int coordZ, const Vec4 &result)
2371*35238bceSAndroid Build Coastguard Worker {
2372*35238bceSAndroid Build Coastguard Worker const Sampler::FilterMode filterMode =
2373*35238bceSAndroid Build Coastguard Worker scaleMode == TEX_LOOKUP_SCALE_MAGNIFY ? sampler.magFilter : sampler.minFilter;
2374*35238bceSAndroid Build Coastguard Worker return isLevelSampleResultValid(access, sampler, filterMode, prec, coord, coordZ, result);
2375*35238bceSAndroid Build Coastguard Worker }
2376*35238bceSAndroid Build Coastguard Worker
isLevel2DLookupResultValid(const ConstPixelBufferAccess & access,const Sampler & sampler,TexLookupScaleMode scaleMode,const IntLookupPrecision & prec,const Vec2 & coord,const int coordZ,const IVec4 & result)2377*35238bceSAndroid Build Coastguard Worker bool isLevel2DLookupResultValid(const ConstPixelBufferAccess &access, const Sampler &sampler,
2378*35238bceSAndroid Build Coastguard Worker TexLookupScaleMode scaleMode, const IntLookupPrecision &prec, const Vec2 &coord,
2379*35238bceSAndroid Build Coastguard Worker const int coordZ, const IVec4 &result)
2380*35238bceSAndroid Build Coastguard Worker {
2381*35238bceSAndroid Build Coastguard Worker DE_ASSERT(sampler.minFilter == Sampler::NEAREST && sampler.magFilter == Sampler::NEAREST);
2382*35238bceSAndroid Build Coastguard Worker DE_UNREF(scaleMode);
2383*35238bceSAndroid Build Coastguard Worker return isNearestSampleResultValid(access, sampler, prec, coord, coordZ, result);
2384*35238bceSAndroid Build Coastguard Worker }
2385*35238bceSAndroid Build Coastguard Worker
isLevel2DLookupResultValid(const ConstPixelBufferAccess & access,const Sampler & sampler,TexLookupScaleMode scaleMode,const IntLookupPrecision & prec,const Vec2 & coord,const int coordZ,const UVec4 & result)2386*35238bceSAndroid Build Coastguard Worker bool isLevel2DLookupResultValid(const ConstPixelBufferAccess &access, const Sampler &sampler,
2387*35238bceSAndroid Build Coastguard Worker TexLookupScaleMode scaleMode, const IntLookupPrecision &prec, const Vec2 &coord,
2388*35238bceSAndroid Build Coastguard Worker const int coordZ, const UVec4 &result)
2389*35238bceSAndroid Build Coastguard Worker {
2390*35238bceSAndroid Build Coastguard Worker DE_ASSERT(sampler.minFilter == Sampler::NEAREST && sampler.magFilter == Sampler::NEAREST);
2391*35238bceSAndroid Build Coastguard Worker DE_UNREF(scaleMode);
2392*35238bceSAndroid Build Coastguard Worker return isNearestSampleResultValid(access, sampler, prec, coord, coordZ, result);
2393*35238bceSAndroid Build Coastguard Worker }
2394*35238bceSAndroid Build Coastguard Worker
isLevel3DLookupResultValid(const ConstPixelBufferAccess & access,const Sampler & sampler,TexLookupScaleMode scaleMode,const LookupPrecision & prec,const Vec3 & coord,const Vec4 & result)2395*35238bceSAndroid Build Coastguard Worker bool isLevel3DLookupResultValid(const ConstPixelBufferAccess &access, const Sampler &sampler,
2396*35238bceSAndroid Build Coastguard Worker TexLookupScaleMode scaleMode, const LookupPrecision &prec, const Vec3 &coord,
2397*35238bceSAndroid Build Coastguard Worker const Vec4 &result)
2398*35238bceSAndroid Build Coastguard Worker {
2399*35238bceSAndroid Build Coastguard Worker const tcu::Sampler::FilterMode filterMode =
2400*35238bceSAndroid Build Coastguard Worker scaleMode == TEX_LOOKUP_SCALE_MAGNIFY ? sampler.magFilter : sampler.minFilter;
2401*35238bceSAndroid Build Coastguard Worker return isLevelSampleResultValid(access, sampler, filterMode, prec, coord, result);
2402*35238bceSAndroid Build Coastguard Worker }
2403*35238bceSAndroid Build Coastguard Worker
isLevel3DLookupResultValid(const ConstPixelBufferAccess & access,const Sampler & sampler,TexLookupScaleMode scaleMode,const IntLookupPrecision & prec,const Vec3 & coord,const IVec4 & result)2404*35238bceSAndroid Build Coastguard Worker bool isLevel3DLookupResultValid(const ConstPixelBufferAccess &access, const Sampler &sampler,
2405*35238bceSAndroid Build Coastguard Worker TexLookupScaleMode scaleMode, const IntLookupPrecision &prec, const Vec3 &coord,
2406*35238bceSAndroid Build Coastguard Worker const IVec4 &result)
2407*35238bceSAndroid Build Coastguard Worker {
2408*35238bceSAndroid Build Coastguard Worker DE_ASSERT(sampler.minFilter == Sampler::NEAREST && sampler.magFilter == Sampler::NEAREST);
2409*35238bceSAndroid Build Coastguard Worker DE_UNREF(scaleMode);
2410*35238bceSAndroid Build Coastguard Worker return isNearestSampleResultValid(access, sampler, prec, coord, result);
2411*35238bceSAndroid Build Coastguard Worker }
2412*35238bceSAndroid Build Coastguard Worker
isLevel3DLookupResultValid(const ConstPixelBufferAccess & access,const Sampler & sampler,TexLookupScaleMode scaleMode,const IntLookupPrecision & prec,const Vec3 & coord,const UVec4 & result)2413*35238bceSAndroid Build Coastguard Worker bool isLevel3DLookupResultValid(const ConstPixelBufferAccess &access, const Sampler &sampler,
2414*35238bceSAndroid Build Coastguard Worker TexLookupScaleMode scaleMode, const IntLookupPrecision &prec, const Vec3 &coord,
2415*35238bceSAndroid Build Coastguard Worker const UVec4 &result)
2416*35238bceSAndroid Build Coastguard Worker {
2417*35238bceSAndroid Build Coastguard Worker DE_ASSERT(sampler.minFilter == Sampler::NEAREST && sampler.magFilter == Sampler::NEAREST);
2418*35238bceSAndroid Build Coastguard Worker DE_UNREF(scaleMode);
2419*35238bceSAndroid Build Coastguard Worker return isNearestSampleResultValid(access, sampler, prec, coord, result);
2420*35238bceSAndroid Build Coastguard Worker }
2421*35238bceSAndroid Build Coastguard Worker
2422*35238bceSAndroid Build Coastguard Worker template <typename PrecType, typename ScalarType>
isGatherOffsetsResultValid(const ConstPixelBufferAccess & level,const Sampler & sampler,const PrecType & prec,const Vec2 & coord,int coordZ,int componentNdx,const IVec2 (& offsets)[4],const Vector<ScalarType,4> & result)2423*35238bceSAndroid Build Coastguard Worker static bool isGatherOffsetsResultValid(const ConstPixelBufferAccess &level, const Sampler &sampler,
2424*35238bceSAndroid Build Coastguard Worker const PrecType &prec, const Vec2 &coord, int coordZ, int componentNdx,
2425*35238bceSAndroid Build Coastguard Worker const IVec2 (&offsets)[4], const Vector<ScalarType, 4> &result)
2426*35238bceSAndroid Build Coastguard Worker {
2427*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(), coord.x(),
2428*35238bceSAndroid Build Coastguard Worker prec.coordBits.x(), prec.uvwBits.x());
2429*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds = computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(), coord.y(),
2430*35238bceSAndroid Build Coastguard Worker prec.coordBits.y(), prec.uvwBits.y());
2431*35238bceSAndroid Build Coastguard Worker
2432*35238bceSAndroid Build Coastguard Worker // Integer coordinate bounds for (x0, y0) - without wrap mode
2433*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x() - 0.5f);
2434*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y() - 0.5f);
2435*35238bceSAndroid Build Coastguard Worker const int minJ = deFloorFloatToInt32(vBounds.x() - 0.5f);
2436*35238bceSAndroid Build Coastguard Worker const int maxJ = deFloorFloatToInt32(vBounds.y() - 0.5f);
2437*35238bceSAndroid Build Coastguard Worker
2438*35238bceSAndroid Build Coastguard Worker const int w = level.getWidth();
2439*35238bceSAndroid Build Coastguard Worker const int h = level.getHeight();
2440*35238bceSAndroid Build Coastguard Worker
2441*35238bceSAndroid Build Coastguard Worker for (int j = minJ; j <= maxJ; j++)
2442*35238bceSAndroid Build Coastguard Worker {
2443*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
2444*35238bceSAndroid Build Coastguard Worker {
2445*35238bceSAndroid Build Coastguard Worker Vector<ScalarType, 4> color;
2446*35238bceSAndroid Build Coastguard Worker for (int offNdx = 0; offNdx < 4; offNdx++)
2447*35238bceSAndroid Build Coastguard Worker {
2448*35238bceSAndroid Build Coastguard Worker // offNdx-th coordinate offset and then wrapped.
2449*35238bceSAndroid Build Coastguard Worker const int x = wrap(sampler.wrapS, i + offsets[offNdx].x(), w);
2450*35238bceSAndroid Build Coastguard Worker const int y = wrap(sampler.wrapT, j + offsets[offNdx].y(), h);
2451*35238bceSAndroid Build Coastguard Worker color[offNdx] = lookup<ScalarType>(level, sampler, x, y, coordZ)[componentNdx];
2452*35238bceSAndroid Build Coastguard Worker }
2453*35238bceSAndroid Build Coastguard Worker
2454*35238bceSAndroid Build Coastguard Worker if (isColorValid(prec, color, result))
2455*35238bceSAndroid Build Coastguard Worker return true;
2456*35238bceSAndroid Build Coastguard Worker }
2457*35238bceSAndroid Build Coastguard Worker }
2458*35238bceSAndroid Build Coastguard Worker
2459*35238bceSAndroid Build Coastguard Worker return false;
2460*35238bceSAndroid Build Coastguard Worker }
2461*35238bceSAndroid Build Coastguard Worker
isGatherOffsetsResultValid(const Texture2DView & texture,const Sampler & sampler,const LookupPrecision & prec,const Vec2 & coord,int componentNdx,const IVec2 (& offsets)[4],const Vec4 & result)2462*35238bceSAndroid Build Coastguard Worker bool isGatherOffsetsResultValid(const Texture2DView &texture, const Sampler &sampler, const LookupPrecision &prec,
2463*35238bceSAndroid Build Coastguard Worker const Vec2 &coord, int componentNdx, const IVec2 (&offsets)[4], const Vec4 &result)
2464*35238bceSAndroid Build Coastguard Worker {
2465*35238bceSAndroid Build Coastguard Worker return isGatherOffsetsResultValid(texture.getLevel(0), sampler, prec, coord, 0, componentNdx, offsets, result);
2466*35238bceSAndroid Build Coastguard Worker }
2467*35238bceSAndroid Build Coastguard Worker
isGatherOffsetsResultValid(const Texture2DView & texture,const Sampler & sampler,const IntLookupPrecision & prec,const Vec2 & coord,int componentNdx,const IVec2 (& offsets)[4],const IVec4 & result)2468*35238bceSAndroid Build Coastguard Worker bool isGatherOffsetsResultValid(const Texture2DView &texture, const Sampler &sampler, const IntLookupPrecision &prec,
2469*35238bceSAndroid Build Coastguard Worker const Vec2 &coord, int componentNdx, const IVec2 (&offsets)[4], const IVec4 &result)
2470*35238bceSAndroid Build Coastguard Worker {
2471*35238bceSAndroid Build Coastguard Worker return isGatherOffsetsResultValid(texture.getLevel(0), sampler, prec, coord, 0, componentNdx, offsets, result);
2472*35238bceSAndroid Build Coastguard Worker }
2473*35238bceSAndroid Build Coastguard Worker
isGatherOffsetsResultValid(const Texture2DView & texture,const Sampler & sampler,const IntLookupPrecision & prec,const Vec2 & coord,int componentNdx,const IVec2 (& offsets)[4],const UVec4 & result)2474*35238bceSAndroid Build Coastguard Worker bool isGatherOffsetsResultValid(const Texture2DView &texture, const Sampler &sampler, const IntLookupPrecision &prec,
2475*35238bceSAndroid Build Coastguard Worker const Vec2 &coord, int componentNdx, const IVec2 (&offsets)[4], const UVec4 &result)
2476*35238bceSAndroid Build Coastguard Worker {
2477*35238bceSAndroid Build Coastguard Worker return isGatherOffsetsResultValid(texture.getLevel(0), sampler, prec, coord, 0, componentNdx, offsets, result);
2478*35238bceSAndroid Build Coastguard Worker }
2479*35238bceSAndroid Build Coastguard Worker
2480*35238bceSAndroid Build Coastguard Worker template <typename PrecType, typename ScalarType>
is2DArrayGatherOffsetsResultValid(const Texture2DArrayView & texture,const Sampler & sampler,const PrecType & prec,const Vec3 & coord,int componentNdx,const IVec2 (& offsets)[4],const Vector<ScalarType,4> & result)2481*35238bceSAndroid Build Coastguard Worker static bool is2DArrayGatherOffsetsResultValid(const Texture2DArrayView &texture, const Sampler &sampler,
2482*35238bceSAndroid Build Coastguard Worker const PrecType &prec, const Vec3 &coord, int componentNdx,
2483*35238bceSAndroid Build Coastguard Worker const IVec2 (&offsets)[4], const Vector<ScalarType, 4> &result)
2484*35238bceSAndroid Build Coastguard Worker {
2485*35238bceSAndroid Build Coastguard Worker const IVec2 layerRange = computeLayerRange(texture.getNumLayers(), prec.coordBits.z(), coord.z());
2486*35238bceSAndroid Build Coastguard Worker for (int layer = layerRange.x(); layer <= layerRange.y(); layer++)
2487*35238bceSAndroid Build Coastguard Worker {
2488*35238bceSAndroid Build Coastguard Worker if (isGatherOffsetsResultValid(texture.getLevel(0), sampler, prec, coord.swizzle(0, 1), layer, componentNdx,
2489*35238bceSAndroid Build Coastguard Worker offsets, result))
2490*35238bceSAndroid Build Coastguard Worker return true;
2491*35238bceSAndroid Build Coastguard Worker }
2492*35238bceSAndroid Build Coastguard Worker return false;
2493*35238bceSAndroid Build Coastguard Worker }
2494*35238bceSAndroid Build Coastguard Worker
isGatherOffsetsResultValid(const Texture2DArrayView & texture,const Sampler & sampler,const LookupPrecision & prec,const Vec3 & coord,int componentNdx,const IVec2 (& offsets)[4],const Vec4 & result)2495*35238bceSAndroid Build Coastguard Worker bool isGatherOffsetsResultValid(const Texture2DArrayView &texture, const Sampler &sampler, const LookupPrecision &prec,
2496*35238bceSAndroid Build Coastguard Worker const Vec3 &coord, int componentNdx, const IVec2 (&offsets)[4], const Vec4 &result)
2497*35238bceSAndroid Build Coastguard Worker {
2498*35238bceSAndroid Build Coastguard Worker return is2DArrayGatherOffsetsResultValid(texture, sampler, prec, coord, componentNdx, offsets, result);
2499*35238bceSAndroid Build Coastguard Worker }
2500*35238bceSAndroid Build Coastguard Worker
isGatherOffsetsResultValid(const Texture2DArrayView & texture,const Sampler & sampler,const IntLookupPrecision & prec,const Vec3 & coord,int componentNdx,const IVec2 (& offsets)[4],const IVec4 & result)2501*35238bceSAndroid Build Coastguard Worker bool isGatherOffsetsResultValid(const Texture2DArrayView &texture, const Sampler &sampler,
2502*35238bceSAndroid Build Coastguard Worker const IntLookupPrecision &prec, const Vec3 &coord, int componentNdx,
2503*35238bceSAndroid Build Coastguard Worker const IVec2 (&offsets)[4], const IVec4 &result)
2504*35238bceSAndroid Build Coastguard Worker {
2505*35238bceSAndroid Build Coastguard Worker return is2DArrayGatherOffsetsResultValid(texture, sampler, prec, coord, componentNdx, offsets, result);
2506*35238bceSAndroid Build Coastguard Worker }
2507*35238bceSAndroid Build Coastguard Worker
isGatherOffsetsResultValid(const Texture2DArrayView & texture,const Sampler & sampler,const IntLookupPrecision & prec,const Vec3 & coord,int componentNdx,const IVec2 (& offsets)[4],const UVec4 & result)2508*35238bceSAndroid Build Coastguard Worker bool isGatherOffsetsResultValid(const Texture2DArrayView &texture, const Sampler &sampler,
2509*35238bceSAndroid Build Coastguard Worker const IntLookupPrecision &prec, const Vec3 &coord, int componentNdx,
2510*35238bceSAndroid Build Coastguard Worker const IVec2 (&offsets)[4], const UVec4 &result)
2511*35238bceSAndroid Build Coastguard Worker {
2512*35238bceSAndroid Build Coastguard Worker return is2DArrayGatherOffsetsResultValid(texture, sampler, prec, coord, componentNdx, offsets, result);
2513*35238bceSAndroid Build Coastguard Worker }
2514*35238bceSAndroid Build Coastguard Worker
2515*35238bceSAndroid Build Coastguard Worker template <typename PrecType, typename ScalarType>
isGatherResultValid(const TextureCubeView & texture,const Sampler & sampler,const PrecType & prec,const CubeFaceFloatCoords & coords,int componentNdx,const Vector<ScalarType,4> & result)2516*35238bceSAndroid Build Coastguard Worker static bool isGatherResultValid(const TextureCubeView &texture, const Sampler &sampler, const PrecType &prec,
2517*35238bceSAndroid Build Coastguard Worker const CubeFaceFloatCoords &coords, int componentNdx,
2518*35238bceSAndroid Build Coastguard Worker const Vector<ScalarType, 4> &result)
2519*35238bceSAndroid Build Coastguard Worker {
2520*35238bceSAndroid Build Coastguard Worker const int size = texture.getLevelFace(0, coords.face).getWidth();
2521*35238bceSAndroid Build Coastguard Worker
2522*35238bceSAndroid Build Coastguard Worker const Vec2 uBounds =
2523*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.s, prec.coordBits.x(), prec.uvwBits.x());
2524*35238bceSAndroid Build Coastguard Worker const Vec2 vBounds =
2525*35238bceSAndroid Build Coastguard Worker computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.t, prec.coordBits.y(), prec.uvwBits.y());
2526*35238bceSAndroid Build Coastguard Worker
2527*35238bceSAndroid Build Coastguard Worker // Integer coordinate bounds for (x0,y0) - without wrap mode
2528*35238bceSAndroid Build Coastguard Worker const int minI = deFloorFloatToInt32(uBounds.x() - 0.5f);
2529*35238bceSAndroid Build Coastguard Worker const int maxI = deFloorFloatToInt32(uBounds.y() - 0.5f);
2530*35238bceSAndroid Build Coastguard Worker const int minJ = deFloorFloatToInt32(vBounds.x() - 0.5f);
2531*35238bceSAndroid Build Coastguard Worker const int maxJ = deFloorFloatToInt32(vBounds.y() - 0.5f);
2532*35238bceSAndroid Build Coastguard Worker
2533*35238bceSAndroid Build Coastguard Worker // Face accesses
2534*35238bceSAndroid Build Coastguard Worker ConstPixelBufferAccess faces[CUBEFACE_LAST];
2535*35238bceSAndroid Build Coastguard Worker for (int face = 0; face < CUBEFACE_LAST; face++)
2536*35238bceSAndroid Build Coastguard Worker faces[face] = texture.getLevelFace(0, CubeFace(face));
2537*35238bceSAndroid Build Coastguard Worker
2538*35238bceSAndroid Build Coastguard Worker for (int j = minJ; j <= maxJ; j++)
2539*35238bceSAndroid Build Coastguard Worker {
2540*35238bceSAndroid Build Coastguard Worker for (int i = minI; i <= maxI; i++)
2541*35238bceSAndroid Build Coastguard Worker {
2542*35238bceSAndroid Build Coastguard Worker static const IVec2 offsets[4] = {IVec2(0, 1), IVec2(1, 1), IVec2(1, 0), IVec2(0, 0)};
2543*35238bceSAndroid Build Coastguard Worker
2544*35238bceSAndroid Build Coastguard Worker Vector<ScalarType, 4> color;
2545*35238bceSAndroid Build Coastguard Worker for (int offNdx = 0; offNdx < 4; offNdx++)
2546*35238bceSAndroid Build Coastguard Worker {
2547*35238bceSAndroid Build Coastguard Worker const CubeFaceIntCoords c = remapCubeEdgeCoords(
2548*35238bceSAndroid Build Coastguard Worker CubeFaceIntCoords(coords.face, i + offsets[offNdx].x(), j + offsets[offNdx].y()), size);
2549*35238bceSAndroid Build Coastguard Worker // If any of samples is out of both edges, implementations can do pretty much anything according to spec.
2550*35238bceSAndroid Build Coastguard Worker // \todo [2014-06-05 nuutti] Test the special case where all corner pixels have exactly the same color.
2551*35238bceSAndroid Build Coastguard Worker // See also isSeamlessLinearSampleResultValid and similar.
2552*35238bceSAndroid Build Coastguard Worker if (c.face == CUBEFACE_LAST)
2553*35238bceSAndroid Build Coastguard Worker return true;
2554*35238bceSAndroid Build Coastguard Worker
2555*35238bceSAndroid Build Coastguard Worker color[offNdx] = lookup<ScalarType>(faces[c.face], sampler, c.s, c.t, 0)[componentNdx];
2556*35238bceSAndroid Build Coastguard Worker }
2557*35238bceSAndroid Build Coastguard Worker
2558*35238bceSAndroid Build Coastguard Worker if (isColorValid(prec, color, result))
2559*35238bceSAndroid Build Coastguard Worker return true;
2560*35238bceSAndroid Build Coastguard Worker }
2561*35238bceSAndroid Build Coastguard Worker }
2562*35238bceSAndroid Build Coastguard Worker
2563*35238bceSAndroid Build Coastguard Worker return false;
2564*35238bceSAndroid Build Coastguard Worker }
2565*35238bceSAndroid Build Coastguard Worker
2566*35238bceSAndroid Build Coastguard Worker template <typename PrecType, typename ScalarType>
isCubeGatherResultValid(const TextureCubeView & texture,const Sampler & sampler,const PrecType & prec,const Vec3 & coord,int componentNdx,const Vector<ScalarType,4> & result)2567*35238bceSAndroid Build Coastguard Worker static bool isCubeGatherResultValid(const TextureCubeView &texture, const Sampler &sampler, const PrecType &prec,
2568*35238bceSAndroid Build Coastguard Worker const Vec3 &coord, int componentNdx, const Vector<ScalarType, 4> &result)
2569*35238bceSAndroid Build Coastguard Worker {
2570*35238bceSAndroid Build Coastguard Worker int numPossibleFaces = 0;
2571*35238bceSAndroid Build Coastguard Worker CubeFace possibleFaces[CUBEFACE_LAST];
2572*35238bceSAndroid Build Coastguard Worker
2573*35238bceSAndroid Build Coastguard Worker getPossibleCubeFaces(coord, prec.coordBits, &possibleFaces[0], numPossibleFaces);
2574*35238bceSAndroid Build Coastguard Worker
2575*35238bceSAndroid Build Coastguard Worker if (numPossibleFaces == 0)
2576*35238bceSAndroid Build Coastguard Worker return true; // Result is undefined.
2577*35238bceSAndroid Build Coastguard Worker
2578*35238bceSAndroid Build Coastguard Worker for (int tryFaceNdx = 0; tryFaceNdx < numPossibleFaces; tryFaceNdx++)
2579*35238bceSAndroid Build Coastguard Worker {
2580*35238bceSAndroid Build Coastguard Worker const CubeFaceFloatCoords faceCoords(possibleFaces[tryFaceNdx],
2581*35238bceSAndroid Build Coastguard Worker projectToFace(possibleFaces[tryFaceNdx], coord));
2582*35238bceSAndroid Build Coastguard Worker
2583*35238bceSAndroid Build Coastguard Worker if (isGatherResultValid(texture, sampler, prec, faceCoords, componentNdx, result))
2584*35238bceSAndroid Build Coastguard Worker return true;
2585*35238bceSAndroid Build Coastguard Worker }
2586*35238bceSAndroid Build Coastguard Worker
2587*35238bceSAndroid Build Coastguard Worker return false;
2588*35238bceSAndroid Build Coastguard Worker }
2589*35238bceSAndroid Build Coastguard Worker
isGatherResultValid(const TextureCubeView & texture,const Sampler & sampler,const LookupPrecision & prec,const Vec3 & coord,int componentNdx,const Vec4 & result)2590*35238bceSAndroid Build Coastguard Worker bool isGatherResultValid(const TextureCubeView &texture, const Sampler &sampler, const LookupPrecision &prec,
2591*35238bceSAndroid Build Coastguard Worker const Vec3 &coord, int componentNdx, const Vec4 &result)
2592*35238bceSAndroid Build Coastguard Worker {
2593*35238bceSAndroid Build Coastguard Worker return isCubeGatherResultValid(texture, sampler, prec, coord, componentNdx, result);
2594*35238bceSAndroid Build Coastguard Worker }
2595*35238bceSAndroid Build Coastguard Worker
isGatherResultValid(const TextureCubeView & texture,const Sampler & sampler,const IntLookupPrecision & prec,const Vec3 & coord,int componentNdx,const IVec4 & result)2596*35238bceSAndroid Build Coastguard Worker bool isGatherResultValid(const TextureCubeView &texture, const Sampler &sampler, const IntLookupPrecision &prec,
2597*35238bceSAndroid Build Coastguard Worker const Vec3 &coord, int componentNdx, const IVec4 &result)
2598*35238bceSAndroid Build Coastguard Worker {
2599*35238bceSAndroid Build Coastguard Worker return isCubeGatherResultValid(texture, sampler, prec, coord, componentNdx, result);
2600*35238bceSAndroid Build Coastguard Worker }
2601*35238bceSAndroid Build Coastguard Worker
isGatherResultValid(const TextureCubeView & texture,const Sampler & sampler,const IntLookupPrecision & prec,const Vec3 & coord,int componentNdx,const UVec4 & result)2602*35238bceSAndroid Build Coastguard Worker bool isGatherResultValid(const TextureCubeView &texture, const Sampler &sampler, const IntLookupPrecision &prec,
2603*35238bceSAndroid Build Coastguard Worker const Vec3 &coord, int componentNdx, const UVec4 &result)
2604*35238bceSAndroid Build Coastguard Worker {
2605*35238bceSAndroid Build Coastguard Worker return isCubeGatherResultValid(texture, sampler, prec, coord, componentNdx, result);
2606*35238bceSAndroid Build Coastguard Worker }
2607*35238bceSAndroid Build Coastguard Worker
2608*35238bceSAndroid Build Coastguard Worker } // namespace tcu
2609