Commit bffbf346 authored by Matteo Bruni's avatar Matteo Bruni Committed by Alexandre Julliard

d3dx9: Implement D3DXFillTexture function.

parent dbb2d287
......@@ -124,7 +124,7 @@
@ stub D3DXFileCreate
@ stub D3DXFillCubeTexture
@ stub D3DXFillCubeTextureTX
@ stub D3DXFillTexture
@ stdcall D3DXFillTexture(ptr ptr ptr)
@ stub D3DXFillTextureTX
@ stub D3DXFillVolumeTexture
@ stub D3DXFillVolumeTextureTX
......
......@@ -656,6 +656,126 @@ static void test_D3DXFilterTexture(IDirect3DDevice9 *device)
IDirect3DCubeTexture9_Release(cubetex);
}
static BOOL color_match(const DWORD *value, const DWORD *expected)
{
int i;
for (i = 0; i < 4; i++)
{
DWORD diff = value[i] > expected[i] ? value[i] - expected[i] : expected[i] - value[i];
if (diff > 1) return FALSE;
}
return TRUE;
}
static void WINAPI fillfunc(D3DXVECTOR4 *value, const D3DXVECTOR2 *texcoord,
const D3DXVECTOR2 *texelsize, void *data)
{
value->x = texcoord->x;
value->y = texcoord->y;
value->z = texelsize->x;
value->w = 1.0f;
}
static void test_D3DXFillTexture(IDirect3DDevice9 *device)
{
IDirect3DTexture9 *tex;
HRESULT hr;
D3DLOCKED_RECT lock_rect;
DWORD x, y, m;
DWORD v[4], e[4];
DWORD value, expected, size, pitch;
size = 4;
hr = IDirect3DDevice9_CreateTexture(device, size, size, 0, 0, D3DFMT_A8R8G8B8,
D3DPOOL_MANAGED, &tex, NULL);
if (SUCCEEDED(hr))
{
hr = D3DXFillTexture(tex, fillfunc, NULL);
ok(hr == D3D_OK, "D3DXFillTexture returned %#x, expected %#x\n", hr, D3D_OK);
for (m = 0; m < 3; m++)
{
hr = IDirect3DTexture9_LockRect(tex, m, &lock_rect, NULL, D3DLOCK_READONLY);
ok(hr == D3D_OK, "Couldn't lock the texture, error %#x\n", hr);
if (SUCCEEDED(hr))
{
pitch = lock_rect.Pitch / sizeof(DWORD);
for (y = 0; y < size; y++)
{
for (x = 0; x < size; x++)
{
value = ((DWORD *)lock_rect.pBits)[y * pitch + x];
v[0] = (value >> 24) & 0xff;
v[1] = (value >> 16) & 0xff;
v[2] = (value >> 8) & 0xff;
v[3] = value & 0xff;
e[0] = 0xff;
e[1] = (x + 0.5f) / size * 255.0f + 0.5f;
e[2] = (y + 0.5f) / size * 255.0f + 0.5f;
e[3] = 255.0f / size + 0.5f;
expected = e[0] << 24 | e[1] << 16 | e[2] << 8 | e[3];
ok(color_match(v, e),
"Texel at (%u, %u) doesn't match: %#x, expected %#x\n",
x, y, value, expected);
}
}
IDirect3DTexture9_UnlockRect(tex, m);
}
size >>= 1;
}
}
else
skip("Failed to create texture\n");
IDirect3DTexture9_Release(tex);
hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_A1R5G5B5,
D3DPOOL_MANAGED, &tex, NULL);
if (SUCCEEDED(hr))
{
hr = D3DXFillTexture(tex, fillfunc, NULL);
ok(hr == D3D_OK, "D3DXFillTexture returned %#x, expected %#x\n", hr, D3D_OK);
hr = IDirect3DTexture9_LockRect(tex, 0, &lock_rect, NULL, D3DLOCK_READONLY);
ok(hr == D3D_OK, "Couldn't lock the texture, error %#x\n", hr);
if (SUCCEEDED(hr))
{
pitch = lock_rect.Pitch / sizeof(WORD);
for (y = 0; y < 4; y++)
{
for (x = 0; x < 4; x++)
{
value = ((WORD *)lock_rect.pBits)[y * pitch + x];
v[0] = value >> 15;
v[1] = value >> 10 & 0x1f;
v[2] = value >> 5 & 0x1f;
v[3] = value & 0x1f;
e[0] = 1;
e[1] = (x + 0.5f) / 4.0f * 31.0f + 0.5f;
e[2] = (y + 0.5f) / 4.0f * 31.0f + 0.5f;
e[3] = 8;
expected = e[0] << 15 | e[1] << 10 | e[2] << 5 | e[3];
ok(color_match(v, e),
"Texel at (%u, %u) doesn't match: %#x, expected %#x\n",
x, y, value, expected);
}
}
IDirect3DTexture9_UnlockRect(tex, 0);
}
}
else
skip("Failed to create texture\n");
IDirect3DTexture9_Release(tex);
}
START_TEST(texture)
{
HWND wnd;
......@@ -692,6 +812,7 @@ START_TEST(texture)
test_D3DXCheckVolumeTextureRequirements(device);
test_D3DXCreateTexture(device);
test_D3DXFilterTexture(device);
test_D3DXFillTexture(device);
IDirect3DDevice9_Release(device);
IDirect3D9_Release(d3d);
......
......@@ -936,3 +936,95 @@ HRESULT WINAPI D3DXCreateVolumeTexture(LPDIRECT3DDEVICE9 device,
return IDirect3DDevice9_CreateVolumeTexture(device, width, height, depth, miplevels,
usage, format, pool, texture, NULL);
}
HRESULT WINAPI D3DXFillTexture(LPDIRECT3DTEXTURE9 texture,
LPD3DXFILL2D function,
LPVOID funcdata)
{
DWORD miplevels;
DWORD m, i, x, y, c, v;
D3DSURFACE_DESC desc;
D3DLOCKED_RECT lock_rect;
D3DXVECTOR4 value;
D3DXVECTOR2 coord, size;
const PixelFormatDesc *format;
BYTE *data, *pos;
BYTE byte, mask;
float comp_value;
if (texture == NULL || function == NULL)
return D3DERR_INVALIDCALL;
miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
for (m = 0; m < miplevels; m++)
{
if (FAILED(IDirect3DTexture9_GetLevelDesc(texture, m, &desc)))
return D3DERR_INVALIDCALL;
format = get_format_info(desc.Format);
if (format->format == D3DFMT_UNKNOWN)
{
FIXME("Unsupported texture format %#x\n", desc.Format);
return D3DERR_INVALIDCALL;
}
if (FAILED(IDirect3DTexture9_LockRect(texture, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
return D3DERR_INVALIDCALL;
size.x = 1.0f / desc.Width;
size.y = 1.0f / desc.Height;
data = lock_rect.pBits;
for (y = 0; y < desc.Height; y++)
{
/* The callback function expects the coordinates of the center
of the texel */
coord.y = (y + 0.5f) / desc.Height;
for (x = 0; x < desc.Width; x++)
{
coord.x = (x + 0.5f) / desc.Width;
function(&value, &coord, &size, funcdata);
pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
for (i = 0; i < format->bytes_per_pixel; i++)
pos[i] = 0;
for (c = 0; c < 4; c++)
{
switch (c)
{
case 0: /* Alpha */
comp_value = value.w;
break;
case 1: /* Red */
comp_value = value.x;
break;
case 2: /* Green */
comp_value = value.y;
break;
case 3: /* Blue */
comp_value = value.z;
break;
}
v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
{
mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
byte = (v << format->shift[c] >> i) & mask;
pos[i / 8] |= byte;
}
}
}
}
IDirect3DTexture9_UnlockRect(texture, m);
}
return D3D_OK;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment