On Mon, Jul 14, 2008 at 02:51:42AM +0400, Victor Eremin wrote:
>
> Converter function supports conversion between most of
> "unsigned color" argb/xrgb surface formats (like D3DFMT_A8R8G8B8,
> D3DFMT_A8R3G3B2, and so on), and between "luminosity" color formats
> (D3DFMT_L8, etc), excluding D3DFMT_A16R16G16B16, D3DFMT_A8P8,
> D3DFMT_P8 and D3DFMT_A1.
>
> Conversion from rgba to luminosity (and vice versa) is not currently
> implemented.
>
> The patch removes "Cannot find coverter" FIXMEs from "Ancient Evil" and
> "Stranded 2" games.
>
> Patch also fixes water glitches in "Stranded 2" game.
I've attached my pixel conversion function which uses the table in
utils.c. Hope you find it useful although I haven't really polished it.
/* Counts the number of leading zeros in a mask, returns 0 if the mask is zero. */
static unsigned int count_zeros(unsigned int mask)
{
unsigned int count;
if (!mask)
return 0;
for (count = 0; !(mask & 1); ++count)
{
mask >>= 1;
}
return count;
}
/* Scales a value masked by one mask to another. */
static DWORD convert_channel(DWORD src, DWORD srcmask, DWORD dstmask)
{
src = src & srcmask;
src >>= count_zeros(srcmask);
src *= (dstmask >> count_zeros(dstmask)) / (srcmask >> count_zeros(srcmask));
src <<= count_zeros(dstmask);
return src;
}
static DWORD get_mask(DWORD value, DWORD mask)
{
return (value & mask) >> count_zeros(mask);
}
static DWORD put_mask(DWORD value, DWORD mask)
{
return (value << count_zeros(mask)) & mask;
}
/* MSDN states that the default value is 1 for missing channels; and that
* D3DFMT_A8 is the exception where the missing channels are 0.
*
* I assume 1 means 1 in every bit. */
static DWORD convert_pixel(DWORD srcword, const StaticPixelFormatDesc* srcentry, const StaticPixelFormatDesc* dstentry)
{
DWORD pixel = 0;
if (srcentry->alphaMask && dstentry->alphaMask)
pixel |= convert_channel(srcword, srcentry->alphaMask, dstentry->alphaMask);
else
pixel |= dstentry->alphaMask;
if (srcentry->redMask && dstentry->redMask)
pixel |= convert_channel(srcword, srcentry->redMask, dstentry->redMask);
else
pixel |= dstentry->redMask;
if (srcentry->greenMask && dstentry->greenMask)
pixel |= convert_channel(srcword, srcentry->greenMask, dstentry->greenMask);
else
pixel |= dstentry->greenMask;
if (srcentry->blueMask && dstentry->blueMask)
pixel |= convert_channel(srcword, srcentry->blueMask, dstentry->blueMask);
else
pixel |= dstentry->blueMask;
return pixel;
}
DWORD convert_pixelformat(DWORD pixel, WINED3DFORMAT srcformat, WINED3DFORMAT dstformat)
{
const StaticPixelFormatDesc* srcentry = getFormatDescEntry(srcformat, NULL, NULL);
const StaticPixelFormatDesc* dstentry = getFormatDescEntry(dstformat, NULL, NULL);
if (!srcentry) {
FIXME("Unsupported pixelformat.\n");
return 0;
}
if (!dstentry) {
FIXME("Unsupported pixelformat.\n");
return 0;
}
return convert_pixel(pixel, srcentry, dstentry);
}
static UINT get_pixel(const LPCVOID data, UINT bpp, const RECT* const rect, UINT pitch, UINT x, UINT y)
{
DWORD pixel = 0;
memcpy(&pixel, (char*)data + (rect->top + y) * pitch + (rect->left + x) * bpp, bpp);
return pixel;
}