mirror of https://github.com/odrling/Aegisub
Attempt to add some documentation for what Rasterizer::Draw does.
Originally committed to SVN as r1541.
This commit is contained in:
parent
8909ea48e2
commit
6465b086e7
|
@ -819,10 +819,19 @@ static __forceinline void pixmix_sse2(DWORD* dst, DWORD color, DWORD alpha)
|
||||||
*dst = (DWORD)_mm_cvtsi128_si32(r);
|
*dst = (DWORD)_mm_cvtsi128_si32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For CPUID usage in Rasterizer::Draw
|
||||||
#include "../dsutil/vd.h"
|
#include "../dsutil/vd.h"
|
||||||
|
|
||||||
static const __int64 _00ff00ff00ff00ff = 0x00ff00ff00ff00ffi64;
|
static const __int64 _00ff00ff00ff00ff = 0x00ff00ff00ff00ffi64;
|
||||||
|
|
||||||
|
// Render a subpicture onto a surface.
|
||||||
|
// spd is the surface to render on.
|
||||||
|
// clipRect is a rectangular clip region to render inside.
|
||||||
|
// pAlphaMask is an alpha clipping mask.
|
||||||
|
// xsub and ysub ???
|
||||||
|
// switchpts seems to be an array of interlaced colour switching coordinates/colours to switch to.
|
||||||
|
// fBody tells whether to render the body of the subs.
|
||||||
|
// fBorder tells whether to render the border of the subs.
|
||||||
CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int xsub, int ysub, const long* switchpts, bool fBody, bool fBorder)
|
CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int xsub, int ysub, const long* switchpts, bool fBody, bool fBorder)
|
||||||
{
|
{
|
||||||
CRect bbox(0, 0, 0, 0);
|
CRect bbox(0, 0, 0, 0);
|
||||||
|
@ -831,20 +840,26 @@ CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int x
|
||||||
|
|
||||||
// clip
|
// clip
|
||||||
|
|
||||||
|
// Limit drawn area to intersection of rendering surface and rectangular clip area
|
||||||
CRect r(0, 0, spd.w, spd.h);
|
CRect r(0, 0, spd.w, spd.h);
|
||||||
r &= clipRect;
|
r &= clipRect;
|
||||||
|
|
||||||
|
// Remember that all subtitle coordinates are specified in 1/8 pixels
|
||||||
|
// (x+4)>>3 rounds to nearest whole pixel.
|
||||||
|
// ??? What is xsub, ysub, mOffsetX and mOffsetY ?
|
||||||
int x = (xsub + mOffsetX + 4)>>3;
|
int x = (xsub + mOffsetX + 4)>>3;
|
||||||
int y = (ysub + mOffsetY + 4)>>3;
|
int y = (ysub + mOffsetY + 4)>>3;
|
||||||
int w = mOverlayWidth;
|
int w = mOverlayWidth;
|
||||||
int h = mOverlayHeight;
|
int h = mOverlayHeight;
|
||||||
int xo = 0, yo = 0;
|
int xo = 0, yo = 0;
|
||||||
|
|
||||||
|
// Again, limiting?
|
||||||
if(x < r.left) {xo = r.left-x; w -= r.left-x; x = r.left;}
|
if(x < r.left) {xo = r.left-x; w -= r.left-x; x = r.left;}
|
||||||
if(y < r.top) {yo = r.top-y; h -= r.top-y; y = r.top;}
|
if(y < r.top) {yo = r.top-y; h -= r.top-y; y = r.top;}
|
||||||
if(x+w > r.right) w = r.right-x;
|
if(x+w > r.right) w = r.right-x;
|
||||||
if(y+h > r.bottom) h = r.bottom-y;
|
if(y+h > r.bottom) h = r.bottom-y;
|
||||||
|
|
||||||
|
// Check if there's actually anything to render
|
||||||
if(w <= 0 || h <= 0) return(bbox);
|
if(w <= 0 || h <= 0) return(bbox);
|
||||||
|
|
||||||
bbox.SetRect(x, y, x+w, y+h);
|
bbox.SetRect(x, y, x+w, y+h);
|
||||||
|
@ -852,25 +867,35 @@ CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int x
|
||||||
|
|
||||||
// draw
|
// draw
|
||||||
|
|
||||||
|
// The alpha bitmap of the subtitles?
|
||||||
const byte* src = mpOverlayBuffer + 2*(mOverlayWidth * yo + xo);
|
const byte* src = mpOverlayBuffer + 2*(mOverlayWidth * yo + xo);
|
||||||
const byte* s = fBorder ? (src+1) : src;
|
const byte* s = fBorder ? (src+1) : src;
|
||||||
|
// The complex "vector clip mask" I think.
|
||||||
const byte* am = pAlphaMask + spd.w * y + x;
|
const byte* am = pAlphaMask + spd.w * y + x;
|
||||||
|
// How would this differ from src?
|
||||||
unsigned long* dst = (unsigned long *)((char *)spd.bits + spd.pitch * y) + x;
|
unsigned long* dst = (unsigned long *)((char *)spd.bits + spd.pitch * y) + x;
|
||||||
|
|
||||||
|
// ??? What is switchpts ?
|
||||||
unsigned long color = switchpts[0];
|
unsigned long color = switchpts[0];
|
||||||
|
|
||||||
|
// CPUID from VDub
|
||||||
bool fSSE2 = !!(g_cpuid.m_flags & CCpuID::sse2);
|
bool fSSE2 = !!(g_cpuid.m_flags & CCpuID::sse2);
|
||||||
|
|
||||||
|
// Every remaining line in the bitmap to be rendered...
|
||||||
while(h--)
|
while(h--)
|
||||||
{
|
{
|
||||||
|
// Basic case of no complex clipping mask
|
||||||
if(!pAlphaMask)
|
if(!pAlphaMask)
|
||||||
{
|
{
|
||||||
|
// Again, what is switchpts?
|
||||||
if(switchpts[1] == 0xffffffff)
|
if(switchpts[1] == 0xffffffff)
|
||||||
{
|
{
|
||||||
|
// Are we rendering the fill or a border/shadow? I think...
|
||||||
if(fBody)
|
if(fBody)
|
||||||
{
|
{
|
||||||
const byte* s = fBorder?(src+1):src;
|
// Old code
|
||||||
/*
|
/*
|
||||||
|
const byte* s = fBorder?(src+1):src;
|
||||||
for(int wt=0; wt<w; ++wt)
|
for(int wt=0; wt<w; ++wt)
|
||||||
{
|
{
|
||||||
pixmix(s[wt*2]);
|
pixmix(s[wt*2]);
|
||||||
|
@ -917,13 +942,19 @@ CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int x
|
||||||
add edi, 4
|
add edi, 4
|
||||||
loop pixmixloop
|
loop pixmixloop
|
||||||
}*/
|
}*/
|
||||||
|
// Run over every pixel, overlaying the subtitles with the fill colour
|
||||||
if(fSSE2)
|
if(fSSE2)
|
||||||
for(int wt=0; wt<w; ++wt)
|
for(int wt=0; wt<w; ++wt)
|
||||||
|
// Why s[wt*2] and not s[wt] ?
|
||||||
|
// The <<6 is due to pixmix expecting the alpha parameter to be
|
||||||
|
// the multiplication of two 6-bit unsigned numbers but we
|
||||||
|
// only have one here. (No alpha mask.)
|
||||||
pixmix_sse2(&dst[wt], color, s[wt*2]<<6);
|
pixmix_sse2(&dst[wt], color, s[wt*2]<<6);
|
||||||
else
|
else
|
||||||
for(int wt=0; wt<w; ++wt)
|
for(int wt=0; wt<w; ++wt)
|
||||||
pixmix(&dst[wt], color, s[wt*2]<<6);
|
pixmix(&dst[wt], color, s[wt*2]<<6);
|
||||||
}
|
}
|
||||||
|
// Not body, ie. something else (border, shadow, I guess)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* for(int wt=0; wt<w; ++wt)
|
/* for(int wt=0; wt<w; ++wt)
|
||||||
|
@ -975,6 +1006,14 @@ 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)
|
||||||
|
// It would seems src (not s here?) contains two different
|
||||||
|
// bitmaps interlaced per pixel.
|
||||||
|
// So here's using the difference between those two.
|
||||||
|
// What if the difference underflows??
|
||||||
|
// I guess src[wt*2+1] is the widened region for border
|
||||||
|
// created by CreateWidenedRegion, and thus contains
|
||||||
|
// both the fill and the border, so subtracting the fill
|
||||||
|
// from that is always safe.
|
||||||
pixmix_sse2(&dst[wt], color, (src[wt*2+1] - src[wt*2])<<6);
|
pixmix_sse2(&dst[wt], color, (src[wt*2+1] - src[wt*2])<<6);
|
||||||
else
|
else
|
||||||
for(int wt=0; wt<w; ++wt)
|
for(int wt=0; wt<w; ++wt)
|
||||||
|
@ -982,8 +1021,10 @@ CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int x
|
||||||
}
|
}
|
||||||
//__asm emms;
|
//__asm emms;
|
||||||
}
|
}
|
||||||
|
// not (switchpts[1] == 0xffffffff)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// switchpts plays an important rule here
|
||||||
const long *sw = switchpts;
|
const long *sw = switchpts;
|
||||||
|
|
||||||
if(fBody)
|
if(fBody)
|
||||||
|
@ -1003,6 +1044,9 @@ 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)
|
||||||
{
|
{
|
||||||
|
// xo is the offset (usually negative) we have moved into the image
|
||||||
|
// So if we have passed the switchpoint (?) switch to another colour
|
||||||
|
// (So switchpts stores both colours *and* coordinates?)
|
||||||
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, s[wt*2]<<6);
|
pixmix_sse2(&dst[wt], color, s[wt*2]<<6);
|
||||||
}
|
}
|
||||||
|
@ -1013,6 +1057,7 @@ CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int x
|
||||||
pixmix(&dst[wt], color, s[wt*2]<<6);
|
pixmix(&dst[wt], color, s[wt*2]<<6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Not body
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*for(int wt=0; wt<w; ++wt)
|
/*for(int wt=0; wt<w; ++wt)
|
||||||
|
@ -1040,6 +1085,7 @@ CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Here we *do* have an alpha mask
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(switchpts[1] == 0xffffffff)
|
if(switchpts[1] == 0xffffffff)
|
||||||
|
@ -1054,6 +1100,11 @@ 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)
|
||||||
|
// Both s and am contain 6-bit bitmaps of two different
|
||||||
|
// alpha masks; s is the subtitle shape and am is the
|
||||||
|
// clipping mask.
|
||||||
|
// Multiplying them together yields a 12-bit number.
|
||||||
|
// I think some imprecision is introduced here??
|
||||||
pixmix_sse2(&dst[wt], color, s[wt*2] * am[wt]);
|
pixmix_sse2(&dst[wt], color, s[wt*2] * am[wt]);
|
||||||
else
|
else
|
||||||
for(int wt=0; wt<w; ++wt)
|
for(int wt=0; wt<w; ++wt)
|
||||||
|
@ -1144,6 +1195,7 @@ CRect Rasterizer::Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step to next scanline
|
||||||
src += 2*mOverlayWidth;
|
src += 2*mOverlayWidth;
|
||||||
s += 2*mOverlayWidth;
|
s += 2*mOverlayWidth;
|
||||||
am += spd.w;
|
am += spd.w;
|
||||||
|
|
Loading…
Reference in New Issue