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