diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h index 0aef8cdee3a..492b665f2f9 100644 --- a/dlls/d3dx9_36/d3dx9_36_private.h +++ b/dlls/d3dx9_36/d3dx9_36_private.h @@ -88,7 +88,8 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic const struct pixel_format_desc *dst_format, D3DCOLOR color_key, const PALETTEENTRY *palette) DECLSPEC_HIDDEN; HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const void *src_data, const PALETTEENTRY *palette, - DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info) DECLSPEC_HIDDEN; + DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info, + unsigned int *loaded_miplevels) 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_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette, diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 5e87d946fdc..97c71bfdf4b 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -539,7 +539,8 @@ HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *d } HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const void *src_data, const PALETTEENTRY *palette, - DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info) + DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info, + unsigned int *loaded_miplevels) { HRESULT hr; @@ -553,13 +554,21 @@ HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const void *src_data, const struct dds_header *header = src_data; const BYTE *pixels = (BYTE *)(header + 1); - /* Loading a cube texture as a simple texture is also supported (only first face texture is taken) */ - if ((src_info->ResourceType != D3DRTYPE_TEXTURE) && (src_info->ResourceType != D3DRTYPE_CUBETEXTURE)) + /* Loading a cube texture as a simple texture is also supported + * (only first face texture is taken). Same with volume textures. */ + if ((src_info->ResourceType != D3DRTYPE_TEXTURE) + && (src_info->ResourceType != D3DRTYPE_CUBETEXTURE) + && (src_info->ResourceType != D3DRTYPE_VOLUMETEXTURE)) + { + WARN("Trying to load a %u resource as a 2D texture, returning failure.\n", src_info->ResourceType); return D3DXERR_INVALIDDATA; + } width = src_info->Width; height = src_info->Height; mip_levels = min(src_info->MipLevels, IDirect3DTexture9_GetLevelCount(texture)); + if (src_info->ResourceType == D3DRTYPE_VOLUMETEXTURE) + mip_levels = 1; for (mip_level = 0; mip_level < mip_levels; mip_level++) { hr = calculate_dds_surface_size(src_info->Format, width, height, &src_pitch, &mip_level_size); @@ -578,6 +587,8 @@ HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const void *src_data, height = max(1, height / 2); } + *loaded_miplevels = mip_levels; + return D3D_OK; } diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 4a93ac67618..a2fc55156bd 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -25,7 +25,7 @@ #include "d3dx9tex.h" #include "resources.h" -static int has_2d_dxt5, has_cube_dxt5; +static int has_2d_dxt3, has_2d_dxt5, has_cube_dxt5; /* 2x2 16-bit dds, no mipmaps */ static const unsigned char dds_16bit[] = { @@ -1433,6 +1433,7 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) D3DSURFACE_DESC desc; D3DLOCKED_RECT lock_rect; int i; + DWORD level_count; hr = D3DXCreateTextureFromFileInMemory(device, dds_16bit, sizeof(dds_16bit), &texture); ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); @@ -1464,12 +1465,46 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) if (SUCCEEDED(hr)) { for (i = 0; i < 16; i++) - ok(((BYTE*)lock_rect.pBits)[i] == dds_cube_map[128+i], "Byte at index %u is 0x%02x, expected 0x%02x\n", i, ((BYTE*)lock_rect.pBits)[i], dds_cube_map[144+i]); + ok(((BYTE *)lock_rect.pBits)[i] == dds_cube_map[128 + i], + "Byte at index %u is 0x%02x, expected 0x%02x.\n", + i, ((BYTE *)lock_rect.pBits)[i], dds_cube_map[128 + i]); IDirect3DTexture9_UnlockRect(texture, 0); } IDirect3DTexture9_Release(texture); } + + /* Volume textures work too. */ + hr = D3DXCreateTextureFromFileInMemory(device, dds_volume_map, sizeof(dds_volume_map), &texture); + if (has_2d_dxt3) + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemory returned %#x, expected %#x.\n", hr, D3D_OK); + else + todo_wine ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemory returned %#x, expected %#x.\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + type = IDirect3DTexture9_GetType(texture); + ok(type == D3DRTYPE_TEXTURE, "IDirect3DTexture9_GetType returned %u, expected %u.\n", type, D3DRTYPE_TEXTURE); + level_count = IDirect3DBaseTexture9_GetLevelCount((IDirect3DBaseTexture9 *)texture); + todo_wine ok(level_count == 3, "Texture has %u mip levels, 3 expected.\n", level_count); + hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); + ok(hr == D3D_OK, "IDirect3DTexture9_GetLevelDesc returned %#x, expected %#x.\n", hr, D3D_OK); + ok(desc.Width == 4, "Width is %u, expected 4.\n", desc.Width); + ok(desc.Height == 4, "Height is %u, expected 4.\n", desc.Height); + + hr = IDirect3DTexture9_LockRect(texture, 0, &lock_rect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %#x, expected %#x.\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + for (i = 0; i < 16; ++i) + ok(((BYTE *)lock_rect.pBits)[i] == dds_volume_map[128 + i], + "Byte at index %u is 0x%02x, expected 0x%02x.\n", + i, ((BYTE *)lock_rect.pBits)[i], dds_volume_map[128 + i]); + IDirect3DTexture9_UnlockRect(texture, 0); + } + /* The lower texture levels are apparently generated by filtering the level 0 surface + * I.e. following levels from the file are ignored. */ + IDirect3DTexture9_Release(texture); + } } static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) @@ -1821,7 +1856,9 @@ START_TEST(texture) return; } - /* Check whether DXT5 textures are supported */ + /* Check whether DXTn textures are supported. */ + has_2d_dxt3 = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3)); hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5); has_2d_dxt5 = SUCCEEDED(hr); diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index be863474073..f5f754d51dc 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -602,6 +602,12 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi FIXME("Generation of mipmaps for compressed pixel formats is not implemented yet\n"); miplevels = imginfo.MipLevels; } + if (imginfo.ResourceType == D3DRTYPE_VOLUMETEXTURE + && D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5 && miplevels > 1) + { + FIXME("Generation of mipmaps for compressed pixel formats is not implemented yet.\n"); + miplevels = 1; + } if (((file_width) && (width != imginfo.Width)) || ((file_height) && (height != imginfo.Height)) || @@ -640,10 +646,12 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi IDirect3DTexture9_GetSurfaceLevel(*texptr, 0, &surface); hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL); IDirect3DSurface9_Release(surface); + loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(*texptr), imginfo.MipLevels); } else { - hr = load_texture_from_dds(*texptr, srcdata, palette, filter, colorkey, &imginfo); + hr = load_texture_from_dds(*texptr, srcdata, palette, filter, colorkey, &imginfo, + &loaded_miplevels); } if (FAILED(hr)) @@ -654,7 +662,6 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi return hr; } - loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(*texptr), imginfo.MipLevels); hr = D3DXFilterTexture((IDirect3DBaseTexture9*) *texptr, palette, loaded_miplevels - 1, mipfilter); if (FAILED(hr)) {