diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h index 1cbb7cffabe..fe3d0907092 100644 --- a/dlls/d3dx9_36/d3dx9_36_private.h +++ b/dlls/d3dx9_36/d3dx9_36_private.h @@ -68,6 +68,8 @@ HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const void *src_data, DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info) DECLSPEC_HIDDEN; HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data, const PALETTEENTRY *palette, DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info) DECLSPEC_HIDDEN; +HRESULT load_volume_texture_from_dds(IDirect3DVolumeTexture9 *volume_texture, const void *src_data, + const PALETTEENTRY *palette, DWORD filter, DWORD color_key, const D3DXIMAGE_INFO *src_info) DECLSPEC_HIDDEN; /* debug helpers */ const char *debug_d3dxparameter_class(D3DXPARAMETER_CLASS c) DECLSPEC_HIDDEN; diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 7be3ebe65cb..845a1f70f3a 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -499,6 +499,58 @@ HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const vo return D3D_OK; } +HRESULT load_volume_texture_from_dds(IDirect3DVolumeTexture9 *volume_texture, const void *src_data, + const PALETTEENTRY *palette, DWORD filter, DWORD color_key, const D3DXIMAGE_INFO *src_info) +{ + HRESULT hr; + UINT mip_level; + UINT mip_levels; + UINT src_slice_pitch; + UINT src_row_pitch; + D3DBOX src_box; + UINT width, height, depth; + IDirect3DVolume9 *volume; + const struct dds_header *header = src_data; + const BYTE *pixels = (BYTE *)(header + 1); + + if (src_info->ResourceType != D3DRTYPE_VOLUMETEXTURE) + return D3DXERR_INVALIDDATA; + + width = src_info->Width; + height = src_info->Height; + depth = src_info->Depth; + mip_levels = min(src_info->MipLevels, IDirect3DVolumeTexture9_GetLevelCount(volume_texture)); + + for (mip_level = 0; mip_level < mip_levels; mip_level++) + { + hr = calculate_dds_surface_size(src_info, width, height, &src_row_pitch, &src_slice_pitch); + if (FAILED(hr)) return hr; + + hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, mip_level, &volume); + if (FAILED(hr)) return hr; + + src_box.Left = 0; + src_box.Top = 0; + src_box.Right = width; + src_box.Bottom = height; + src_box.Front = 0; + src_box.Back = depth; + + hr = D3DXLoadVolumeFromMemory(volume, palette, NULL, pixels, src_info->Format, + src_row_pitch, src_slice_pitch, NULL, &src_box, filter, color_key); + + IDirect3DVolume9_Release(volume); + if (FAILED(hr)) return hr; + + pixels += depth * src_slice_pitch; + width = max(1, width / 2); + height = max(1, height / 2); + depth = max(1, depth / 2); + } + + return D3D_OK; +} + /************************************************************ * D3DXGetImageInfoFromFileInMemory * diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 6cee06507e4..44bf235f0aa 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -1359,40 +1359,39 @@ static void test_D3DXCreateVolumeTextureFromFileInMemory(IDirect3DDevice9 *devic IDirect3DVolumeTexture9 *volume_texture; D3DVOLUME_DESC volume_desc; - todo_wine { - hr = D3DXCreateVolumeTextureFromFileInMemory(NULL, dds_volume_map, sizeof(dds_volume_map), &volume_texture); - ok(hr == D3DERR_INVALIDCALL, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + hr = D3DXCreateVolumeTextureFromFileInMemory(NULL, dds_volume_map, sizeof(dds_volume_map), &volume_texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); - hr = D3DXCreateVolumeTextureFromFileInMemory(device, NULL, sizeof(dds_volume_map), &volume_texture); - ok(hr == D3DERR_INVALIDCALL, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + hr = D3DXCreateVolumeTextureFromFileInMemory(device, NULL, sizeof(dds_volume_map), &volume_texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); - hr = D3DXCreateVolumeTextureFromFileInMemory(device, dds_volume_map, 0, &volume_texture); - ok(hr == D3DERR_INVALIDCALL, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + hr = D3DXCreateVolumeTextureFromFileInMemory(device, dds_volume_map, 0, &volume_texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); - hr = D3DXCreateVolumeTextureFromFileInMemory(device, dds_volume_map, sizeof(dds_volume_map), NULL); - ok(hr == D3DERR_INVALIDCALL, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + hr = D3DXCreateVolumeTextureFromFileInMemory(device, dds_volume_map, sizeof(dds_volume_map), NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); - hr = D3DXCreateVolumeTextureFromFileInMemory(device, dds_volume_map, sizeof(dds_volume_map), &volume_texture); - if (SUCCEEDED(hr)) - { - levelcount = IDirect3DVolumeTexture9_GetLevelCount(volume_texture); - ok(levelcount == 3, "GetLevelCount returned %u, expected 3\n", levelcount); + hr = D3DXCreateVolumeTextureFromFileInMemory(device, dds_volume_map, sizeof(dds_volume_map), &volume_texture); + ok(hr == D3D_OK, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + levelcount = IDirect3DVolumeTexture9_GetLevelCount(volume_texture); + ok(levelcount == 3, "GetLevelCount returned %u, expected 3\n", levelcount); - hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc); - ok(hr == D3D_OK, "GetLevelDesc returend %#x, expected %#x\n", hr, D3D_OK); - ok(volume_desc.Width == 4, "Got width %u, expected 4\n", volume_desc.Width); - ok(volume_desc.Height == 4, "Got height %u, expected 4\n", volume_desc.Height); - ok(volume_desc.Depth == 2, "Got depth %u, expected 2\n", volume_desc.Depth); + hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc); + ok(hr == D3D_OK, "GetLevelDesc returend %#x, expected %#x\n", hr, D3D_OK); + ok(volume_desc.Width == 4, "Got width %u, expected 4\n", volume_desc.Width); + ok(volume_desc.Height == 4, "Got height %u, expected 4\n", volume_desc.Height); + ok(volume_desc.Depth == 2, "Got depth %u, expected 2\n", volume_desc.Depth); - hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 1, &volume_desc); - ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr, D3D_OK); - ok(volume_desc.Width == 2, "Got width %u, expected 2\n", volume_desc.Width); - ok(volume_desc.Height == 2, "Got height %u, expected 2\n", volume_desc.Height); - ok(volume_desc.Depth == 1, "Got depth %u, expected 1\n", volume_desc.Depth); + hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 1, &volume_desc); + ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr, D3D_OK); + ok(volume_desc.Width == 2, "Got width %u, expected 2\n", volume_desc.Width); + ok(volume_desc.Height == 2, "Got height %u, expected 2\n", volume_desc.Height); + ok(volume_desc.Depth == 1, "Got depth %u, expected 1\n", volume_desc.Depth); - ref = IDirect3DVolumeTexture9_Release(volume_texture); - ok(ref == 0, "Invalid reference count. Got %u, expected 0\n", ref); - } + ref = IDirect3DVolumeTexture9_Release(volume_texture); + ok(ref == 0, "Invalid reference count. Got %u, expected 0\n", ref); } } diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index 1e87a00d05c..f439913de8b 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -977,40 +977,166 @@ HRESULT WINAPI D3DXCreateVolumeTexture(LPDIRECT3DDEVICE9 device, usage, format, pool, texture, NULL); } -HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemory(LPDIRECT3DDEVICE9 device, - LPCVOID data, - UINT datasize, - LPDIRECT3DVOLUMETEXTURE9 *texture) +HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemory(IDirect3DDevice9 *device, + const void *data, + UINT data_size, + IDirect3DVolumeTexture9 **volume_texture) { - TRACE("(%p, %p, %u, %p)\n", device, data, datasize, texture); + TRACE("(%p, %p, %u, %p): relay\n", device, data, data_size, volume_texture); - return D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, datasize, D3DX_DEFAULT, D3DX_DEFAULT, + return D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, - 0, NULL, NULL, texture); + 0, NULL, NULL, volume_texture); } -HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device, - LPCVOID data, - UINT datasize, +HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *device, + const void *data, + UINT data_size, UINT width, UINT height, UINT depth, - UINT miplevels, + UINT mip_levels, DWORD usage, D3DFORMAT format, D3DPOOL pool, DWORD filter, - DWORD mipfilter, - D3DCOLOR colorkey, - D3DXIMAGE_INFO *imageinfo, + DWORD mip_filter, + D3DCOLOR color_key, + D3DXIMAGE_INFO *info, PALETTEENTRY *palette, - LPDIRECT3DVOLUMETEXTURE9 *texture) + IDirect3DVolumeTexture9 **volume_texture) { - FIXME("(%p, %p, %u, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p) : stub\n", - device, data, datasize, width, height, depth, miplevels, usage, format, pool, - filter, mipfilter, colorkey, imageinfo, palette, texture); + HRESULT hr; + D3DCAPS9 caps; + D3DXIMAGE_INFO image_info; + BOOL dynamic_texture; + BOOL file_width = FALSE; + BOOL file_height = FALSE; + BOOL file_depth = FALSE; + BOOL file_format = FALSE; + BOOL file_mip_levels = FALSE; + IDirect3DVolumeTexture9 *tex, *buftex; - return E_NOTIMPL; + TRACE("(%p, %p, %u, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p)\n", + device, data, data_size, width, height, depth, mip_levels, usage, format, pool, + filter, mip_filter, color_key, info, palette, volume_texture); + + if (!device || !data || !data_size || !volume_texture) + return D3DERR_INVALIDCALL; + + hr = D3DXGetImageInfoFromFileInMemory(data, data_size, &image_info); + if (FAILED(hr)) return hr; + + if (image_info.ImageFileFormat != D3DXIFF_DDS) + return D3DXERR_INVALIDDATA; + + if (width == 0 || width == D3DX_DEFAULT_NONPOW2) + width = image_info.Width; + if (width == D3DX_DEFAULT) + width = make_pow2(image_info.Width); + + if (height == 0 || height == D3DX_DEFAULT_NONPOW2) + height = image_info.Height; + if (height == D3DX_DEFAULT) + height = make_pow2(image_info.Height); + + if (depth == 0 || depth == D3DX_DEFAULT_NONPOW2) + depth = image_info.Depth; + if (depth == D3DX_DEFAULT) + depth = make_pow2(image_info.Depth); + + if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT) + format = image_info.Format; + + if (width == D3DX_FROM_FILE) + { + file_width = TRUE; + width = image_info.Width; + } + + if (height == D3DX_FROM_FILE) + { + file_height = TRUE; + height = image_info.Height; + } + + if (depth == D3DX_FROM_FILE) + { + file_depth = TRUE; + depth = image_info.Depth; + } + + if (format == D3DFMT_FROM_FILE) + { + file_format = TRUE; + format = image_info.Format; + } + + if (mip_levels == D3DX_FROM_FILE) + { + file_mip_levels = TRUE; + mip_levels = image_info.MipLevels; + } + + hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth, &mip_levels, usage, &format, pool); + if (FAILED(hr)) return hr; + + if ((file_width && width != image_info.Width) + || (file_height && height != image_info.Height) + || (file_depth && depth != image_info.Depth) + || (file_format && format != image_info.Format) + || (file_mip_levels && mip_levels != image_info.MipLevels)) + return D3DERR_NOTAVAILABLE; + + hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); + if (FAILED(hr)) + return D3DERR_INVALIDCALL; + + if (mip_levels > image_info.MipLevels) + { + FIXME("Generation of mipmaps for volume textures is not implemented yet\n"); + mip_levels = image_info.MipLevels; + } + + dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC); + if (pool == D3DPOOL_DEFAULT && !dynamic_texture) + { + hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, D3DPOOL_SYSTEMMEM, &buftex); + tex = buftex; + } + else + { + hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, pool, &tex); + buftex = NULL; + } + + if (FAILED(hr)) return hr; + + hr = load_volume_texture_from_dds(tex, data, palette, filter, color_key, &image_info); + if (FAILED(hr)) + { + IDirect3DVolumeTexture9_Release(tex); + return hr; + } + + if (buftex) + { + hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, pool, &tex); + if (FAILED(hr)) + { + IDirect3DVolumeTexture9_Release(buftex); + return hr; + } + + IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)buftex, (IDirect3DBaseTexture9 *)tex); + IDirect3DVolumeTexture9_Release(buftex); + } + + if (info) + *info = image_info; + + *volume_texture = tex; + return D3D_OK; } HRESULT WINAPI D3DXFillTexture(LPDIRECT3DTEXTURE9 texture,