13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Reference Renderer 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ----------------------------------------------- 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License"); 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License. 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * http://www.apache.org/licenses/LICENSE-2.0 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS, 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License. 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*! 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Reference rasterizer 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "rrRasterizer.hpp" 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h" 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVectorUtil.hpp" 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace rr 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deInt64 toSubpixelCoord (float v) 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return (deInt64)(v * (1<<RASTERIZER_SUBPIXEL_BITS) + (v < 0.f ? -0.5f : 0.5f)); 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deInt64 toSubpixelCoord (deInt32 v) 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return v << RASTERIZER_SUBPIXEL_BITS; 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deInt32 ceilSubpixelToPixelCoord (deInt64 coord, bool fillEdge) 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (coord >= 0) 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return (deInt32)((coord + ((1ll<<RASTERIZER_SUBPIXEL_BITS) - (fillEdge ? 0 : 1))) >> RASTERIZER_SUBPIXEL_BITS); 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return (deInt32)((coord + (fillEdge ? 1 : 0)) >> RASTERIZER_SUBPIXEL_BITS); 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deInt32 floorSubpixelToPixelCoord (deInt64 coord, bool fillEdge) 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (coord >= 0) 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return (deInt32)((coord - (fillEdge ? 1 : 0)) >> RASTERIZER_SUBPIXEL_BITS); 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return (deInt32)((coord - ((1ll<<RASTERIZER_SUBPIXEL_BITS) - (fillEdge ? 0 : 1))) >> RASTERIZER_SUBPIXEL_BITS); 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline void initEdgeCCW (EdgeFunction& edge, const HorizontalFill horizontalFill, const VerticalFill verticalFill, const deInt64 x0, const deInt64 y0, const deInt64 x1, const deInt64 y1) 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note See EdgeFunction documentation for details. 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 xd = x1-x0; 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 yd = y1-y0; 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool inclusive = false; //!< Inclusive in CCW orientation. 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (yd == 0) 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inclusive = verticalFill == FILL_BOTTOM ? xd >= 0 : xd <= 0; 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inclusive = horizontalFill == FILL_LEFT ? yd <= 0 : yd >= 0; 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry edge.a = (y0 - y1); 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry edge.b = (x1 - x0); 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry edge.c = x0*y1 - y0*x1; 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry edge.inclusive = inclusive; //!< \todo [pyry] Swap for CW triangles 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline void reverseEdge (EdgeFunction& edge) 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry edge.a = -edge.a; 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry edge.b = -edge.b; 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry edge.c = -edge.c; 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry edge.inclusive = !edge.inclusive; 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deInt64 evaluateEdge (const EdgeFunction& edge, const deInt64 x, const deInt64 y) 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return edge.a*x + edge.b*y + edge.c; 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool isInsideCCW (const EdgeFunction& edge, const deInt64 edgeVal) 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return edge.inclusive ? (edgeVal >= 0) : (edgeVal > 0); 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace LineRasterUtil 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct SubpixelLineSegment 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> m_v0; 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> m_v1; 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SubpixelLineSegment (const tcu::Vector<deInt64,2>& v0, const tcu::Vector<deInt64,2>& v1) 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_v0(v0) 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_v1(v1) 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<deInt64,2> direction (void) const 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return m_v1 - m_v0; 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum LINE_SIDE 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LINE_SIDE_INTERSECT = 0, 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LINE_SIDE_LEFT, 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LINE_SIDE_RIGHT 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::Vector<deInt64,2> toSubpixelVector (const tcu::Vec2& v) 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return tcu::Vector<deInt64,2>(toSubpixelCoord(v.x()), toSubpixelCoord(v.y())); 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::Vector<deInt64,2> toSubpixelVector (const tcu::IVec2& v) 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return tcu::Vector<deInt64,2>(toSubpixelCoord(v.x()), toSubpixelCoord(v.y())); 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_DEBUG) 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool isTheCenterOfTheFragment (const tcu::Vector<deInt64,2>& a) 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint64 pixelSize = 1ll << (RASTERIZER_SUBPIXEL_BITS); 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint64 halfPixel = 1ll << (RASTERIZER_SUBPIXEL_BITS-1); 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return ((a.x() & (pixelSize-1)) == halfPixel && 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (a.y() & (pixelSize-1)) == halfPixel); 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool inViewport (const tcu::IVec2& p, const tcu::IVec4& viewport) 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return p.x() >= viewport.x() && 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry p.y() >= viewport.y() && 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry p.x() < viewport.x() + viewport.z() && 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry p.y() < viewport.y() + viewport.w(); 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1473e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry#endif // DE_DEBUG 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// returns true if vertex is on the left side of the line 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool vertexOnLeftSideOfLine (const tcu::Vector<deInt64,2>& p, const SubpixelLineSegment& l) 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> u = l.direction(); 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> v = ( p - l.m_v0); 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 crossProduct = (u.x() * v.y() - u.y() * v.x()); 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return crossProduct < 0; 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// returns true if vertex is on the right side of the line 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool vertexOnRightSideOfLine (const tcu::Vector<deInt64,2>& p, const SubpixelLineSegment& l) 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> u = l.direction(); 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> v = ( p - l.m_v0); 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 crossProduct = (u.x() * v.y() - u.y() * v.x()); 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return crossProduct > 0; 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// returns true if vertex is on the line 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool vertexOnLine (const tcu::Vector<deInt64,2>& p, const SubpixelLineSegment& l) 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> u = l.direction(); 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> v = ( p - l.m_v0); 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 crossProduct = (u.x() * v.y() - u.y() * v.x()); 1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return crossProduct == 0; // cross product == 0 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// returns true if vertex is on the line segment 1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool vertexOnLineSegment (const tcu::Vector<deInt64,2>& p, const SubpixelLineSegment& l) 1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!vertexOnLine(p, l)) 1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> v = l.direction(); 1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> u1 = ( p - l.m_v0); 1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> u2 = ( p - l.m_v1); 1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (v.x() == 0 && v.y() == 0) 1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return tcu::dot( v, u1) >= 0 && 1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::dot(-v, u2) >= 0; // dot (A->B, A->V) >= 0 and dot (B->A, B->V) >= 0 1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic LINE_SIDE getVertexSide (const tcu::Vector<deInt64,2>& v, const SubpixelLineSegment& l) 1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (vertexOnLeftSideOfLine(v, l)) 1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return LINE_SIDE_LEFT; 1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (vertexOnRightSideOfLine(v, l)) 1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return LINE_SIDE_RIGHT; 1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (vertexOnLine(v, l)) 2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return LINE_SIDE_INTERSECT; 2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return LINE_SIDE_INTERSECT; 2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// returns true if angle between line and given cornerExitNormal is in range (-45, 45) 2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool lineInCornerAngleRange (const SubpixelLineSegment& line, const tcu::Vector<deInt64,2>& cornerExitNormal) 2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // v0 -> v1 has angle difference to cornerExitNormal in range (-45, 45) 2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> v = line.direction(); 2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 dotProduct = dot(v, cornerExitNormal); 2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // dotProduct > |v1-v0|*|cornerExitNormal|/sqrt(2) 2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (dotProduct < 0) 2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return 2 * dotProduct * dotProduct > tcu::lengthSquared(v)*tcu::lengthSquared(cornerExitNormal); 2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// returns true if angle between line and given cornerExitNormal is in range (-135, 135) 2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool lineInCornerOutsideAngleRange (const SubpixelLineSegment& line, const tcu::Vector<deInt64,2>& cornerExitNormal) 2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // v0 -> v1 has angle difference to cornerExitNormal in range (-135, 135) 2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> v = line.direction(); 2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 dotProduct = dot(v, cornerExitNormal); 2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // dotProduct > -|v1-v0|*|cornerExitNormal|/sqrt(2) 2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (dotProduct >= 0) 2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return 2 * (-dotProduct) * (-dotProduct) < tcu::lengthSquared(v)*tcu::lengthSquared(cornerExitNormal); 2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool doesLineSegmentExitDiamond (const SubpixelLineSegment& line, const tcu::Vector<deInt64,2>& diamondCenter) 2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(isTheCenterOfTheFragment(diamondCenter)); 2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Diamond Center is at diamondCenter in subpixel coords 2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 halfPixel = 1ll << (RASTERIZER_SUBPIXEL_BITS-1); 2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24206beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry // Reject distant diamonds early 24306beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry { 24406beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry const tcu::Vector<deInt64,2> u = line.direction(); 24506beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry const tcu::Vector<deInt64,2> v = (diamondCenter - line.m_v0); 24606beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry const deInt64 crossProduct = (u.x() * v.y() - u.y() * v.x()); 24706beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry 24806beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry // crossProduct = |p| |l| sin(theta) 24906beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry // distanceFromLine = |p| sin(theta) 25006beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry // => distanceFromLine = crossProduct / |l| 25106beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry // 25206beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry // |distanceFromLine| > C 25306beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry // => distanceFromLine^2 > C^2 25406beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry // => crossProduct^2 / |l|^2 > C^2 25506beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry // => crossProduct^2 > |l|^2 * C^2 25606beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry 25706beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry const deInt64 floorSqrtMaxInt64 = 3037000499LL; //!< floor(sqrt(MAX_INT64)) 25806beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry 25906beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry const deInt64 broadRejectDistance = 2 * halfPixel; 26006beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry const deInt64 broadRejectDistanceSquared = broadRejectDistance * broadRejectDistance; 26106beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry const bool crossProductOverflows = (crossProduct > floorSqrtMaxInt64 || crossProduct < -floorSqrtMaxInt64); 26206beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry const deInt64 crossProductSquared = (crossProductOverflows) ? (0) : (crossProduct * crossProduct); // avoid overflow 26306beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry const deInt64 lineLengthSquared = tcu::lengthSquared(u); 26406beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry const bool limitValueCouldOverflow = ((64 - deClz64(lineLengthSquared)) + (64 - deClz64(broadRejectDistanceSquared))) > 63; 26506beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry const deInt64 limitValue = (limitValueCouldOverflow) ? (0) : (lineLengthSquared * broadRejectDistanceSquared); // avoid overflow 26606beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry 26706beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry // only cross overflows 26806beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry if (crossProductOverflows && !limitValueCouldOverflow) 26906beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry return false; 27006beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry 27106beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry // both representable 27206beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry if (!crossProductOverflows && !limitValueCouldOverflow) 27306beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry { 27406beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry if (crossProductSquared > limitValue) 27506beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry return false; 27606beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry } 27706beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry } 27806beb4d23816942e7ccc49c81530bb8702a6f336Jarkko Pöyry 2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const struct DiamondBound 2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<deInt64,2> p0; 2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<deInt64,2> p1; 2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool edgeInclusive; // would a point on the bound be inside of the region 2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } bounds[] = 2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { diamondCenter + tcu::Vector<deInt64,2>(0, -halfPixel), diamondCenter + tcu::Vector<deInt64,2>(-halfPixel, 0), false }, 2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { diamondCenter + tcu::Vector<deInt64,2>(-halfPixel, 0), diamondCenter + tcu::Vector<deInt64,2>(0, halfPixel), false }, 2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { diamondCenter + tcu::Vector<deInt64,2>(0, halfPixel), diamondCenter + tcu::Vector<deInt64,2>(halfPixel, 0), true }, 2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { diamondCenter + tcu::Vector<deInt64,2>(halfPixel, 0), diamondCenter + tcu::Vector<deInt64,2>(0, -halfPixel), true }, 2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const struct DiamondCorners 2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry enum CORNER_EDGE_CASE_BEHAVIOR 2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CORNER_EDGE_CASE_NONE, // if the line intersects just a corner, no entering or exiting 2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CORNER_EDGE_CASE_HIT, // if the line intersects just a corner, entering and exit 2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 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) 2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 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) 3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry enum CORNER_START_CASE_BEHAVIOR 3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CORNER_START_CASE_NONE, // the line starting point is outside, no exiting 3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CORNER_START_CASE_OUTSIDE, // exit, if line does not intersect the region (preturbing moves the start point inside) 3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 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. 3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 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. 3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry enum CORNER_END_CASE_BEHAVIOR 3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CORNER_END_CASE_NONE, // end is inside, no exiting (preturbing moves the line end inside) 3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CORNER_END_CASE_DIRECTION, // exit, if line intersected the region (preturbing moves the line end outside) 3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 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) 3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 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) 3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<deInt64,2> dp; 3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool pointInclusive; // would a point in this corner intersect with the region 3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CORNER_EDGE_CASE_BEHAVIOR lineBehavior; // would a line segment going through this corner intersect with the region 3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CORNER_START_CASE_BEHAVIOR startBehavior; // how the corner behaves if the start point at the corner 3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CORNER_END_CASE_BEHAVIOR endBehavior; // how the corner behaves if the end point at the corner 3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } corners[] = 3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 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}, 3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { tcu::Vector<deInt64,2>(-halfPixel, 0), false, DiamondCorners::CORNER_EDGE_CASE_NONE, DiamondCorners::CORNER_START_CASE_NONE, DiamondCorners::CORNER_END_CASE_DIRECTION }, 3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 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 }, 3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { tcu::Vector<deInt64,2>(halfPixel, 0), true, DiamondCorners::CORNER_EDGE_CASE_HIT, DiamondCorners::CORNER_START_CASE_OUTSIDE, DiamondCorners::CORNER_END_CASE_NONE }, 3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Corner cases at the corners 3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(corners); ++ndx) 3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> p = diamondCenter + corners[ndx].dp; 3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool intersectsAtCorner = LineRasterUtil::vertexOnLineSegment(p, line); 3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!intersectsAtCorner) 3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // line segment body intersects with the corner 3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (p != line.m_v0 && p != line.m_v1) 3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (corners[ndx].lineBehavior == DiamondCorners::CORNER_EDGE_CASE_HIT) 3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // endpoint in (+X, -Y) (X or Y may be 0) direction <==> x*y <= 0 3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (corners[ndx].lineBehavior == DiamondCorners::CORNER_EDGE_CASE_HIT_FIRST_QUARTER && 3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (line.direction().x() * line.direction().y()) <= 0) 3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // endpoint in (+X, +Y) (Y > 0) direction <==> x*y > 0 3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (corners[ndx].lineBehavior == DiamondCorners::CORNER_EDGE_CASE_HIT_SECOND_QUARTER && 3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (line.direction().x() * line.direction().y()) > 0) 3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // line exits the area at the corner 3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (lineInCornerAngleRange(line, corners[ndx].dp)) 3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool startIsInside = corners[ndx].pointInclusive || p != line.m_v0; 3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool endIsOutside = !corners[ndx].pointInclusive || p != line.m_v1; 3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // starting point is inside the region and end endpoint is outside 3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (startIsInside && endIsOutside) 3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // line end is at the corner 3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (p == line.m_v1) 3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (corners[ndx].endBehavior == DiamondCorners::CORNER_END_CASE_DIRECTION || 3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry corners[ndx].endBehavior == DiamondCorners::CORNER_END_CASE_DIRECTION_AND_FIRST_QUARTER || 3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry corners[ndx].endBehavior == DiamondCorners::CORNER_END_CASE_DIRECTION_AND_SECOND_QUARTER) 3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // did the line intersect the region 3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (lineInCornerAngleRange(line, corners[ndx].dp)) 3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // due to the perturbed endpoint, lines at this the angle will cause and enter-exit pair 3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (corners[ndx].endBehavior == DiamondCorners::CORNER_END_CASE_DIRECTION_AND_FIRST_QUARTER && 3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry line.direction().x() < 0 && 3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry line.direction().y() > 0) 3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (corners[ndx].endBehavior == DiamondCorners::CORNER_END_CASE_DIRECTION_AND_SECOND_QUARTER && 3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry line.direction().x() > 0 && 3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry line.direction().y() > 0) 3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // line start is at the corner 3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (p == line.m_v0) 3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (corners[ndx].startBehavior == DiamondCorners::CORNER_START_CASE_OUTSIDE) 3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // if the line is not going inside, it will exit 3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (lineInCornerOutsideAngleRange(line, corners[ndx].dp)) 3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // exit, if line the angle between line vector and X-axis is in range (0, 45] in positive Y side. 4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (corners[ndx].startBehavior == DiamondCorners::CORNER_START_CASE_POSITIVE_Y_45 && 4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry line.direction().x() > 0 && 4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry line.direction().y() > 0 && 4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry line.direction().y() <= line.direction().x()) 4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // exit, if line the angle between line vector and X-axis is in range [0, 45] in negative Y side. 4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (corners[ndx].startBehavior == DiamondCorners::CORNER_START_CASE_NEGATIVE_Y_45 && 4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry line.direction().x() > 0 && 4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry line.direction().y() <= 0 && 4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry -line.direction().y() <= line.direction().x()) 4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Does the line intersect boundary at the left == exits the diamond 4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bounds); ++ndx) 4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool startVertexInside = LineRasterUtil::vertexOnLeftSideOfLine (line.m_v0, LineRasterUtil::SubpixelLineSegment(bounds[ndx].p0, bounds[ndx].p1)) || 4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (bounds[ndx].edgeInclusive && LineRasterUtil::vertexOnLine (line.m_v0, LineRasterUtil::SubpixelLineSegment(bounds[ndx].p0, bounds[ndx].p1))); 4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool endVertexInside = LineRasterUtil::vertexOnLeftSideOfLine (line.m_v1, LineRasterUtil::SubpixelLineSegment(bounds[ndx].p0, bounds[ndx].p1)) || 4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (bounds[ndx].edgeInclusive && LineRasterUtil::vertexOnLine (line.m_v1, LineRasterUtil::SubpixelLineSegment(bounds[ndx].p0, bounds[ndx].p1))); 4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // start must be on inside this half space (left or at the inclusive boundary) 4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!startVertexInside) 4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // end must be outside of this half-space (right or at non-inclusive boundary) 4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (endVertexInside) 4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Does the line via v0 and v1 intersect the line segment p0-p1 4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // <==> p0 and p1 are the different sides (LEFT, RIGHT) of the v0-v1 line. 4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Corners are not allowed, they are checked already 4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LineRasterUtil::LINE_SIDE sideP0 = LineRasterUtil::getVertexSide(bounds[ndx].p0, line); 4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LineRasterUtil::LINE_SIDE sideP1 = LineRasterUtil::getVertexSide(bounds[ndx].p1, line); 4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (sideP0 != LineRasterUtil::LINE_SIDE_INTERSECT && 4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry sideP1 != LineRasterUtil::LINE_SIDE_INTERSECT && 4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry sideP0 != sideP1) 4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // LineRasterUtil 4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4483c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTriangleRasterizer::TriangleRasterizer (const tcu::IVec4& viewport, const int numSamples, const RasterizationState& state) 4491409d3b197da7b68b13c2f5e15023f50b7078294David Sodman : m_viewport (viewport) 4501409d3b197da7b68b13c2f5e15023f50b7078294David Sodman , m_numSamples (numSamples) 4511409d3b197da7b68b13c2f5e15023f50b7078294David Sodman , m_winding (state.winding) 4521409d3b197da7b68b13c2f5e15023f50b7078294David Sodman , m_horizontalFill (state.horizontalFill) 4531409d3b197da7b68b13c2f5e15023f50b7078294David Sodman , m_verticalFill (state.verticalFill) 4541409d3b197da7b68b13c2f5e15023f50b7078294David Sodman , m_face (FACETYPE_LAST) 4551409d3b197da7b68b13c2f5e15023f50b7078294David Sodman , m_viewportOrientation (state.viewportOrientation) 4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*! 4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Initialize triangle rasterization 4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param v0 Screen-space coordinates (x, y, z) and 1/w for vertex 0. 4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param v1 Screen-space coordinates (x, y, z) and 1/w for vertex 1. 4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param v2 Screen-space coordinates (x, y, z) and 1/w for vertex 2. 4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TriangleRasterizer::init (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) 4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_v0 = v0; 4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_v1 = v1; 4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_v2 = v2; 4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Positions in fixed-point coordinates. 4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 x0 = toSubpixelCoord(v0.x()); 4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 y0 = toSubpixelCoord(v0.y()); 4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 x1 = toSubpixelCoord(v1.x()); 4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 y1 = toSubpixelCoord(v1.y()); 4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 x2 = toSubpixelCoord(v2.x()); 4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 y2 = toSubpixelCoord(v2.y()); 4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Initialize edge functions. 4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_winding == WINDING_CCW) 4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry initEdgeCCW(m_edge01, m_horizontalFill, m_verticalFill, x0, y0, x1, y1); 4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry initEdgeCCW(m_edge12, m_horizontalFill, m_verticalFill, x1, y1, x2, y2); 4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry initEdgeCCW(m_edge20, m_horizontalFill, m_verticalFill, x2, y2, x0, y0); 4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Reverse edges 4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry initEdgeCCW(m_edge01, m_horizontalFill, m_verticalFill, x1, y1, x0, y0); 4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry initEdgeCCW(m_edge12, m_horizontalFill, m_verticalFill, x2, y2, x1, y1); 4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry initEdgeCCW(m_edge20, m_horizontalFill, m_verticalFill, x0, y0, x2, y2); 4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Determine face. 4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 s = evaluateEdge(m_edge01, x2, y2); 4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool positiveArea = (m_winding == WINDING_CCW) ? (s > 0) : (s < 0); 4971409d3b197da7b68b13c2f5e15023f50b7078294David Sodman 4981409d3b197da7b68b13c2f5e15023f50b7078294David Sodman if (m_viewportOrientation == VIEWPORTORIENTATION_UPPER_LEFT) 4991409d3b197da7b68b13c2f5e15023f50b7078294David Sodman m_face = positiveArea ? FACETYPE_BACK : FACETYPE_FRONT; 5001409d3b197da7b68b13c2f5e15023f50b7078294David Sodman else 5011409d3b197da7b68b13c2f5e15023f50b7078294David Sodman m_face = positiveArea ? FACETYPE_FRONT : FACETYPE_BACK; 5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!positiveArea) 5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Reverse edges so that we can use CCW area tests & interpolation 5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reverseEdge(m_edge01); 5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reverseEdge(m_edge12); 5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reverseEdge(m_edge20); 5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Bounding box 5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 xMin = de::min(de::min(x0, x1), x2); 5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 xMax = de::max(de::max(x0, x1), x2); 5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 yMin = de::min(de::min(y0, y1), y2); 5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 yMax = de::max(de::max(y0, y1), y2); 5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_bboxMin.x() = floorSubpixelToPixelCoord (xMin, m_horizontalFill == FILL_LEFT); 5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_bboxMin.y() = floorSubpixelToPixelCoord (yMin, m_verticalFill == FILL_BOTTOM); 5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_bboxMax.x() = ceilSubpixelToPixelCoord (xMax, m_horizontalFill == FILL_RIGHT); 5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_bboxMax.y() = ceilSubpixelToPixelCoord (yMax, m_verticalFill == FILL_TOP); 5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Clamp to viewport 5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int wX0 = m_viewport.x(); 5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int wY0 = m_viewport.y(); 5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int wX1 = wX0 + m_viewport.z() - 1; 5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int wY1 = wY0 + m_viewport.w() -1; 5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_bboxMin.x() = de::clamp(m_bboxMin.x(), wX0, wX1); 5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_bboxMin.y() = de::clamp(m_bboxMin.y(), wY0, wY1); 5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_bboxMax.x() = de::clamp(m_bboxMax.x(), wX0, wX1); 5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_bboxMax.y() = de::clamp(m_bboxMax.y(), wY0, wY1); 5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curPos = m_bboxMin; 5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TriangleRasterizer::rasterizeSingleSample (FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized) 5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(maxFragmentPackets > 0); 5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint64 halfPixel = 1ll << (RASTERIZER_SUBPIXEL_BITS-1); 5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int packetNdx = 0; 5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 543f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos // For depth interpolation; given barycentrics A, B, C = (1 - A - B) 544f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos // we can reformulate the usual z = z0*A + z1*B + z2*C into more 545f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos // stable equation z = A*(z0 - z2) + B*(z1 - z2) + z2. 546f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const float za = m_v0.z()-m_v2.z(); 547f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const float zb = m_v1.z()-m_v2.z(); 548f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const float zc = m_v2.z(); 549f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos 5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry while (m_curPos.y() <= m_bboxMax.y() && packetNdx < maxFragmentPackets) 5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int x0 = m_curPos.x(); 5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int y0 = m_curPos.y(); 5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Subpixel coords 5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 sx0 = toSubpixelCoord(x0) + halfPixel; 5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 sx1 = toSubpixelCoord(x0+1) + halfPixel; 5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 sy0 = toSubpixelCoord(y0) + halfPixel; 5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 sy1 = toSubpixelCoord(y0+1) + halfPixel; 5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 sx[4] = { sx0, sx1, sx0, sx1 }; 5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 sy[4] = { sy0, sy0, sy1, sy1 }; 5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Viewport test 5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool outX1 = x0+1 == m_viewport.x()+m_viewport.z(); 5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool outY1 = y0+1 == m_viewport.y()+m_viewport.w(); 5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(x0 < m_viewport.x()+m_viewport.z()); 5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(y0 < m_viewport.y()+m_viewport.w()); 5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Edge values 5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<deInt64, 4> e01; 5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<deInt64, 4> e12; 5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<deInt64, 4> e20; 5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Coverage 5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint64 coverage = 0; 5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Evaluate edge values 5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int i = 0; i < 4; i++) 5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry e01[i] = evaluateEdge(m_edge01, sx[i], sy[i]); 5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry e12[i] = evaluateEdge(m_edge12, sx[i], sy[i]); 5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry e20[i] = evaluateEdge(m_edge20, sx[i], sy[i]); 5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Compute coverage mask 5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry coverage = setCoverageValue(coverage, 1, 0, 0, 0, isInsideCCW(m_edge01, e01[0]) && isInsideCCW(m_edge12, e12[0]) && isInsideCCW(m_edge20, e20[0])); 5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry coverage = setCoverageValue(coverage, 1, 1, 0, 0, !outX1 && isInsideCCW(m_edge01, e01[1]) && isInsideCCW(m_edge12, e12[1]) && isInsideCCW(m_edge20, e20[1])); 5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry coverage = setCoverageValue(coverage, 1, 0, 1, 0, !outY1 && isInsideCCW(m_edge01, e01[2]) && isInsideCCW(m_edge12, e12[2]) && isInsideCCW(m_edge20, e20[2])); 5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry coverage = setCoverageValue(coverage, 1, 1, 1, 0, !outX1 && !outY1 && isInsideCCW(m_edge01, e01[3]) && isInsideCCW(m_edge12, e12[3]) && isInsideCCW(m_edge20, e20[3])); 5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Advance to next location 5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curPos.x() += 2; 5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_curPos.x() > m_bboxMax.x()) 5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curPos.y() += 2; 5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curPos.x() = m_bboxMin.x(); 5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (coverage == 0) 6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; // Discard. 6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Floating-point edge values for barycentrics etc. 6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 e01f = e01.asFloat(); 6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 e12f = e12.asFloat(); 6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 e20f = e20.asFloat(); 6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Compute depth values. 6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (depthValues) 6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 612f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const tcu::Vec4 edgeSum = e01f + e12f + e20f; 613f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const tcu::Vec4 z0 = e12f / edgeSum; 614f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const tcu::Vec4 z1 = e20f / edgeSum; 615f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos 616f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos depthValues[packetNdx*4+0] = z0[0]*za + z1[0]*zb + zc; 617f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos depthValues[packetNdx*4+1] = z0[1]*za + z1[1]*zb + zc; 618f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos depthValues[packetNdx*4+2] = z0[2]*za + z1[2]*zb + zc; 619f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos depthValues[packetNdx*4+3] = z0[3]*za + z1[3]*zb + zc; 6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Compute barycentrics and write out fragment packet 6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FragmentPacket& packet = fragmentPackets[packetNdx]; 6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 b0 = e12f * m_v0.w(); 6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 b1 = e20f * m_v1.w(); 6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 b2 = e01f * m_v2.w(); 629f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const tcu::Vec4 bSum = b0 + b1 + b2; 6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packet.position = tcu::IVec2(x0, y0); 6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packet.coverage = coverage; 633f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos packet.barycentric[0] = b0 / bSum; 634f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos packet.barycentric[1] = b1 / bSum; 6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packet.barycentric[2] = 1.0f - packet.barycentric[0] - packet.barycentric[1]; 6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packetNdx += 1; 6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(packetNdx <= maxFragmentPackets); 6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numPacketsRasterized = packetNdx; 6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Sample positions - ordered as (x, y) list. 6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \note Macros are used to eliminate function calls even in debug builds. 6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define SAMPLE_POS_TO_SUBPIXEL_COORD(POS) \ 6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (deInt64)((POS) * (1<<RASTERIZER_SUBPIXEL_BITS) + 0.5f) 6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define SAMPLE_POS(X, Y) \ 6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS_TO_SUBPIXEL_COORD(X), SAMPLE_POS_TO_SUBPIXEL_COORD(Y) 6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const deInt64 s_samplePos2[] = 6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(0.3f, 0.3f), 6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(0.7f, 0.7f) 6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const deInt64 s_samplePos4[] = 6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(0.25f, 0.25f), 6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(0.75f, 0.25f), 6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(0.25f, 0.75f), 6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(0.75f, 0.75f) 6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 6673c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_samplePos4) == 4*2); 6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const deInt64 s_samplePos8[] = 6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS( 7.f/16.f, 9.f/16.f), 6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS( 9.f/16.f, 13.f/16.f), 6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(11.f/16.f, 3.f/16.f), 6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(13.f/16.f, 11.f/16.f), 6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS( 1.f/16.f, 7.f/16.f), 6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS( 5.f/16.f, 1.f/16.f), 6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(15.f/16.f, 5.f/16.f), 6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS( 3.f/16.f, 15.f/16.f) 6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 6803c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_samplePos8) == 8*2); 6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const deInt64 s_samplePos16[] = 6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(1.f/8.f, 1.f/8.f), 6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(3.f/8.f, 1.f/8.f), 6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(5.f/8.f, 1.f/8.f), 6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(7.f/8.f, 1.f/8.f), 6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(1.f/8.f, 3.f/8.f), 6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(3.f/8.f, 3.f/8.f), 6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(5.f/8.f, 3.f/8.f), 6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(7.f/8.f, 3.f/8.f), 6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(1.f/8.f, 5.f/8.f), 6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(3.f/8.f, 5.f/8.f), 6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(5.f/8.f, 5.f/8.f), 6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(7.f/8.f, 5.f/8.f), 6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(1.f/8.f, 7.f/8.f), 6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(3.f/8.f, 7.f/8.f), 6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(5.f/8.f, 7.f/8.f), 6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SAMPLE_POS(7.f/8.f, 7.f/8.f) 7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 7013c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_samplePos16) == 16*2); 7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#undef SAMPLE_POS 7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#undef SAMPLE_POS_TO_SUBPIXEL_COORD 7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<int NumSamples> 7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TriangleRasterizer::rasterizeMultiSample (FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized) 7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(maxFragmentPackets > 0); 7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64* samplePos = DE_NULL; 7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint64 halfPixel = 1ll << (RASTERIZER_SUBPIXEL_BITS-1); 7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int packetNdx = 0; 7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 715f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos // For depth interpolation, see rasterizeSingleSample 716f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const float za = m_v0.z()-m_v2.z(); 717f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const float zb = m_v1.z()-m_v2.z(); 718f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const float zc = m_v2.z(); 719f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos 7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (NumSamples) 7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 2: samplePos = s_samplePos2; break; 7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 4: samplePos = s_samplePos4; break; 7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 8: samplePos = s_samplePos8; break; 7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 16: samplePos = s_samplePos16; break; 7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry while (m_curPos.y() <= m_bboxMax.y() && packetNdx < maxFragmentPackets) 7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int x0 = m_curPos.x(); 7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int y0 = m_curPos.y(); 7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Base subpixel coords 7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 sx0 = toSubpixelCoord(x0); 7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 sx1 = toSubpixelCoord(x0+1); 7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 sy0 = toSubpixelCoord(y0); 7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 sy1 = toSubpixelCoord(y0+1); 7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 sx[4] = { sx0, sx1, sx0, sx1 }; 7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 sy[4] = { sy0, sy0, sy1, sy1 }; 7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Viewport test 7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool outX1 = x0+1 == m_viewport.x()+m_viewport.z(); 7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool outY1 = y0+1 == m_viewport.y()+m_viewport.w(); 7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(x0 < m_viewport.x()+m_viewport.z()); 7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(y0 < m_viewport.y()+m_viewport.w()); 7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Edge values 7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<deInt64, 4> e01[NumSamples]; 7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<deInt64, 4> e12[NumSamples]; 7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<deInt64, 4> e20[NumSamples]; 7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Coverage 7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint64 coverage = 0; 7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Evaluate edge values at sample positions 7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int sampleNdx = 0; sampleNdx < NumSamples; sampleNdx++) 7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 ox = samplePos[sampleNdx*2 + 0]; 7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 oy = samplePos[sampleNdx*2 + 1]; 7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int fragNdx = 0; fragNdx < 4; fragNdx++) 7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry e01[sampleNdx][fragNdx] = evaluateEdge(m_edge01, sx[fragNdx] + ox, sy[fragNdx] + oy); 7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry e12[sampleNdx][fragNdx] = evaluateEdge(m_edge12, sx[fragNdx] + ox, sy[fragNdx] + oy); 7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry e20[sampleNdx][fragNdx] = evaluateEdge(m_edge20, sx[fragNdx] + ox, sy[fragNdx] + oy); 7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Compute coverage mask 7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int sampleNdx = 0; sampleNdx < NumSamples; sampleNdx++) 7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 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])); 7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 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])); 7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 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])); 7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 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])); 7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Advance to next location 7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curPos.x() += 2; 7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_curPos.x() > m_bboxMax.x()) 7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curPos.y() += 2; 7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curPos.x() = m_bboxMin.x(); 7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (coverage == 0) 7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; // Discard. 7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Compute depth values. 7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (depthValues) 7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int sampleNdx = 0; sampleNdx < NumSamples; sampleNdx++) 7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Floating-point edge values at sample coordinates. 7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4& e01f = e01[sampleNdx].asFloat(); 8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4& e12f = e12[sampleNdx].asFloat(); 8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4& e20f = e20[sampleNdx].asFloat(); 8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 803f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const tcu::Vec4 edgeSum = e01f + e12f + e20f; 804f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const tcu::Vec4 z0 = e12f / edgeSum; 805f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const tcu::Vec4 z1 = e20f / edgeSum; 8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 807f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos depthValues[(packetNdx*4+0)*NumSamples + sampleNdx] = z0[0]*za + z1[0]*zb + zc; 808f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos depthValues[(packetNdx*4+1)*NumSamples + sampleNdx] = z0[1]*za + z1[1]*zb + zc; 809f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos depthValues[(packetNdx*4+2)*NumSamples + sampleNdx] = z0[2]*za + z1[2]*zb + zc; 810f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos depthValues[(packetNdx*4+3)*NumSamples + sampleNdx] = z0[3]*za + z1[3]*zb + zc; 8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Compute barycentrics and write out fragment packet 8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FragmentPacket& packet = fragmentPackets[packetNdx]; 8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Floating-point edge values at pixel center. 8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec4 e01f; 8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec4 e12f; 8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec4 e20f; 8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int i = 0; i < 4; i++) 8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry e01f[i] = float(evaluateEdge(m_edge01, sx[i] + halfPixel, sy[i] + halfPixel)); 8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry e12f[i] = float(evaluateEdge(m_edge12, sx[i] + halfPixel, sy[i] + halfPixel)); 8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry e20f[i] = float(evaluateEdge(m_edge20, sx[i] + halfPixel, sy[i] + halfPixel)); 8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Barycentrics & scale. 8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 b0 = e12f * m_v0.w(); 8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 b1 = e20f * m_v1.w(); 8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 b2 = e01f * m_v2.w(); 834f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos const tcu::Vec4 bSum = b0 + b1 + b2; 8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packet.position = tcu::IVec2(x0, y0); 8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packet.coverage = coverage; 838f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos packet.barycentric[0] = b0 / bSum; 839f4238ec8ad0e9b0995142dc3b0b9a18de167ae3fPyry Haulos packet.barycentric[1] = b1 / bSum; 8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packet.barycentric[2] = 1.0f - packet.barycentric[0] - packet.barycentric[1]; 8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packetNdx += 1; 8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(packetNdx <= maxFragmentPackets); 8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numPacketsRasterized = packetNdx; 8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TriangleRasterizer::rasterize (FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized) 8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(maxFragmentPackets > 0); 8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (m_numSamples) 8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 1: rasterizeSingleSample (fragmentPackets, depthValues, maxFragmentPackets, numPacketsRasterized); break; 8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 2: rasterizeMultiSample<2> (fragmentPackets, depthValues, maxFragmentPackets, numPacketsRasterized); break; 8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 4: rasterizeMultiSample<4> (fragmentPackets, depthValues, maxFragmentPackets, numPacketsRasterized); break; 8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 8: rasterizeMultiSample<8> (fragmentPackets, depthValues, maxFragmentPackets, numPacketsRasterized); break; 8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 16: rasterizeMultiSample<16> (fragmentPackets, depthValues, maxFragmentPackets, numPacketsRasterized); break; 8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(DE_FALSE); 8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8663c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySingleSampleLineRasterizer::SingleSampleLineRasterizer (const tcu::IVec4& viewport) 8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_viewport (viewport) 8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_curRowFragment (0) 8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_lineWidth (0.0f) 8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8732306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko PöyrySingleSampleLineRasterizer::~SingleSampleLineRasterizer (void) 8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SingleSampleLineRasterizer::init (const tcu::Vec4& v0, const tcu::Vec4& v1, float lineWidth) 8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8793e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry const bool isXMajor = de::abs((v1 - v0).x()) >= de::abs((v1 - v0).y()); 8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8813e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry // Bounding box \note: with wide lines, the line is actually moved as in the spec 8823e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry const deInt32 lineWidthPixels = (lineWidth > 1.0f) ? (deInt32)floor(lineWidth + 0.5f) : 1; 8833e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry 8843e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry const tcu::Vector<deInt64,2> widthOffset = (isXMajor ? tcu::Vector<deInt64,2>(0, -1) : tcu::Vector<deInt64,2>(-1, 0)) * (toSubpixelCoord(lineWidthPixels - 1) / 2); 8853e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry 8863e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry const deInt64 x0 = toSubpixelCoord(v0.x()) + widthOffset.x(); 8873e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry const deInt64 y0 = toSubpixelCoord(v0.y()) + widthOffset.y(); 8883e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry const deInt64 x1 = toSubpixelCoord(v1.x()) + widthOffset.x(); 8893e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry const deInt64 y1 = toSubpixelCoord(v1.y()) + widthOffset.y(); 8903e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry 8913e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry // line endpoints might be perturbed, add some margin 8923e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry const deInt64 xMin = de::min(x0, x1) - toSubpixelCoord(1); 8933e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry const deInt64 xMax = de::max(x0, x1) + toSubpixelCoord(1); 8943e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry const deInt64 yMin = de::min(y0, y1) - toSubpixelCoord(1); 8953e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry const deInt64 yMax = de::max(y0, y1) + toSubpixelCoord(1); 8963e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry 8973e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry // Remove invisible area 8983e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry 8993e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry if (isXMajor) 9003e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry { 9013e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry // clamp to viewport in major direction 9023e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry m_bboxMin.x() = de::clamp(floorSubpixelToPixelCoord(xMin, true), m_viewport.x(), m_viewport.x() + m_viewport.z() - 1); 9033e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry m_bboxMax.x() = de::clamp(ceilSubpixelToPixelCoord (xMax, true), m_viewport.x(), m_viewport.x() + m_viewport.z() - 1); 9043e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry 9053e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry // clamp to padded viewport in minor direction (wide lines might bleed over viewport in minor direction) 9063e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry m_bboxMin.y() = de::clamp(floorSubpixelToPixelCoord(yMin, true), m_viewport.y() - lineWidthPixels, m_viewport.y() + m_viewport.w() - 1); 9073e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry m_bboxMax.y() = de::clamp(ceilSubpixelToPixelCoord (yMax, true), m_viewport.y() - lineWidthPixels, m_viewport.y() + m_viewport.w() - 1); 9083e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry } 9093e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry else 9103e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry { 9113e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry // clamp to viewport in major direction 9123e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry m_bboxMin.y() = de::clamp(floorSubpixelToPixelCoord(yMin, true), m_viewport.y(), m_viewport.y() + m_viewport.w() - 1); 9133e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry m_bboxMax.y() = de::clamp(ceilSubpixelToPixelCoord (yMax, true), m_viewport.y(), m_viewport.y() + m_viewport.w() - 1); 9143e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry 9153e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry // clamp to padded viewport in minor direction (wide lines might bleed over viewport in minor direction) 9163e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry m_bboxMin.x() = de::clamp(floorSubpixelToPixelCoord(xMin, true), m_viewport.x() - lineWidthPixels, m_viewport.x() + m_viewport.z() - 1); 9173e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry m_bboxMax.x() = de::clamp(ceilSubpixelToPixelCoord (xMax, true), m_viewport.x() - lineWidthPixels, m_viewport.x() + m_viewport.z() - 1); 9183e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry } 9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_lineWidth = lineWidth; 9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_v0 = v0; 9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_v1 = v1; 9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curPos = m_bboxMin; 9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curRowFragment = 0; 9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SingleSampleLineRasterizer::rasterize (FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized) 9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(maxFragmentPackets > 0); 9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9332306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const deInt64 halfPixel = 1ll << (RASTERIZER_SUBPIXEL_BITS-1); 9342306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const deInt32 lineWidth = (m_lineWidth > 1.0f) ? deFloorFloatToInt32(m_lineWidth + 0.5f) : 1; 9352306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const bool isXMajor = de::abs((m_v1 - m_v0).x()) >= de::abs((m_v1 - m_v0).y()); 9362306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec2 minorDirection = (isXMajor) ? (tcu::IVec2(0, 1)) : (tcu::IVec2(1, 0)); 9372306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int minViewportLimit = (isXMajor) ? (m_viewport.y()) : (m_viewport.x()); 9382306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int maxViewportLimit = (isXMajor) ? (m_viewport.y() + m_viewport.w()) : (m_viewport.x() + m_viewport.z()); 9392306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vector<deInt64,2> widthOffset = -minorDirection.cast<deInt64>() * (toSubpixelCoord(lineWidth - 1) / 2); 9402306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vector<deInt64,2> pa = LineRasterUtil::toSubpixelVector(m_v0.xy()) + widthOffset; 9412306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vector<deInt64,2> pb = LineRasterUtil::toSubpixelVector(m_v1.xy()) + widthOffset; 9422306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const LineRasterUtil::SubpixelLineSegment line = LineRasterUtil::SubpixelLineSegment(pa, pb); 9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9442306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int packetNdx = 0; 9453e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry 9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry while (m_curPos.y() <= m_bboxMax.y() && packetNdx < maxFragmentPackets) 9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<deInt64,2> diamondPosition = LineRasterUtil::toSubpixelVector(m_curPos) + tcu::Vector<deInt64,2>(halfPixel,halfPixel); 9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Should current fragment be drawn? == does the segment exit this diamond? 9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (LineRasterUtil::doesLineSegmentExitDiamond(line, diamondPosition)) 9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9532306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vector<deInt64,2> pr = diamondPosition; 9542306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float t = tcu::dot((pr - pa).asFloat(), (pb - pa).asFloat()) / tcu::lengthSquared(pb.asFloat() - pa.asFloat()); 9553e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry 9563e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry // Rasterize on only fragments that are would end up in the viewport (i.e. visible) 9572306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int fragmentLocation = (isXMajor) ? (m_curPos.y()) : (m_curPos.x()); 9583e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry const int rowFragBegin = de::max(0, minViewportLimit - fragmentLocation); 9593e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry const int rowFragEnd = de::min(maxViewportLimit - fragmentLocation, lineWidth); 9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Wide lines require multiple fragments. 9623e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry for (; rowFragBegin + m_curRowFragment < rowFragEnd; m_curRowFragment++) 9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9642306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int replicationId = rowFragBegin + m_curRowFragment; 9652306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec2 fragmentPos = m_curPos + minorDirection * replicationId; 9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9673e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry // We only rasterize visible area 9683e351a9e69e78f8893d2cea7b1ed4089dfaebecbJarkko Pöyry DE_ASSERT(LineRasterUtil::inViewport(fragmentPos, m_viewport)); 9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Compute depth values. 9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (depthValues) 9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float za = m_v0.z(); 9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float zb = m_v1.z(); 9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry depthValues[packetNdx*4+0] = (1 - t) * za + t * zb; 9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry depthValues[packetNdx*4+1] = 0; 9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry depthValues[packetNdx*4+2] = 0; 9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry depthValues[packetNdx*4+3] = 0; 9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // output this fragment 9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note In order to make consistent output with multisampled line rasterization, output "barycentric" coordinates 9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FragmentPacket& packet = fragmentPackets[packetNdx]; 9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 b0 = tcu::Vec4(1 - t); 9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 b1 = tcu::Vec4(t); 9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 ooSum = 1.0f / (b0 + b1); 9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packet.position = fragmentPos; 9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packet.coverage = getCoverageBit(1, 0, 0, 0); 9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packet.barycentric[0] = b0 * ooSum; 9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packet.barycentric[1] = b1 * ooSum; 9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packet.barycentric[2] = tcu::Vec4(0.0f); 9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry packetNdx += 1; 9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (packetNdx == maxFragmentPackets) 10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curRowFragment++; // don't redraw this fragment again next time 10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numPacketsRasterized = packetNdx; 10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return; 10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curRowFragment = 0; 10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++m_curPos.x(); 10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_curPos.x() > m_bboxMax.x()) 10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++m_curPos.y(); 10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curPos.x() = m_bboxMin.x(); 10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(packetNdx <= maxFragmentPackets); 10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numPacketsRasterized = packetNdx; 10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10233c827367444ee418f129b2c238299f49d3264554Jarkko PoyryMultiSampleLineRasterizer::MultiSampleLineRasterizer (const int numSamples, const tcu::IVec4& viewport) 10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_numSamples (numSamples) 10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_triangleRasterizer0 (viewport, m_numSamples, RasterizationState()) 10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_triangleRasterizer1 (viewport, m_numSamples, RasterizationState()) 10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10303c827367444ee418f129b2c238299f49d3264554Jarkko PoyryMultiSampleLineRasterizer::~MultiSampleLineRasterizer () 10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid MultiSampleLineRasterizer::init (const tcu::Vec4& v0, const tcu::Vec4& v1, float lineWidth) 10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // allow creation of single sampled rasterizer objects but do not allow using them 10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(m_numSamples > 1); 10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineVec = tcu::Vec2(tcu::Vec4(v1).xy()) - tcu::Vec2(tcu::Vec4(v0).xy()); 10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 normal2 = tcu::normalize(tcu::Vec2(-lineVec[1], lineVec[0])); 10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 normal4 = tcu::Vec4(normal2.x(), normal2.y(), 0, 0); 10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float offset = lineWidth / 2.0f; 10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 p0 = v0 + normal4 * offset; 10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 p1 = v0 - normal4 * offset; 10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 p2 = v1 - normal4 * offset; 10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 p3 = v1 + normal4 * offset; 10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Edge 0 -> 1 is always along the line and edge 1 -> 2 is in 90 degree angle to the line 10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_triangleRasterizer0.init(p0, p3, p2); 10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_triangleRasterizer1.init(p2, p1, p0); 10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid MultiSampleLineRasterizer::rasterize (FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized) 10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(maxFragmentPackets > 0); 10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_triangleRasterizer0.rasterize(fragmentPackets, depthValues, maxFragmentPackets, numPacketsRasterized); 10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Remove 3rd barycentric value and rebalance. Lines do not have non-zero barycentric at index 2 10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int packNdx = 0; packNdx < numPacketsRasterized; ++packNdx) 10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int fragNdx = 0; fragNdx < 4; fragNdx++) 10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry float removedValue = fragmentPackets[packNdx].barycentric[2][fragNdx]; 10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fragmentPackets[packNdx].barycentric[2][fragNdx] = 0.0f; 10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fragmentPackets[packNdx].barycentric[1][fragNdx] += removedValue; 10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // rasterizer 0 filled the whole buffer? 10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (numPacketsRasterized == maxFragmentPackets) 10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return; 10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FragmentPacket* const nextFragmentPackets = fragmentPackets + numPacketsRasterized; 10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry float* nextDepthValues = (depthValues) ? (depthValues+4*numPacketsRasterized*m_numSamples) : (DE_NULL); 10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numPacketsRasterized2 = 0; 10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_triangleRasterizer1.rasterize(nextFragmentPackets, nextDepthValues, maxFragmentPackets - numPacketsRasterized, numPacketsRasterized2); 10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numPacketsRasterized += numPacketsRasterized2; 10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Fix swapped barycentrics in the second triangle 10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int packNdx = 0; packNdx < numPacketsRasterized2; ++packNdx) 10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int fragNdx = 0; fragNdx < 4; fragNdx++) 10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry float removedValue = nextFragmentPackets[packNdx].barycentric[2][fragNdx]; 10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry nextFragmentPackets[packNdx].barycentric[2][fragNdx] = 0.0f; 10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry nextFragmentPackets[packNdx].barycentric[1][fragNdx] += removedValue; 10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // edge has reversed direction 10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::swap(nextFragmentPackets[packNdx].barycentric[0][fragNdx], nextFragmentPackets[packNdx].barycentric[1][fragNdx]); 10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10962306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko PöyryLineExitDiamondGenerator::LineExitDiamondGenerator (void) 10972306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 10982306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 10992306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11002306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko PöyryLineExitDiamondGenerator::~LineExitDiamondGenerator (void) 11012306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 11022306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 11032306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11042306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyryvoid LineExitDiamondGenerator::init (const tcu::Vec4& v0, const tcu::Vec4& v1) 11052306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 11062306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const deInt64 x0 = toSubpixelCoord(v0.x()); 11072306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const deInt64 y0 = toSubpixelCoord(v0.y()); 11082306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const deInt64 x1 = toSubpixelCoord(v1.x()); 11092306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const deInt64 y1 = toSubpixelCoord(v1.y()); 11102306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11112306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // line endpoints might be perturbed, add some margin 11122306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const deInt64 xMin = de::min(x0, x1) - toSubpixelCoord(1); 11132306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const deInt64 xMax = de::max(x0, x1) + toSubpixelCoord(1); 11142306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const deInt64 yMin = de::min(y0, y1) - toSubpixelCoord(1); 11152306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const deInt64 yMax = de::max(y0, y1) + toSubpixelCoord(1); 11162306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11172306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry m_bboxMin.x() = floorSubpixelToPixelCoord(xMin, true); 11182306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry m_bboxMin.y() = floorSubpixelToPixelCoord(yMin, true); 11192306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry m_bboxMax.x() = ceilSubpixelToPixelCoord (xMax, true); 11202306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry m_bboxMax.y() = ceilSubpixelToPixelCoord (yMax, true); 11212306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11222306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry m_v0 = v0; 11232306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry m_v1 = v1; 11242306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11252306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry m_curPos = m_bboxMin; 11262306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 11272306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11282306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyryvoid LineExitDiamondGenerator::rasterize (LineExitDiamond* const lineDiamonds, const int maxDiamonds, int& numWritten) 11292306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 11302306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(maxDiamonds > 0); 11312306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11322306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const deInt64 halfPixel = 1ll << (RASTERIZER_SUBPIXEL_BITS-1); 11332306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vector<deInt64,2> pa = LineRasterUtil::toSubpixelVector(m_v0.xy()); 11342306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vector<deInt64,2> pb = LineRasterUtil::toSubpixelVector(m_v1.xy()); 11352306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const LineRasterUtil::SubpixelLineSegment line = LineRasterUtil::SubpixelLineSegment(pa, pb); 11362306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11372306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int diamondNdx = 0; 11382306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11392306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry while (m_curPos.y() <= m_bboxMax.y() && diamondNdx < maxDiamonds) 11402306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 11412306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vector<deInt64,2> diamondPosition = LineRasterUtil::toSubpixelVector(m_curPos) + tcu::Vector<deInt64,2>(halfPixel,halfPixel); 11422306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11432306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (LineRasterUtil::doesLineSegmentExitDiamond(line, diamondPosition)) 11442306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 11452306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry LineExitDiamond& packet = lineDiamonds[diamondNdx]; 11462306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry packet.position = m_curPos; 11472306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry ++diamondNdx; 11482306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 11492306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11502306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry ++m_curPos.x(); 11512306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (m_curPos.x() > m_bboxMax.x()) 11522306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 11532306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry ++m_curPos.y(); 11542306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry m_curPos.x() = m_bboxMin.x(); 11552306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 11562306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 11572306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11582306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(diamondNdx <= maxDiamonds); 11592306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry numWritten = diamondNdx; 11602306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 11612306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // rr 1163