From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 1 + dlls/d3dx9_36/surface.c | 172 +++++++++++++++++++++++++--------- 2 files changed, 127 insertions(+), 46 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 6ffb1e7ae08..4fc755338df 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -83,6 +83,7 @@ struct d3dx_sub_resource uint32_t width; uint32_t height; uint32_t depth; + RECT unaligned_rect; };
struct d3dx_resource; diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index ebaf347d65f..e2106f4b110 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -768,6 +768,7 @@ static HRESULT __stdcall d3dx_image_resource_get_sub_resource(struct d3dx_resour sub_rsrc->width = resource->width; sub_rsrc->height = resource->height; sub_rsrc->depth = resource->depth; + SetRect(&sub_rsrc->unaligned_rect, 0, 0, sub_rsrc->width, sub_rsrc->height);
return hr; } @@ -1995,6 +1996,49 @@ exit: return S_OK; }
+/* + * Pack a d3dx_sub_resource structure for an image in memory, offsetting the + * base address if necessary. + */ +static HRESULT set_d3dx_sub_resource_from_memory(const void *data, uint32_t row_pitch, uint32_t slice_pitch, + const PALETTEENTRY *palette, D3DFORMAT format, int32_t left, int32_t top, int32_t right, int32_t bottom, + uint32_t front, uint32_t back, struct d3dx_sub_resource *sub_rsrc) +{ + const struct pixel_format_desc *fmt_desc = get_format_info(format); + const BYTE *data_offset = data; + + memset(sub_rsrc, 0, sizeof(*sub_rsrc)); + if (fmt_desc->type == FORMAT_UNKNOWN) + { + FIXME("Unsupported format %#x.\n", format); + return E_NOTIMPL; + } + + data_offset += front * slice_pitch; + data_offset += (top / fmt_desc->block_height) * row_pitch; + data_offset += (left / fmt_desc->block_width) * fmt_desc->block_byte_count; + + sub_rsrc->data = data_offset; + sub_rsrc->row_pitch = row_pitch; + sub_rsrc->slice_pitch = slice_pitch; + sub_rsrc->palette = palette; + sub_rsrc->width = right - left; + sub_rsrc->height = bottom - top; + sub_rsrc->depth = back - front; + + if (fmt_desc->type == FORMAT_DXT) + { + int32_t left_aligned, top_aligned; + + top_aligned = top & ~(fmt_desc->block_height - 1); + left_aligned = left & ~(fmt_desc->block_width - 1); + SetRect(&sub_rsrc->unaligned_rect, left, top, right, bottom); + OffsetRect(&sub_rsrc->unaligned_rect, -left_aligned, -top_aligned); + } + + return S_OK; +} + static void set_volume_struct(struct volume *volume, uint32_t width, uint32_t height, uint32_t depth) { volume->width = width; @@ -2002,40 +2046,51 @@ static void set_volume_struct(struct volume *volume, uint32_t width, uint32_t he volume->depth = depth; }
-static HRESULT d3dx_load_image_from_memory(void *dst_memory, uint32_t dst_row_pitch, const struct pixel_format_desc *dst_desc, - const PALETTEENTRY *dst_palette, const RECT *dst_rect, const RECT *dst_rect_aligned, const void *src_memory, - uint32_t src_row_pitch, const struct pixel_format_desc *src_desc, const PALETTEENTRY *src_palette, const RECT *src_rect, - uint32_t filter_flags, uint32_t color_key) +static const char *debug_d3dx_sub_resource(struct d3dx_sub_resource *sub_rsrc) +{ + if (!sub_rsrc) return "(null)"; + return wine_dbg_sprintf("data %p, row_pitch %d, slice_pitch %d, palette %p, width %d, height %d, depth %d, " + "unaligned_rect %s", sub_rsrc->data, sub_rsrc->row_pitch, sub_rsrc->slice_pitch, sub_rsrc->palette, + sub_rsrc->width, sub_rsrc->height, sub_rsrc->depth, wine_dbgstr_rect(&sub_rsrc->unaligned_rect)); +} + +static HRESULT d3dx_load_sub_resource_from_sub_resource(struct d3dx_sub_resource *dst_sub_rsrc, + const struct pixel_format_desc *dst_desc, struct d3dx_sub_resource *src_sub_rsrc, + const struct pixel_format_desc *src_desc, uint32_t filter_flags, uint32_t color_key) { struct volume src_size, dst_size, dst_size_aligned; - const BYTE *src_memory_offset = src_memory; HRESULT hr = S_OK;
- TRACE("dst_memory %p, dst_row_pitch %d, dst_desc %p, dst_palette %p, dst_rect %s, dst_rect_aligned %s, src_memory %p, " - "src_row_pitch %d, src_desc %p, src_palette %p, src_rect %s, filter %#x, color_key 0x%08x.\n", - dst_memory, dst_row_pitch, dst_desc, dst_palette, wine_dbgstr_rect(dst_rect), wine_dbgstr_rect(dst_rect_aligned), - src_memory, src_row_pitch, src_desc, src_palette, wine_dbgstr_rect(src_rect), filter_flags, color_key); + TRACE("dst_sub_rsrc %s, dst_desc %p, src_sub_rsrc %s, src_desc %p, filter_flags %#x, color_key %#x.\n", + debug_d3dx_sub_resource(dst_sub_rsrc), dst_desc, debug_d3dx_sub_resource(src_sub_rsrc), src_desc, + filter_flags, color_key);
- set_volume_struct(&src_size, (src_rect->right - src_rect->left), (src_rect->bottom - src_rect->top), 1); - set_volume_struct(&dst_size, (dst_rect->right - dst_rect->left), (dst_rect->bottom - dst_rect->top), 1); - set_volume_struct(&dst_size_aligned, (dst_rect_aligned->right - dst_rect_aligned->left), - (dst_rect_aligned->bottom - dst_rect_aligned->top), 1); + if (src_desc->type == FORMAT_DXT) + set_volume_struct(&src_size, (src_sub_rsrc->unaligned_rect.right - src_sub_rsrc->unaligned_rect.left), + (src_sub_rsrc->unaligned_rect.bottom - src_sub_rsrc->unaligned_rect.top), src_sub_rsrc->depth); + else + set_volume_struct(&src_size, src_sub_rsrc->width, src_sub_rsrc->height, src_sub_rsrc->depth);
- src_memory_offset += (src_rect->top / src_desc->block_height) * src_row_pitch; - src_memory_offset += (src_rect->left / src_desc->block_width) * src_desc->block_byte_count; + set_volume_struct(&dst_size_aligned, dst_sub_rsrc->width, dst_sub_rsrc->height, dst_sub_rsrc->depth); + if (dst_desc->type == FORMAT_DXT) + set_volume_struct(&dst_size, (dst_sub_rsrc->unaligned_rect.right - dst_sub_rsrc->unaligned_rect.left), + (dst_sub_rsrc->unaligned_rect.bottom - dst_sub_rsrc->unaligned_rect.top), dst_sub_rsrc->depth); + else + dst_size = dst_size_aligned;
/* Everything matches, simply copy the 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)) && color_key == 0 - && !(src_rect->left & (src_desc->block_width - 1)) - && !(src_rect->top & (src_desc->block_height - 1)) - && !(dst_rect->left & (dst_desc->block_width - 1)) - && !(dst_rect->top & (dst_desc->block_height - 1))) + && !(src_sub_rsrc->unaligned_rect.left & (src_desc->block_width - 1)) + && !(src_sub_rsrc->unaligned_rect.top & (src_desc->block_height - 1)) + && !(dst_sub_rsrc->unaligned_rect.left & (dst_desc->block_width - 1)) + && !(dst_sub_rsrc->unaligned_rect.top & (dst_desc->block_height - 1))) { TRACE("Simple copy.\n"); - copy_pixels(src_memory_offset, src_row_pitch, 0, dst_memory, dst_row_pitch, 0, &src_size, src_desc); + copy_pixels(src_sub_rsrc->data, src_sub_rsrc->row_pitch, src_sub_rsrc->slice_pitch, (void *)dst_sub_rsrc->data, + dst_sub_rsrc->row_pitch, dst_sub_rsrc->slice_pitch, &src_size, src_desc); return S_OK; }
@@ -2058,13 +2113,18 @@ static HRESULT d3dx_load_image_from_memory(void *dst_memory, uint32_t dst_row_pi void *uncompressed_mem = NULL; RECT uncompressed_rect;
- hr = d3dx_image_decompress(src_memory, src_row_pitch, src_rect, NULL, &src_size, src_desc, - &uncompressed_mem, &uncompressed_row_pitch, &uncompressed_rect, &uncompressed_desc); + hr = d3dx_image_decompress(src_sub_rsrc->data, src_sub_rsrc->row_pitch, &src_sub_rsrc->unaligned_rect, NULL, + &src_size, src_desc, &uncompressed_mem, &uncompressed_row_pitch, &uncompressed_rect, &uncompressed_desc); if (SUCCEEDED(hr)) { - hr = d3dx_load_image_from_memory(dst_memory, dst_row_pitch, dst_desc, dst_palette, dst_rect, dst_rect_aligned, - uncompressed_mem, uncompressed_row_pitch, uncompressed_desc, src_palette, &uncompressed_rect, - filter_flags, color_key); + struct d3dx_sub_resource uncompressed_sub_rsrc; + + set_d3dx_sub_resource_from_memory((const void *)uncompressed_mem, uncompressed_row_pitch, 0, NULL, + uncompressed_desc->format, 0, 0, src_sub_rsrc->width, src_sub_rsrc->height, 0, src_sub_rsrc->depth, + &uncompressed_sub_rsrc); + + hr = d3dx_load_sub_resource_from_sub_resource(dst_sub_rsrc, dst_desc, &uncompressed_sub_rsrc, + uncompressed_desc, filter_flags, color_key); } free(uncompressed_mem); return hr; @@ -2074,21 +2134,24 @@ static HRESULT d3dx_load_image_from_memory(void *dst_memory, uint32_t dst_row_pi if (dst_desc->type == FORMAT_DXT) { const struct pixel_format_desc *uncompressed_desc; + struct d3dx_sub_resource uncompressed_sub_rsrc; + RECT uncompressed_rect, aligned_rect; uint32_t uncompressed_row_pitch; void *uncompressed_mem = NULL; - BYTE *uncompressed_mem_offset; - RECT uncompressed_rect;
- hr = d3dx_image_decompress(dst_memory, dst_row_pitch, dst_rect_aligned, dst_rect, &dst_size_aligned, dst_desc, - &uncompressed_mem, &uncompressed_row_pitch, &uncompressed_rect, &uncompressed_desc); + SetRect(&aligned_rect, 0, 0, dst_sub_rsrc->width, dst_sub_rsrc->height); + hr = d3dx_image_decompress(dst_sub_rsrc->data, dst_sub_rsrc->row_pitch, &aligned_rect, + &dst_sub_rsrc->unaligned_rect, &dst_size_aligned, dst_desc, &uncompressed_mem, &uncompressed_row_pitch, + &uncompressed_rect, &uncompressed_desc); if (FAILED(hr)) return hr;
- uncompressed_mem_offset = (BYTE *)uncompressed_mem + (dst_rect->top - dst_rect_aligned->top) * uncompressed_row_pitch - + (dst_rect->left - dst_rect_aligned->left) * uncompressed_desc->bytes_per_pixel; - hr = d3dx_load_image_from_memory(uncompressed_mem_offset, uncompressed_row_pitch, uncompressed_desc, dst_palette, - &uncompressed_rect, &uncompressed_rect, src_memory, src_row_pitch, src_desc, src_palette, - src_rect, filter_flags, color_key); + set_d3dx_sub_resource_from_memory((const void *)uncompressed_mem, uncompressed_row_pitch, 0, NULL, + uncompressed_desc->format, dst_sub_rsrc->unaligned_rect.left, dst_sub_rsrc->unaligned_rect.top, + dst_sub_rsrc->unaligned_rect.right, dst_sub_rsrc->unaligned_rect.bottom, 0, 1, &uncompressed_sub_rsrc); + + hr = d3dx_load_sub_resource_from_sub_resource(&uncompressed_sub_rsrc, uncompressed_desc, src_sub_rsrc, + src_desc, filter_flags, color_key); if (SUCCEEDED(hr)) { GLenum gl_format = 0; @@ -2111,7 +2174,7 @@ static HRESULT d3dx_load_image_from_memory(void *dst_memory, uint32_t dst_row_pi 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, - dst_memory, dst_row_pitch); + (BYTE *)dst_sub_rsrc->data, dst_sub_rsrc->row_pitch); } free(uncompressed_mem); return hr; @@ -2119,8 +2182,9 @@ static HRESULT d3dx_load_image_from_memory(void *dst_memory, uint32_t dst_row_pi
if ((filter_flags & 0xf) == D3DX_FILTER_NONE) { - convert_argb_pixels(src_memory_offset, src_row_pitch, 0, &src_size, src_desc, - dst_memory, dst_row_pitch, 0, &dst_size, dst_desc, color_key, src_palette); + convert_argb_pixels(src_sub_rsrc->data, src_sub_rsrc->row_pitch, src_sub_rsrc->slice_pitch, &src_size, src_desc, + (BYTE *)dst_sub_rsrc->data, dst_sub_rsrc->row_pitch, dst_sub_rsrc->slice_pitch, &dst_size, dst_desc, + color_key, src_sub_rsrc->palette); } else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */ { @@ -2129,8 +2193,9 @@ static HRESULT d3dx_load_image_from_memory(void *dst_memory, uint32_t dst_row_pi
/* Always apply a point filter until D3DX_FILTER_LINEAR, * D3DX_FILTER_TRIANGLE and D3DX_FILTER_BOX are implemented. */ - point_filter_argb_pixels(src_memory_offset, src_row_pitch, 0, &src_size, src_desc, dst_memory, dst_row_pitch, 0, - &dst_size, dst_desc, color_key, src_palette); + point_filter_argb_pixels(src_sub_rsrc->data, src_sub_rsrc->row_pitch, src_sub_rsrc->slice_pitch, &src_size, + src_desc, (BYTE *)dst_sub_rsrc->data, dst_sub_rsrc->row_pitch, dst_sub_rsrc->slice_pitch, &dst_size, + dst_desc, color_key, src_sub_rsrc->palette); }
return hr; @@ -2173,8 +2238,9 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, D3DFORMAT src_format, UINT src_pitch, const PALETTEENTRY *src_palette, const RECT *src_rect, DWORD filter, D3DCOLOR color_key) { - RECT dst_rect_temp, dst_rect_aligned, dst_locked_rect, dst_locked_rect_aligned; const struct pixel_format_desc *srcformatdesc, *destformatdesc; + struct d3dx_sub_resource src_sub_rsrc, dst_sub_rsrc; + RECT dst_rect_temp, dst_rect_aligned; IDirect3DSurface9 *surface; D3DSURFACE_DESC surfdesc; D3DLOCKED_RECT lockrect; @@ -2246,15 +2312,29 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, if (filter == D3DX_DEFAULT) filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
+ hr = set_d3dx_sub_resource_from_memory(src_memory, src_pitch, 0, src_palette, srcformatdesc->format, + src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1, &src_sub_rsrc); + if (FAILED(hr)) + { + WARN("set_d3dx_sub_resource_from_memory failed with hr %#lx.\n", hr); + return hr; + } + if (FAILED(hr = lock_surface(dst_surface, &dst_rect_aligned, &lockrect, &surface, TRUE))) return hr;
- dst_locked_rect_aligned = dst_rect_aligned; - dst_locked_rect = *dst_rect; - OffsetRect(&dst_locked_rect_aligned, -dst_rect_aligned.left, -dst_rect_aligned.top); - OffsetRect(&dst_locked_rect, -dst_rect_aligned.left, -dst_rect_aligned.top); - hr = d3dx_load_image_from_memory(lockrect.pBits, lockrect.Pitch, destformatdesc, dst_palette, &dst_locked_rect, - &dst_locked_rect_aligned, src_memory, src_pitch, srcformatdesc, src_palette, src_rect, filter, color_key); + dst_sub_rsrc.data = lockrect.pBits; + dst_sub_rsrc.row_pitch = lockrect.Pitch; + dst_sub_rsrc.slice_pitch = 0; + dst_sub_rsrc.palette = dst_palette; + dst_sub_rsrc.width = dst_rect_aligned.right - dst_rect_aligned.left; + dst_sub_rsrc.height = dst_rect_aligned.bottom - dst_rect_aligned.top; + dst_sub_rsrc.depth = 1; + dst_sub_rsrc.unaligned_rect = *dst_rect; + OffsetRect(&dst_sub_rsrc.unaligned_rect, -dst_rect_aligned.left, -dst_rect_aligned.top); + + hr = d3dx_load_sub_resource_from_sub_resource(&dst_sub_rsrc, destformatdesc, &src_sub_rsrc, srcformatdesc, filter, + color_key); if (FAILED(hr)) WARN("d3dx_load_image_from_memory failed with hr %#lx\n", hr);