From bffbf3460b01903209fc280abef53fdb4f84b274 Mon Sep 17 00:00:00 2001 From: Matteo Bruni Date: Tue, 9 Nov 2010 19:10:17 +0100 Subject: [PATCH] d3dx9: Implement D3DXFillTexture function. --- dlls/d3dx9_36/d3dx9_36.spec | 2 +- dlls/d3dx9_36/tests/texture.c | 121 ++++++++++++++++++++++++++++++++++ dlls/d3dx9_36/texture.c | 92 ++++++++++++++++++++++++++ 3 files changed, 214 insertions(+), 1 deletion(-) diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec index efe28c5eb8b..43362aa5254 100644 --- a/dlls/d3dx9_36/d3dx9_36.spec +++ b/dlls/d3dx9_36/d3dx9_36.spec @@ -124,7 +124,7 @@ @ stub D3DXFileCreate @ stub D3DXFillCubeTexture @ stub D3DXFillCubeTextureTX -@ stub D3DXFillTexture +@ stdcall D3DXFillTexture(ptr ptr ptr) @ stub D3DXFillTextureTX @ stub D3DXFillVolumeTexture @ stub D3DXFillVolumeTextureTX diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 177b4c7b21f..fb3cee03e5d 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -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); diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index 04422e5a471..2c88ca64618 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -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; +}