From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 3 + dlls/d3dx9_36/surface.c | 13 +++- dlls/d3dx9_36/tests/volume.c | 6 -- dlls/d3dx9_36/volume.c | 127 +++++++++++++++++++++++++++++++--- 4 files changed, 132 insertions(+), 17 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 6a9b3e12b7b..7da9f9dd788 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -316,6 +316,9 @@ HRESULT lock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect, D3DLO IDirect3DSurface9 **temp_surface, BOOL write); HRESULT unlock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect, IDirect3DSurface9 *temp_surface, BOOL update); +HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const struct pixel_format_desc *src_fmt_desc, + D3DXIMAGE_FILEFORMAT file_format, ID3DXBuffer **dst_buffer); +const char *debug_d3dx_image_file_format(D3DXIMAGE_FILEFORMAT format); HRESULT d3dx_pixels_init(const void *data, uint32_t row_pitch, uint32_t slice_pitch, const PALETTEENTRY *palette, enum d3dx_pixel_format_id format, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t front, uint32_t back, struct d3dx_pixels *pixels); diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 6b986055b06..3813461bc9b 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -508,6 +508,12 @@ static HRESULT d3dx_init_dds_header(struct dds_header *header, D3DRESOURCETYPE r header->height = size->height; header->width = size->width; header->caps = DDS_CAPS_TEXTURE; + if (size->depth > 1) + { + header->flags |= DDS_DEPTH; + header->depth = size->depth; + header->caps2 |= DDS_CAPS2_VOLUME; + } if (header->pixel_format.flags & DDS_PF_ALPHA || header->pixel_format.flags & DDS_PF_ALPHA_ONLY) header->caps |= DDSCAPS_ALPHA; if (header->pixel_format.flags & DDS_PF_INDEXED) @@ -799,7 +805,7 @@ static enum d3dx_pixel_format_id d3dx_get_closest_d3dx_pixel_format_id(const enu return (bestfmt) ? bestfmt->format : D3DX_PIXEL_FORMAT_COUNT; }
-static HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const struct pixel_format_desc *src_fmt_desc, +HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const struct pixel_format_desc *src_fmt_desc, D3DXIMAGE_FILEFORMAT file_format, ID3DXBuffer **dst_buffer) { enum d3dx_pixel_format_id dst_format = src_fmt_desc->format; @@ -871,6 +877,7 @@ static HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const }
dst_fmt_desc = get_d3dx_pixel_format_info(dst_format); + src_pixels->size.depth = (file_format == D3DXIFF_DDS) ? src_pixels->size.depth : 1; hr = d3dx_calculate_pixels_size(dst_format, src_pixels->size.width, src_pixels->size.height, &dst_row_pitch, &dst_slice_pitch); if (FAILED(hr)) @@ -884,7 +891,7 @@ static HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const uint32_t header_size;
header_size = is_index_format(dst_fmt_desc) ? sizeof(*header) + DDS_PALETTE_SIZE : sizeof(*header); - hr = D3DXCreateBuffer(dst_slice_pitch + header_size, &buffer); + hr = D3DXCreateBuffer((dst_slice_pitch * src_pixels->size.depth) + header_size, &buffer); if (FAILED(hr)) return hr;
@@ -1226,7 +1233,7 @@ static BOOL image_is_argb(IWICBitmapFrameDecode *frame, struct d3dx_image *image return FALSE; }
-static const char *debug_d3dx_image_file_format(D3DXIMAGE_FILEFORMAT format) +const char *debug_d3dx_image_file_format(D3DXIMAGE_FILEFORMAT format) { switch (format) { diff --git a/dlls/d3dx9_36/tests/volume.c b/dlls/d3dx9_36/tests/volume.c index eed356be29e..14df6552c74 100644 --- a/dlls/d3dx9_36/tests/volume.c +++ b/dlls/d3dx9_36/tests/volume.c @@ -477,12 +477,6 @@ static void test_d3dx_save_volume_to_file(IDirect3DDevice9 *device) D3DBOX box; HRESULT hr;
- if (!strcmp(winetest_platform, "wine")) - { - skip("Skipping D3DXSaveVolumeToFile{A,W,InMemory}() tests.\n"); - return; - } - hr = IDirect3DDevice9_CreateVolumeTexture(device, 16, 16, 2, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &volume_texture, NULL); if (FAILED(hr)) diff --git a/dlls/d3dx9_36/volume.c b/dlls/d3dx9_36/volume.c index 14f6bdbfc33..f2d498b7ba2 100644 --- a/dlls/d3dx9_36/volume.c +++ b/dlls/d3dx9_36/volume.c @@ -283,24 +283,135 @@ HRESULT WINAPI D3DXLoadVolumeFromVolume(IDirect3DVolume9 *dst_volume, const PALE HRESULT WINAPI D3DXSaveVolumeToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE_FILEFORMAT file_format, IDirect3DVolume9 *src_volume, const PALETTEENTRY *src_palette, const D3DBOX *src_box) { - FIXME("dst_buffer %p, file_format %#x, src_volume %p, src_palette %p, src_box %p, stub.\n", + const struct pixel_format_desc *src_fmt_desc; + RECT src_rect_aligned, src_rect_unaligned; + D3DBOX src_box_aligned, src_box_tmp; + struct d3dx_pixels src_pixels; + D3DLOCKED_BOX locked_box; + ID3DXBuffer *buffer; + D3DVOLUME_DESC desc; + HRESULT hr; + + TRACE("dst_buffer %p, file_format %#x, src_volume %p, src_palette %p, src_box %p.\n", dst_buffer, file_format, src_volume, src_palette, src_box);
- return E_NOTIMPL; + if (!dst_buffer || !src_volume || file_format > D3DXIFF_PFM) + return D3DERR_INVALIDCALL; + + *dst_buffer = NULL; + switch (file_format) + { + case D3DXIFF_HDR: + case D3DXIFF_PFM: + case D3DXIFF_PPM: + FIXME("File format %s is not supported yet.\n", debug_d3dx_image_file_format(file_format)); + return E_NOTIMPL; + + default: + break; + } + + IDirect3DVolume9_GetDesc(src_volume, &desc); + src_fmt_desc = get_format_info(desc.Format); + if (is_unknown_format(src_fmt_desc)) + return E_NOTIMPL; + + if (!src_palette && is_index_format(src_fmt_desc)) + { + FIXME("Default palette unimplemented.\n"); + return E_NOTIMPL; + } + + if (!src_box) + { + set_d3dbox(&src_box_tmp, 0, 0, desc.Width, desc.Height, 0, desc.Depth); + src_box = &src_box_tmp; + } + else + { + if (src_box->Left >= src_box->Right || src_box->Right > desc.Width + || src_box->Top >= src_box->Bottom || src_box->Bottom > desc.Height + || src_box->Front >= src_box->Back || src_box->Back > desc.Depth) + { + WARN("Invalid src_box specified.\n"); + return D3DERR_INVALIDCALL; + } + } + + get_aligned_rect(src_box->Left, src_box->Top, src_box->Right, src_box->Bottom, desc.Width, desc.Height, + src_fmt_desc, &src_rect_aligned); + set_d3dbox(&src_box_aligned, src_rect_aligned.left, src_rect_aligned.top, src_rect_aligned.right, + src_rect_aligned.bottom, src_box->Front, src_box->Back); + + hr = IDirect3DVolume9_LockBox(src_volume, &locked_box, &src_box_aligned, 0); + if (FAILED(hr)) + return hr; + + SetRect(&src_rect_unaligned, src_box->Left, src_box->Top, src_box->Right, src_box->Bottom); + OffsetRect(&src_rect_unaligned, -src_rect_aligned.left, -src_rect_aligned.top); + set_d3dx_pixels(&src_pixels, locked_box.pBits, locked_box.RowPitch, locked_box.SlicePitch, src_palette, + (src_box_aligned.Right - src_box_aligned.Left), (src_box_aligned.Bottom - src_box_aligned.Top), + (src_box_aligned.Back - src_box_aligned.Front), &src_rect_unaligned); + + hr = d3dx_save_pixels_to_memory(&src_pixels, src_fmt_desc, file_format, &buffer); + if (FAILED(hr)) + { + IDirect3DVolume9_UnlockBox(src_volume); + return hr; + } + + IDirect3DVolume9_UnlockBox(src_volume); + *dst_buffer = buffer; + return D3D_OK; }
HRESULT WINAPI D3DXSaveVolumeToFileA(const char *dst_filename, D3DXIMAGE_FILEFORMAT file_format, IDirect3DVolume9 *src_volume, const PALETTEENTRY *src_palette, const D3DBOX *src_box) { - FIXME("dst_filename %s, file_format %#x, src_volume %p, src_palette %p, src_box %p stub.\n", - wine_dbgstr_a(dst_filename), file_format, src_volume, src_palette, src_box); - return E_NOTIMPL; + ID3DXBuffer *buffer; + WCHAR *filename; + int32_t len; + HRESULT hr; + + TRACE("(%s, %#x, %p, %p, %p): relay.\n", wine_dbgstr_a(dst_filename), file_format, src_volume, src_palette, src_box); + + if (!dst_filename) + return D3DERR_INVALIDCALL; + + len = MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, NULL, 0); + filename = malloc(len * sizeof(WCHAR)); + if (!filename) + return E_OUTOFMEMORY; + MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, filename, len); + + hr = D3DXSaveVolumeToFileInMemory(&buffer, file_format, src_volume, src_palette, src_box); + if (SUCCEEDED(hr)) + { + hr = write_buffer_to_file(filename, buffer); + ID3DXBuffer_Release(buffer); + } + + free(filename); + return hr; }
HRESULT WINAPI D3DXSaveVolumeToFileW(const WCHAR *dst_filename, D3DXIMAGE_FILEFORMAT file_format, IDirect3DVolume9 *src_volume, const PALETTEENTRY *src_palette, const D3DBOX *src_box) { - FIXME("dst_filename %s, file_format %#x, src_volume %p, src_palette %p, src_box %p stub.\n", - wine_dbgstr_w(dst_filename), file_format, src_volume, src_palette, src_box); - return E_NOTIMPL; + ID3DXBuffer *buffer; + HRESULT hr; + + TRACE("(%s, %#x, %p, %p, %p): relay.\n", wine_dbgstr_w(dst_filename), file_format, src_volume, src_palette, src_box); + + if (!dst_filename) + return D3DERR_INVALIDCALL; + + hr = D3DXSaveVolumeToFileInMemory(&buffer, file_format, src_volume, src_palette, src_box); + if (SUCCEEDED(hr)) + { + hr = write_buffer_to_file(dst_filename, buffer); + ID3DXBuffer_Release(buffer); + } + + return hr; }