Search code examples
cgame-enginedirect3dxboxquake

Issue displaying IDirect3DTexture8 after backporting from IDirect3DTexture9


I'm trying to backport someones Direct3d9 port of Quake 1 by ID software to Direct3d8 so I can port it to the original Xbox (only uses the D3D8 API).

After making the changes to use Direct3d8 it displays some mashed up pixels on the screen that appear to be in little squares :/ (see pictures).

Does anyone know whats gone wrong here? It works flawlessly with D3D9, is there some extra arguments required that I'm missing require for D3D8, rect pitch maybe?

The data been passed in is a Quake 1 .lmp 2d image file. "It consists of two integers (width and height) followed by a string of width x height bytes, each of which is an index into the Quake palette"

Its been passed to the D3D_ResampleTexture() function.

Any help would be much appreciated.

Image output using D3D8

Image output using D3D9

The code:

void D3D_ResampleTexture (image_t *src, image_t *dst)
{
    int y, x , srcpos, srcbase,  dstpos;

    unsigned int *dstdata, *srcdata;

    // take an unsigned pointer to the dest data that we'll actually fill
    dstdata = (unsigned int *) dst->data;

    // easier access to src data for 32 bit resampling
    srcdata = (unsigned int *) src->data;

    // nearest neighbour for now
    for (y = 0, dstpos = 0; y < dst->height; y++)
    {
        srcbase = (y * src->height / dst->height) * src->width;

        for (x = 0; x < dst->width; x++, dstpos++)
        {
            srcpos = srcbase + (x * src->width / dst->width);

            if (src->flags & IMAGE_32BIT)
                dstdata[dstpos] = srcdata[srcpos];
            else if (src->palette)
                dstdata[dstpos] = src->palette[src->data[srcpos]];
            else Sys_Error ("D3D_ResampleTexture: !(flags & IMAGE_32BIT) without palette set");
        }
    }
}


void D3D_LoadTextureStage3 (LPDIRECT3DTEXTURE8/*9*/ *tex, image_t *image)
{
    int i;
    image_t scaled;

    D3DLOCKED_RECT LockRect;

    memset (&LockRect, 0, sizeof(D3DLOCKED_RECT));

    // check scaling here first
    for (scaled.width = 1; scaled.width < image->width; scaled.width *= 2);
    for (scaled.height = 1; scaled.height < image->height; scaled.height *= 2);

    // clamp to max texture size
    if (scaled.width > /*d3d_DeviceCaps.MaxTextureWidth*/640) scaled.width = /*d3d_DeviceCaps.MaxTextureWidth*/640;
    if (scaled.height > /*d3d_DeviceCaps.MaxTextureHeight*/480) scaled.height = /*d3d_DeviceCaps.MaxTextureHeight*/480;


    IDirect3DDevice8/*9*/_CreateTexture(d3d_Device, scaled.width, scaled.height,
    (image->flags & IMAGE_MIPMAP) ? 0 : 1,
    /*(image->flags & IMAGE_MIPMAP) ? D3DUSAGE_AUTOGENMIPMAP :*/ 0,
    (image->flags & IMAGE_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8,
    D3DPOOL_MANAGED,
    tex
    );

    // lock the texture rectangle
    //(*tex)->LockRect (0, &LockRect, NULL, 0);
    IDirect3DTexture8/*9*/_LockRect(*tex, 0, &LockRect, NULL, 0);

    // fill it in - how we do it depends on the scaling
    if (scaled.width == image->width && scaled.height == image->height)
    {
        // no scaling
        for (i = 0; i < (scaled.width * scaled.height); i++)
        {
            unsigned int p;

            // retrieve the correct texel - this will either be direct or a palette lookup
            if (image->flags & IMAGE_32BIT)
                p = ((unsigned *) image->data)[i];
            else if (image->palette)
                p = image->palette[image->data[i]];
            else Sys_Error ("D3D_LoadTexture: !(flags & IMAGE_32BIT) without palette set");
            // store it back
            ((unsigned *) LockRect.pBits)[i] = p;
        }
    }
    else
    {
        // save out lockbits in scaled data pointer
        scaled.data = (byte *) LockRect.pBits;

        // resample data into the texture
        D3D_ResampleTexture (image, &scaled);
    }

    // unlock it
    //(*tex)->UnlockRect (0);
    IDirect3DTexture8/*9*/_UnlockRect(*tex, 0);

    // tell Direct 3D that we're going to be needing to use this managed resource shortly
    //FIXME
    //(*tex)->PreLoad ();
}


LPDIRECT3DTEXTURE8/*9*/ D3D_LoadTextureStage2 (image_t *image)
{
    d3d_texture_t *tex;

    // look for a match

    // create a new one
    tex = (d3d_texture_t *) malloc (sizeof (d3d_texture_t));

    // link it in
    tex->next = d3d_Textures;
    d3d_Textures = tex;

    // fill in the struct
    tex->LastUsage = 0;
    tex->d3d_Texture = NULL;

    // copy the image
    memcpy (&tex->TexImage, image, sizeof (image_t));

    // upload through direct 3d
    D3D_LoadTextureStage3 (&tex->d3d_Texture, image);

    // return the texture we got
    return tex->d3d_Texture;
}


LPDIRECT3DTEXTURE8/*9*/ D3D_LoadTexture (char *identifier, int width, int height, byte *data, /*bool*/qboolean mipmap, /*bool*/qboolean alpha)
{
    image_t image;

    image.data = data;
    image.flags = 0;
    image.height = height;
    image.width = width;
    image.palette = d_8to24table;

    strcpy (image.identifier, identifier);

    if (mipmap) image.flags |= IMAGE_MIPMAP;
    if (alpha) image.flags |= IMAGE_ALPHA;

    return D3D_LoadTextureStage2 (&image);
}

Solution

  • For anyone else that comes across this issue, it was due to the way the image was been loaded into the Xbox's memory, it needed to be swizzled.