From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 8 ++ dlls/d3dx9_36/surface.c | 105 +++++++++++++++---------- dlls/d3dx9_36/tests/volume.c | 2 +- dlls/d3dx9_36/volume.c | 142 ++++++++++++---------------------- 4 files changed, 122 insertions(+), 135 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 722ed73ae0f..001a7f26f4f 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -182,6 +182,14 @@ 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_pixels_init(const void *data, uint32_t row_pitch, uint32_t slice_pitch, + const PALETTEENTRY *palette, D3DFORMAT format, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, + uint32_t front, uint32_t back, struct d3dx_pixels *pixels); +HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, + const struct pixel_format_desc *dst_desc, struct d3dx_pixels *src_pixels, + const struct pixel_format_desc *src_desc, uint32_t filter_flags, uint32_t color_key); +void get_aligned_rect(uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t width, uint32_t height, + const struct pixel_format_desc *fmt_desc, RECT *aligned_rect);
unsigned short float_32_to_16(const float in); float float_16_to_32(const unsigned short in); diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index a249fedde84..dd84528a0d5 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1902,12 +1902,13 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic }
static HRESULT d3dx_pixels_decompress(struct d3dx_pixels *pixels, const struct pixel_format_desc *desc, - BOOL is_dst, void **out_memory, uint32_t *out_row_pitch, const struct pixel_format_desc **out_desc) + BOOL is_dst, void **out_memory, uint32_t *out_row_pitch, uint32_t *out_slice_pitch, + const struct pixel_format_desc **out_desc) { void (*fetch_dxt_texel)(int srcRowStride, const BYTE *pixdata, int i, int j, void *texel); + uint32_t x, y, z, tmp_pitch, uncompressed_slice_pitch, uncompressed_row_pitch; const struct pixel_format_desc *uncompressed_desc = NULL; const struct volume *size = &pixels->size; - uint32_t x, y, tmp_pitch; BYTE *uncompressed_mem;
switch (desc->format) @@ -1931,7 +1932,9 @@ static HRESULT d3dx_pixels_decompress(struct d3dx_pixels *pixels, const struct p return E_NOTIMPL; }
- if (!(uncompressed_mem = malloc(size->width * size->height * size->depth * uncompressed_desc->bytes_per_pixel))) + uncompressed_row_pitch = size->width * uncompressed_desc->bytes_per_pixel; + uncompressed_slice_pitch = uncompressed_row_pitch * size->height; + if (!(uncompressed_mem = malloc(size->depth * uncompressed_slice_pitch))) return E_OUTOFMEMORY;
/* @@ -1954,31 +1957,37 @@ static HRESULT d3dx_pixels_decompress(struct d3dx_pixels *pixels, const struct p
TRACE("Decompressing pixels.\n"); tmp_pitch = pixels->row_pitch * desc->block_width / desc->block_byte_count; - for (y = 0; y < size->height; ++y) + for (z = 0; z < size->depth; ++z) { - BYTE *ptr = &uncompressed_mem[y * size->width * uncompressed_desc->bytes_per_pixel]; - for (x = 0; x < size->width; ++x) + const BYTE *slice_data = ((BYTE *)pixels->data) + (pixels->slice_pitch * z); + + for (y = 0; y < size->height; ++y) { - const POINT pt = { x, y }; - - if (!is_dst) - fetch_dxt_texel(tmp_pitch, (BYTE *)pixels->data, x + pixels->unaligned_rect.left, - y + pixels->unaligned_rect.top, ptr); - else if (!PtInRect(&pixels->unaligned_rect, pt)) - fetch_dxt_texel(tmp_pitch, (BYTE *)pixels->data, x, y, ptr); - ptr += uncompressed_desc->bytes_per_pixel; + BYTE *ptr = &uncompressed_mem[(z * uncompressed_slice_pitch) + (y * uncompressed_row_pitch)]; + for (x = 0; x < size->width; ++x) + { + const POINT pt = { x, y }; + + if (!is_dst) + fetch_dxt_texel(tmp_pitch, slice_data, x + pixels->unaligned_rect.left, + y + pixels->unaligned_rect.top, ptr); + else if (!PtInRect(&pixels->unaligned_rect, pt)) + fetch_dxt_texel(tmp_pitch, slice_data, x, y, ptr); + ptr += uncompressed_desc->bytes_per_pixel; + } } }
exit: *out_memory = uncompressed_mem; - *out_row_pitch = size->width * uncompressed_desc->bytes_per_pixel; + *out_row_pitch = uncompressed_row_pitch; + *out_slice_pitch = uncompressed_slice_pitch; *out_desc = uncompressed_desc;
return S_OK; }
-static HRESULT d3dx_pixels_init(const void *data, uint32_t row_pitch, uint32_t slice_pitch, +HRESULT d3dx_pixels_init(const void *data, uint32_t row_pitch, uint32_t slice_pitch, const PALETTEENTRY *palette, D3DFORMAT format, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t front, uint32_t back, struct d3dx_pixels *pixels) { @@ -2026,7 +2035,7 @@ static const char *debug_d3dx_pixels(struct d3dx_pixels *pixels) pixels->size.width, pixels->size.height, pixels->size.depth, wine_dbgstr_rect(&pixels->unaligned_rect)); }
-static HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, +HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, const struct pixel_format_desc *dst_desc, struct d3dx_pixels *src_pixels, const struct pixel_format_desc *src_desc, uint32_t filter_flags, uint32_t color_key) { @@ -2054,6 +2063,7 @@ static HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, if (src_desc->format == dst_desc->format && (dst_size.width == src_size.width && !(dst_size.width % dst_desc->block_width)) && (dst_size.height == src_size.height && !(dst_size.height % dst_desc->block_height)) + && (dst_size.depth == src_size.depth) && color_key == 0 && !(src_pixels->unaligned_rect.left & (src_desc->block_width - 1)) && !(src_pixels->unaligned_rect.top & (src_desc->block_height - 1)) @@ -2080,19 +2090,19 @@ static HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, */ if (src_desc->type == FORMAT_DXT) { + uint32_t uncompressed_row_pitch, uncompressed_slice_pitch; const struct pixel_format_desc *uncompressed_desc; - uint32_t uncompressed_row_pitch; void *uncompressed_mem = NULL;
hr = d3dx_pixels_decompress(src_pixels, src_desc, FALSE, &uncompressed_mem, &uncompressed_row_pitch, - &uncompressed_desc); + &uncompressed_slice_pitch, &uncompressed_desc); if (SUCCEEDED(hr)) { struct d3dx_pixels uncompressed_pixels;
- d3dx_pixels_init(uncompressed_mem, uncompressed_row_pitch, 0, NULL, uncompressed_desc->format, - 0, 0, src_pixels->size.width, src_pixels->size.height, 0, src_pixels->size.depth, - &uncompressed_pixels); + d3dx_pixels_init(uncompressed_mem, uncompressed_row_pitch, uncompressed_slice_pitch, NULL, + uncompressed_desc->format, 0, 0, src_pixels->size.width, src_pixels->size.height, + 0, src_pixels->size.depth, &uncompressed_pixels);
hr = d3dx_load_pixels_from_pixels(dst_pixels, dst_desc, &uncompressed_pixels, uncompressed_desc, filter_flags, color_key); @@ -2104,25 +2114,27 @@ static HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, /* Same as the above, need to decompress the destination prior to modifying. */ if (dst_desc->type == FORMAT_DXT) { + uint32_t uncompressed_row_pitch, uncompressed_slice_pitch; const struct pixel_format_desc *uncompressed_desc; struct d3dx_pixels uncompressed_pixels; - uint32_t uncompressed_row_pitch; void *uncompressed_mem = NULL;
hr = d3dx_pixels_decompress(dst_pixels, dst_desc, TRUE, &uncompressed_mem, &uncompressed_row_pitch, - &uncompressed_desc); + &uncompressed_slice_pitch, &uncompressed_desc); if (FAILED(hr)) goto exit;
- d3dx_pixels_init(uncompressed_mem, uncompressed_row_pitch, 0, NULL, + d3dx_pixels_init(uncompressed_mem, uncompressed_row_pitch, uncompressed_slice_pitch, NULL, uncompressed_desc->format, dst_pixels->unaligned_rect.left, dst_pixels->unaligned_rect.top, - dst_pixels->unaligned_rect.right, dst_pixels->unaligned_rect.bottom, 0, 1, &uncompressed_pixels); + dst_pixels->unaligned_rect.right, dst_pixels->unaligned_rect.bottom, 0, dst_pixels->size.depth, + &uncompressed_pixels);
hr = d3dx_load_pixels_from_pixels(&uncompressed_pixels, uncompressed_desc, src_pixels, src_desc, filter_flags, color_key); if (SUCCEEDED(hr)) { GLenum gl_format = 0; + uint32_t i;
TRACE("Compressing DXTn surface.\n"); switch (dst_desc->format) @@ -2141,8 +2153,15 @@ static HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, default: ERR("Unexpected destination compressed format %u.\n", dst_desc->format); } - tx_compress_dxtn(4, dst_size_aligned.width, dst_size_aligned.height, uncompressed_mem, gl_format, - (BYTE *)dst_pixels->data, dst_pixels->row_pitch); + + for (i = 0; i < dst_size_aligned.depth; ++i) + { + BYTE *uncompressed_mem_slice = (BYTE *)uncompressed_mem + (i * uncompressed_slice_pitch); + BYTE *dst_memory_slice = ((BYTE *)dst_pixels->data) + (i * dst_pixels->slice_pitch); + + tx_compress_dxtn(4, dst_size_aligned.width, dst_size_aligned.height, uncompressed_mem_slice, gl_format, + dst_memory_slice, dst_pixels->row_pitch); + } } free(uncompressed_mem); goto exit; @@ -2172,6 +2191,22 @@ exit: return hr; }
+void get_aligned_rect(uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t width, uint32_t height, + const struct pixel_format_desc *fmt_desc, RECT *aligned_rect) +{ + SetRect(aligned_rect, left, top, right, bottom); + if (aligned_rect->left & (fmt_desc->block_width - 1)) + aligned_rect->left = aligned_rect->left & ~(fmt_desc->block_width - 1); + if (aligned_rect->top & (fmt_desc->block_height - 1)) + aligned_rect->top = aligned_rect->top & ~(fmt_desc->block_height - 1); + if (aligned_rect->right & (fmt_desc->block_width - 1) && aligned_rect->right != width) + aligned_rect->right = min((aligned_rect->right + fmt_desc->block_width - 1) + & ~(fmt_desc->block_width - 1), width); + if (aligned_rect->bottom & (fmt_desc->block_height - 1) && aligned_rect->bottom != height) + aligned_rect->bottom = min((aligned_rect->bottom + fmt_desc->block_height - 1) + & ~(fmt_desc->block_height - 1), height); +} + /************************************************************ * D3DXLoadSurfaceFromMemory * @@ -2268,18 +2303,6 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, } }
- dst_rect_aligned = *dst_rect; - if (dst_rect_aligned.left & (destformatdesc->block_width - 1)) - dst_rect_aligned.left = dst_rect_aligned.left & ~(destformatdesc->block_width - 1); - if (dst_rect_aligned.top & (destformatdesc->block_height - 1)) - dst_rect_aligned.top = dst_rect_aligned.top & ~(destformatdesc->block_height - 1); - if (dst_rect_aligned.right & (destformatdesc->block_width - 1) && dst_rect_aligned.right != surfdesc.Width) - dst_rect_aligned.right = min((dst_rect_aligned.right + destformatdesc->block_width - 1) - & ~(destformatdesc->block_width - 1), surfdesc.Width); - if (dst_rect_aligned.bottom & (destformatdesc->block_height - 1) && dst_rect_aligned.bottom != surfdesc.Height) - dst_rect_aligned.bottom = min((dst_rect_aligned.bottom + destformatdesc->block_height - 1) - & ~(destformatdesc->block_height - 1), surfdesc.Height); - if (filter == D3DX_DEFAULT) filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
@@ -2288,6 +2311,8 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, if (FAILED(hr)) return hr;
+ get_aligned_rect(dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, surfdesc.Width, surfdesc.Height, + destformatdesc, &dst_rect_aligned); if (FAILED(hr = lock_surface(dst_surface, &dst_rect_aligned, &lockrect, &surface, TRUE))) return hr;
diff --git a/dlls/d3dx9_36/tests/volume.c b/dlls/d3dx9_36/tests/volume.c index 52075aa6314..f990221f06b 100644 --- a/dlls/d3dx9_36/tests/volume.c +++ b/dlls/d3dx9_36/tests/volume.c @@ -205,7 +205,7 @@ static void test_D3DXLoadVolumeFromMemory(IDirect3DDevice9 *device) set_box(&src_box, 1, 1, 7, 7, 0, 1); set_box(&dst_box, 1, 1, 7, 7, 0, 1); hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 32, NULL, &src_box, D3DX_DEFAULT, 0); - todo_wine ok(hr == D3D_OK, "D3DXLoadVolumeFromMemory returned %#lx, expected %#lx\n", hr, D3D_OK); + ok(hr == D3D_OK, "D3DXLoadVolumeFromMemory returned %#lx, expected %#lx\n", hr, D3D_OK);
IDirect3DVolume9_Release(volume); IDirect3DVolumeTexture9_Release(volume_texture); diff --git a/dlls/d3dx9_36/volume.c b/dlls/d3dx9_36/volume.c index 4d29cfe1e31..0006a521532 100644 --- a/dlls/d3dx9_36/volume.c +++ b/dlls/d3dx9_36/volume.c @@ -71,16 +71,29 @@ HRESULT WINAPI D3DXLoadVolumeFromFileW(IDirect3DVolume9 *dst_volume, const PALET return hr; }
+static void set_d3dbox(D3DBOX *box, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t front, + uint32_t back) +{ + box->Left = left; + box->Top = top; + box->Right = right; + box->Bottom = bottom; + box->Front = front; + box->Back = back; +} + HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette, const D3DBOX *dst_box, const void *src_memory, D3DFORMAT src_format, UINT src_row_pitch, UINT src_slice_pitch, const PALETTEENTRY *src_palette, const D3DBOX *src_box, DWORD filter, D3DCOLOR color_key) { - HRESULT hr; - D3DVOLUME_DESC desc; - D3DLOCKED_BOX locked_box; - struct volume dst_size, src_size; const struct pixel_format_desc *src_format_desc, *dst_format_desc; + struct d3dx_pixels src_pixels, dst_pixels; + RECT dst_rect_aligned, dst_rect_unaligned; + D3DBOX dst_box_aligned, dst_box_tmp; + D3DLOCKED_BOX locked_box; + D3DVOLUME_DESC desc; + HRESULT hr;
TRACE("dst_volume %p, dst_palette %p, dst_box %p, src_memory %p, src_format %#x, " "src_row_pitch %u, src_slice_pitch %u, src_palette %p, src_box %p, filter %#lx, color_key 0x%08lx.\n", @@ -98,17 +111,19 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, if (filter == D3DX_DEFAULT) filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
- IDirect3DVolume9_GetDesc(dst_volume, &desc); + src_format_desc = get_format_info(src_format); + if (src_format_desc->type == FORMAT_UNKNOWN) + return E_NOTIMPL;
- src_size.width = src_box->Right - src_box->Left; - src_size.height = src_box->Bottom - src_box->Top; - src_size.depth = src_box->Back - src_box->Front; + IDirect3DVolume9_GetDesc(dst_volume, &desc); + dst_format_desc = get_format_info(desc.Format); + if (dst_format_desc->type == FORMAT_UNKNOWN) + return E_NOTIMPL;
if (!dst_box) { - dst_size.width = desc.Width; - dst_size.height = desc.Height; - dst_size.depth = desc.Depth; + set_d3dbox(&dst_box_tmp, 0, 0, desc.Width, desc.Height, 0, desc.Depth); + dst_box = &dst_box_tmp; } else { @@ -118,94 +133,33 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, return D3DERR_INVALIDCALL; if (dst_box->Front >= dst_box->Back || dst_box->Back > desc.Depth) return D3DERR_INVALIDCALL; - - dst_size.width = dst_box->Right - dst_box->Left; - dst_size.height = dst_box->Bottom - dst_box->Top; - dst_size.depth = dst_box->Back - dst_box->Front; }
- src_format_desc = get_format_info(src_format); - if (src_format_desc->type == FORMAT_UNKNOWN) - return E_NOTIMPL; + hr = d3dx_pixels_init(src_memory, src_row_pitch, src_slice_pitch, + src_palette, src_format, src_box->Left, src_box->Top, src_box->Right, src_box->Bottom, + src_box->Front, src_box->Back, &src_pixels); + if (FAILED(hr)) + return hr;
- dst_format_desc = get_format_info(desc.Format); - if (dst_format_desc->type == FORMAT_UNKNOWN) - return E_NOTIMPL; + get_aligned_rect(dst_box->Left, dst_box->Top, dst_box->Right, dst_box->Bottom, desc.Width, desc.Height, + dst_format_desc, &dst_rect_aligned); + set_d3dbox(&dst_box_aligned, dst_rect_aligned.left, dst_rect_aligned.top, dst_rect_aligned.right, + dst_rect_aligned.bottom, dst_box->Front, dst_box->Back);
- if (desc.Format == src_format - && dst_size.width == src_size.width - && dst_size.height == src_size.height - && dst_size.depth == src_size.depth - && color_key == 0) - { - const BYTE *src_addr; - - if (src_box->Left & (src_format_desc->block_width - 1) - || src_box->Top & (src_format_desc->block_height - 1) - || (src_box->Right & (src_format_desc->block_width - 1) - && src_size.width != desc.Width) - || (src_box->Bottom & (src_format_desc->block_height - 1) - && src_size.height != desc.Height)) - { - FIXME("Source box (%u, %u, %u, %u) is misaligned\n", - src_box->Left, src_box->Top, src_box->Right, src_box->Bottom); - return E_NOTIMPL; - } - - src_addr = src_memory; - src_addr += src_box->Front * src_slice_pitch; - src_addr += (src_box->Top / src_format_desc->block_height) * src_row_pitch; - src_addr += (src_box->Left / src_format_desc->block_width) * src_format_desc->block_byte_count; - - hr = IDirect3DVolume9_LockBox(dst_volume, &locked_box, dst_box, 0); - if (FAILED(hr)) return hr; - - copy_pixels(src_addr, src_row_pitch, src_slice_pitch, - locked_box.pBits, locked_box.RowPitch, locked_box.SlicePitch, - &dst_size, dst_format_desc); - - IDirect3DVolume9_UnlockBox(dst_volume); - } - else - { - const BYTE *src_addr; - - if (!is_conversion_from_supported(src_format_desc) - || !is_conversion_to_supported(dst_format_desc)) - { - FIXME("Pixel format conversion is not implemented %#x -> %#x\n", - src_format_desc->format, dst_format_desc->format); - return E_NOTIMPL; - } - - src_addr = src_memory; - src_addr += src_box->Front * src_slice_pitch; - src_addr += src_box->Top * src_row_pitch; - src_addr += src_box->Left * src_format_desc->bytes_per_pixel; - - hr = IDirect3DVolume9_LockBox(dst_volume, &locked_box, dst_box, 0); - if (FAILED(hr)) return hr; - - if ((filter & 0xf) == D3DX_FILTER_NONE) - { - convert_argb_pixels(src_memory, src_row_pitch, src_slice_pitch, &src_size, src_format_desc, - locked_box.pBits, locked_box.RowPitch, locked_box.SlicePitch, &dst_size, dst_format_desc, color_key, - src_palette); - } - else - { - if ((filter & 0xf) != D3DX_FILTER_POINT) - FIXME("Unhandled filter %#lx.\n", filter); - - point_filter_argb_pixels(src_addr, src_row_pitch, src_slice_pitch, &src_size, src_format_desc, - locked_box.pBits, locked_box.RowPitch, locked_box.SlicePitch, &dst_size, dst_format_desc, color_key, - src_palette); - } - - IDirect3DVolume9_UnlockBox(dst_volume); - } + hr = IDirect3DVolume9_LockBox(dst_volume, &locked_box, &dst_box_aligned, 0); + if (FAILED(hr)) + return hr;
- return D3D_OK; + SetRect(&dst_rect_unaligned, dst_box->Left, dst_box->Top, dst_box->Right, dst_box->Bottom); + OffsetRect(&dst_rect_unaligned, -dst_rect_aligned.left, -dst_rect_aligned.top); + set_d3dx_pixels(&dst_pixels, locked_box.pBits, locked_box.RowPitch, locked_box.SlicePitch, dst_palette, + (dst_box_aligned.Right - dst_box_aligned.Left), (dst_box_aligned.Bottom - dst_box_aligned.Top), + (dst_box_aligned.Back - dst_box_aligned.Front), &dst_rect_unaligned); + + hr = d3dx_load_pixels_from_pixels(&dst_pixels, dst_format_desc, &src_pixels, src_format_desc, filter, + color_key); + IDirect3DVolume9_UnlockBox(dst_volume); + return hr; }
HRESULT WINAPI D3DXLoadVolumeFromFileInMemory(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette,