Module: wine Branch: master Commit: 892502479c3acf64257e19ec4aac113024642f4d URL: http://source.winehq.org/git/wine.git/?a=commit;h=892502479c3acf64257e19ec4a...
Author: Matteo Bruni mbruni@codeweavers.com Date: Mon Nov 15 23:28:09 2010 +0100
d3dx9: Implement D3DXFillVolumeTexture function.
---
dlls/d3dx9_36/d3dx9_36.spec | 2 +- dlls/d3dx9_36/tests/texture.c | 116 +++++++++++++++++++++++++++++++++++++++++ dlls/d3dx9_36/texture.c | 98 ++++++++++++++++++++++++++++++++++ 3 files changed, 215 insertions(+), 1 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec index 327c406..cbb6d20 100644 --- a/dlls/d3dx9_36/d3dx9_36.spec +++ b/dlls/d3dx9_36/d3dx9_36.spec @@ -126,7 +126,7 @@ @ stub D3DXFillCubeTextureTX @ stdcall D3DXFillTexture(ptr ptr ptr) @ stub D3DXFillTextureTX -@ stub D3DXFillVolumeTexture +@ stdcall D3DXFillVolumeTexture(ptr ptr ptr) @ stub D3DXFillVolumeTextureTX @ stdcall D3DXFilterTexture(ptr ptr long long) @ stdcall D3DXFindShaderComment(ptr long ptr ptr) diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 2d5cd72..44e7719 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -932,6 +932,121 @@ static void test_D3DXFillCubeTexture(IDirect3DDevice9 *device) IDirect3DCubeTexture9_Release(tex); }
+static void WINAPI fillfunc_volume(D3DXVECTOR4 *value, const D3DXVECTOR3 *texcoord, + const D3DXVECTOR3 *texelsize, void *data) +{ + value->x = texcoord->x; + value->y = texcoord->y; + value->z = texcoord->z; + value->w = texelsize->x; +} + +static void test_D3DXFillVolumeTexture(IDirect3DDevice9 *device) +{ + IDirect3DVolumeTexture9 *tex; + HRESULT hr; + D3DLOCKED_BOX lock_box; + DWORD x, y, z, m; + DWORD v[4], e[4]; + DWORD value, expected, size, row_pitch, slice_pitch; + + size = 4; + hr = IDirect3DDevice9_CreateVolumeTexture(device, size, size, size, 0, 0, D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFillVolumeTexture(tex, fillfunc_volume, NULL); + ok(hr == D3D_OK, "D3DXFillVolumeTexture returned %#x, expected %#x\n", hr, D3D_OK); + + for (m = 0; m < 3; m++) + { + hr = IDirect3DVolumeTexture9_LockBox(tex, m, &lock_box, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Couldn't lock the texture, error %#x\n", hr); + if (SUCCEEDED(hr)) + { + row_pitch = lock_box.RowPitch / sizeof(DWORD); + slice_pitch = lock_box.SlicePitch / sizeof(DWORD); + for (z = 0; z < size; z++) + { + for (y = 0; y < size; y++) + { + for (x = 0; x < size; x++) + { + value = ((DWORD *)lock_box.pBits)[z * slice_pitch + y * row_pitch + x]; + v[0] = (value >> 24) & 0xff; + v[1] = (value >> 16) & 0xff; + v[2] = (value >> 8) & 0xff; + v[3] = value & 0xff; + + e[0] = 255.0f / size + 0.5f; + e[1] = (x + 0.5f) / size * 255.0f + 0.5f; + e[2] = (y + 0.5f) / size * 255.0f + 0.5f; + e[3] = (z + 0.5f) / size * 255.0f + 0.5f; + expected = e[0] << 24 | e[1] << 16 | e[2] << 8 | e[3]; + + ok(color_match(v, e), + "Texel at (%u, %u, %u) doesn't match: %#x, expected %#x\n", + x, y, z, value, expected); + } + } + } + IDirect3DVolumeTexture9_UnlockBox(tex, m); + } + size >>= 1; + } + } + else + skip("Failed to create texture\n"); + + IDirect3DVolumeTexture9_Release(tex); + + hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, 0, D3DFMT_A1R5G5B5, + D3DPOOL_MANAGED, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFillVolumeTexture(tex, fillfunc_volume, NULL); + ok(hr == D3D_OK, "D3DXFillTexture returned %#x, expected %#x\n", hr, D3D_OK); + hr = IDirect3DVolumeTexture9_LockBox(tex, 0, &lock_box, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Couldn't lock the texture, error %#x\n", hr); + if (SUCCEEDED(hr)) + { + row_pitch = lock_box.RowPitch / sizeof(WORD); + slice_pitch = lock_box.SlicePitch / sizeof(WORD); + for (z = 0; z < 4; z++) + { + for (y = 0; y < 4; y++) + { + for (x = 0; x < 4; x++) + { + value = ((WORD *)lock_box.pBits)[z * slice_pitch + y * row_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 * 31.0f + 0.5f; + e[2] = (y + 0.5f) / 4 * 31.0f + 0.5f; + e[3] = (z + 0.5f) / 4 * 31.0f + 0.5f; + expected = e[0] << 15 | e[1] << 10 | e[2] << 5 | e[3]; + + ok(color_match(v, e), + "Texel at (%u, %u, %u) doesn't match: %#x, expected %#x\n", + x, y, z, value, expected); + } + } + } + IDirect3DVolumeTexture9_UnlockBox(tex, 0); + } + } + else + skip("Failed to create texture\n"); + + IDirect3DVolumeTexture9_Release(tex); +} + START_TEST(texture) { HWND wnd; @@ -970,6 +1085,7 @@ START_TEST(texture) test_D3DXFilterTexture(device); test_D3DXFillTexture(device); test_D3DXFillCubeTexture(device); + test_D3DXFillVolumeTexture(device);
IDirect3DDevice9_Release(device); IDirect3D9_Release(d3d); diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index 550f61f..c6e2273 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -1163,3 +1163,101 @@ HRESULT WINAPI D3DXFillCubeTexture(LPDIRECT3DCUBETEXTURE9 texture,
return D3D_OK; } + +HRESULT WINAPI D3DXFillVolumeTexture(LPDIRECT3DVOLUMETEXTURE9 texture, + LPD3DXFILL3D function, + LPVOID funcdata) +{ + DWORD miplevels; + DWORD m, i, x, y, z, c, v; + D3DVOLUME_DESC desc; + D3DLOCKED_BOX lock_box; + D3DXVECTOR4 value; + D3DXVECTOR3 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(IDirect3DVolumeTexture9_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(IDirect3DVolumeTexture9_LockBox(texture, m, &lock_box, NULL, D3DLOCK_DISCARD))) + return D3DERR_INVALIDCALL; + + size.x = 1.0f / desc.Width; + size.y = 1.0f / desc.Height; + size.z = 1.0f / desc.Depth; + + data = lock_box.pBits; + + for (z = 0; z < desc.Depth; z++) + { + /* The callback function expects the coordinates of the center + of the texel */ + coord.z = (z + 0.5f) / desc.Depth; + + for (y = 0; y < desc.Height; y++) + { + 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 + z * lock_box.SlicePitch + y * lock_box.RowPitch + 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; + } + } + } + } + } + IDirect3DVolumeTexture9_UnlockBox(texture, m); + } + + return D3D_OK; +}