Issue displaying IDirect3DTexture8 after backporting from IDirect3DTexture9

Started by
2 comments, last by snake5 8 years, 5 months ago

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.

D3D8

[attachment=29496:d3d8.jpg]

D3D9

[attachment=29497:d3d9.jpg]

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

Seems like you don't use D3DLOCKED_RECT.Pitch!

(Pitch is measured in bytes)


pBits[y * lockrect.Pitch + x * pixelbytesize]

.:vinterberg:.

Thanks for the advised, I've now added the Pitch to the algorithm but unfortunately I'm getting the same result.

It looks more like reading from old/uninitialized GPU memory than anything else. Tiles of this size cannot be realistically achieved by bugs in the code, they would require an entirely different (tile-aware) loop. This is more likely to be coming from GPU driver errors or API misuse. For example, not filling all mipmap levels of a mipmapped texture could cause this.

This topic is closed to new replies.

Advertisement