Fix rendering bug exposed with \be1, \bord smaller than 1.5 and non-zero fill alpha, causing "stray dots" to appear.

The problem was caused by an integer underflow, the fix involves spending a few more instructions per pixel to avoid that.

Originally committed to SVN as r2275.
This commit is contained in:
Niels Martin Hansen 2008-07-22 16:21:26 +00:00
parent 741476c96d
commit e504c61065
1 changed files with 16 additions and 9 deletions

View File

@ -528,7 +528,7 @@ bool Rasterizer::ScanConvert()
using namespace std; using namespace std;
// Overlap the subtitle with itself displaces (dx,dy) and (-dx,dy) pixels, conceptually. // Overlap the subtitle with itself displaced (dx,dy) and (-dx,dy) pixels, conceptually.
// Actually, mark in the widened region buffer such that the normal region // Actually, mark in the widened region buffer such that the normal region
// translated dy in the Y axis has its spans extended by dx pixels in both directions. // translated dy in the Y axis has its spans extended by dx pixels in both directions.
// If any spans overlap after this extension, they are merged. // If any spans overlap after this extension, they are merged.
@ -846,6 +846,13 @@ static __forceinline void pixmix2_sse2(DWORD* dst, DWORD color, DWORD shapealpha
*dst = (DWORD)_mm_cvtsi128_si32(r); *dst = (DWORD)_mm_cvtsi128_si32(r);
} }
// Calculate a-b but without risk of underflow
template<class T>
static __forceinline T safe_subtract(T a, T b)
{
return (b > a) ? 0 : a - b;
}
// For CPUID usage in Rasterizer::Draw // For CPUID usage in Rasterizer::Draw
#include "../dsutil/vd.h" #include "../dsutil/vd.h"
@ -950,10 +957,10 @@ CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int x
// created by CreateWidenedRegion, and thus contains // created by CreateWidenedRegion, and thus contains
// both the fill and the border, so subtracting the fill // both the fill and the border, so subtracting the fill
// from that is always safe. // from that is always safe.
pixmix_sse2(&dst[wt], color, src[wt*2+1] - src[wt*2]); pixmix_sse2(&dst[wt], color, safe_subtract(src[wt*2+1], src[wt*2]));
else else
for(int wt=0; wt<w; ++wt) for(int wt=0; wt<w; ++wt)
pixmix(&dst[wt], color, src[wt*2+1] - src[wt*2]); pixmix(&dst[wt], color, safe_subtract(src[wt*2+1], src[wt*2]));
} }
} }
// not (switchpts[1] == 0xffffffff) // not (switchpts[1] == 0xffffffff)
@ -987,13 +994,13 @@ CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int x
for(int wt=0; wt<w; ++wt) for(int wt=0; wt<w; ++wt)
{ {
if(wt+xo >= sw[1]) {while(wt+xo >= sw[1]) sw += 2; color = sw[-2];} if(wt+xo >= sw[1]) {while(wt+xo >= sw[1]) sw += 2; color = sw[-2];}
pixmix_sse2(&dst[wt], color, src[wt*2+1] - src[wt*2]); pixmix_sse2(&dst[wt], color, safe_subtract(src[wt*2+1], src[wt*2]));
} }
else else
for(int wt=0; wt<w; ++wt) for(int wt=0; wt<w; ++wt)
{ {
if(wt+xo >= sw[1]) {while(wt+xo >= sw[1]) sw += 2; color = sw[-2];} if(wt+xo >= sw[1]) {while(wt+xo >= sw[1]) sw += 2; color = sw[-2];}
pixmix(&dst[wt], color, src[wt*2+1] - src[wt*2]); pixmix(&dst[wt], color, safe_subtract(src[wt*2+1], src[wt*2]));
} }
} }
} }
@ -1021,10 +1028,10 @@ CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int x
{ {
if(fSSE2) if(fSSE2)
for(int wt=0; wt<w; ++wt) for(int wt=0; wt<w; ++wt)
pixmix2_sse2(&dst[wt], color, src[wt*2+1] - src[wt*2], am[wt]); pixmix2_sse2(&dst[wt], color, safe_subtract(src[wt*2+1], src[wt*2]), am[wt]);
else else
for(int wt=0; wt<w; ++wt) for(int wt=0; wt<w; ++wt)
pixmix2(&dst[wt], color, src[wt*2+1] - src[wt*2], am[wt]); pixmix2(&dst[wt], color, safe_subtract(src[wt*2+1], src[wt*2]), am[wt]);
} }
} }
else else
@ -1061,7 +1068,7 @@ CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int x
while(wt+xo >= sw[1]) while(wt+xo >= sw[1])
sw += 2; color = sw[-2]; sw += 2; color = sw[-2];
} }
pixmix2_sse2(&dst[wt], color, src[wt*2+1] - src[wt*2], am[wt]); pixmix2_sse2(&dst[wt], color, safe_subtract(src[wt*2+1], src[wt*2]), am[wt]);
} }
else else
for(int wt=0; wt<w; ++wt) for(int wt=0; wt<w; ++wt)
@ -1070,7 +1077,7 @@ CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int x
while(wt+xo >= sw[1]) while(wt+xo >= sw[1])
sw += 2; color = sw[-2]; sw += 2; color = sw[-2];
} }
pixmix2(&dst[wt], color, src[wt*2+1] - src[wt*2], am[wt]); pixmix2(&dst[wt], color, safe_subtract(src[wt*2+1], src[wt*2]), am[wt]);
} }
} }
} }