1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker * drawElements Quality Program Reference Renderer
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 Reference rasterizer
22*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker
24*35238bceSAndroid Build Coastguard Worker #include "rrRasterizer.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "deMath.h"
26*35238bceSAndroid Build Coastguard Worker #include "tcuVectorUtil.hpp"
27*35238bceSAndroid Build Coastguard Worker
28*35238bceSAndroid Build Coastguard Worker namespace rr
29*35238bceSAndroid Build Coastguard Worker {
30*35238bceSAndroid Build Coastguard Worker
toSubpixelCoord(float v,int bits)31*35238bceSAndroid Build Coastguard Worker inline int64_t toSubpixelCoord(float v, int bits)
32*35238bceSAndroid Build Coastguard Worker {
33*35238bceSAndroid Build Coastguard Worker return (int64_t)(v * (float)(1 << bits) + (v < 0.f ? -0.5f : 0.5f));
34*35238bceSAndroid Build Coastguard Worker }
35*35238bceSAndroid Build Coastguard Worker
toSubpixelCoord(int32_t v,int bits)36*35238bceSAndroid Build Coastguard Worker inline int64_t toSubpixelCoord(int32_t v, int bits)
37*35238bceSAndroid Build Coastguard Worker {
38*35238bceSAndroid Build Coastguard Worker return v << bits;
39*35238bceSAndroid Build Coastguard Worker }
40*35238bceSAndroid Build Coastguard Worker
ceilSubpixelToPixelCoord(int64_t coord,int bits,bool fillEdge)41*35238bceSAndroid Build Coastguard Worker inline int32_t ceilSubpixelToPixelCoord(int64_t coord, int bits, bool fillEdge)
42*35238bceSAndroid Build Coastguard Worker {
43*35238bceSAndroid Build Coastguard Worker if (coord >= 0)
44*35238bceSAndroid Build Coastguard Worker return (int32_t)((coord + ((1ll << bits) - (fillEdge ? 0 : 1))) >> bits);
45*35238bceSAndroid Build Coastguard Worker else
46*35238bceSAndroid Build Coastguard Worker return (int32_t)((coord + (fillEdge ? 1 : 0)) >> bits);
47*35238bceSAndroid Build Coastguard Worker }
48*35238bceSAndroid Build Coastguard Worker
floorSubpixelToPixelCoord(int64_t coord,int bits,bool fillEdge)49*35238bceSAndroid Build Coastguard Worker inline int32_t floorSubpixelToPixelCoord(int64_t coord, int bits, bool fillEdge)
50*35238bceSAndroid Build Coastguard Worker {
51*35238bceSAndroid Build Coastguard Worker if (coord >= 0)
52*35238bceSAndroid Build Coastguard Worker return (int32_t)((coord - (fillEdge ? 1 : 0)) >> bits);
53*35238bceSAndroid Build Coastguard Worker else
54*35238bceSAndroid Build Coastguard Worker return (int32_t)((coord - ((1ll << bits) - (fillEdge ? 0 : 1))) >> bits);
55*35238bceSAndroid Build Coastguard Worker }
56*35238bceSAndroid Build Coastguard Worker
initEdgeCCW(EdgeFunction & edge,const HorizontalFill horizontalFill,const VerticalFill verticalFill,const int64_t x0,const int64_t y0,const int64_t x1,const int64_t y1)57*35238bceSAndroid Build Coastguard Worker static inline void initEdgeCCW(EdgeFunction &edge, const HorizontalFill horizontalFill, const VerticalFill verticalFill,
58*35238bceSAndroid Build Coastguard Worker const int64_t x0, const int64_t y0, const int64_t x1, const int64_t y1)
59*35238bceSAndroid Build Coastguard Worker {
60*35238bceSAndroid Build Coastguard Worker // \note See EdgeFunction documentation for details.
61*35238bceSAndroid Build Coastguard Worker
62*35238bceSAndroid Build Coastguard Worker const int64_t xd = x1 - x0;
63*35238bceSAndroid Build Coastguard Worker const int64_t yd = y1 - y0;
64*35238bceSAndroid Build Coastguard Worker bool inclusive = false; //!< Inclusive in CCW orientation.
65*35238bceSAndroid Build Coastguard Worker
66*35238bceSAndroid Build Coastguard Worker if (yd == 0)
67*35238bceSAndroid Build Coastguard Worker inclusive = verticalFill == FILL_BOTTOM ? xd >= 0 : xd <= 0;
68*35238bceSAndroid Build Coastguard Worker else
69*35238bceSAndroid Build Coastguard Worker inclusive = horizontalFill == FILL_LEFT ? yd <= 0 : yd >= 0;
70*35238bceSAndroid Build Coastguard Worker
71*35238bceSAndroid Build Coastguard Worker edge.a = (y0 - y1);
72*35238bceSAndroid Build Coastguard Worker edge.b = (x1 - x0);
73*35238bceSAndroid Build Coastguard Worker edge.c = x0 * y1 - y0 * x1;
74*35238bceSAndroid Build Coastguard Worker edge.inclusive = inclusive; //!< \todo [pyry] Swap for CW triangles
75*35238bceSAndroid Build Coastguard Worker }
76*35238bceSAndroid Build Coastguard Worker
reverseEdge(EdgeFunction & edge)77*35238bceSAndroid Build Coastguard Worker static inline void reverseEdge(EdgeFunction &edge)
78*35238bceSAndroid Build Coastguard Worker {
79*35238bceSAndroid Build Coastguard Worker edge.a = -edge.a;
80*35238bceSAndroid Build Coastguard Worker edge.b = -edge.b;
81*35238bceSAndroid Build Coastguard Worker edge.c = -edge.c;
82*35238bceSAndroid Build Coastguard Worker edge.inclusive = !edge.inclusive;
83*35238bceSAndroid Build Coastguard Worker }
84*35238bceSAndroid Build Coastguard Worker
evaluateEdge(const EdgeFunction & edge,const int64_t x,const int64_t y)85*35238bceSAndroid Build Coastguard Worker static inline int64_t evaluateEdge(const EdgeFunction &edge, const int64_t x, const int64_t y)
86*35238bceSAndroid Build Coastguard Worker {
87*35238bceSAndroid Build Coastguard Worker return edge.a * x + edge.b * y + edge.c;
88*35238bceSAndroid Build Coastguard Worker }
89*35238bceSAndroid Build Coastguard Worker
isInsideCCW(const EdgeFunction & edge,const int64_t edgeVal)90*35238bceSAndroid Build Coastguard Worker static inline bool isInsideCCW(const EdgeFunction &edge, const int64_t edgeVal)
91*35238bceSAndroid Build Coastguard Worker {
92*35238bceSAndroid Build Coastguard Worker return edge.inclusive ? (edgeVal >= 0) : (edgeVal > 0);
93*35238bceSAndroid Build Coastguard Worker }
94*35238bceSAndroid Build Coastguard Worker
95*35238bceSAndroid Build Coastguard Worker namespace LineRasterUtil
96*35238bceSAndroid Build Coastguard Worker {
97*35238bceSAndroid Build Coastguard Worker
98*35238bceSAndroid Build Coastguard Worker struct SubpixelLineSegment
99*35238bceSAndroid Build Coastguard Worker {
100*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> m_v0;
101*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> m_v1;
102*35238bceSAndroid Build Coastguard Worker
SubpixelLineSegmentrr::LineRasterUtil::SubpixelLineSegment103*35238bceSAndroid Build Coastguard Worker SubpixelLineSegment(const tcu::Vector<int64_t, 2> &v0, const tcu::Vector<int64_t, 2> &v1) : m_v0(v0), m_v1(v1)
104*35238bceSAndroid Build Coastguard Worker {
105*35238bceSAndroid Build Coastguard Worker }
106*35238bceSAndroid Build Coastguard Worker
directionrr::LineRasterUtil::SubpixelLineSegment107*35238bceSAndroid Build Coastguard Worker tcu::Vector<int64_t, 2> direction(void) const
108*35238bceSAndroid Build Coastguard Worker {
109*35238bceSAndroid Build Coastguard Worker return m_v1 - m_v0;
110*35238bceSAndroid Build Coastguard Worker }
111*35238bceSAndroid Build Coastguard Worker };
112*35238bceSAndroid Build Coastguard Worker
113*35238bceSAndroid Build Coastguard Worker enum LINE_SIDE
114*35238bceSAndroid Build Coastguard Worker {
115*35238bceSAndroid Build Coastguard Worker LINE_SIDE_INTERSECT = 0,
116*35238bceSAndroid Build Coastguard Worker LINE_SIDE_LEFT,
117*35238bceSAndroid Build Coastguard Worker LINE_SIDE_RIGHT
118*35238bceSAndroid Build Coastguard Worker };
119*35238bceSAndroid Build Coastguard Worker
toSubpixelVector(const tcu::Vec2 & v,int bits)120*35238bceSAndroid Build Coastguard Worker static tcu::Vector<int64_t, 2> toSubpixelVector(const tcu::Vec2 &v, int bits)
121*35238bceSAndroid Build Coastguard Worker {
122*35238bceSAndroid Build Coastguard Worker return tcu::Vector<int64_t, 2>(toSubpixelCoord(v.x(), bits), toSubpixelCoord(v.y(), bits));
123*35238bceSAndroid Build Coastguard Worker }
124*35238bceSAndroid Build Coastguard Worker
toSubpixelVector(const tcu::IVec2 & v,int bits)125*35238bceSAndroid Build Coastguard Worker static tcu::Vector<int64_t, 2> toSubpixelVector(const tcu::IVec2 &v, int bits)
126*35238bceSAndroid Build Coastguard Worker {
127*35238bceSAndroid Build Coastguard Worker return tcu::Vector<int64_t, 2>(toSubpixelCoord(v.x(), bits), toSubpixelCoord(v.y(), bits));
128*35238bceSAndroid Build Coastguard Worker }
129*35238bceSAndroid Build Coastguard Worker
130*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
isTheCenterOfTheFragment(const tcu::Vector<int64_t,2> & a,int bits)131*35238bceSAndroid Build Coastguard Worker static bool isTheCenterOfTheFragment(const tcu::Vector<int64_t, 2> &a, int bits)
132*35238bceSAndroid Build Coastguard Worker {
133*35238bceSAndroid Build Coastguard Worker const uint64_t pixelSize = 1ll << bits;
134*35238bceSAndroid Build Coastguard Worker const uint64_t halfPixel = 1ll << (bits - 1);
135*35238bceSAndroid Build Coastguard Worker return ((a.x() & (pixelSize - 1)) == halfPixel && (a.y() & (pixelSize - 1)) == halfPixel);
136*35238bceSAndroid Build Coastguard Worker }
137*35238bceSAndroid Build Coastguard Worker
inViewport(const tcu::IVec2 & p,const tcu::IVec4 & viewport)138*35238bceSAndroid Build Coastguard Worker static bool inViewport(const tcu::IVec2 &p, const tcu::IVec4 &viewport)
139*35238bceSAndroid Build Coastguard Worker {
140*35238bceSAndroid Build Coastguard Worker return p.x() >= viewport.x() && p.y() >= viewport.y() && p.x() < viewport.x() + viewport.z() &&
141*35238bceSAndroid Build Coastguard Worker p.y() < viewport.y() + viewport.w();
142*35238bceSAndroid Build Coastguard Worker }
143*35238bceSAndroid Build Coastguard Worker #endif // DE_DEBUG
144*35238bceSAndroid Build Coastguard Worker
145*35238bceSAndroid Build Coastguard Worker // returns true if vertex is on the left side of the line
vertexOnLeftSideOfLine(const tcu::Vector<int64_t,2> & p,const SubpixelLineSegment & l)146*35238bceSAndroid Build Coastguard Worker static bool vertexOnLeftSideOfLine(const tcu::Vector<int64_t, 2> &p, const SubpixelLineSegment &l)
147*35238bceSAndroid Build Coastguard Worker {
148*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> u = l.direction();
149*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> v = (p - l.m_v0);
150*35238bceSAndroid Build Coastguard Worker const int64_t crossProduct = (u.x() * v.y() - u.y() * v.x());
151*35238bceSAndroid Build Coastguard Worker return crossProduct < 0;
152*35238bceSAndroid Build Coastguard Worker }
153*35238bceSAndroid Build Coastguard Worker
154*35238bceSAndroid Build Coastguard Worker // returns true if vertex is on the right side of the line
vertexOnRightSideOfLine(const tcu::Vector<int64_t,2> & p,const SubpixelLineSegment & l)155*35238bceSAndroid Build Coastguard Worker static bool vertexOnRightSideOfLine(const tcu::Vector<int64_t, 2> &p, const SubpixelLineSegment &l)
156*35238bceSAndroid Build Coastguard Worker {
157*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> u = l.direction();
158*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> v = (p - l.m_v0);
159*35238bceSAndroid Build Coastguard Worker const int64_t crossProduct = (u.x() * v.y() - u.y() * v.x());
160*35238bceSAndroid Build Coastguard Worker return crossProduct > 0;
161*35238bceSAndroid Build Coastguard Worker }
162*35238bceSAndroid Build Coastguard Worker
163*35238bceSAndroid Build Coastguard Worker // returns true if vertex is on the line
vertexOnLine(const tcu::Vector<int64_t,2> & p,const SubpixelLineSegment & l)164*35238bceSAndroid Build Coastguard Worker static bool vertexOnLine(const tcu::Vector<int64_t, 2> &p, const SubpixelLineSegment &l)
165*35238bceSAndroid Build Coastguard Worker {
166*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> u = l.direction();
167*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> v = (p - l.m_v0);
168*35238bceSAndroid Build Coastguard Worker const int64_t crossProduct = (u.x() * v.y() - u.y() * v.x());
169*35238bceSAndroid Build Coastguard Worker return crossProduct == 0; // cross product == 0
170*35238bceSAndroid Build Coastguard Worker }
171*35238bceSAndroid Build Coastguard Worker
172*35238bceSAndroid Build Coastguard Worker // returns true if vertex is on the line segment
vertexOnLineSegment(const tcu::Vector<int64_t,2> & p,const SubpixelLineSegment & l)173*35238bceSAndroid Build Coastguard Worker static bool vertexOnLineSegment(const tcu::Vector<int64_t, 2> &p, const SubpixelLineSegment &l)
174*35238bceSAndroid Build Coastguard Worker {
175*35238bceSAndroid Build Coastguard Worker if (!vertexOnLine(p, l))
176*35238bceSAndroid Build Coastguard Worker return false;
177*35238bceSAndroid Build Coastguard Worker
178*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> v = l.direction();
179*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> u1 = (p - l.m_v0);
180*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> u2 = (p - l.m_v1);
181*35238bceSAndroid Build Coastguard Worker
182*35238bceSAndroid Build Coastguard Worker if (v.x() == 0 && v.y() == 0)
183*35238bceSAndroid Build Coastguard Worker return false;
184*35238bceSAndroid Build Coastguard Worker
185*35238bceSAndroid Build Coastguard Worker return tcu::dot(v, u1) >= 0 && tcu::dot(-v, u2) >= 0; // dot (A->B, A->V) >= 0 and dot (B->A, B->V) >= 0
186*35238bceSAndroid Build Coastguard Worker }
187*35238bceSAndroid Build Coastguard Worker
getVertexSide(const tcu::Vector<int64_t,2> & v,const SubpixelLineSegment & l)188*35238bceSAndroid Build Coastguard Worker static LINE_SIDE getVertexSide(const tcu::Vector<int64_t, 2> &v, const SubpixelLineSegment &l)
189*35238bceSAndroid Build Coastguard Worker {
190*35238bceSAndroid Build Coastguard Worker if (vertexOnLeftSideOfLine(v, l))
191*35238bceSAndroid Build Coastguard Worker return LINE_SIDE_LEFT;
192*35238bceSAndroid Build Coastguard Worker else if (vertexOnRightSideOfLine(v, l))
193*35238bceSAndroid Build Coastguard Worker return LINE_SIDE_RIGHT;
194*35238bceSAndroid Build Coastguard Worker else if (vertexOnLine(v, l))
195*35238bceSAndroid Build Coastguard Worker return LINE_SIDE_INTERSECT;
196*35238bceSAndroid Build Coastguard Worker else
197*35238bceSAndroid Build Coastguard Worker {
198*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
199*35238bceSAndroid Build Coastguard Worker return LINE_SIDE_INTERSECT;
200*35238bceSAndroid Build Coastguard Worker }
201*35238bceSAndroid Build Coastguard Worker }
202*35238bceSAndroid Build Coastguard Worker
203*35238bceSAndroid Build Coastguard Worker // returns true if angle between line and given cornerExitNormal is in range (-45, 45)
lineInCornerAngleRange(const SubpixelLineSegment & line,const tcu::Vector<int64_t,2> & cornerExitNormal)204*35238bceSAndroid Build Coastguard Worker bool lineInCornerAngleRange(const SubpixelLineSegment &line, const tcu::Vector<int64_t, 2> &cornerExitNormal)
205*35238bceSAndroid Build Coastguard Worker {
206*35238bceSAndroid Build Coastguard Worker // v0 -> v1 has angle difference to cornerExitNormal in range (-45, 45)
207*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> v = line.direction();
208*35238bceSAndroid Build Coastguard Worker const int64_t dotProduct = dot(v, cornerExitNormal);
209*35238bceSAndroid Build Coastguard Worker
210*35238bceSAndroid Build Coastguard Worker // dotProduct > |v1-v0|*|cornerExitNormal|/sqrt(2)
211*35238bceSAndroid Build Coastguard Worker if (dotProduct < 0)
212*35238bceSAndroid Build Coastguard Worker return false;
213*35238bceSAndroid Build Coastguard Worker return 2 * dotProduct * dotProduct > tcu::lengthSquared(v) * tcu::lengthSquared(cornerExitNormal);
214*35238bceSAndroid Build Coastguard Worker }
215*35238bceSAndroid Build Coastguard Worker
216*35238bceSAndroid Build Coastguard Worker // returns true if angle between line and given cornerExitNormal is in range (-135, 135)
lineInCornerOutsideAngleRange(const SubpixelLineSegment & line,const tcu::Vector<int64_t,2> & cornerExitNormal)217*35238bceSAndroid Build Coastguard Worker bool lineInCornerOutsideAngleRange(const SubpixelLineSegment &line, const tcu::Vector<int64_t, 2> &cornerExitNormal)
218*35238bceSAndroid Build Coastguard Worker {
219*35238bceSAndroid Build Coastguard Worker // v0 -> v1 has angle difference to cornerExitNormal in range (-135, 135)
220*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> v = line.direction();
221*35238bceSAndroid Build Coastguard Worker const int64_t dotProduct = dot(v, cornerExitNormal);
222*35238bceSAndroid Build Coastguard Worker
223*35238bceSAndroid Build Coastguard Worker // dotProduct > -|v1-v0|*|cornerExitNormal|/sqrt(2)
224*35238bceSAndroid Build Coastguard Worker if (dotProduct >= 0)
225*35238bceSAndroid Build Coastguard Worker return true;
226*35238bceSAndroid Build Coastguard Worker return 2 * (-dotProduct) * (-dotProduct) < tcu::lengthSquared(v) * tcu::lengthSquared(cornerExitNormal);
227*35238bceSAndroid Build Coastguard Worker }
228*35238bceSAndroid Build Coastguard Worker
doesLineSegmentExitDiamond(const SubpixelLineSegment & line,const tcu::Vector<int64_t,2> & diamondCenter,int bits)229*35238bceSAndroid Build Coastguard Worker bool doesLineSegmentExitDiamond(const SubpixelLineSegment &line, const tcu::Vector<int64_t, 2> &diamondCenter, int bits)
230*35238bceSAndroid Build Coastguard Worker {
231*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isTheCenterOfTheFragment(diamondCenter, bits));
232*35238bceSAndroid Build Coastguard Worker
233*35238bceSAndroid Build Coastguard Worker // Diamond Center is at diamondCenter in subpixel coords
234*35238bceSAndroid Build Coastguard Worker
235*35238bceSAndroid Build Coastguard Worker const int64_t halfPixel = 1ll << (bits - 1);
236*35238bceSAndroid Build Coastguard Worker
237*35238bceSAndroid Build Coastguard Worker // Reject distant diamonds early
238*35238bceSAndroid Build Coastguard Worker {
239*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> u = line.direction();
240*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> v = (diamondCenter - line.m_v0);
241*35238bceSAndroid Build Coastguard Worker const int64_t crossProduct = (u.x() * v.y() - u.y() * v.x());
242*35238bceSAndroid Build Coastguard Worker
243*35238bceSAndroid Build Coastguard Worker // crossProduct = |p| |l| sin(theta)
244*35238bceSAndroid Build Coastguard Worker // distanceFromLine = |p| sin(theta)
245*35238bceSAndroid Build Coastguard Worker // => distanceFromLine = crossProduct / |l|
246*35238bceSAndroid Build Coastguard Worker //
247*35238bceSAndroid Build Coastguard Worker // |distanceFromLine| > C
248*35238bceSAndroid Build Coastguard Worker // => distanceFromLine^2 > C^2
249*35238bceSAndroid Build Coastguard Worker // => crossProduct^2 / |l|^2 > C^2
250*35238bceSAndroid Build Coastguard Worker // => crossProduct^2 > |l|^2 * C^2
251*35238bceSAndroid Build Coastguard Worker
252*35238bceSAndroid Build Coastguard Worker const int64_t floorSqrtMaxInt64 = 3037000499LL; //!< floor(sqrt(MAX_INT64))
253*35238bceSAndroid Build Coastguard Worker
254*35238bceSAndroid Build Coastguard Worker const int64_t broadRejectDistance = 2 * halfPixel;
255*35238bceSAndroid Build Coastguard Worker const int64_t broadRejectDistanceSquared = broadRejectDistance * broadRejectDistance;
256*35238bceSAndroid Build Coastguard Worker const bool crossProductOverflows = (crossProduct > floorSqrtMaxInt64 || crossProduct < -floorSqrtMaxInt64);
257*35238bceSAndroid Build Coastguard Worker const int64_t crossProductSquared =
258*35238bceSAndroid Build Coastguard Worker (crossProductOverflows) ? (0) : (crossProduct * crossProduct); // avoid overflow
259*35238bceSAndroid Build Coastguard Worker const int64_t lineLengthSquared = tcu::lengthSquared(u);
260*35238bceSAndroid Build Coastguard Worker const bool limitValueCouldOverflow =
261*35238bceSAndroid Build Coastguard Worker ((64 - deClz64(lineLengthSquared)) + (64 - deClz64(broadRejectDistanceSquared))) > 63;
262*35238bceSAndroid Build Coastguard Worker const int64_t limitValue =
263*35238bceSAndroid Build Coastguard Worker (limitValueCouldOverflow) ? (0) : (lineLengthSquared * broadRejectDistanceSquared); // avoid overflow
264*35238bceSAndroid Build Coastguard Worker
265*35238bceSAndroid Build Coastguard Worker // only cross overflows
266*35238bceSAndroid Build Coastguard Worker if (crossProductOverflows && !limitValueCouldOverflow)
267*35238bceSAndroid Build Coastguard Worker return false;
268*35238bceSAndroid Build Coastguard Worker
269*35238bceSAndroid Build Coastguard Worker // both representable
270*35238bceSAndroid Build Coastguard Worker if (!crossProductOverflows && !limitValueCouldOverflow)
271*35238bceSAndroid Build Coastguard Worker {
272*35238bceSAndroid Build Coastguard Worker if (crossProductSquared > limitValue)
273*35238bceSAndroid Build Coastguard Worker return false;
274*35238bceSAndroid Build Coastguard Worker }
275*35238bceSAndroid Build Coastguard Worker }
276*35238bceSAndroid Build Coastguard Worker
277*35238bceSAndroid Build Coastguard Worker const struct DiamondBound
278*35238bceSAndroid Build Coastguard Worker {
279*35238bceSAndroid Build Coastguard Worker tcu::Vector<int64_t, 2> p0;
280*35238bceSAndroid Build Coastguard Worker tcu::Vector<int64_t, 2> p1;
281*35238bceSAndroid Build Coastguard Worker bool edgeInclusive; // would a point on the bound be inside of the region
282*35238bceSAndroid Build Coastguard Worker } bounds[] = {
283*35238bceSAndroid Build Coastguard Worker {diamondCenter + tcu::Vector<int64_t, 2>(0, -halfPixel), diamondCenter + tcu::Vector<int64_t, 2>(-halfPixel, 0),
284*35238bceSAndroid Build Coastguard Worker false},
285*35238bceSAndroid Build Coastguard Worker {diamondCenter + tcu::Vector<int64_t, 2>(-halfPixel, 0), diamondCenter + tcu::Vector<int64_t, 2>(0, halfPixel),
286*35238bceSAndroid Build Coastguard Worker false},
287*35238bceSAndroid Build Coastguard Worker {diamondCenter + tcu::Vector<int64_t, 2>(0, halfPixel), diamondCenter + tcu::Vector<int64_t, 2>(halfPixel, 0),
288*35238bceSAndroid Build Coastguard Worker true},
289*35238bceSAndroid Build Coastguard Worker {diamondCenter + tcu::Vector<int64_t, 2>(halfPixel, 0), diamondCenter + tcu::Vector<int64_t, 2>(0, -halfPixel),
290*35238bceSAndroid Build Coastguard Worker true},
291*35238bceSAndroid Build Coastguard Worker };
292*35238bceSAndroid Build Coastguard Worker
293*35238bceSAndroid Build Coastguard Worker const struct DiamondCorners
294*35238bceSAndroid Build Coastguard Worker {
295*35238bceSAndroid Build Coastguard Worker enum CORNER_EDGE_CASE_BEHAVIOR
296*35238bceSAndroid Build Coastguard Worker {
297*35238bceSAndroid Build Coastguard Worker CORNER_EDGE_CASE_NONE, // if the line intersects just a corner, no entering or exiting
298*35238bceSAndroid Build Coastguard Worker CORNER_EDGE_CASE_HIT, // if the line intersects just a corner, entering and exit
299*35238bceSAndroid Build Coastguard Worker CORNER_EDGE_CASE_HIT_FIRST_QUARTER, // if the line intersects just a corner and the line has either endpoint in (+X,-Y) direction (preturbing moves the line inside)
300*35238bceSAndroid Build Coastguard Worker CORNER_EDGE_CASE_HIT_SECOND_QUARTER // if the line intersects just a corner and the line has either endpoint in (+X,+Y) direction (preturbing moves the line inside)
301*35238bceSAndroid Build Coastguard Worker };
302*35238bceSAndroid Build Coastguard Worker enum CORNER_START_CASE_BEHAVIOR
303*35238bceSAndroid Build Coastguard Worker {
304*35238bceSAndroid Build Coastguard Worker CORNER_START_CASE_NONE, // the line starting point is outside, no exiting
305*35238bceSAndroid Build Coastguard Worker CORNER_START_CASE_OUTSIDE, // exit, if line does not intersect the region (preturbing moves the start point inside)
306*35238bceSAndroid Build Coastguard Worker CORNER_START_CASE_POSITIVE_Y_45, // exit, if line the angle of line vector and X-axis is in range (0, 45] in positive Y side.
307*35238bceSAndroid Build Coastguard Worker CORNER_START_CASE_NEGATIVE_Y_45 // exit, if line the angle of line vector and X-axis is in range [0, 45] in negative Y side.
308*35238bceSAndroid Build Coastguard Worker };
309*35238bceSAndroid Build Coastguard Worker enum CORNER_END_CASE_BEHAVIOR
310*35238bceSAndroid Build Coastguard Worker {
311*35238bceSAndroid Build Coastguard Worker CORNER_END_CASE_NONE, // end is inside, no exiting (preturbing moves the line end inside)
312*35238bceSAndroid Build Coastguard Worker CORNER_END_CASE_DIRECTION, // exit, if line intersected the region (preturbing moves the line end outside)
313*35238bceSAndroid Build Coastguard Worker CORNER_END_CASE_DIRECTION_AND_FIRST_QUARTER, // exit, if line intersected the region, or line originates from (+X,-Y) direction (preturbing moves the line end outside)
314*35238bceSAndroid Build Coastguard Worker CORNER_END_CASE_DIRECTION_AND_SECOND_QUARTER // exit, if line intersected the region, or line originates from (+X,+Y) direction (preturbing moves the line end outside)
315*35238bceSAndroid Build Coastguard Worker };
316*35238bceSAndroid Build Coastguard Worker
317*35238bceSAndroid Build Coastguard Worker tcu::Vector<int64_t, 2> dp;
318*35238bceSAndroid Build Coastguard Worker bool pointInclusive; // would a point in this corner intersect with the region
319*35238bceSAndroid Build Coastguard Worker CORNER_EDGE_CASE_BEHAVIOR
320*35238bceSAndroid Build Coastguard Worker lineBehavior; // would a line segment going through this corner intersect with the region
321*35238bceSAndroid Build Coastguard Worker CORNER_START_CASE_BEHAVIOR startBehavior; // how the corner behaves if the start point at the corner
322*35238bceSAndroid Build Coastguard Worker CORNER_END_CASE_BEHAVIOR endBehavior; // how the corner behaves if the end point at the corner
323*35238bceSAndroid Build Coastguard Worker } corners[] = {
324*35238bceSAndroid Build Coastguard Worker {tcu::Vector<int64_t, 2>(0, -halfPixel), false, DiamondCorners::CORNER_EDGE_CASE_HIT_SECOND_QUARTER,
325*35238bceSAndroid Build Coastguard Worker DiamondCorners::CORNER_START_CASE_POSITIVE_Y_45, DiamondCorners::CORNER_END_CASE_DIRECTION_AND_SECOND_QUARTER},
326*35238bceSAndroid Build Coastguard Worker {tcu::Vector<int64_t, 2>(-halfPixel, 0), false, DiamondCorners::CORNER_EDGE_CASE_NONE,
327*35238bceSAndroid Build Coastguard Worker DiamondCorners::CORNER_START_CASE_NONE, DiamondCorners::CORNER_END_CASE_DIRECTION},
328*35238bceSAndroid Build Coastguard Worker {tcu::Vector<int64_t, 2>(0, halfPixel), false, DiamondCorners::CORNER_EDGE_CASE_HIT_FIRST_QUARTER,
329*35238bceSAndroid Build Coastguard Worker DiamondCorners::CORNER_START_CASE_NEGATIVE_Y_45, DiamondCorners::CORNER_END_CASE_DIRECTION_AND_FIRST_QUARTER},
330*35238bceSAndroid Build Coastguard Worker {tcu::Vector<int64_t, 2>(halfPixel, 0), true, DiamondCorners::CORNER_EDGE_CASE_HIT,
331*35238bceSAndroid Build Coastguard Worker DiamondCorners::CORNER_START_CASE_OUTSIDE, DiamondCorners::CORNER_END_CASE_NONE},
332*35238bceSAndroid Build Coastguard Worker };
333*35238bceSAndroid Build Coastguard Worker
334*35238bceSAndroid Build Coastguard Worker // Corner cases at the corners
335*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(corners); ++ndx)
336*35238bceSAndroid Build Coastguard Worker {
337*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> p = diamondCenter + corners[ndx].dp;
338*35238bceSAndroid Build Coastguard Worker const bool intersectsAtCorner = LineRasterUtil::vertexOnLineSegment(p, line);
339*35238bceSAndroid Build Coastguard Worker
340*35238bceSAndroid Build Coastguard Worker if (!intersectsAtCorner)
341*35238bceSAndroid Build Coastguard Worker continue;
342*35238bceSAndroid Build Coastguard Worker
343*35238bceSAndroid Build Coastguard Worker // line segment body intersects with the corner
344*35238bceSAndroid Build Coastguard Worker if (p != line.m_v0 && p != line.m_v1)
345*35238bceSAndroid Build Coastguard Worker {
346*35238bceSAndroid Build Coastguard Worker if (corners[ndx].lineBehavior == DiamondCorners::CORNER_EDGE_CASE_HIT)
347*35238bceSAndroid Build Coastguard Worker return true;
348*35238bceSAndroid Build Coastguard Worker
349*35238bceSAndroid Build Coastguard Worker // endpoint in (+X, -Y) (X or Y may be 0) direction <==> x*y <= 0
350*35238bceSAndroid Build Coastguard Worker if (corners[ndx].lineBehavior == DiamondCorners::CORNER_EDGE_CASE_HIT_FIRST_QUARTER &&
351*35238bceSAndroid Build Coastguard Worker (line.direction().x() * line.direction().y()) <= 0)
352*35238bceSAndroid Build Coastguard Worker return true;
353*35238bceSAndroid Build Coastguard Worker
354*35238bceSAndroid Build Coastguard Worker // endpoint in (+X, +Y) (Y > 0) direction <==> x*y > 0
355*35238bceSAndroid Build Coastguard Worker if (corners[ndx].lineBehavior == DiamondCorners::CORNER_EDGE_CASE_HIT_SECOND_QUARTER &&
356*35238bceSAndroid Build Coastguard Worker (line.direction().x() * line.direction().y()) > 0)
357*35238bceSAndroid Build Coastguard Worker return true;
358*35238bceSAndroid Build Coastguard Worker }
359*35238bceSAndroid Build Coastguard Worker
360*35238bceSAndroid Build Coastguard Worker // line exits the area at the corner
361*35238bceSAndroid Build Coastguard Worker if (lineInCornerAngleRange(line, corners[ndx].dp))
362*35238bceSAndroid Build Coastguard Worker {
363*35238bceSAndroid Build Coastguard Worker const bool startIsInside = corners[ndx].pointInclusive || p != line.m_v0;
364*35238bceSAndroid Build Coastguard Worker const bool endIsOutside = !corners[ndx].pointInclusive || p != line.m_v1;
365*35238bceSAndroid Build Coastguard Worker
366*35238bceSAndroid Build Coastguard Worker // starting point is inside the region and end endpoint is outside
367*35238bceSAndroid Build Coastguard Worker if (startIsInside && endIsOutside)
368*35238bceSAndroid Build Coastguard Worker return true;
369*35238bceSAndroid Build Coastguard Worker }
370*35238bceSAndroid Build Coastguard Worker
371*35238bceSAndroid Build Coastguard Worker // line end is at the corner
372*35238bceSAndroid Build Coastguard Worker if (p == line.m_v1)
373*35238bceSAndroid Build Coastguard Worker {
374*35238bceSAndroid Build Coastguard Worker if (corners[ndx].endBehavior == DiamondCorners::CORNER_END_CASE_DIRECTION ||
375*35238bceSAndroid Build Coastguard Worker corners[ndx].endBehavior == DiamondCorners::CORNER_END_CASE_DIRECTION_AND_FIRST_QUARTER ||
376*35238bceSAndroid Build Coastguard Worker corners[ndx].endBehavior == DiamondCorners::CORNER_END_CASE_DIRECTION_AND_SECOND_QUARTER)
377*35238bceSAndroid Build Coastguard Worker {
378*35238bceSAndroid Build Coastguard Worker // did the line intersect the region
379*35238bceSAndroid Build Coastguard Worker if (lineInCornerAngleRange(line, corners[ndx].dp))
380*35238bceSAndroid Build Coastguard Worker return true;
381*35238bceSAndroid Build Coastguard Worker }
382*35238bceSAndroid Build Coastguard Worker
383*35238bceSAndroid Build Coastguard Worker // due to the perturbed endpoint, lines at this the angle will cause and enter-exit pair
384*35238bceSAndroid Build Coastguard Worker if (corners[ndx].endBehavior == DiamondCorners::CORNER_END_CASE_DIRECTION_AND_FIRST_QUARTER &&
385*35238bceSAndroid Build Coastguard Worker line.direction().x() < 0 && line.direction().y() > 0)
386*35238bceSAndroid Build Coastguard Worker return true;
387*35238bceSAndroid Build Coastguard Worker if (corners[ndx].endBehavior == DiamondCorners::CORNER_END_CASE_DIRECTION_AND_SECOND_QUARTER &&
388*35238bceSAndroid Build Coastguard Worker line.direction().x() > 0 && line.direction().y() > 0)
389*35238bceSAndroid Build Coastguard Worker return true;
390*35238bceSAndroid Build Coastguard Worker }
391*35238bceSAndroid Build Coastguard Worker
392*35238bceSAndroid Build Coastguard Worker // line start is at the corner
393*35238bceSAndroid Build Coastguard Worker if (p == line.m_v0)
394*35238bceSAndroid Build Coastguard Worker {
395*35238bceSAndroid Build Coastguard Worker if (corners[ndx].startBehavior == DiamondCorners::CORNER_START_CASE_OUTSIDE)
396*35238bceSAndroid Build Coastguard Worker {
397*35238bceSAndroid Build Coastguard Worker // if the line is not going inside, it will exit
398*35238bceSAndroid Build Coastguard Worker if (lineInCornerOutsideAngleRange(line, corners[ndx].dp))
399*35238bceSAndroid Build Coastguard Worker return true;
400*35238bceSAndroid Build Coastguard Worker }
401*35238bceSAndroid Build Coastguard Worker
402*35238bceSAndroid Build Coastguard Worker // exit, if line the angle between line vector and X-axis is in range (0, 45] in positive Y side.
403*35238bceSAndroid Build Coastguard Worker if (corners[ndx].startBehavior == DiamondCorners::CORNER_START_CASE_POSITIVE_Y_45 &&
404*35238bceSAndroid Build Coastguard Worker line.direction().x() > 0 && line.direction().y() > 0 && line.direction().y() <= line.direction().x())
405*35238bceSAndroid Build Coastguard Worker return true;
406*35238bceSAndroid Build Coastguard Worker
407*35238bceSAndroid Build Coastguard Worker // exit, if line the angle between line vector and X-axis is in range [0, 45] in negative Y side.
408*35238bceSAndroid Build Coastguard Worker if (corners[ndx].startBehavior == DiamondCorners::CORNER_START_CASE_NEGATIVE_Y_45 &&
409*35238bceSAndroid Build Coastguard Worker line.direction().x() > 0 && line.direction().y() <= 0 && -line.direction().y() <= line.direction().x())
410*35238bceSAndroid Build Coastguard Worker return true;
411*35238bceSAndroid Build Coastguard Worker }
412*35238bceSAndroid Build Coastguard Worker }
413*35238bceSAndroid Build Coastguard Worker
414*35238bceSAndroid Build Coastguard Worker // Does the line intersect boundary at the left == exits the diamond
415*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bounds); ++ndx)
416*35238bceSAndroid Build Coastguard Worker {
417*35238bceSAndroid Build Coastguard Worker const bool startVertexInside =
418*35238bceSAndroid Build Coastguard Worker LineRasterUtil::vertexOnLeftSideOfLine(
419*35238bceSAndroid Build Coastguard Worker line.m_v0, LineRasterUtil::SubpixelLineSegment(bounds[ndx].p0, bounds[ndx].p1)) ||
420*35238bceSAndroid Build Coastguard Worker (bounds[ndx].edgeInclusive && LineRasterUtil::vertexOnLine(line.m_v0, LineRasterUtil::SubpixelLineSegment(
421*35238bceSAndroid Build Coastguard Worker bounds[ndx].p0, bounds[ndx].p1)));
422*35238bceSAndroid Build Coastguard Worker const bool endVertexInside =
423*35238bceSAndroid Build Coastguard Worker LineRasterUtil::vertexOnLeftSideOfLine(
424*35238bceSAndroid Build Coastguard Worker line.m_v1, LineRasterUtil::SubpixelLineSegment(bounds[ndx].p0, bounds[ndx].p1)) ||
425*35238bceSAndroid Build Coastguard Worker (bounds[ndx].edgeInclusive && LineRasterUtil::vertexOnLine(line.m_v1, LineRasterUtil::SubpixelLineSegment(
426*35238bceSAndroid Build Coastguard Worker bounds[ndx].p0, bounds[ndx].p1)));
427*35238bceSAndroid Build Coastguard Worker
428*35238bceSAndroid Build Coastguard Worker // start must be on inside this half space (left or at the inclusive boundary)
429*35238bceSAndroid Build Coastguard Worker if (!startVertexInside)
430*35238bceSAndroid Build Coastguard Worker continue;
431*35238bceSAndroid Build Coastguard Worker
432*35238bceSAndroid Build Coastguard Worker // end must be outside of this half-space (right or at non-inclusive boundary)
433*35238bceSAndroid Build Coastguard Worker if (endVertexInside)
434*35238bceSAndroid Build Coastguard Worker continue;
435*35238bceSAndroid Build Coastguard Worker
436*35238bceSAndroid Build Coastguard Worker // Does the line via v0 and v1 intersect the line segment p0-p1
437*35238bceSAndroid Build Coastguard Worker // <==> p0 and p1 are the different sides (LEFT, RIGHT) of the v0-v1 line.
438*35238bceSAndroid Build Coastguard Worker // Corners are not allowed, they are checked already
439*35238bceSAndroid Build Coastguard Worker LineRasterUtil::LINE_SIDE sideP0 = LineRasterUtil::getVertexSide(bounds[ndx].p0, line);
440*35238bceSAndroid Build Coastguard Worker LineRasterUtil::LINE_SIDE sideP1 = LineRasterUtil::getVertexSide(bounds[ndx].p1, line);
441*35238bceSAndroid Build Coastguard Worker
442*35238bceSAndroid Build Coastguard Worker if (sideP0 != LineRasterUtil::LINE_SIDE_INTERSECT && sideP1 != LineRasterUtil::LINE_SIDE_INTERSECT &&
443*35238bceSAndroid Build Coastguard Worker sideP0 != sideP1)
444*35238bceSAndroid Build Coastguard Worker return true;
445*35238bceSAndroid Build Coastguard Worker }
446*35238bceSAndroid Build Coastguard Worker
447*35238bceSAndroid Build Coastguard Worker return false;
448*35238bceSAndroid Build Coastguard Worker }
449*35238bceSAndroid Build Coastguard Worker
450*35238bceSAndroid Build Coastguard Worker } // namespace LineRasterUtil
451*35238bceSAndroid Build Coastguard Worker
TriangleRasterizer(const tcu::IVec4 & viewport,const int numSamples,const RasterizationState & state,const int subpixelBits)452*35238bceSAndroid Build Coastguard Worker TriangleRasterizer::TriangleRasterizer(const tcu::IVec4 &viewport, const int numSamples,
453*35238bceSAndroid Build Coastguard Worker const RasterizationState &state, const int subpixelBits)
454*35238bceSAndroid Build Coastguard Worker : m_viewport(viewport)
455*35238bceSAndroid Build Coastguard Worker , m_numSamples(numSamples)
456*35238bceSAndroid Build Coastguard Worker , m_winding(state.winding)
457*35238bceSAndroid Build Coastguard Worker , m_horizontalFill(state.horizontalFill)
458*35238bceSAndroid Build Coastguard Worker , m_verticalFill(state.verticalFill)
459*35238bceSAndroid Build Coastguard Worker , m_subpixelBits(subpixelBits)
460*35238bceSAndroid Build Coastguard Worker , m_face(FACETYPE_LAST)
461*35238bceSAndroid Build Coastguard Worker , m_viewportOrientation(state.viewportOrientation)
462*35238bceSAndroid Build Coastguard Worker {
463*35238bceSAndroid Build Coastguard Worker }
464*35238bceSAndroid Build Coastguard Worker
465*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
466*35238bceSAndroid Build Coastguard Worker * \brief Initialize triangle rasterization
467*35238bceSAndroid Build Coastguard Worker * \param v0 Screen-space coordinates (x, y, z) and 1/w for vertex 0.
468*35238bceSAndroid Build Coastguard Worker * \param v1 Screen-space coordinates (x, y, z) and 1/w for vertex 1.
469*35238bceSAndroid Build Coastguard Worker * \param v2 Screen-space coordinates (x, y, z) and 1/w for vertex 2.
470*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
init(const tcu::Vec4 & v0,const tcu::Vec4 & v1,const tcu::Vec4 & v2)471*35238bceSAndroid Build Coastguard Worker void TriangleRasterizer::init(const tcu::Vec4 &v0, const tcu::Vec4 &v1, const tcu::Vec4 &v2)
472*35238bceSAndroid Build Coastguard Worker {
473*35238bceSAndroid Build Coastguard Worker m_v0 = v0;
474*35238bceSAndroid Build Coastguard Worker m_v1 = v1;
475*35238bceSAndroid Build Coastguard Worker m_v2 = v2;
476*35238bceSAndroid Build Coastguard Worker
477*35238bceSAndroid Build Coastguard Worker // Positions in fixed-point coordinates.
478*35238bceSAndroid Build Coastguard Worker const int64_t x0 = toSubpixelCoord(v0.x(), m_subpixelBits);
479*35238bceSAndroid Build Coastguard Worker const int64_t y0 = toSubpixelCoord(v0.y(), m_subpixelBits);
480*35238bceSAndroid Build Coastguard Worker const int64_t x1 = toSubpixelCoord(v1.x(), m_subpixelBits);
481*35238bceSAndroid Build Coastguard Worker const int64_t y1 = toSubpixelCoord(v1.y(), m_subpixelBits);
482*35238bceSAndroid Build Coastguard Worker const int64_t x2 = toSubpixelCoord(v2.x(), m_subpixelBits);
483*35238bceSAndroid Build Coastguard Worker const int64_t y2 = toSubpixelCoord(v2.y(), m_subpixelBits);
484*35238bceSAndroid Build Coastguard Worker
485*35238bceSAndroid Build Coastguard Worker // Initialize edge functions.
486*35238bceSAndroid Build Coastguard Worker if (m_winding == WINDING_CCW)
487*35238bceSAndroid Build Coastguard Worker {
488*35238bceSAndroid Build Coastguard Worker initEdgeCCW(m_edge01, m_horizontalFill, m_verticalFill, x0, y0, x1, y1);
489*35238bceSAndroid Build Coastguard Worker initEdgeCCW(m_edge12, m_horizontalFill, m_verticalFill, x1, y1, x2, y2);
490*35238bceSAndroid Build Coastguard Worker initEdgeCCW(m_edge20, m_horizontalFill, m_verticalFill, x2, y2, x0, y0);
491*35238bceSAndroid Build Coastguard Worker }
492*35238bceSAndroid Build Coastguard Worker else
493*35238bceSAndroid Build Coastguard Worker {
494*35238bceSAndroid Build Coastguard Worker // Reverse edges
495*35238bceSAndroid Build Coastguard Worker initEdgeCCW(m_edge01, m_horizontalFill, m_verticalFill, x1, y1, x0, y0);
496*35238bceSAndroid Build Coastguard Worker initEdgeCCW(m_edge12, m_horizontalFill, m_verticalFill, x2, y2, x1, y1);
497*35238bceSAndroid Build Coastguard Worker initEdgeCCW(m_edge20, m_horizontalFill, m_verticalFill, x0, y0, x2, y2);
498*35238bceSAndroid Build Coastguard Worker }
499*35238bceSAndroid Build Coastguard Worker
500*35238bceSAndroid Build Coastguard Worker // Determine face.
501*35238bceSAndroid Build Coastguard Worker const int64_t s = evaluateEdge(m_edge01, x2, y2);
502*35238bceSAndroid Build Coastguard Worker const bool positiveArea = (m_winding == WINDING_CCW) ? (s > 0) : (s < 0);
503*35238bceSAndroid Build Coastguard Worker
504*35238bceSAndroid Build Coastguard Worker if (m_viewportOrientation == VIEWPORTORIENTATION_UPPER_LEFT)
505*35238bceSAndroid Build Coastguard Worker m_face = positiveArea ? FACETYPE_BACK : FACETYPE_FRONT;
506*35238bceSAndroid Build Coastguard Worker else
507*35238bceSAndroid Build Coastguard Worker m_face = positiveArea ? FACETYPE_FRONT : FACETYPE_BACK;
508*35238bceSAndroid Build Coastguard Worker
509*35238bceSAndroid Build Coastguard Worker if (!positiveArea)
510*35238bceSAndroid Build Coastguard Worker {
511*35238bceSAndroid Build Coastguard Worker // Reverse edges so that we can use CCW area tests & interpolation
512*35238bceSAndroid Build Coastguard Worker reverseEdge(m_edge01);
513*35238bceSAndroid Build Coastguard Worker reverseEdge(m_edge12);
514*35238bceSAndroid Build Coastguard Worker reverseEdge(m_edge20);
515*35238bceSAndroid Build Coastguard Worker }
516*35238bceSAndroid Build Coastguard Worker
517*35238bceSAndroid Build Coastguard Worker // Bounding box
518*35238bceSAndroid Build Coastguard Worker const int64_t xMin = de::min(de::min(x0, x1), x2);
519*35238bceSAndroid Build Coastguard Worker const int64_t xMax = de::max(de::max(x0, x1), x2);
520*35238bceSAndroid Build Coastguard Worker const int64_t yMin = de::min(de::min(y0, y1), y2);
521*35238bceSAndroid Build Coastguard Worker const int64_t yMax = de::max(de::max(y0, y1), y2);
522*35238bceSAndroid Build Coastguard Worker
523*35238bceSAndroid Build Coastguard Worker m_bboxMin.x() = floorSubpixelToPixelCoord(xMin, m_subpixelBits, m_horizontalFill == FILL_LEFT);
524*35238bceSAndroid Build Coastguard Worker m_bboxMin.y() = floorSubpixelToPixelCoord(yMin, m_subpixelBits, m_verticalFill == FILL_BOTTOM);
525*35238bceSAndroid Build Coastguard Worker m_bboxMax.x() = ceilSubpixelToPixelCoord(xMax, m_subpixelBits, m_horizontalFill == FILL_RIGHT);
526*35238bceSAndroid Build Coastguard Worker m_bboxMax.y() = ceilSubpixelToPixelCoord(yMax, m_subpixelBits, m_verticalFill == FILL_TOP);
527*35238bceSAndroid Build Coastguard Worker
528*35238bceSAndroid Build Coastguard Worker // Clamp to viewport
529*35238bceSAndroid Build Coastguard Worker const int wX0 = m_viewport.x();
530*35238bceSAndroid Build Coastguard Worker const int wY0 = m_viewport.y();
531*35238bceSAndroid Build Coastguard Worker const int wX1 = wX0 + m_viewport.z() - 1;
532*35238bceSAndroid Build Coastguard Worker const int wY1 = wY0 + m_viewport.w() - 1;
533*35238bceSAndroid Build Coastguard Worker
534*35238bceSAndroid Build Coastguard Worker m_bboxMin.x() = de::clamp(m_bboxMin.x(), wX0, wX1);
535*35238bceSAndroid Build Coastguard Worker m_bboxMin.y() = de::clamp(m_bboxMin.y(), wY0, wY1);
536*35238bceSAndroid Build Coastguard Worker m_bboxMax.x() = de::clamp(m_bboxMax.x(), wX0, wX1);
537*35238bceSAndroid Build Coastguard Worker m_bboxMax.y() = de::clamp(m_bboxMax.y(), wY0, wY1);
538*35238bceSAndroid Build Coastguard Worker
539*35238bceSAndroid Build Coastguard Worker m_curPos = m_bboxMin;
540*35238bceSAndroid Build Coastguard Worker }
541*35238bceSAndroid Build Coastguard Worker
rasterizeSingleSample(FragmentPacket * const fragmentPackets,float * const depthValues,const int maxFragmentPackets,int & numPacketsRasterized)542*35238bceSAndroid Build Coastguard Worker void TriangleRasterizer::rasterizeSingleSample(FragmentPacket *const fragmentPackets, float *const depthValues,
543*35238bceSAndroid Build Coastguard Worker const int maxFragmentPackets, int &numPacketsRasterized)
544*35238bceSAndroid Build Coastguard Worker {
545*35238bceSAndroid Build Coastguard Worker DE_ASSERT(maxFragmentPackets > 0);
546*35238bceSAndroid Build Coastguard Worker
547*35238bceSAndroid Build Coastguard Worker const uint64_t halfPixel = 1ll << (m_subpixelBits - 1);
548*35238bceSAndroid Build Coastguard Worker int packetNdx = 0;
549*35238bceSAndroid Build Coastguard Worker
550*35238bceSAndroid Build Coastguard Worker // For depth interpolation; given barycentrics A, B, C = (1 - A - B)
551*35238bceSAndroid Build Coastguard Worker // we can reformulate the usual z = z0*A + z1*B + z2*C into more
552*35238bceSAndroid Build Coastguard Worker // stable equation z = A*(z0 - z2) + B*(z1 - z2) + z2.
553*35238bceSAndroid Build Coastguard Worker const float za = m_v0.z() - m_v2.z();
554*35238bceSAndroid Build Coastguard Worker const float zb = m_v1.z() - m_v2.z();
555*35238bceSAndroid Build Coastguard Worker const float zc = m_v2.z();
556*35238bceSAndroid Build Coastguard Worker
557*35238bceSAndroid Build Coastguard Worker while (m_curPos.y() <= m_bboxMax.y() && packetNdx < maxFragmentPackets)
558*35238bceSAndroid Build Coastguard Worker {
559*35238bceSAndroid Build Coastguard Worker const int x0 = m_curPos.x();
560*35238bceSAndroid Build Coastguard Worker const int y0 = m_curPos.y();
561*35238bceSAndroid Build Coastguard Worker
562*35238bceSAndroid Build Coastguard Worker // Subpixel coords
563*35238bceSAndroid Build Coastguard Worker const int64_t sx0 = toSubpixelCoord(x0, m_subpixelBits) + halfPixel;
564*35238bceSAndroid Build Coastguard Worker const int64_t sx1 = toSubpixelCoord(x0 + 1, m_subpixelBits) + halfPixel;
565*35238bceSAndroid Build Coastguard Worker const int64_t sy0 = toSubpixelCoord(y0, m_subpixelBits) + halfPixel;
566*35238bceSAndroid Build Coastguard Worker const int64_t sy1 = toSubpixelCoord(y0 + 1, m_subpixelBits) + halfPixel;
567*35238bceSAndroid Build Coastguard Worker
568*35238bceSAndroid Build Coastguard Worker const int64_t sx[4] = {sx0, sx1, sx0, sx1};
569*35238bceSAndroid Build Coastguard Worker const int64_t sy[4] = {sy0, sy0, sy1, sy1};
570*35238bceSAndroid Build Coastguard Worker
571*35238bceSAndroid Build Coastguard Worker // Viewport test
572*35238bceSAndroid Build Coastguard Worker const bool outX1 = x0 + 1 == m_viewport.x() + m_viewport.z();
573*35238bceSAndroid Build Coastguard Worker const bool outY1 = y0 + 1 == m_viewport.y() + m_viewport.w();
574*35238bceSAndroid Build Coastguard Worker
575*35238bceSAndroid Build Coastguard Worker DE_ASSERT(x0 < m_viewport.x() + m_viewport.z());
576*35238bceSAndroid Build Coastguard Worker DE_ASSERT(y0 < m_viewport.y() + m_viewport.w());
577*35238bceSAndroid Build Coastguard Worker
578*35238bceSAndroid Build Coastguard Worker // Edge values
579*35238bceSAndroid Build Coastguard Worker tcu::Vector<int64_t, 4> e01;
580*35238bceSAndroid Build Coastguard Worker tcu::Vector<int64_t, 4> e12;
581*35238bceSAndroid Build Coastguard Worker tcu::Vector<int64_t, 4> e20;
582*35238bceSAndroid Build Coastguard Worker
583*35238bceSAndroid Build Coastguard Worker // Coverage
584*35238bceSAndroid Build Coastguard Worker uint64_t coverage = 0;
585*35238bceSAndroid Build Coastguard Worker
586*35238bceSAndroid Build Coastguard Worker // Evaluate edge values
587*35238bceSAndroid Build Coastguard Worker for (int i = 0; i < 4; i++)
588*35238bceSAndroid Build Coastguard Worker {
589*35238bceSAndroid Build Coastguard Worker e01[i] = evaluateEdge(m_edge01, sx[i], sy[i]);
590*35238bceSAndroid Build Coastguard Worker e12[i] = evaluateEdge(m_edge12, sx[i], sy[i]);
591*35238bceSAndroid Build Coastguard Worker e20[i] = evaluateEdge(m_edge20, sx[i], sy[i]);
592*35238bceSAndroid Build Coastguard Worker }
593*35238bceSAndroid Build Coastguard Worker
594*35238bceSAndroid Build Coastguard Worker // Compute coverage mask
595*35238bceSAndroid Build Coastguard Worker coverage = setCoverageValue(coverage, 1, 0, 0, 0,
596*35238bceSAndroid Build Coastguard Worker isInsideCCW(m_edge01, e01[0]) && isInsideCCW(m_edge12, e12[0]) &&
597*35238bceSAndroid Build Coastguard Worker isInsideCCW(m_edge20, e20[0]));
598*35238bceSAndroid Build Coastguard Worker coverage = setCoverageValue(coverage, 1, 1, 0, 0,
599*35238bceSAndroid Build Coastguard Worker !outX1 && isInsideCCW(m_edge01, e01[1]) && isInsideCCW(m_edge12, e12[1]) &&
600*35238bceSAndroid Build Coastguard Worker isInsideCCW(m_edge20, e20[1]));
601*35238bceSAndroid Build Coastguard Worker coverage = setCoverageValue(coverage, 1, 0, 1, 0,
602*35238bceSAndroid Build Coastguard Worker !outY1 && isInsideCCW(m_edge01, e01[2]) && isInsideCCW(m_edge12, e12[2]) &&
603*35238bceSAndroid Build Coastguard Worker isInsideCCW(m_edge20, e20[2]));
604*35238bceSAndroid Build Coastguard Worker coverage = setCoverageValue(coverage, 1, 1, 1, 0,
605*35238bceSAndroid Build Coastguard Worker !outX1 && !outY1 && isInsideCCW(m_edge01, e01[3]) &&
606*35238bceSAndroid Build Coastguard Worker isInsideCCW(m_edge12, e12[3]) && isInsideCCW(m_edge20, e20[3]));
607*35238bceSAndroid Build Coastguard Worker
608*35238bceSAndroid Build Coastguard Worker // Advance to next location
609*35238bceSAndroid Build Coastguard Worker m_curPos.x() += 2;
610*35238bceSAndroid Build Coastguard Worker if (m_curPos.x() > m_bboxMax.x())
611*35238bceSAndroid Build Coastguard Worker {
612*35238bceSAndroid Build Coastguard Worker m_curPos.y() += 2;
613*35238bceSAndroid Build Coastguard Worker m_curPos.x() = m_bboxMin.x();
614*35238bceSAndroid Build Coastguard Worker }
615*35238bceSAndroid Build Coastguard Worker
616*35238bceSAndroid Build Coastguard Worker if (coverage == 0)
617*35238bceSAndroid Build Coastguard Worker continue; // Discard.
618*35238bceSAndroid Build Coastguard Worker
619*35238bceSAndroid Build Coastguard Worker // Floating-point edge values for barycentrics etc.
620*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 e01f = e01.asFloat();
621*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 e12f = e12.asFloat();
622*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 e20f = e20.asFloat();
623*35238bceSAndroid Build Coastguard Worker
624*35238bceSAndroid Build Coastguard Worker // Compute depth values.
625*35238bceSAndroid Build Coastguard Worker if (depthValues)
626*35238bceSAndroid Build Coastguard Worker {
627*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 edgeSum = e01f + e12f + e20f;
628*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 z0 = e12f / edgeSum;
629*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 z1 = e20f / edgeSum;
630*35238bceSAndroid Build Coastguard Worker
631*35238bceSAndroid Build Coastguard Worker depthValues[packetNdx * 4 + 0] = z0[0] * za + z1[0] * zb + zc;
632*35238bceSAndroid Build Coastguard Worker depthValues[packetNdx * 4 + 1] = z0[1] * za + z1[1] * zb + zc;
633*35238bceSAndroid Build Coastguard Worker depthValues[packetNdx * 4 + 2] = z0[2] * za + z1[2] * zb + zc;
634*35238bceSAndroid Build Coastguard Worker depthValues[packetNdx * 4 + 3] = z0[3] * za + z1[3] * zb + zc;
635*35238bceSAndroid Build Coastguard Worker }
636*35238bceSAndroid Build Coastguard Worker
637*35238bceSAndroid Build Coastguard Worker // Compute barycentrics and write out fragment packet
638*35238bceSAndroid Build Coastguard Worker {
639*35238bceSAndroid Build Coastguard Worker FragmentPacket &packet = fragmentPackets[packetNdx];
640*35238bceSAndroid Build Coastguard Worker
641*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 b0 = e12f * m_v0.w();
642*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 b1 = e20f * m_v1.w();
643*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 b2 = e01f * m_v2.w();
644*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 bSum = b0 + b1 + b2;
645*35238bceSAndroid Build Coastguard Worker
646*35238bceSAndroid Build Coastguard Worker packet.position = tcu::IVec2(x0, y0);
647*35238bceSAndroid Build Coastguard Worker packet.coverage = coverage;
648*35238bceSAndroid Build Coastguard Worker packet.barycentric[0] = b0 / bSum;
649*35238bceSAndroid Build Coastguard Worker packet.barycentric[1] = b1 / bSum;
650*35238bceSAndroid Build Coastguard Worker packet.barycentric[2] = 1.0f - packet.barycentric[0] - packet.barycentric[1];
651*35238bceSAndroid Build Coastguard Worker
652*35238bceSAndroid Build Coastguard Worker packetNdx += 1;
653*35238bceSAndroid Build Coastguard Worker }
654*35238bceSAndroid Build Coastguard Worker }
655*35238bceSAndroid Build Coastguard Worker
656*35238bceSAndroid Build Coastguard Worker DE_ASSERT(packetNdx <= maxFragmentPackets);
657*35238bceSAndroid Build Coastguard Worker numPacketsRasterized = packetNdx;
658*35238bceSAndroid Build Coastguard Worker }
659*35238bceSAndroid Build Coastguard Worker
660*35238bceSAndroid Build Coastguard Worker // Sample positions - ordered as (x, y) list.
661*35238bceSAndroid Build Coastguard Worker static const float s_samplePts2[] = {0.3f, 0.3f, 0.7f, 0.7f};
662*35238bceSAndroid Build Coastguard Worker
663*35238bceSAndroid Build Coastguard Worker static const float s_samplePts4[] = {0.25f, 0.25f, 0.75f, 0.25f, 0.25f, 0.75f, 0.75f, 0.75f};
664*35238bceSAndroid Build Coastguard Worker
665*35238bceSAndroid Build Coastguard Worker static const float s_samplePts8[] = {7.f / 16.f, 9.f / 16.f, 9.f / 16.f, 13.f / 16.f, 11.f / 16.f, 3.f / 16.f,
666*35238bceSAndroid Build Coastguard Worker 13.f / 16.f, 11.f / 16.f, 1.f / 16.f, 7.f / 16.f, 5.f / 16.f, 1.f / 16.f,
667*35238bceSAndroid Build Coastguard Worker 15.f / 16.f, 5.f / 16.f, 3.f / 16.f, 15.f / 16.f};
668*35238bceSAndroid Build Coastguard Worker
669*35238bceSAndroid Build Coastguard Worker static const float s_samplePts16[] = {1.f / 8.f, 1.f / 8.f, 3.f / 8.f, 1.f / 8.f, 5.f / 8.f, 1.f / 8.f, 7.f / 8.f,
670*35238bceSAndroid Build Coastguard Worker 1.f / 8.f, 1.f / 8.f, 3.f / 8.f, 3.f / 8.f, 3.f / 8.f, 5.f / 8.f, 3.f / 8.f,
671*35238bceSAndroid Build Coastguard Worker 7.f / 8.f, 3.f / 8.f, 1.f / 8.f, 5.f / 8.f, 3.f / 8.f, 5.f / 8.f, 5.f / 8.f,
672*35238bceSAndroid Build Coastguard Worker 5.f / 8.f, 7.f / 8.f, 5.f / 8.f, 1.f / 8.f, 7.f / 8.f, 3.f / 8.f, 7.f / 8.f,
673*35238bceSAndroid Build Coastguard Worker 5.f / 8.f, 7.f / 8.f, 7.f / 8.f, 7.f / 8.f};
674*35238bceSAndroid Build Coastguard Worker
675*35238bceSAndroid Build Coastguard Worker template <int NumSamples>
rasterizeMultiSample(FragmentPacket * const fragmentPackets,float * const depthValues,const int maxFragmentPackets,int & numPacketsRasterized)676*35238bceSAndroid Build Coastguard Worker void TriangleRasterizer::rasterizeMultiSample(FragmentPacket *const fragmentPackets, float *const depthValues,
677*35238bceSAndroid Build Coastguard Worker const int maxFragmentPackets, int &numPacketsRasterized)
678*35238bceSAndroid Build Coastguard Worker {
679*35238bceSAndroid Build Coastguard Worker DE_ASSERT(maxFragmentPackets > 0);
680*35238bceSAndroid Build Coastguard Worker
681*35238bceSAndroid Build Coastguard Worker // Big enough to hold maximum multisample count
682*35238bceSAndroid Build Coastguard Worker int64_t samplePos[DE_LENGTH_OF_ARRAY(s_samplePts16)];
683*35238bceSAndroid Build Coastguard Worker const float *samplePts = DE_NULL;
684*35238bceSAndroid Build Coastguard Worker const uint64_t halfPixel = 1ll << (m_subpixelBits - 1);
685*35238bceSAndroid Build Coastguard Worker int packetNdx = 0;
686*35238bceSAndroid Build Coastguard Worker
687*35238bceSAndroid Build Coastguard Worker // For depth interpolation, see rasterizeSingleSample
688*35238bceSAndroid Build Coastguard Worker const float za = m_v0.z() - m_v2.z();
689*35238bceSAndroid Build Coastguard Worker const float zb = m_v1.z() - m_v2.z();
690*35238bceSAndroid Build Coastguard Worker const float zc = m_v2.z();
691*35238bceSAndroid Build Coastguard Worker
692*35238bceSAndroid Build Coastguard Worker switch (NumSamples)
693*35238bceSAndroid Build Coastguard Worker {
694*35238bceSAndroid Build Coastguard Worker case 2:
695*35238bceSAndroid Build Coastguard Worker samplePts = s_samplePts2;
696*35238bceSAndroid Build Coastguard Worker break;
697*35238bceSAndroid Build Coastguard Worker case 4:
698*35238bceSAndroid Build Coastguard Worker samplePts = s_samplePts4;
699*35238bceSAndroid Build Coastguard Worker break;
700*35238bceSAndroid Build Coastguard Worker case 8:
701*35238bceSAndroid Build Coastguard Worker samplePts = s_samplePts8;
702*35238bceSAndroid Build Coastguard Worker break;
703*35238bceSAndroid Build Coastguard Worker case 16:
704*35238bceSAndroid Build Coastguard Worker samplePts = s_samplePts16;
705*35238bceSAndroid Build Coastguard Worker break;
706*35238bceSAndroid Build Coastguard Worker default:
707*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
708*35238bceSAndroid Build Coastguard Worker }
709*35238bceSAndroid Build Coastguard Worker
710*35238bceSAndroid Build Coastguard Worker for (int c = 0; c < NumSamples * 2; ++c)
711*35238bceSAndroid Build Coastguard Worker samplePos[c] = toSubpixelCoord(samplePts[c], m_subpixelBits);
712*35238bceSAndroid Build Coastguard Worker
713*35238bceSAndroid Build Coastguard Worker while (m_curPos.y() <= m_bboxMax.y() && packetNdx < maxFragmentPackets)
714*35238bceSAndroid Build Coastguard Worker {
715*35238bceSAndroid Build Coastguard Worker const int x0 = m_curPos.x();
716*35238bceSAndroid Build Coastguard Worker const int y0 = m_curPos.y();
717*35238bceSAndroid Build Coastguard Worker
718*35238bceSAndroid Build Coastguard Worker // Base subpixel coords
719*35238bceSAndroid Build Coastguard Worker const int64_t sx0 = toSubpixelCoord(x0, m_subpixelBits);
720*35238bceSAndroid Build Coastguard Worker const int64_t sx1 = toSubpixelCoord(x0 + 1, m_subpixelBits);
721*35238bceSAndroid Build Coastguard Worker const int64_t sy0 = toSubpixelCoord(y0, m_subpixelBits);
722*35238bceSAndroid Build Coastguard Worker const int64_t sy1 = toSubpixelCoord(y0 + 1, m_subpixelBits);
723*35238bceSAndroid Build Coastguard Worker
724*35238bceSAndroid Build Coastguard Worker const int64_t sx[4] = {sx0, sx1, sx0, sx1};
725*35238bceSAndroid Build Coastguard Worker const int64_t sy[4] = {sy0, sy0, sy1, sy1};
726*35238bceSAndroid Build Coastguard Worker
727*35238bceSAndroid Build Coastguard Worker // Viewport test
728*35238bceSAndroid Build Coastguard Worker const bool outX1 = x0 + 1 == m_viewport.x() + m_viewport.z();
729*35238bceSAndroid Build Coastguard Worker const bool outY1 = y0 + 1 == m_viewport.y() + m_viewport.w();
730*35238bceSAndroid Build Coastguard Worker
731*35238bceSAndroid Build Coastguard Worker DE_ASSERT(x0 < m_viewport.x() + m_viewport.z());
732*35238bceSAndroid Build Coastguard Worker DE_ASSERT(y0 < m_viewport.y() + m_viewport.w());
733*35238bceSAndroid Build Coastguard Worker
734*35238bceSAndroid Build Coastguard Worker // Edge values
735*35238bceSAndroid Build Coastguard Worker tcu::Vector<int64_t, 4> e01[NumSamples];
736*35238bceSAndroid Build Coastguard Worker tcu::Vector<int64_t, 4> e12[NumSamples];
737*35238bceSAndroid Build Coastguard Worker tcu::Vector<int64_t, 4> e20[NumSamples];
738*35238bceSAndroid Build Coastguard Worker
739*35238bceSAndroid Build Coastguard Worker // Coverage
740*35238bceSAndroid Build Coastguard Worker uint64_t coverage = 0;
741*35238bceSAndroid Build Coastguard Worker
742*35238bceSAndroid Build Coastguard Worker // Evaluate edge values at sample positions
743*35238bceSAndroid Build Coastguard Worker for (int sampleNdx = 0; sampleNdx < NumSamples; sampleNdx++)
744*35238bceSAndroid Build Coastguard Worker {
745*35238bceSAndroid Build Coastguard Worker const int64_t ox = samplePos[sampleNdx * 2 + 0];
746*35238bceSAndroid Build Coastguard Worker const int64_t oy = samplePos[sampleNdx * 2 + 1];
747*35238bceSAndroid Build Coastguard Worker
748*35238bceSAndroid Build Coastguard Worker for (int fragNdx = 0; fragNdx < 4; fragNdx++)
749*35238bceSAndroid Build Coastguard Worker {
750*35238bceSAndroid Build Coastguard Worker e01[sampleNdx][fragNdx] = evaluateEdge(m_edge01, sx[fragNdx] + ox, sy[fragNdx] + oy);
751*35238bceSAndroid Build Coastguard Worker e12[sampleNdx][fragNdx] = evaluateEdge(m_edge12, sx[fragNdx] + ox, sy[fragNdx] + oy);
752*35238bceSAndroid Build Coastguard Worker e20[sampleNdx][fragNdx] = evaluateEdge(m_edge20, sx[fragNdx] + ox, sy[fragNdx] + oy);
753*35238bceSAndroid Build Coastguard Worker }
754*35238bceSAndroid Build Coastguard Worker }
755*35238bceSAndroid Build Coastguard Worker
756*35238bceSAndroid Build Coastguard Worker // Compute coverage mask
757*35238bceSAndroid Build Coastguard Worker for (int sampleNdx = 0; sampleNdx < NumSamples; sampleNdx++)
758*35238bceSAndroid Build Coastguard Worker {
759*35238bceSAndroid Build Coastguard Worker coverage =
760*35238bceSAndroid Build Coastguard Worker setCoverageValue(coverage, NumSamples, 0, 0, sampleNdx,
761*35238bceSAndroid Build Coastguard Worker isInsideCCW(m_edge01, e01[sampleNdx][0]) && isInsideCCW(m_edge12, e12[sampleNdx][0]) &&
762*35238bceSAndroid Build Coastguard Worker isInsideCCW(m_edge20, e20[sampleNdx][0]));
763*35238bceSAndroid Build Coastguard Worker coverage = setCoverageValue(coverage, NumSamples, 1, 0, sampleNdx,
764*35238bceSAndroid Build Coastguard Worker !outX1 && isInsideCCW(m_edge01, e01[sampleNdx][1]) &&
765*35238bceSAndroid Build Coastguard Worker isInsideCCW(m_edge12, e12[sampleNdx][1]) &&
766*35238bceSAndroid Build Coastguard Worker isInsideCCW(m_edge20, e20[sampleNdx][1]));
767*35238bceSAndroid Build Coastguard Worker coverage = setCoverageValue(coverage, NumSamples, 0, 1, sampleNdx,
768*35238bceSAndroid Build Coastguard Worker !outY1 && isInsideCCW(m_edge01, e01[sampleNdx][2]) &&
769*35238bceSAndroid Build Coastguard Worker isInsideCCW(m_edge12, e12[sampleNdx][2]) &&
770*35238bceSAndroid Build Coastguard Worker isInsideCCW(m_edge20, e20[sampleNdx][2]));
771*35238bceSAndroid Build Coastguard Worker coverage = setCoverageValue(coverage, NumSamples, 1, 1, sampleNdx,
772*35238bceSAndroid Build Coastguard Worker !outX1 && !outY1 && isInsideCCW(m_edge01, e01[sampleNdx][3]) &&
773*35238bceSAndroid Build Coastguard Worker isInsideCCW(m_edge12, e12[sampleNdx][3]) &&
774*35238bceSAndroid Build Coastguard Worker isInsideCCW(m_edge20, e20[sampleNdx][3]));
775*35238bceSAndroid Build Coastguard Worker }
776*35238bceSAndroid Build Coastguard Worker
777*35238bceSAndroid Build Coastguard Worker // Advance to next location
778*35238bceSAndroid Build Coastguard Worker m_curPos.x() += 2;
779*35238bceSAndroid Build Coastguard Worker if (m_curPos.x() > m_bboxMax.x())
780*35238bceSAndroid Build Coastguard Worker {
781*35238bceSAndroid Build Coastguard Worker m_curPos.y() += 2;
782*35238bceSAndroid Build Coastguard Worker m_curPos.x() = m_bboxMin.x();
783*35238bceSAndroid Build Coastguard Worker }
784*35238bceSAndroid Build Coastguard Worker
785*35238bceSAndroid Build Coastguard Worker if (coverage == 0)
786*35238bceSAndroid Build Coastguard Worker continue; // Discard.
787*35238bceSAndroid Build Coastguard Worker
788*35238bceSAndroid Build Coastguard Worker // Compute depth values.
789*35238bceSAndroid Build Coastguard Worker if (depthValues)
790*35238bceSAndroid Build Coastguard Worker {
791*35238bceSAndroid Build Coastguard Worker for (int sampleNdx = 0; sampleNdx < NumSamples; sampleNdx++)
792*35238bceSAndroid Build Coastguard Worker {
793*35238bceSAndroid Build Coastguard Worker // Floating-point edge values at sample coordinates.
794*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 &e01f = e01[sampleNdx].asFloat();
795*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 &e12f = e12[sampleNdx].asFloat();
796*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 &e20f = e20[sampleNdx].asFloat();
797*35238bceSAndroid Build Coastguard Worker
798*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 edgeSum = e01f + e12f + e20f;
799*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 z0 = e12f / edgeSum;
800*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 z1 = e20f / edgeSum;
801*35238bceSAndroid Build Coastguard Worker
802*35238bceSAndroid Build Coastguard Worker depthValues[(packetNdx * 4 + 0) * NumSamples + sampleNdx] = z0[0] * za + z1[0] * zb + zc;
803*35238bceSAndroid Build Coastguard Worker depthValues[(packetNdx * 4 + 1) * NumSamples + sampleNdx] = z0[1] * za + z1[1] * zb + zc;
804*35238bceSAndroid Build Coastguard Worker depthValues[(packetNdx * 4 + 2) * NumSamples + sampleNdx] = z0[2] * za + z1[2] * zb + zc;
805*35238bceSAndroid Build Coastguard Worker depthValues[(packetNdx * 4 + 3) * NumSamples + sampleNdx] = z0[3] * za + z1[3] * zb + zc;
806*35238bceSAndroid Build Coastguard Worker }
807*35238bceSAndroid Build Coastguard Worker }
808*35238bceSAndroid Build Coastguard Worker
809*35238bceSAndroid Build Coastguard Worker // Compute barycentrics and write out fragment packet
810*35238bceSAndroid Build Coastguard Worker {
811*35238bceSAndroid Build Coastguard Worker FragmentPacket &packet = fragmentPackets[packetNdx];
812*35238bceSAndroid Build Coastguard Worker
813*35238bceSAndroid Build Coastguard Worker // Floating-point edge values at pixel center.
814*35238bceSAndroid Build Coastguard Worker tcu::Vec4 e01f;
815*35238bceSAndroid Build Coastguard Worker tcu::Vec4 e12f;
816*35238bceSAndroid Build Coastguard Worker tcu::Vec4 e20f;
817*35238bceSAndroid Build Coastguard Worker
818*35238bceSAndroid Build Coastguard Worker for (int i = 0; i < 4; i++)
819*35238bceSAndroid Build Coastguard Worker {
820*35238bceSAndroid Build Coastguard Worker e01f[i] = float(evaluateEdge(m_edge01, sx[i] + halfPixel, sy[i] + halfPixel));
821*35238bceSAndroid Build Coastguard Worker e12f[i] = float(evaluateEdge(m_edge12, sx[i] + halfPixel, sy[i] + halfPixel));
822*35238bceSAndroid Build Coastguard Worker e20f[i] = float(evaluateEdge(m_edge20, sx[i] + halfPixel, sy[i] + halfPixel));
823*35238bceSAndroid Build Coastguard Worker }
824*35238bceSAndroid Build Coastguard Worker
825*35238bceSAndroid Build Coastguard Worker // Barycentrics & scale.
826*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 b0 = e12f * m_v0.w();
827*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 b1 = e20f * m_v1.w();
828*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 b2 = e01f * m_v2.w();
829*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 bSum = b0 + b1 + b2;
830*35238bceSAndroid Build Coastguard Worker
831*35238bceSAndroid Build Coastguard Worker packet.position = tcu::IVec2(x0, y0);
832*35238bceSAndroid Build Coastguard Worker packet.coverage = coverage;
833*35238bceSAndroid Build Coastguard Worker packet.barycentric[0] = b0 / bSum;
834*35238bceSAndroid Build Coastguard Worker packet.barycentric[1] = b1 / bSum;
835*35238bceSAndroid Build Coastguard Worker packet.barycentric[2] = 1.0f - packet.barycentric[0] - packet.barycentric[1];
836*35238bceSAndroid Build Coastguard Worker
837*35238bceSAndroid Build Coastguard Worker packetNdx += 1;
838*35238bceSAndroid Build Coastguard Worker }
839*35238bceSAndroid Build Coastguard Worker }
840*35238bceSAndroid Build Coastguard Worker
841*35238bceSAndroid Build Coastguard Worker DE_ASSERT(packetNdx <= maxFragmentPackets);
842*35238bceSAndroid Build Coastguard Worker numPacketsRasterized = packetNdx;
843*35238bceSAndroid Build Coastguard Worker }
844*35238bceSAndroid Build Coastguard Worker
rasterize(FragmentPacket * const fragmentPackets,float * const depthValues,const int maxFragmentPackets,int & numPacketsRasterized)845*35238bceSAndroid Build Coastguard Worker void TriangleRasterizer::rasterize(FragmentPacket *const fragmentPackets, float *const depthValues,
846*35238bceSAndroid Build Coastguard Worker const int maxFragmentPackets, int &numPacketsRasterized)
847*35238bceSAndroid Build Coastguard Worker {
848*35238bceSAndroid Build Coastguard Worker DE_ASSERT(maxFragmentPackets > 0);
849*35238bceSAndroid Build Coastguard Worker
850*35238bceSAndroid Build Coastguard Worker switch (m_numSamples)
851*35238bceSAndroid Build Coastguard Worker {
852*35238bceSAndroid Build Coastguard Worker case 1:
853*35238bceSAndroid Build Coastguard Worker rasterizeSingleSample(fragmentPackets, depthValues, maxFragmentPackets, numPacketsRasterized);
854*35238bceSAndroid Build Coastguard Worker break;
855*35238bceSAndroid Build Coastguard Worker case 2:
856*35238bceSAndroid Build Coastguard Worker rasterizeMultiSample<2>(fragmentPackets, depthValues, maxFragmentPackets, numPacketsRasterized);
857*35238bceSAndroid Build Coastguard Worker break;
858*35238bceSAndroid Build Coastguard Worker case 4:
859*35238bceSAndroid Build Coastguard Worker rasterizeMultiSample<4>(fragmentPackets, depthValues, maxFragmentPackets, numPacketsRasterized);
860*35238bceSAndroid Build Coastguard Worker break;
861*35238bceSAndroid Build Coastguard Worker case 8:
862*35238bceSAndroid Build Coastguard Worker rasterizeMultiSample<8>(fragmentPackets, depthValues, maxFragmentPackets, numPacketsRasterized);
863*35238bceSAndroid Build Coastguard Worker break;
864*35238bceSAndroid Build Coastguard Worker case 16:
865*35238bceSAndroid Build Coastguard Worker rasterizeMultiSample<16>(fragmentPackets, depthValues, maxFragmentPackets, numPacketsRasterized);
866*35238bceSAndroid Build Coastguard Worker break;
867*35238bceSAndroid Build Coastguard Worker default:
868*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
869*35238bceSAndroid Build Coastguard Worker }
870*35238bceSAndroid Build Coastguard Worker }
871*35238bceSAndroid Build Coastguard Worker
SingleSampleLineRasterizer(const tcu::IVec4 & viewport,const int subpixelBits)872*35238bceSAndroid Build Coastguard Worker SingleSampleLineRasterizer::SingleSampleLineRasterizer(const tcu::IVec4 &viewport, const int subpixelBits)
873*35238bceSAndroid Build Coastguard Worker : m_viewport(viewport)
874*35238bceSAndroid Build Coastguard Worker , m_subpixelBits(subpixelBits)
875*35238bceSAndroid Build Coastguard Worker , m_curRowFragment(0)
876*35238bceSAndroid Build Coastguard Worker , m_lineWidth(0.0f)
877*35238bceSAndroid Build Coastguard Worker , m_stippleCounter(0)
878*35238bceSAndroid Build Coastguard Worker {
879*35238bceSAndroid Build Coastguard Worker }
880*35238bceSAndroid Build Coastguard Worker
~SingleSampleLineRasterizer(void)881*35238bceSAndroid Build Coastguard Worker SingleSampleLineRasterizer::~SingleSampleLineRasterizer(void)
882*35238bceSAndroid Build Coastguard Worker {
883*35238bceSAndroid Build Coastguard Worker }
884*35238bceSAndroid Build Coastguard Worker
init(const tcu::Vec4 & v0,const tcu::Vec4 & v1,float lineWidth,uint32_t stippleFactor,uint16_t stipplePattern)885*35238bceSAndroid Build Coastguard Worker void SingleSampleLineRasterizer::init(const tcu::Vec4 &v0, const tcu::Vec4 &v1, float lineWidth, uint32_t stippleFactor,
886*35238bceSAndroid Build Coastguard Worker uint16_t stipplePattern)
887*35238bceSAndroid Build Coastguard Worker {
888*35238bceSAndroid Build Coastguard Worker const bool isXMajor = de::abs((v1 - v0).x()) >= de::abs((v1 - v0).y());
889*35238bceSAndroid Build Coastguard Worker
890*35238bceSAndroid Build Coastguard Worker // Bounding box \note: with wide lines, the line is actually moved as in the spec
891*35238bceSAndroid Build Coastguard Worker const int32_t lineWidthPixels = (lineWidth > 1.0f) ? (int32_t)floor(lineWidth + 0.5f) : 1;
892*35238bceSAndroid Build Coastguard Worker
893*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> widthOffset =
894*35238bceSAndroid Build Coastguard Worker (isXMajor ? tcu::Vector<int64_t, 2>(0, -1) : tcu::Vector<int64_t, 2>(-1, 0)) *
895*35238bceSAndroid Build Coastguard Worker (toSubpixelCoord(lineWidthPixels - 1, m_subpixelBits) / 2);
896*35238bceSAndroid Build Coastguard Worker
897*35238bceSAndroid Build Coastguard Worker const int64_t x0 = toSubpixelCoord(v0.x(), m_subpixelBits) + widthOffset.x();
898*35238bceSAndroid Build Coastguard Worker const int64_t y0 = toSubpixelCoord(v0.y(), m_subpixelBits) + widthOffset.y();
899*35238bceSAndroid Build Coastguard Worker const int64_t x1 = toSubpixelCoord(v1.x(), m_subpixelBits) + widthOffset.x();
900*35238bceSAndroid Build Coastguard Worker const int64_t y1 = toSubpixelCoord(v1.y(), m_subpixelBits) + widthOffset.y();
901*35238bceSAndroid Build Coastguard Worker
902*35238bceSAndroid Build Coastguard Worker // line endpoints might be perturbed, add some margin
903*35238bceSAndroid Build Coastguard Worker const int64_t xMin = de::min(x0, x1) - toSubpixelCoord(1, m_subpixelBits);
904*35238bceSAndroid Build Coastguard Worker const int64_t xMax = de::max(x0, x1) + toSubpixelCoord(1, m_subpixelBits);
905*35238bceSAndroid Build Coastguard Worker const int64_t yMin = de::min(y0, y1) - toSubpixelCoord(1, m_subpixelBits);
906*35238bceSAndroid Build Coastguard Worker const int64_t yMax = de::max(y0, y1) + toSubpixelCoord(1, m_subpixelBits);
907*35238bceSAndroid Build Coastguard Worker
908*35238bceSAndroid Build Coastguard Worker // Remove invisible area
909*35238bceSAndroid Build Coastguard Worker
910*35238bceSAndroid Build Coastguard Worker if (isXMajor)
911*35238bceSAndroid Build Coastguard Worker {
912*35238bceSAndroid Build Coastguard Worker // clamp to viewport in major direction
913*35238bceSAndroid Build Coastguard Worker m_bboxMin.x() = de::clamp(floorSubpixelToPixelCoord(xMin, m_subpixelBits, true), m_viewport.x(),
914*35238bceSAndroid Build Coastguard Worker m_viewport.x() + m_viewport.z() - 1);
915*35238bceSAndroid Build Coastguard Worker m_bboxMax.x() = de::clamp(ceilSubpixelToPixelCoord(xMax, m_subpixelBits, true), m_viewport.x(),
916*35238bceSAndroid Build Coastguard Worker m_viewport.x() + m_viewport.z() - 1);
917*35238bceSAndroid Build Coastguard Worker
918*35238bceSAndroid Build Coastguard Worker // clamp to padded viewport in minor direction (wide lines might bleed over viewport in minor direction)
919*35238bceSAndroid Build Coastguard Worker m_bboxMin.y() = de::clamp(floorSubpixelToPixelCoord(yMin, m_subpixelBits, true),
920*35238bceSAndroid Build Coastguard Worker m_viewport.y() - lineWidthPixels, m_viewport.y() + m_viewport.w() - 1);
921*35238bceSAndroid Build Coastguard Worker m_bboxMax.y() = de::clamp(ceilSubpixelToPixelCoord(yMax, m_subpixelBits, true),
922*35238bceSAndroid Build Coastguard Worker m_viewport.y() - lineWidthPixels, m_viewport.y() + m_viewport.w() - 1);
923*35238bceSAndroid Build Coastguard Worker }
924*35238bceSAndroid Build Coastguard Worker else
925*35238bceSAndroid Build Coastguard Worker {
926*35238bceSAndroid Build Coastguard Worker // clamp to viewport in major direction
927*35238bceSAndroid Build Coastguard Worker m_bboxMin.y() = de::clamp(floorSubpixelToPixelCoord(yMin, m_subpixelBits, true), m_viewport.y(),
928*35238bceSAndroid Build Coastguard Worker m_viewport.y() + m_viewport.w() - 1);
929*35238bceSAndroid Build Coastguard Worker m_bboxMax.y() = de::clamp(ceilSubpixelToPixelCoord(yMax, m_subpixelBits, true), m_viewport.y(),
930*35238bceSAndroid Build Coastguard Worker m_viewport.y() + m_viewport.w() - 1);
931*35238bceSAndroid Build Coastguard Worker
932*35238bceSAndroid Build Coastguard Worker // clamp to padded viewport in minor direction (wide lines might bleed over viewport in minor direction)
933*35238bceSAndroid Build Coastguard Worker m_bboxMin.x() = de::clamp(floorSubpixelToPixelCoord(xMin, m_subpixelBits, true),
934*35238bceSAndroid Build Coastguard Worker m_viewport.x() - lineWidthPixels, m_viewport.x() + m_viewport.z() - 1);
935*35238bceSAndroid Build Coastguard Worker m_bboxMax.x() = de::clamp(ceilSubpixelToPixelCoord(xMax, m_subpixelBits, true),
936*35238bceSAndroid Build Coastguard Worker m_viewport.x() - lineWidthPixels, m_viewport.x() + m_viewport.z() - 1);
937*35238bceSAndroid Build Coastguard Worker }
938*35238bceSAndroid Build Coastguard Worker
939*35238bceSAndroid Build Coastguard Worker m_lineWidth = lineWidth;
940*35238bceSAndroid Build Coastguard Worker
941*35238bceSAndroid Build Coastguard Worker m_v0 = v0;
942*35238bceSAndroid Build Coastguard Worker m_v1 = v1;
943*35238bceSAndroid Build Coastguard Worker
944*35238bceSAndroid Build Coastguard Worker // Choose direction of traversal and whether to start at bbox min or max. Direction matters
945*35238bceSAndroid Build Coastguard Worker // for the stipple counter.
946*35238bceSAndroid Build Coastguard Worker int xDelta = (m_v1 - m_v0).x() > 0 ? 1 : -1;
947*35238bceSAndroid Build Coastguard Worker int yDelta = (m_v1 - m_v0).y() > 0 ? 1 : -1;
948*35238bceSAndroid Build Coastguard Worker
949*35238bceSAndroid Build Coastguard Worker m_curPos.x() = xDelta > 0 ? m_bboxMin.x() : m_bboxMax.x();
950*35238bceSAndroid Build Coastguard Worker m_curPos.y() = yDelta > 0 ? m_bboxMin.y() : m_bboxMax.y();
951*35238bceSAndroid Build Coastguard Worker
952*35238bceSAndroid Build Coastguard Worker m_curRowFragment = 0;
953*35238bceSAndroid Build Coastguard Worker m_stippleFactor = stippleFactor;
954*35238bceSAndroid Build Coastguard Worker m_stipplePattern = stipplePattern;
955*35238bceSAndroid Build Coastguard Worker }
956*35238bceSAndroid Build Coastguard Worker
rasterize(FragmentPacket * const fragmentPackets,float * const depthValues,const int maxFragmentPackets,int & numPacketsRasterized)957*35238bceSAndroid Build Coastguard Worker void SingleSampleLineRasterizer::rasterize(FragmentPacket *const fragmentPackets, float *const depthValues,
958*35238bceSAndroid Build Coastguard Worker const int maxFragmentPackets, int &numPacketsRasterized)
959*35238bceSAndroid Build Coastguard Worker {
960*35238bceSAndroid Build Coastguard Worker DE_ASSERT(maxFragmentPackets > 0);
961*35238bceSAndroid Build Coastguard Worker
962*35238bceSAndroid Build Coastguard Worker const int64_t halfPixel = 1ll << (m_subpixelBits - 1);
963*35238bceSAndroid Build Coastguard Worker const int32_t lineWidth = (m_lineWidth > 1.0f) ? deFloorFloatToInt32(m_lineWidth + 0.5f) : 1;
964*35238bceSAndroid Build Coastguard Worker const bool isXMajor = de::abs((m_v1 - m_v0).x()) >= de::abs((m_v1 - m_v0).y());
965*35238bceSAndroid Build Coastguard Worker const tcu::IVec2 minorDirection = (isXMajor) ? (tcu::IVec2(0, 1)) : (tcu::IVec2(1, 0));
966*35238bceSAndroid Build Coastguard Worker const int minViewportLimit = (isXMajor) ? (m_viewport.y()) : (m_viewport.x());
967*35238bceSAndroid Build Coastguard Worker const int maxViewportLimit = (isXMajor) ? (m_viewport.y() + m_viewport.w()) : (m_viewport.x() + m_viewport.z());
968*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> widthOffset =
969*35238bceSAndroid Build Coastguard Worker -minorDirection.cast<int64_t>() * (toSubpixelCoord(lineWidth - 1, m_subpixelBits) / 2);
970*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> pa = LineRasterUtil::toSubpixelVector(m_v0.xy(), m_subpixelBits) + widthOffset;
971*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> pb = LineRasterUtil::toSubpixelVector(m_v1.xy(), m_subpixelBits) + widthOffset;
972*35238bceSAndroid Build Coastguard Worker const LineRasterUtil::SubpixelLineSegment line = LineRasterUtil::SubpixelLineSegment(pa, pb);
973*35238bceSAndroid Build Coastguard Worker
974*35238bceSAndroid Build Coastguard Worker int packetNdx = 0;
975*35238bceSAndroid Build Coastguard Worker int xDelta = (m_v1 - m_v0).x() > 0 ? 1 : -1;
976*35238bceSAndroid Build Coastguard Worker int yDelta = (m_v1 - m_v0).y() > 0 ? 1 : -1;
977*35238bceSAndroid Build Coastguard Worker
978*35238bceSAndroid Build Coastguard Worker while (m_curPos.y() <= m_bboxMax.y() && m_curPos.y() >= m_bboxMin.y() && packetNdx < maxFragmentPackets)
979*35238bceSAndroid Build Coastguard Worker {
980*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> diamondPosition =
981*35238bceSAndroid Build Coastguard Worker LineRasterUtil::toSubpixelVector(m_curPos, m_subpixelBits) + tcu::Vector<int64_t, 2>(halfPixel, halfPixel);
982*35238bceSAndroid Build Coastguard Worker
983*35238bceSAndroid Build Coastguard Worker // Should current fragment be drawn? == does the segment exit this diamond?
984*35238bceSAndroid Build Coastguard Worker if (LineRasterUtil::doesLineSegmentExitDiamond(line, diamondPosition, m_subpixelBits))
985*35238bceSAndroid Build Coastguard Worker {
986*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> pr = diamondPosition;
987*35238bceSAndroid Build Coastguard Worker const float t =
988*35238bceSAndroid Build Coastguard Worker tcu::dot((pr - pa).asFloat(), (pb - pa).asFloat()) / tcu::lengthSquared(pb.asFloat() - pa.asFloat());
989*35238bceSAndroid Build Coastguard Worker
990*35238bceSAndroid Build Coastguard Worker // Rasterize on only fragments that are would end up in the viewport (i.e. visible)
991*35238bceSAndroid Build Coastguard Worker const int fragmentLocation = (isXMajor) ? (m_curPos.y()) : (m_curPos.x());
992*35238bceSAndroid Build Coastguard Worker const int rowFragBegin = de::max(0, minViewportLimit - fragmentLocation);
993*35238bceSAndroid Build Coastguard Worker const int rowFragEnd = de::min(maxViewportLimit - fragmentLocation, lineWidth);
994*35238bceSAndroid Build Coastguard Worker
995*35238bceSAndroid Build Coastguard Worker int stippleBit = (m_stippleCounter / m_stippleFactor) % 16;
996*35238bceSAndroid Build Coastguard Worker bool stipplePass = (m_stipplePattern & (1 << stippleBit)) != 0;
997*35238bceSAndroid Build Coastguard Worker m_stippleCounter++;
998*35238bceSAndroid Build Coastguard Worker
999*35238bceSAndroid Build Coastguard Worker if (stipplePass)
1000*35238bceSAndroid Build Coastguard Worker {
1001*35238bceSAndroid Build Coastguard Worker // Wide lines require multiple fragments.
1002*35238bceSAndroid Build Coastguard Worker for (; rowFragBegin + m_curRowFragment < rowFragEnd; m_curRowFragment++)
1003*35238bceSAndroid Build Coastguard Worker {
1004*35238bceSAndroid Build Coastguard Worker const int replicationId = rowFragBegin + m_curRowFragment;
1005*35238bceSAndroid Build Coastguard Worker const tcu::IVec2 fragmentPos = m_curPos + minorDirection * replicationId;
1006*35238bceSAndroid Build Coastguard Worker
1007*35238bceSAndroid Build Coastguard Worker // We only rasterize visible area
1008*35238bceSAndroid Build Coastguard Worker DE_ASSERT(LineRasterUtil::inViewport(fragmentPos, m_viewport));
1009*35238bceSAndroid Build Coastguard Worker
1010*35238bceSAndroid Build Coastguard Worker // Compute depth values.
1011*35238bceSAndroid Build Coastguard Worker if (depthValues)
1012*35238bceSAndroid Build Coastguard Worker {
1013*35238bceSAndroid Build Coastguard Worker const float za = m_v0.z();
1014*35238bceSAndroid Build Coastguard Worker const float zb = m_v1.z();
1015*35238bceSAndroid Build Coastguard Worker
1016*35238bceSAndroid Build Coastguard Worker depthValues[packetNdx * 4 + 0] = (1 - t) * za + t * zb;
1017*35238bceSAndroid Build Coastguard Worker depthValues[packetNdx * 4 + 1] = 0;
1018*35238bceSAndroid Build Coastguard Worker depthValues[packetNdx * 4 + 2] = 0;
1019*35238bceSAndroid Build Coastguard Worker depthValues[packetNdx * 4 + 3] = 0;
1020*35238bceSAndroid Build Coastguard Worker }
1021*35238bceSAndroid Build Coastguard Worker
1022*35238bceSAndroid Build Coastguard Worker {
1023*35238bceSAndroid Build Coastguard Worker // output this fragment
1024*35238bceSAndroid Build Coastguard Worker // \note In order to make consistent output with multisampled line rasterization, output "barycentric" coordinates
1025*35238bceSAndroid Build Coastguard Worker FragmentPacket &packet = fragmentPackets[packetNdx];
1026*35238bceSAndroid Build Coastguard Worker
1027*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 b0 = tcu::Vec4(1 - t);
1028*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 b1 = tcu::Vec4(t);
1029*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 ooSum = 1.0f / (b0 + b1);
1030*35238bceSAndroid Build Coastguard Worker
1031*35238bceSAndroid Build Coastguard Worker packet.position = fragmentPos;
1032*35238bceSAndroid Build Coastguard Worker packet.coverage = getCoverageBit(1, 0, 0, 0);
1033*35238bceSAndroid Build Coastguard Worker packet.barycentric[0] = b0 * ooSum;
1034*35238bceSAndroid Build Coastguard Worker packet.barycentric[1] = b1 * ooSum;
1035*35238bceSAndroid Build Coastguard Worker packet.barycentric[2] = tcu::Vec4(0.0f);
1036*35238bceSAndroid Build Coastguard Worker
1037*35238bceSAndroid Build Coastguard Worker packetNdx += 1;
1038*35238bceSAndroid Build Coastguard Worker }
1039*35238bceSAndroid Build Coastguard Worker
1040*35238bceSAndroid Build Coastguard Worker if (packetNdx == maxFragmentPackets)
1041*35238bceSAndroid Build Coastguard Worker {
1042*35238bceSAndroid Build Coastguard Worker m_curRowFragment++; // don't redraw this fragment again next time
1043*35238bceSAndroid Build Coastguard Worker m_stippleCounter--; // reuse same stipple counter next time
1044*35238bceSAndroid Build Coastguard Worker numPacketsRasterized = packetNdx;
1045*35238bceSAndroid Build Coastguard Worker return;
1046*35238bceSAndroid Build Coastguard Worker }
1047*35238bceSAndroid Build Coastguard Worker }
1048*35238bceSAndroid Build Coastguard Worker
1049*35238bceSAndroid Build Coastguard Worker m_curRowFragment = 0;
1050*35238bceSAndroid Build Coastguard Worker }
1051*35238bceSAndroid Build Coastguard Worker }
1052*35238bceSAndroid Build Coastguard Worker
1053*35238bceSAndroid Build Coastguard Worker m_curPos.x() += xDelta;
1054*35238bceSAndroid Build Coastguard Worker if (m_curPos.x() > m_bboxMax.x() || m_curPos.x() < m_bboxMin.x())
1055*35238bceSAndroid Build Coastguard Worker {
1056*35238bceSAndroid Build Coastguard Worker m_curPos.y() += yDelta;
1057*35238bceSAndroid Build Coastguard Worker m_curPos.x() = xDelta > 0 ? m_bboxMin.x() : m_bboxMax.x();
1058*35238bceSAndroid Build Coastguard Worker }
1059*35238bceSAndroid Build Coastguard Worker }
1060*35238bceSAndroid Build Coastguard Worker
1061*35238bceSAndroid Build Coastguard Worker DE_ASSERT(packetNdx <= maxFragmentPackets);
1062*35238bceSAndroid Build Coastguard Worker numPacketsRasterized = packetNdx;
1063*35238bceSAndroid Build Coastguard Worker }
1064*35238bceSAndroid Build Coastguard Worker
MultiSampleLineRasterizer(const int numSamples,const tcu::IVec4 & viewport,const int subpixelBits)1065*35238bceSAndroid Build Coastguard Worker MultiSampleLineRasterizer::MultiSampleLineRasterizer(const int numSamples, const tcu::IVec4 &viewport,
1066*35238bceSAndroid Build Coastguard Worker const int subpixelBits)
1067*35238bceSAndroid Build Coastguard Worker : m_numSamples(numSamples)
1068*35238bceSAndroid Build Coastguard Worker , m_triangleRasterizer0(viewport, m_numSamples, RasterizationState(), subpixelBits)
1069*35238bceSAndroid Build Coastguard Worker , m_triangleRasterizer1(viewport, m_numSamples, RasterizationState(), subpixelBits)
1070*35238bceSAndroid Build Coastguard Worker {
1071*35238bceSAndroid Build Coastguard Worker }
1072*35238bceSAndroid Build Coastguard Worker
~MultiSampleLineRasterizer()1073*35238bceSAndroid Build Coastguard Worker MultiSampleLineRasterizer::~MultiSampleLineRasterizer()
1074*35238bceSAndroid Build Coastguard Worker {
1075*35238bceSAndroid Build Coastguard Worker }
1076*35238bceSAndroid Build Coastguard Worker
init(const tcu::Vec4 & v0,const tcu::Vec4 & v1,float lineWidth)1077*35238bceSAndroid Build Coastguard Worker void MultiSampleLineRasterizer::init(const tcu::Vec4 &v0, const tcu::Vec4 &v1, float lineWidth)
1078*35238bceSAndroid Build Coastguard Worker {
1079*35238bceSAndroid Build Coastguard Worker // allow creation of single sampled rasterizer objects but do not allow using them
1080*35238bceSAndroid Build Coastguard Worker DE_ASSERT(m_numSamples > 1);
1081*35238bceSAndroid Build Coastguard Worker
1082*35238bceSAndroid Build Coastguard Worker const tcu::Vec2 lineVec = tcu::Vec2(tcu::Vec4(v1).xy()) - tcu::Vec2(tcu::Vec4(v0).xy());
1083*35238bceSAndroid Build Coastguard Worker const tcu::Vec2 normal2 = tcu::normalize(tcu::Vec2(-lineVec[1], lineVec[0]));
1084*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 normal4 = tcu::Vec4(normal2.x(), normal2.y(), 0, 0);
1085*35238bceSAndroid Build Coastguard Worker const float offset = lineWidth / 2.0f;
1086*35238bceSAndroid Build Coastguard Worker
1087*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 p0 = v0 + normal4 * offset;
1088*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 p1 = v0 - normal4 * offset;
1089*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 p2 = v1 - normal4 * offset;
1090*35238bceSAndroid Build Coastguard Worker const tcu::Vec4 p3 = v1 + normal4 * offset;
1091*35238bceSAndroid Build Coastguard Worker
1092*35238bceSAndroid Build Coastguard Worker // Edge 0 -> 1 is always along the line and edge 1 -> 2 is in 90 degree angle to the line
1093*35238bceSAndroid Build Coastguard Worker m_triangleRasterizer0.init(p0, p3, p2);
1094*35238bceSAndroid Build Coastguard Worker m_triangleRasterizer1.init(p2, p1, p0);
1095*35238bceSAndroid Build Coastguard Worker }
1096*35238bceSAndroid Build Coastguard Worker
rasterize(FragmentPacket * const fragmentPackets,float * const depthValues,const int maxFragmentPackets,int & numPacketsRasterized)1097*35238bceSAndroid Build Coastguard Worker void MultiSampleLineRasterizer::rasterize(FragmentPacket *const fragmentPackets, float *const depthValues,
1098*35238bceSAndroid Build Coastguard Worker const int maxFragmentPackets, int &numPacketsRasterized)
1099*35238bceSAndroid Build Coastguard Worker {
1100*35238bceSAndroid Build Coastguard Worker DE_ASSERT(maxFragmentPackets > 0);
1101*35238bceSAndroid Build Coastguard Worker
1102*35238bceSAndroid Build Coastguard Worker m_triangleRasterizer0.rasterize(fragmentPackets, depthValues, maxFragmentPackets, numPacketsRasterized);
1103*35238bceSAndroid Build Coastguard Worker
1104*35238bceSAndroid Build Coastguard Worker // Remove 3rd barycentric value and rebalance. Lines do not have non-zero barycentric at index 2
1105*35238bceSAndroid Build Coastguard Worker for (int packNdx = 0; packNdx < numPacketsRasterized; ++packNdx)
1106*35238bceSAndroid Build Coastguard Worker for (int fragNdx = 0; fragNdx < 4; fragNdx++)
1107*35238bceSAndroid Build Coastguard Worker {
1108*35238bceSAndroid Build Coastguard Worker float removedValue = fragmentPackets[packNdx].barycentric[2][fragNdx];
1109*35238bceSAndroid Build Coastguard Worker fragmentPackets[packNdx].barycentric[2][fragNdx] = 0.0f;
1110*35238bceSAndroid Build Coastguard Worker fragmentPackets[packNdx].barycentric[1][fragNdx] += removedValue;
1111*35238bceSAndroid Build Coastguard Worker }
1112*35238bceSAndroid Build Coastguard Worker
1113*35238bceSAndroid Build Coastguard Worker // rasterizer 0 filled the whole buffer?
1114*35238bceSAndroid Build Coastguard Worker if (numPacketsRasterized == maxFragmentPackets)
1115*35238bceSAndroid Build Coastguard Worker return;
1116*35238bceSAndroid Build Coastguard Worker
1117*35238bceSAndroid Build Coastguard Worker {
1118*35238bceSAndroid Build Coastguard Worker FragmentPacket *const nextFragmentPackets = fragmentPackets + numPacketsRasterized;
1119*35238bceSAndroid Build Coastguard Worker float *nextDepthValues = (depthValues) ? (depthValues + 4 * numPacketsRasterized * m_numSamples) : (DE_NULL);
1120*35238bceSAndroid Build Coastguard Worker int numPacketsRasterized2 = 0;
1121*35238bceSAndroid Build Coastguard Worker
1122*35238bceSAndroid Build Coastguard Worker m_triangleRasterizer1.rasterize(nextFragmentPackets, nextDepthValues, maxFragmentPackets - numPacketsRasterized,
1123*35238bceSAndroid Build Coastguard Worker numPacketsRasterized2);
1124*35238bceSAndroid Build Coastguard Worker
1125*35238bceSAndroid Build Coastguard Worker numPacketsRasterized += numPacketsRasterized2;
1126*35238bceSAndroid Build Coastguard Worker
1127*35238bceSAndroid Build Coastguard Worker // Fix swapped barycentrics in the second triangle
1128*35238bceSAndroid Build Coastguard Worker for (int packNdx = 0; packNdx < numPacketsRasterized2; ++packNdx)
1129*35238bceSAndroid Build Coastguard Worker for (int fragNdx = 0; fragNdx < 4; fragNdx++)
1130*35238bceSAndroid Build Coastguard Worker {
1131*35238bceSAndroid Build Coastguard Worker float removedValue = nextFragmentPackets[packNdx].barycentric[2][fragNdx];
1132*35238bceSAndroid Build Coastguard Worker nextFragmentPackets[packNdx].barycentric[2][fragNdx] = 0.0f;
1133*35238bceSAndroid Build Coastguard Worker nextFragmentPackets[packNdx].barycentric[1][fragNdx] += removedValue;
1134*35238bceSAndroid Build Coastguard Worker
1135*35238bceSAndroid Build Coastguard Worker // edge has reversed direction
1136*35238bceSAndroid Build Coastguard Worker std::swap(nextFragmentPackets[packNdx].barycentric[0][fragNdx],
1137*35238bceSAndroid Build Coastguard Worker nextFragmentPackets[packNdx].barycentric[1][fragNdx]);
1138*35238bceSAndroid Build Coastguard Worker }
1139*35238bceSAndroid Build Coastguard Worker }
1140*35238bceSAndroid Build Coastguard Worker }
1141*35238bceSAndroid Build Coastguard Worker
LineExitDiamondGenerator(const int subpixelBits)1142*35238bceSAndroid Build Coastguard Worker LineExitDiamondGenerator::LineExitDiamondGenerator(const int subpixelBits) : m_subpixelBits(subpixelBits)
1143*35238bceSAndroid Build Coastguard Worker {
1144*35238bceSAndroid Build Coastguard Worker }
1145*35238bceSAndroid Build Coastguard Worker
~LineExitDiamondGenerator(void)1146*35238bceSAndroid Build Coastguard Worker LineExitDiamondGenerator::~LineExitDiamondGenerator(void)
1147*35238bceSAndroid Build Coastguard Worker {
1148*35238bceSAndroid Build Coastguard Worker }
1149*35238bceSAndroid Build Coastguard Worker
init(const tcu::Vec4 & v0,const tcu::Vec4 & v1)1150*35238bceSAndroid Build Coastguard Worker void LineExitDiamondGenerator::init(const tcu::Vec4 &v0, const tcu::Vec4 &v1)
1151*35238bceSAndroid Build Coastguard Worker {
1152*35238bceSAndroid Build Coastguard Worker const int64_t x0 = toSubpixelCoord(v0.x(), m_subpixelBits);
1153*35238bceSAndroid Build Coastguard Worker const int64_t y0 = toSubpixelCoord(v0.y(), m_subpixelBits);
1154*35238bceSAndroid Build Coastguard Worker const int64_t x1 = toSubpixelCoord(v1.x(), m_subpixelBits);
1155*35238bceSAndroid Build Coastguard Worker const int64_t y1 = toSubpixelCoord(v1.y(), m_subpixelBits);
1156*35238bceSAndroid Build Coastguard Worker
1157*35238bceSAndroid Build Coastguard Worker // line endpoints might be perturbed, add some margin
1158*35238bceSAndroid Build Coastguard Worker const int64_t xMin = de::min(x0, x1) - toSubpixelCoord(1, m_subpixelBits);
1159*35238bceSAndroid Build Coastguard Worker const int64_t xMax = de::max(x0, x1) + toSubpixelCoord(1, m_subpixelBits);
1160*35238bceSAndroid Build Coastguard Worker const int64_t yMin = de::min(y0, y1) - toSubpixelCoord(1, m_subpixelBits);
1161*35238bceSAndroid Build Coastguard Worker const int64_t yMax = de::max(y0, y1) + toSubpixelCoord(1, m_subpixelBits);
1162*35238bceSAndroid Build Coastguard Worker
1163*35238bceSAndroid Build Coastguard Worker m_bboxMin.x() = floorSubpixelToPixelCoord(xMin, m_subpixelBits, true);
1164*35238bceSAndroid Build Coastguard Worker m_bboxMin.y() = floorSubpixelToPixelCoord(yMin, m_subpixelBits, true);
1165*35238bceSAndroid Build Coastguard Worker m_bboxMax.x() = ceilSubpixelToPixelCoord(xMax, m_subpixelBits, true);
1166*35238bceSAndroid Build Coastguard Worker m_bboxMax.y() = ceilSubpixelToPixelCoord(yMax, m_subpixelBits, true);
1167*35238bceSAndroid Build Coastguard Worker
1168*35238bceSAndroid Build Coastguard Worker m_v0 = v0;
1169*35238bceSAndroid Build Coastguard Worker m_v1 = v1;
1170*35238bceSAndroid Build Coastguard Worker
1171*35238bceSAndroid Build Coastguard Worker m_curPos = m_bboxMin;
1172*35238bceSAndroid Build Coastguard Worker }
1173*35238bceSAndroid Build Coastguard Worker
rasterize(LineExitDiamond * const lineDiamonds,const int maxDiamonds,int & numWritten)1174*35238bceSAndroid Build Coastguard Worker void LineExitDiamondGenerator::rasterize(LineExitDiamond *const lineDiamonds, const int maxDiamonds, int &numWritten)
1175*35238bceSAndroid Build Coastguard Worker {
1176*35238bceSAndroid Build Coastguard Worker DE_ASSERT(maxDiamonds > 0);
1177*35238bceSAndroid Build Coastguard Worker
1178*35238bceSAndroid Build Coastguard Worker const int64_t halfPixel = 1ll << (m_subpixelBits - 1);
1179*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> pa = LineRasterUtil::toSubpixelVector(m_v0.xy(), m_subpixelBits);
1180*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> pb = LineRasterUtil::toSubpixelVector(m_v1.xy(), m_subpixelBits);
1181*35238bceSAndroid Build Coastguard Worker const LineRasterUtil::SubpixelLineSegment line = LineRasterUtil::SubpixelLineSegment(pa, pb);
1182*35238bceSAndroid Build Coastguard Worker
1183*35238bceSAndroid Build Coastguard Worker int diamondNdx = 0;
1184*35238bceSAndroid Build Coastguard Worker
1185*35238bceSAndroid Build Coastguard Worker while (m_curPos.y() <= m_bboxMax.y() && diamondNdx < maxDiamonds)
1186*35238bceSAndroid Build Coastguard Worker {
1187*35238bceSAndroid Build Coastguard Worker const tcu::Vector<int64_t, 2> diamondPosition =
1188*35238bceSAndroid Build Coastguard Worker LineRasterUtil::toSubpixelVector(m_curPos, m_subpixelBits) + tcu::Vector<int64_t, 2>(halfPixel, halfPixel);
1189*35238bceSAndroid Build Coastguard Worker
1190*35238bceSAndroid Build Coastguard Worker if (LineRasterUtil::doesLineSegmentExitDiamond(line, diamondPosition, m_subpixelBits))
1191*35238bceSAndroid Build Coastguard Worker {
1192*35238bceSAndroid Build Coastguard Worker LineExitDiamond &packet = lineDiamonds[diamondNdx];
1193*35238bceSAndroid Build Coastguard Worker packet.position = m_curPos;
1194*35238bceSAndroid Build Coastguard Worker ++diamondNdx;
1195*35238bceSAndroid Build Coastguard Worker }
1196*35238bceSAndroid Build Coastguard Worker
1197*35238bceSAndroid Build Coastguard Worker ++m_curPos.x();
1198*35238bceSAndroid Build Coastguard Worker if (m_curPos.x() > m_bboxMax.x())
1199*35238bceSAndroid Build Coastguard Worker {
1200*35238bceSAndroid Build Coastguard Worker ++m_curPos.y();
1201*35238bceSAndroid Build Coastguard Worker m_curPos.x() = m_bboxMin.x();
1202*35238bceSAndroid Build Coastguard Worker }
1203*35238bceSAndroid Build Coastguard Worker }
1204*35238bceSAndroid Build Coastguard Worker
1205*35238bceSAndroid Build Coastguard Worker DE_ASSERT(diamondNdx <= maxDiamonds);
1206*35238bceSAndroid Build Coastguard Worker numWritten = diamondNdx;
1207*35238bceSAndroid Build Coastguard Worker }
1208*35238bceSAndroid Build Coastguard Worker
1209*35238bceSAndroid Build Coastguard Worker } // namespace rr
1210