@@ -1704,106 +1704,146 @@ void GSRendererHW::RoundSpriteOffset()
17041704 for (u32 i = 0 ; i < count; i += 2 )
17051705 {
17061706 // Performance note: if it had any impact on perf, someone would port it to SSE (AKA GSVector)
1707-
1708- // Compute the coordinate of first and last texels (in native with a linear filtering)
1707+ // if the draw is page aligned, then don't round it.
1708+ const int tex_width = std::max ( 1 , (v[i + 1 ]. U - v[i]. U ) >> 4 );
17091709 const int ox = m_context->XYOFFSET .OFX ;
1710- const int X0 = v[i].XYZ .X - ox;
1711- const int X1 = v[i + 1 ].XYZ .X - ox;
17121710 const int Lx = (v[i + 1 ].XYZ .X - v[i].XYZ .X );
1713- const float ax0 = alpha0 (Lx, X0 , X1 );
1714- const float ax1 = alpha1 (Lx, X0 , X1 );
1715- const u16 tx0 = Interpolate_UV (ax0, v[i].U , v[i + 1 ].U );
1716- const u16 tx1 = Interpolate_UV (ax1, v[i].U , v[i + 1 ].U );
1717- #ifdef DEBUG_U
1718- if (debug)
1719- {
1720- fprintf (stderr, " u0:%d and u1:%d\n " , v[i].U , v[i + 1 ].U );
1721- fprintf (stderr, " a0:%f and a1:%f\n " , ax0, ax1);
1722- fprintf (stderr, " t0:%d and t1:%d\n " , tx0, tx1);
1723- }
1724- #endif
17251711
1726- const int oy = m_context->XYOFFSET .OFY ;
1727- const int Y0 = v[i].XYZ .Y - oy;
1728- const int Y1 = v[i + 1 ].XYZ .Y - oy;
1729- const int Ly = (v[i + 1 ].XYZ .Y - v[i].XYZ .Y );
1730- const float ay0 = alpha0 (Ly, Y0 , Y1 );
1731- const float ay1 = alpha1 (Ly, Y0 , Y1 );
1732- const u16 ty0 = Interpolate_UV (ay0, v[i].V , v[i + 1 ].V );
1733- const u16 ty1 = Interpolate_UV (ay1, v[i].V , v[i + 1 ].V );
1734- #ifdef DEBUG_V
1735- if (debug)
1712+ if ((((Lx - ox) >> 4 ) % tex_width) != 0 )
17361713 {
1737- fprintf (stderr, " v0:%d and v1:%d\n " , v[i].V , v[i + 1 ].V );
1738- fprintf (stderr, " a0:%f and a1:%f\n " , ay0, ay1);
1739- fprintf (stderr, " t0:%d and t1:%d\n " , ty0, ty1);
1740- }
1741- #endif
1742-
1714+ // Compute the coordinate of first and last texels (in native with a linear filtering)
1715+ const int X0 = v[i].XYZ .X - ox;
1716+ const int X1 = v[i + 1 ].XYZ .X - ox;
1717+ const float ax0 = alpha0 (Lx, X0 , X1 );
1718+ const float ax1 = alpha1 (Lx, X0 , X1 );
1719+ const u16 tx0 = Interpolate_UV (ax0, v[i].U , v[i + 1 ].U );
1720+ const u16 tx1 = Interpolate_UV (ax1, v[i].U , v[i + 1 ].U );
1721+ // DevCon.Warning("Tex width %d draw width %d (X %x -> %x U %x -> %x", tex_width, ((v[i + 1].XYZ.X - v[i].XYZ.X) >> 4), X0, X1, v[i].U, v[i+1].U);
17431722#ifdef DEBUG_U
1744- if (debug)
1745- fprintf (stderr, " GREP_BEFORE %d => %d \n " , v[i]. U , v[i + 1 ]. U );
1746- # endif
1747- # ifdef DEBUG_V
1748- if (debug)
1749- fprintf (stderr, " GREP_BEFORE %d => %d \n " , v[i]. V , v[i + 1 ]. V );
1723+ if (debug)
1724+ {
1725+ fprintf (stderr, " u0:%d and u1:%d \n " , v[i]. U , v[i + 1 ]. U );
1726+ fprintf (stderr, " a0:%f and a1:%f \n " , ax0, ax1);
1727+ fprintf (stderr, " t0:%d and t1:%d \n " , tx0, tx1);
1728+ }
17501729#endif
1751-
17521730#if 1
1753- // Use rounded value of the newly computed texture coordinate. It ensures
1754- // that sampling will remains inside texture boundary
1755- //
1756- // Note for bilinear: by definition it will never work correctly! A sligh modification
1757- // of interpolation migth trigger a discard (with alpha testing)
1758- // Let's use something simple that correct really bad case (for a couple of 2D games).
1759- // I hope it won't create too much glitches.
1760- if (linear)
1761- {
1762- const int Lu = v[i + 1 ].U - v[i].U ;
1763- // Note 32 is based on taisho-mononoke
1764- if ((Lu > 0 ) && (Lu <= (Lx + 32 )))
1731+ // Use rounded value of the newly computed texture coordinate. It ensures
1732+ // that sampling will remains inside texture boundary
1733+ //
1734+ // Note for bilinear: by definition it will never work correctly! A sligh modification
1735+ // of interpolation migth trigger a discard (with alpha testing)
1736+ // Let's use something simple that correct really bad case (for a couple of 2D games).
1737+ // I hope it won't create too much glitches.
1738+ if (linear)
17651739 {
1766- v[i + 1 ].U -= 8 ;
1740+ const int Lu = v[i + 1 ].U - v[i].U ;
1741+ // Note 32 is based on taisho-mononoke
1742+ if ((Lu > 0 ) && (Lu <= (Lx + 32 )))
1743+ {
1744+ v[i + 1 ].U -= 8 ;
1745+ }
17671746 }
1747+ else
1748+ {
1749+ if (tx0 <= tx1)
1750+ {
1751+ v[i].U = tx0;
1752+ v[i + 1 ].U = tx1 + 16 ;
1753+ }
1754+ else
1755+ {
1756+ v[i].U = tx0 + 15 ;
1757+ v[i + 1 ].U = tx1;
1758+ }
1759+ }
1760+ #endif
17681761 }
17691762 else
17701763 {
1771- if (tx0 <= tx1 )
1764+ if (((v[i + 1 ]. U & 0xf ) ^ ((v[i + 1 ]. XYZ . X - ox) & 0xf )) && ((v[i + 1 ]. U - v[i]. U ) >> 4 ) == tex_width && (Lx >> 4 ) / tex_width <= 2 )
17721765 {
1773- v[i].U = tx0 ;
1774- v[i + 1 ].U = tx1 + 16 ;
1766+ v[i].U &= ~ 0xf ;
1767+ v[i + 1 ].U -= 8 ;
17751768 }
17761769 else
17771770 {
1778- v[i].U = tx0 + 15 ;
1779- v[i + 1 ].U = tx1;
1771+ v[i].U &= ~0xf ;
1772+ v[i + 1 ].U &= ~0xf ;
1773+ v[i].U |= (v[i].XYZ .X - ox) & 0xf ;
1774+ v[i + 1 ].U |= (v[i + 1 ].XYZ .X - ox) & 0xf ;
17801775 }
17811776 }
1777+
1778+ const int tex_height = std::max (1 , (v[i + 1 ].V - v[i].V ) >> 4 );
1779+ const int oy = m_context->XYOFFSET .OFY ;
1780+ const int Ly = (v[i + 1 ].XYZ .Y - v[i].XYZ .Y );
1781+
1782+ if ((((Ly - oy) >> 4 ) % tex_height) != 0 )
1783+ {
1784+ const int Y0 = v[i].XYZ .Y - oy;
1785+ const int Y1 = v[i + 1 ].XYZ .Y - oy;
1786+ const float ay0 = alpha0 (Ly, Y0 , Y1 );
1787+ const float ay1 = alpha1 (Ly, Y0 , Y1 );
1788+ const u16 ty0 = Interpolate_UV (ay0, v[i].V , v[i + 1 ].V );
1789+ const u16 ty1 = Interpolate_UV (ay1, v[i].V , v[i + 1 ].V );
1790+ #ifdef DEBUG_V
1791+ if (debug)
1792+ {
1793+ fprintf (stderr, " v0:%d and v1:%d\n " , v[i].V , v[i + 1 ].V );
1794+ fprintf (stderr, " a0:%f and a1:%f\n " , ay0, ay1);
1795+ fprintf (stderr, " t0:%d and t1:%d\n " , ty0, ty1);
1796+ }
17821797#endif
17831798#if 1
1784- if (linear)
1785- {
1786- const int Lv = v[i + 1 ].V - v[i].V ;
1787- if ((Lv > 0 ) && (Lv <= (Ly + 32 )))
1799+ if (linear)
17881800 {
1789- v[i + 1 ].V -= 8 ;
1801+ const int Lv = v[i + 1 ].V - v[i].V ;
1802+ if ((Lv > 0 ) && (Lv <= (Ly + 32 )))
1803+ {
1804+ v[i + 1 ].V -= 8 ;
1805+ }
1806+ }
1807+ else
1808+ {
1809+ if (ty0 <= ty1)
1810+ {
1811+ v[i].V = ty0;
1812+ v[i + 1 ].V = ty1 + 16 ;
1813+ }
1814+ else
1815+ {
1816+ v[i].V = ty0 + 15 ;
1817+ v[i + 1 ].V = ty1;
1818+ }
17901819 }
1820+ #endif
17911821 }
17921822 else
17931823 {
1794- if (ty0 <= ty1 )
1824+ if (((v[i + 1 ]. V & 0xf ) ^ ((v[i + 1 ]. XYZ . Y - oy) & 0xf )) && ((v[i + 1 ]. V - v[i]. V ) >> 4 ) == tex_height && (Ly >> 4 ) / tex_height <= 2 )
17951825 {
1796- v[i].V = ty0 ;
1797- v[i + 1 ].V = ty1 + 16 ;
1826+ v[i].V &= ~ 0xf ;
1827+ v[i + 1 ].V -= 8 ;
17981828 }
17991829 else
18001830 {
1801- v[i].V = ty0 + 15 ;
1802- v[i + 1 ].V = ty1;
1831+ v[i].V &= ~0xf ;
1832+ v[i + 1 ].V &= ~0xf ;
1833+ v[i].V |= (v[i].XYZ .Y - oy) & 0xf ;
1834+ v[i + 1 ].V |= (v[i + 1 ].XYZ .Y - oy) & 0xf ;
18031835 }
18041836 }
1837+ #ifdef DEBUG_U
1838+ if (debug)
1839+ fprintf (stderr, " GREP_BEFORE %d => %d\n " , v[i].U , v[i + 1 ].U );
1840+ #endif
1841+ #ifdef DEBUG_V
1842+ if (debug)
1843+ fprintf (stderr, " GREP_BEFORE %d => %d\n " , v[i].V , v[i + 1 ].V );
18051844#endif
18061845
1846+
18071847#ifdef DEBUG_U
18081848 if (debug)
18091849 fprintf (stderr, " GREP_AFTER %d => %d\n\n " , v[i].U , v[i + 1 ].U );
0 commit comments