xref: /aosp_15_r20/external/deqp/framework/referencerenderer/rrRasterizer.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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