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;
}


Reply via email to