On Sun, Apr 13, 2008 at 06:22:29PM +0200, [EMAIL PROTECTED] wrote:
> Hi,
> Are you still working on the texture functions?
> I'd need them for completing my ID3DXSprite implementation,
> so if you don't mind I could complete your started patches.
> 
> Best regards,
>     Tony

  I have a hacky implementation of D3DXLoadSurfaceFromMemory and
D3DXLoadSurfaceFromSurface, as well as a pretty good implementation of
D3DXCreateTexture and D3DXCheckTextureRequirements.

  I'll send in the patch for the last two when I have time, and have
looked it over a final time.  I pretty much abandoned the first two,
because there's got to be a whole lot of code somewhere in the tree
already.  It does work in some cases, however.  Attached in case it
might be helpful.

-- 
Philip Nilsson
struct d3dformat {
    unsigned int id;
    unsigned int amask;
    unsigned int rmask;
    unsigned int gmask;
    unsigned int bmask;
    unsigned int bytespp;
};

/* TODO: Use the one in dlls/wined3d/utils.c */
struct d3dformat surface_formats[] = {
    {D3DFMT_A8R8G8B8, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff, 4},
    {D3DFMT_X8R8G8B8, 0x00000000, 0x00ff0000, 0x0000ff00, 0x000000ff, 4},
    {D3DFMT_R5G6B5,   0x00000000, 0x0000f800, 0x000007e0, 0x0000001f, 2},
    {D3DFMT_A4R4G4B4, 0x0000f000, 0x00000f00, 0x000000f0, 0x0000000f, 2},
};

static struct d3dformat*
find_format(const unsigned int format)
{
    unsigned int i = 0;
    for (i = 0; i < sizeof(surface_formats); ++i) {
        if (surface_formats[i].id == format)
            return &surface_formats[i];
    }
    return NULL;
}

/* XXX: From dlls/wined3d/utils.c */
/* This small helper function is used to convert a bitmask into the number of masked bits */
unsigned int count_bits(unsigned int mask)
{
    unsigned int count;
    for (count = 0; mask; ++count)
    {
        mask &= mask - 1;
    }
    return count;
}

static void
do_magic_stuff(unsigned int* const dest, const unsigned int destmask, const unsigned int src, const unsigned int srcmask)
{
    if (destmask == srcmask) {
        *dest = (*dest & ~destmask) | (src & srcmask);
    } else {
        unsigned int srcoff = count_bits(srcmask);
        unsigned int destoff = count_bits(destmask);

        /* Find out the maximum values the masks can hold. */
        unsigned int srcmax = srcmask >> srcoff;
        unsigned int destmax = destmask >> destoff;

        /* Calculate a new scaled value. */
        unsigned int newvalue = (float)((float)((src & srcmask) >> srcoff) / (float)srcmax * (float)destmax);

        /* Clear the field first. */
        /* Shift it into position. */
        /* Remove any possible stray bits. */
        /* Add it to the return value. */
        *dest = (*dest & ~destmask) | ((newvalue << destoff) & destmask);
    }
}

/* Translate a single pixel from one pixel format to another.
 * Pixels are passed in as 32-bit integers, the output pixel as a pointer. */
static void
translate_pixel(unsigned int* const dest, const struct d3dformat* const destformat,
                const unsigned int src, const struct d3dformat* const srcformat)
{
    /* Find the formats in the format table. */
    do_magic_stuff(dest, destformat->rmask, src, srcformat->rmask);
    do_magic_stuff(dest, destformat->gmask, src, srcformat->gmask);
    do_magic_stuff(dest, destformat->bmask, src, srcformat->bmask);
    do_magic_stuff(dest, destformat->amask, src, srcformat->amask);
}

static HRESULT
convert_memory(
    void* const dest,           /* Destination buffer. */
    const D3DFORMAT destfmt, /* Destination buffer format. */
    const RECT* const destrect, /* Destination buffer rectangle. */
    unsigned int destsurfacewidth,
    unsigned int destsurfaceheight,
    const void* const src,      /* Source buffer. */
    const D3DFORMAT srcfmt,  /* Source buffer format. */
    const RECT* const srcrect,  /* Source buffer size. */
    DWORD filter)
{
    struct d3dformat* srcformat = find_format(srcfmt);
    struct d3dformat* destformat = find_format(destfmt);

    if (!srcformat || !destformat) {
        ERR("Unsupported format (%d or %d).\n", srcfmt, destfmt);
        return 0;
    }

    if (destrect == NULL ||
        (srcrect->left == destrect->left &&
         srcrect->right == destrect->right &&
         srcrect->top == destrect->top &&
         srcrect->bottom == destrect->bottom)) {
        unsigned int x, y;
        /* I assume the rects are the same size here. */
        /* I further assume that srcrect->left and srcrect->top are 0. */
        /* Don't access destrect as it might be NULL. */
        for (y = 0; y < srcrect->bottom; ++y) {
            for (x = 0; x < srcrect->right; ++x) {
                unsigned int srcpixel = 0;
                unsigned int destpixel = 0;
                unsigned int offset = y * srcrect->right + x; /* srcw == destw */

                memcpy(&srcpixel, (char*)src + offset * srcformat->bytespp, srcformat->bytespp);

                translate_pixel(&destpixel, destformat, srcpixel, srcformat);

                /* I hope endianness doesn't mess this up too bad. */
                memcpy((char*)dest + offset * destformat->bytespp, &destpixel, destformat->bytespp);
                if (srcpixel != destpixel)
                    TRACE("Pixel conversion problem: %08x %08x\n", srcpixel, destpixel);
            }
        }
    } else {
        unsigned int srcwidth = srcrect->right - srcrect->left;
        unsigned int srcheight = srcrect->bottom - srcrect->top;

        unsigned int destwidth = destrect->right - destrect->left;
        unsigned int destheight = destrect->bottom - destrect->top;

        float xscale = (float)srcwidth / (float)destwidth;
        float yscale = (float)srcheight / (float)destheight;
        /* Scaling is necessary. */
        unsigned int x, y;

        for (y = 0; y < destheight; ++y) {
            for (x = 0; x < destwidth; ++x) {
                unsigned int srcpixel = 0;
                unsigned int destpixel = 0;

                unsigned int srcx = (float)x * (float)xscale;
                unsigned int srcy = (float)y * (float)yscale;
                unsigned int srcoffset = srcy * srcwidth + srcx;
                unsigned int destoffset = (y + destrect->top) * destsurfacewidth + x + destrect->left;

                memcpy(&srcpixel, (char*)src + srcoffset * srcformat->bytespp, srcformat->bytespp);

                translate_pixel(&destpixel, destformat, srcpixel, srcformat);

                memcpy((char*)dest + destoffset * destformat->bytespp, &destpixel, destformat->bytespp);
                if (srcpixel != destpixel) {
                    TRACE("Pixel conversion problem: %08x -> %08x for %d -> %d\n", srcpixel, destpixel, srcfmt, destfmt);
                }
            }
        }
    }

    return D3D_OK;
}

/* TODO:
 * Copy palette.
 * Handle formats.
 * Handle filters.
 * Colorkey replacement.
 * Confirm that surfaces can not be upscaled.
 * See if OpenGL can be used.
 */
HRESULT WINAPI D3DXLoadSurfaceFromMemory(
    LPDIRECT3DSURFACE9 surface, CONST PALETTEENTRY *destpalette,
    CONST RECT *destrect, LPCVOID memory, D3DFORMAT memoryformat,
    UINT memorypitch, CONST PALETTEENTRY *memorypalette,
    CONST RECT *memoryrect, DWORD filter, D3DCOLOR colorkey)
{
    D3DLOCKED_RECT lockrect;
    D3DSURFACE_DESC surfdesc;
    TRACE("(%p, %p, %p, %p, %d, %d, %p, %p, %d, %d)\n",
        surface, destpalette, destrect, memory, memoryformat,
        memorypitch, memorypalette, memoryrect, filter, colorkey);

    if (destpalette || memorypalette) {
        TRACE("destpal: %p, srcpal: %p\n", destpalette, memorypalette);
    }

    IDirect3DSurface9_GetDesc(surface, &surfdesc);

    TRACE("(%d..%d, %d..%d) to (%d..%d, %d..%d) of (%d, %d)\n",
        memoryrect->left, memoryrect->right, memoryrect->top, memoryrect->bottom,
        destrect->left, destrect->right, destrect->top, destrect->bottom,
        surfdesc.Width, surfdesc.Height);
    IDirect3DSurface9_LockRect(surface, &lockrect, NULL, 0);
    convert_memory(lockrect.pBits, surfdesc.Format, destrect, surfdesc.Width, surfdesc.Height, memory, memoryformat, memoryrect, filter);
    IDirect3DSurface9_UnlockRect(surface);

    return D3D_OK;
}

HRESULT WINAPI D3DXLoadSurfaceFromSurface(
    LPDIRECT3DSURFACE9 destsurface, CONST PALETTEENTRY* destpalette, CONST RECT* destrect,
    LPDIRECT3DSURFACE9 srcsurface,  CONST PALETTEENTRY* srcpalette,  CONST RECT* srcrect,
    DWORD filter, D3DCOLOR colorkey)
{
    D3DSURFACE_DESC srcdesc;
    D3DSURFACE_DESC destdesc;
    D3DLOCKED_RECT srclock;
    D3DLOCKED_RECT destlock;

    TRACE("(%p, %p, %p, %p, %p, %p, %d, %d)\n", destsurface, destpalette, destrect, srcsurface, srcpalette, srcrect, filter, colorkey);

    IDirect3DSurface9_GetDesc(srcsurface, &srcdesc);
    IDirect3DSurface9_GetDesc(destsurface, &destdesc);

    IDirect3DSurface9_LockRect(destsurface, &destlock, NULL, 0);
    IDirect3DSurface9_LockRect(srcsurface, &srclock, NULL, 0);

    convert_memory(destlock.pBits, destdesc.Format, destrect, destdesc.Width, destdesc.Height, srclock.pBits, srcdesc.Format, srcrect, filter);

    IDirect3DSurface9_UnlockRect(srcsurface);
    IDirect3DSurface9_UnlockRect(destsurface);

    return D3D_OK;
}


Reply via email to