From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 7 +-- dlls/d3dx9_36/surface.c | 92 +++++++++++++---------------------- dlls/d3dx9_36/tests/texture.c | 8 +-- dlls/d3dx9_36/texture.c | 49 ++++++++++++++++--- dlls/d3dx9_36/volume.c | 2 +- 5 files changed, 83 insertions(+), 75 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 34a9f6eec7f..248b6a69b00 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -106,8 +106,10 @@ struct d3dx_image
struct volume size; uint32_t mip_levels; + uint32_t layer_count;
BYTE *pixels; + uint32_t layer_pitch;
/* * image_buf and palette are pointers to allocated memory used to store @@ -123,7 +125,8 @@ struct d3dx_image HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t starting_mip_level, uint32_t flags); void d3dx_image_cleanup(struct d3dx_image *image); -HRESULT d3dx_image_get_pixels(struct d3dx_image *image, uint32_t mip_level, struct d3dx_pixels *pixels); +HRESULT d3dx_image_get_pixels(struct d3dx_image *image, uint32_t layer, uint32_t mip_level, + struct d3dx_pixels *pixels); void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image);
struct d3dx_include_from_file @@ -172,8 +175,6 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *dst_size, const struct pixel_format_desc *dst_format, D3DCOLOR color_key, const PALETTEENTRY *palette);
-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); HRESULT lock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect, D3DLOCKED_RECT *lock, IDirect3DSurface9 **temp_surface, BOOL write); HRESULT unlock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect, diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 79ee4edcbc1..344a491765e 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -475,6 +475,23 @@ static HRESULT d3dx_calculate_pixels_size(D3DFORMAT format, uint32_t width, uint return D3D_OK; }
+static uint32_t d3dx_calculate_layer_pixels_size(D3DFORMAT format, uint32_t width, uint32_t height, uint32_t depth, + uint32_t mip_levels) +{ + uint32_t layer_size, row_pitch, slice_pitch, i; + struct volume dims = { width, height, depth }; + + layer_size = 0; + for (i = 0; i < mip_levels; ++i) + { + d3dx_calculate_pixels_size(format, dims.width, dims.height, &row_pitch, &slice_pitch); + layer_size += slice_pitch * dims.depth; + d3dx_get_next_mip_level_size(&dims); + } + + return layer_size; +} + static UINT calculate_dds_file_size(D3DFORMAT format, UINT width, UINT height, UINT depth, UINT miplevels, UINT faces) { @@ -566,65 +583,11 @@ static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSur return D3D_OK; }
-HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data, - const PALETTEENTRY *palette, DWORD filter, DWORD color_key, const D3DXIMAGE_INFO *src_info) -{ - HRESULT hr; - int face; - UINT mip_level; - UINT size; - RECT src_rect; - UINT src_pitch; - UINT mip_levels; - UINT mip_level_size; - IDirect3DSurface9 *surface; - const struct dds_header *header = src_data; - const BYTE *pixels = (BYTE *)(header + 1); - - if (src_info->ResourceType != D3DRTYPE_CUBETEXTURE) - return D3DXERR_INVALIDDATA; - - if ((header->caps2 & DDS_CAPS2_CUBEMAP_ALL_FACES) != DDS_CAPS2_CUBEMAP_ALL_FACES) - { - WARN("Only full cubemaps are supported\n"); - return D3DXERR_INVALIDDATA; - } - - mip_levels = min(src_info->MipLevels, IDirect3DCubeTexture9_GetLevelCount(cube_texture)); - for (face = D3DCUBEMAP_FACE_POSITIVE_X; face <= D3DCUBEMAP_FACE_NEGATIVE_Z; face++) - { - size = src_info->Width; - for (mip_level = 0; mip_level < src_info->MipLevels; mip_level++) - { - hr = d3dx_calculate_pixels_size(src_info->Format, size, size, &src_pitch, &mip_level_size); - if (FAILED(hr)) return hr; - - /* if texture has fewer mip levels than DDS file, skip excessive mip levels */ - if (mip_level < mip_levels) - { - SetRect(&src_rect, 0, 0, size, size); - - IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, face, mip_level, &surface); - hr = D3DXLoadSurfaceFromMemory(surface, palette, NULL, pixels, src_info->Format, src_pitch, - NULL, &src_rect, filter, color_key); - IDirect3DSurface9_Release(surface); - if (FAILED(hr)) return hr; - } - - pixels += mip_level_size; - size = max(1, size / 2); - } - } - - return D3D_OK; -} - static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t starting_mip_level) { const struct dds_header *header = src_data; uint32_t expected_src_data_size; - uint32_t faces = 1;
if (src_data_size < sizeof(*header) || header->pixel_format.size != sizeof(header->pixel_format)) return D3DXERR_INVALIDDATA; @@ -633,6 +596,7 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src set_volume_struct(&image->size, header->width, header->height, 1); image->mip_levels = header->miplevels ? header->miplevels : 1; image->format = dds_pixel_format_to_d3dformat(&header->pixel_format); + image->layer_count = 1;
if (image->format == D3DFMT_UNKNOWN) return D3DXERR_INVALIDDATA; @@ -651,14 +615,15 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src return D3DXERR_INVALIDDATA; }
- faces = 6; + image->layer_count = 6; image->resource_type = D3DRTYPE_CUBETEXTURE; } else image->resource_type = D3DRTYPE_TEXTURE;
- expected_src_data_size = calculate_dds_file_size(image->format, image->size.width, image->size.height, - image->size.depth, image->mip_levels, faces); + image->layer_pitch = d3dx_calculate_layer_pixels_size(image->format, image->size.width, image->size.height, + image->size.depth, image->mip_levels); + expected_src_data_size = (image->layer_pitch * image->layer_count) + sizeof(*header); if (src_data_size < expected_src_data_size) { WARN("File is too short %u, expected at least %u bytes.\n", src_data_size, expected_src_data_size); @@ -1020,6 +985,7 @@ static HRESULT d3dx_initialize_image_from_wic(const void *src_data, uint32_t src
image->size.depth = 1; image->mip_levels = 1; + image->layer_count = 1; image->resource_type = D3DRTYPE_TEXTURE;
exit: @@ -1055,7 +1021,8 @@ void d3dx_image_cleanup(struct d3dx_image *image) free(image->palette); }
-HRESULT d3dx_image_get_pixels(struct d3dx_image *image, uint32_t mip_level, struct d3dx_pixels *pixels) +HRESULT d3dx_image_get_pixels(struct d3dx_image *image, uint32_t layer, uint32_t mip_level, + struct d3dx_pixels *pixels) { struct volume mip_level_size = image->size; const BYTE *pixels_ptr = image->pixels; @@ -1069,6 +1036,12 @@ HRESULT d3dx_image_get_pixels(struct d3dx_image *image, uint32_t mip_level, stru return E_FAIL; }
+ if (layer >= image->layer_count) + { + ERR("Tried to retrieve layer %u, but image only has %u layers.\n", layer, image->layer_count); + return E_FAIL; + } + slice_pitch = row_pitch = 0; for (i = 0; i < image->mip_levels; i++) { @@ -1083,6 +1056,7 @@ HRESULT d3dx_image_get_pixels(struct d3dx_image *image, uint32_t mip_level, stru d3dx_get_next_mip_level_size(&mip_level_size); }
+ pixels_ptr += (layer * image->layer_pitch); SetRect(&unaligned_rect, 0, 0, mip_level_size.width, mip_level_size.height); set_d3dx_pixels(pixels, pixels_ptr, row_pitch, slice_pitch, image->palette, mip_level_size.width, mip_level_size.height, mip_level_size.depth, &unaligned_rect); @@ -1294,7 +1268,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface, else SetRect(&src_rect, 0, 0, img_info.Width, img_info.Height);
- hr = d3dx_image_get_pixels(&image, 0, &pixels); + hr = d3dx_image_get_pixels(&image, 0, 0, &pixels); if (FAILED(hr)) goto exit;
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 83a6848e37d..c1e54372fb2 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -2632,9 +2632,9 @@ static void test_D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *devic D3DX_SKIP_DDS_MIP_LEVELS(1, D3DX_DEFAULT), 0, &info, NULL, &cube_texture); ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
- check_texture_mip_levels(cube_texture, 1, TRUE); - check_image_info(&info, 2, 2, 1, 1, D3DFMT_X8R8G8B8, D3DRTYPE_CUBETEXTURE, D3DXIFF_DDS, TRUE); - check_cube_texture_level_desc(cube_texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, TRUE); + check_texture_mip_levels(cube_texture, 1, FALSE); + check_image_info(&info, 2, 2, 1, 1, D3DFMT_X8R8G8B8, D3DRTYPE_CUBETEXTURE, D3DXIFF_DDS, FALSE); + check_cube_texture_level_desc(cube_texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, FALSE);
for (i = 0; i < 6; ++i) { @@ -2647,7 +2647,7 @@ static void test_D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *devic { for (x = 0; x < desc.Width; ++x) { - check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, TRUE); + check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, FALSE); } } release_surface_readback(&surface_rb); diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index ea8536c3720..ab0ca312a2c 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -656,7 +656,7 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi D3DLOCKED_RECT dst_locked_rect; RECT dst_rect;
- hr = d3dx_image_get_pixels(&image, i, &src_pixels); + hr = d3dx_image_get_pixels(&image, 0, i, &src_pixels); if (FAILED(hr)) break;
@@ -1185,7 +1185,7 @@ HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *devic D3DLOCKED_BOX dst_locked_box; RECT dst_rect;
- hr = d3dx_image_get_pixels(&image, i, &src_pixels); + hr = d3dx_image_get_pixels(&image, 0, i, &src_pixels); if (FAILED(hr)) break;
@@ -1378,9 +1378,10 @@ HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device, DWORD filter, DWORD mip_filter, D3DCOLOR color_key, D3DXIMAGE_INFO *src_info, PALETTEENTRY *palette, IDirect3DCubeTexture9 **cube_texture) { + const struct pixel_format_desc *src_fmt_desc, *dst_fmt_desc; BOOL dynamic_texture, format_specified = FALSE; + uint32_t loaded_miplevels, skip_levels, i; IDirect3DCubeTexture9 *tex, *staging_tex; - uint32_t loaded_miplevels, skip_levels; struct d3dx_image image; D3DXIMAGE_INFO img_info; D3DCAPS9 caps; @@ -1398,9 +1399,7 @@ HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device, staging_tex = tex = *cube_texture = NULL; skip_levels = mip_filter != D3DX_DEFAULT ? mip_filter >> D3DX_SKIP_DDS_MIP_LEVELS_SHIFT : 0; skip_levels &= D3DX_SKIP_DDS_MIP_LEVELS_MASK; - if (skip_levels) - FIXME("Skipping mip levels is currently unsupported for cube textures.\n"); - hr = d3dx_image_init(src_data, src_data_size, &image, 0, 0); + hr = d3dx_image_init(src_data, src_data_size, &image, skip_levels, 0); if (FAILED(hr)) { FIXME("Unrecognized file format, returning failure.\n"); @@ -1465,14 +1464,48 @@ HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device, }
TRACE("Texture created correctly. Now loading the texture data into it.\n"); - hr = load_cube_texture_from_dds(tex, src_data, palette, filter, color_key, &img_info); + dst_fmt_desc = get_format_info(format); + src_fmt_desc = get_format_info(img_info.Format); + loaded_miplevels = min(img_info.MipLevels, IDirect3DCubeTexture9_GetLevelCount(tex)); + for (i = 0; i < loaded_miplevels; ++i) + { + struct d3dx_pixels src_pixels, dst_pixels; + D3DSURFACE_DESC dst_surface_desc; + D3DLOCKED_RECT dst_locked_rect; + RECT dst_rect; + uint32_t face; + + IDirect3DCubeTexture9_GetLevelDesc(tex, i, &dst_surface_desc); + SetRect(&dst_rect, 0, 0, dst_surface_desc.Width, dst_surface_desc.Height); + for (face = D3DCUBEMAP_FACE_POSITIVE_X; face <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++face) + { + hr = d3dx_image_get_pixels(&image, face, i, &src_pixels); + if (FAILED(hr)) + break; + + hr = IDirect3DCubeTexture9_LockRect(tex, face, i, &dst_locked_rect, NULL, 0); + if (FAILED(hr)) + break; + + set_d3dx_pixels(&dst_pixels, dst_locked_rect.pBits, dst_locked_rect.Pitch, 0, palette, + dst_surface_desc.Width, dst_surface_desc.Height, 1, &dst_rect); + + hr = d3dx_load_pixels_from_pixels(&dst_pixels, dst_fmt_desc, &src_pixels, src_fmt_desc, filter, color_key); + IDirect3DCubeTexture9_UnlockRect(tex, face, i); + if (FAILED(hr)) + break; + } + + if (FAILED(hr)) + break; + } + if (FAILED(hr)) { FIXME("Texture loading failed.\n"); goto err; }
- loaded_miplevels = min(IDirect3DCubeTexture9_GetLevelCount(tex), img_info.MipLevels); hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, palette, loaded_miplevels - 1, mip_filter); if (FAILED(hr)) { diff --git a/dlls/d3dx9_36/volume.c b/dlls/d3dx9_36/volume.c index 06cae72c51e..2088b70ed4c 100644 --- a/dlls/d3dx9_36/volume.c +++ b/dlls/d3dx9_36/volume.c @@ -202,7 +202,7 @@ HRESULT WINAPI D3DXLoadVolumeFromFileInMemory(IDirect3DVolume9 *dst_volume, cons set_d3dbox(&box, 0, 0, image_info.Width, image_info.Height, 0, image_info.Depth); }
- hr = d3dx_image_get_pixels(&image, 0, &pixels); + hr = d3dx_image_get_pixels(&image, 0, 0, &pixels); if (FAILED(hr)) goto exit;