diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h index 79f3b76..d2bacd0 100644 --- a/dlls/d3dx9_36/d3dx9_36_private.h +++ b/dlls/d3dx9_36/d3dx9_36_private.h @@ -67,6 +67,10 @@ struct pixel_format_desc { void (*to_rgba)(const struct vec4 *src, struct vec4 *dst, const PALETTEENTRY *palette); }; +typedef BOOL (*dxtn_conversion_func)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, + int format, unsigned int w, unsigned int h); +dxtn_conversion_func get_dxtn_conversion_func(D3DFORMAT format, BOOL encode) DECLSPEC_HIDDEN; + HRESULT map_view_of_file(const WCHAR *filename, void **buffer, DWORD *length) DECLSPEC_HIDDEN; HRESULT load_resource_into_memory(HMODULE module, HRSRC resinfo, void **buffer, DWORD *length) DECLSPEC_HIDDEN; @@ -86,6 +90,10 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic const struct volume *src_size, const struct pixel_format_desc *src_format, 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) DECLSPEC_HIDDEN; +void smooth_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, + const struct volume *src_size, const struct pixel_format_desc *src_format, + 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, BOOL dither) 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, unsigned int skip_levels, diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 295ef63..05d8bfd 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1716,6 +1928,100 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic } } +typedef struct PIXEL { + BYTE b, g, r, a; +} PIXEL; + +#define SMOOTH(P) \ +do { \ + ((PIXEL*)dst_ptr)->P = (BYTE)((a01.P * (cx - dx) * 3 + a10.P * (cy - dy) * 3 + \ + a21.P * dx * 3 + a12.P * dy * 3 + a11.P * (cx + cy)) / ((cx + cy) * 4)); \ +} while(0) + +#define PRECISION 12 + +/* like triangle filter from ARGB to ARGB */ +void smooth_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, const struct volume *src_size, + const struct pixel_format_desc *src_format, 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, + BOOL dither) +{ + UINT x, y, z; + PIXEL a10, a11, a12, a01, a21; + int fx, cx, lx, dx, fy, cy, ly, dy; + + fx = (dst_size->width << PRECISION) / src_size->width; + fy = (dst_size->height << PRECISION) / src_size->height; + if (!fx || !fy) { + return; + } + + cx = ((fx - 1) >> PRECISION) + 1; + cy = ((fy - 1) >> PRECISION) + 1; + + for (z = 0; z < dst_size->depth; z++) + { + BYTE *dst_slice_ptr = dst + z * dst_slice_pitch; + const BYTE *src_slice_ptr = src + src_slice_pitch * (z * src_size->depth / dst_size->depth); + + for (y = 0; y < dst_size->height; y++) + { + BYTE *dst_ptr = dst_slice_ptr + y * dst_row_pitch; + const BYTE *src_row_ptr = src_slice_ptr + src_row_pitch * (y * src_size->height / dst_size->height); + ly = (y << PRECISION) / fy; + dy = y - ((ly * fy) >> PRECISION); + + for (x = 0; x < dst_size->width; x++) + { + const BYTE *src_ptr = src_row_ptr + (x * src_size->width / dst_size->width) * src_format->bytes_per_pixel; + + lx = (x << PRECISION) / fx; + dx = x - ((lx * fx) >> PRECISION); + + a11 = *(PIXEL*)src_ptr; + a10 = (y == 0)?a11:(*(PIXEL*)(src_ptr - src_row_pitch)); + a01 = (x == 0)?a11:(*(PIXEL*)(src_ptr - src_format->bytes_per_pixel)); + a21 = (x == dst_size->width)?a11:(*(PIXEL*)(src_ptr + src_format->bytes_per_pixel)); + a12 = (y == dst_size->height)?a11:(*(PIXEL*)(src_ptr + src_row_pitch)); + + SMOOTH(r); + SMOOTH(g); + SMOOTH(b); + SMOOTH(a); + + dst_ptr += dst_format->bytes_per_pixel; + } + } + } +} + + +/* typedef BOOL (*dxtn_conversion_func)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, + enum wined3d_format_id format, unsigned int w, unsigned int h); + * format must be WINED3DFMT_B8G8R8A8_UNORM + */ +dxtn_conversion_func get_dxtn_conversion_func(D3DFORMAT format, BOOL encode) +{ +#ifdef DXTN_COMPESSION_SUPPORTED + switch (format) + { + case D3DFMT_DXT1: + if (!wined3d_dxtn_supported()) return NULL; + return encode ? wined3d_dxt1_encode : wined3d_dxt1_decode; + case D3DFMT_DXT3: + if (!wined3d_dxtn_supported()) return NULL; + return encode ? wined3d_dxt3_encode : wined3d_dxt3_decode; + case D3DFMT_DXT5: + if (!wined3d_dxtn_supported()) return NULL; + return encode ? wined3d_dxt5_encode : wined3d_dxt5_decode; + default: + return NULL; + } +#else + return NULL; +#endif +} + /************************************************************ * D3DXLoadSurfaceFromMemory * @@ -1757,6 +1851,9 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, D3DSURFACE_DESC surfdesc; D3DLOCKED_RECT lockrect; struct volume src_size, dst_size; + HRESULT ret = D3D_OK; + RECT tmp_rect; + const BYTE *src_addr; TRACE("(%p, %p, %s, %p, %#x, %u, %p, %s, %#x, 0x%08x)\n", dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), src_memory, src_format, @@ -1787,6 +1884,10 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, { dst_size.width = surfdesc.Width; dst_size.height = surfdesc.Height; + tmp_rect.left = 0; + tmp_rect.right = dst_size.width; + tmp_rect.top = 0; + tmp_rect.bottom = dst_size.height; } else { @@ -1803,6 +1904,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, return D3D_OK; } dst_size.depth = 1; + TRACE("dst_size = (%d, %d, %d)\n", dst_size.width, dst_size.height, dst_size.depth); srcformatdesc = get_format_info(src_format); destformatdesc = get_format_info(surfdesc.Format); @@ -1812,6 +1914,13 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, return E_NOTIMPL; } + /* initial src address shift if top:left != 0:0 + * assume src_rect correspond to image size while src_addr is byte address in compressed array, as src_pitch + */ + src_addr = (const BYTE *)src_memory; + src_addr += ((src_rect->top + srcformatdesc->block_height - 1) / srcformatdesc->block_height) * src_pitch; + src_addr += ((src_rect->left + srcformatdesc->block_width - 1) / srcformatdesc->block_width) * srcformatdesc->block_byte_count; + if (src_format == surfdesc.Format && dst_size.width == src_size.width && dst_size.height == src_size.height @@ -1831,43 +1940,125 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, if (FAILED(IDirect3DSurface9_LockRect(dst_surface, &lockrect, dst_rect, 0))) return D3DXERR_INVALIDDATA; - copy_pixels(src_memory, src_pitch, 0, lockrect.pBits, lockrect.Pitch, 0, + copy_pixels(src_addr, src_pitch, 0, lockrect.pBits, lockrect.Pitch, 0, &src_size, srcformatdesc); IDirect3DSurface9_UnlockRect(dst_surface); } else /* Stretching or format conversion. */ { - if (((srcformatdesc->type != FORMAT_ARGB) && (srcformatdesc->type != FORMAT_INDEX)) || - (destformatdesc->type != FORMAT_ARGB)) + /* Isakov S.L. 2015 + * There is no way to convert DXT1 to DXT3 so I will do this by three steps + * 1. Convert from src_fmt to ARGB with the same size + * 2. Stretch from src_size to dst_size with filtering + * 3. Convert from ARGB to dst_fmt with the same size + */ + + dxtn_conversion_func pre_convert, post_convert; + UINT tmp_src_pitch, tmp_dst_pitch, tmp_src_byte_size; + const struct pixel_format_desc *tmp_format_desc; + void *tmp_src_memory = NULL; + void *tmp_dst_memory = NULL; + BOOL dither = TRUE; + + pre_convert = get_dxtn_conversion_func(srcformatdesc->format, FALSE); + post_convert = get_dxtn_conversion_func(destformatdesc->format, TRUE); + + if ((!pre_convert && (srcformatdesc->type != FORMAT_ARGB) && (srcformatdesc->type != FORMAT_INDEX)) || + (!post_convert && (destformatdesc->type != FORMAT_ARGB))) { FIXME("Format conversion missing %#x -> %#x\n", src_format, surfdesc.Format); return E_NOTIMPL; } + TRACE("Format conversion %#x -> %#x\n", src_format, surfdesc.Format); if (FAILED(IDirect3DSurface9_LockRect(dst_surface, &lockrect, dst_rect, 0))) return D3DXERR_INVALIDDATA; - if ((filter & 0xf) == D3DX_FILTER_NONE) + /* handle pre-conversion from src_fmt to D3DFMT_A8R8G8B8 */ + tmp_format_desc = get_format_info(D3DFMT_A8R8G8B8); + tmp_src_pitch = src_size.width * tmp_format_desc->bytes_per_pixel; + tmp_src_byte_size = tmp_src_pitch * src_size.height; + tmp_src_memory = HeapAlloc(GetProcessHeap(), 0, tmp_src_byte_size); + if (!tmp_src_memory) + { + ret = E_OUTOFMEMORY; + goto error; + } + if (pre_convert) + { + if (!pre_convert(src_addr, tmp_src_memory, src_pitch, tmp_src_pitch, + WINED3DFMT_B8G8R8A8_UNORM, src_size.width, src_size.height)) + { + ret = E_FAIL; + ERR("pre_convert fails\n"); + goto error; + } + } + else { - convert_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc, - lockrect.pBits, lockrect.Pitch, 0, &dst_size, destformatdesc, color_key, src_palette); + convert_argb_pixels(src_addr, src_pitch, 0, &src_size, srcformatdesc, + tmp_src_memory, tmp_src_pitch, 0, &src_size, tmp_format_desc, + color_key, src_palette); } - else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */ + + /* Stretching and filtering */ + tmp_dst_pitch = dst_size.width * tmp_format_desc->bytes_per_pixel; + tmp_src_byte_size = tmp_dst_pitch * dst_size.height; + tmp_dst_memory = HeapAlloc(GetProcessHeap(), 0, tmp_src_byte_size); + if (!tmp_dst_memory) { - if ((filter & 0xf) != D3DX_FILTER_POINT) - FIXME("Unhandled filter %#x.\n", filter); + ret = E_OUTOFMEMORY; + goto error; + } + dither = filter & D3DX_FILTER_DITHER; + switch (filter & 0xf) { + case D3DX_FILTER_NONE: + convert_argb_pixels(tmp_src_memory, tmp_src_pitch, 0, &src_size, tmp_format_desc, + tmp_dst_memory, tmp_dst_pitch, 0, &dst_size, tmp_format_desc, + color_key, src_palette); + + break; + case D3DX_FILTER_TRIANGLE: + smooth_filter_argb_pixels(tmp_src_memory, tmp_src_pitch, 0, &src_size, tmp_format_desc, + tmp_dst_memory, tmp_dst_pitch, 0, &dst_size, tmp_format_desc, + color_key, dither); + break; + case D3DX_FILTER_POINT: + case D3DX_FILTER_BOX: + default: + point_filter_argb_pixels(tmp_src_memory, tmp_src_pitch, 0, &src_size, tmp_format_desc, + tmp_dst_memory, tmp_dst_pitch, 0, &dst_size, tmp_format_desc, + color_key, src_palette); + break; + } - /* Always apply a point filter until D3DX_FILTER_LINEAR, - * D3DX_FILTER_TRIANGLE and D3DX_FILTER_BOX are implemented. */ - point_filter_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc, - lockrect.pBits, lockrect.Pitch, 0, &dst_size, destformatdesc, color_key, src_palette); + /* handle post-conversion */ + if (post_convert) + { + if (!post_convert(tmp_dst_memory, lockrect.pBits, tmp_dst_pitch, lockrect.Pitch, + WINED3DFMT_B8G8R8A8_UNORM, dst_size.width, dst_size.height)) + { + ret = E_FAIL; + goto error; + } + } + else + { + convert_argb_pixels(tmp_dst_memory, tmp_dst_pitch, 0, &dst_size, tmp_format_desc, + lockrect.pBits, lockrect.Pitch, 0, + &dst_size, destformatdesc, color_key, src_palette); } +error: + if (tmp_dst_memory) + HeapFree(GetProcessHeap(), 0, tmp_dst_memory); + if (tmp_src_memory) + HeapFree(GetProcessHeap(), 0, tmp_src_memory); IDirect3DSurface9_UnlockRect(dst_surface); } - return D3D_OK; + return ret; } /************************************************************ diff --git a/dlls/d3dx9_36/volume.c b/dlls/d3dx9_36/volume.c index fae8542..7f74aea 100644 --- a/dlls/d3dx9_36/volume.c +++ b/dlls/d3dx9_36/volume.c @@ -16,9 +16,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include "config.h" #include "wine/debug.h" #include "d3dx9_36_private.h" +#include "wine/wined3d.h" + WINE_DEFAULT_DEBUG_CHANNEL(d3dx); HRESULT WINAPI D3DXLoadVolumeFromFileA(IDirect3DVolume9 *dst_volume, @@ -95,8 +125,10 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, HRESULT hr; D3DVOLUME_DESC desc; D3DLOCKED_BOX locked_box; + D3DBOX tmp_box; struct volume dst_size, src_size; const struct pixel_format_desc *src_format_desc, *dst_format_desc; + const BYTE *src_addr; TRACE("(%p, %p, %p, %p, %#x, %u, %u, %p, %p, %x, %x)\n", dst_volume, dst_palette, dst_box, src_memory, src_format, src_row_pitch, src_slice_pitch, src_palette, src_box, @@ -124,6 +156,12 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, dst_size.width = desc.Width; dst_size.height = desc.Height; dst_size.depth = desc.Depth; + tmp_box.Left = 0; + tmp_box.Right = dst_size.width; + tmp_box.Bottom = dst_size.height; + tmp_box.Top = 0; + tmp_box.Front = 0; + tmp_box.Back = dst_size.depth; } else { @@ -143,6 +181,18 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, if (src_format_desc->type == FORMAT_UNKNOWN) return E_NOTIMPL; + if (src_slice_pitch == 0) + { + src_slice_pitch = src_row_pitch * max(1, (src_size.height + src_format_desc->block_height - 1) / src_format_desc->block_height); + WARN("workaround for src_slice_pitch = %d\n", src_slice_pitch); + } + + /* this is initial shift of source pixels/cells */ + 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; + dst_format_desc = get_format_info(desc.Format); if (dst_format_desc->type == FORMAT_UNKNOWN) return E_NOTIMPL; @@ -153,7 +203,7 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, && 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) @@ -167,61 +217,170 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, 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); + &src_size, src_format_desc); IDirect3DVolume9_UnlockBox(dst_volume); } else { - const BYTE *src_addr; - - - if (((src_format_desc->type != FORMAT_ARGB) && (src_format_desc->type != FORMAT_INDEX)) || - (dst_format_desc->type != FORMAT_ARGB)) + /* Isakov S.L. 2015 + * There is no way to convert DXT1 to DXT3 so I will do this by three steps + * 1. Convert from src_fmt to ARGB with the same size + * 2. Stretch from src_size to dst_size with filtering + * 3. Convert from ARGB to dst_fmt with the same size + */ + dxtn_conversion_func pre_convert, post_convert; + void *tmp_src_memory = NULL; + void *tmp_dst_memory = NULL; + BYTE *tmp_memory; + const struct pixel_format_desc *tmp_format_desc; + UINT depth_i; + UINT tmp_src_row_pitch, tmp_src_slice_pitch, tmp_src_byte_size; + UINT tmp_dst_row_pitch, tmp_dst_slice_pitch, tmp_dst_byte_size; + int tmp_depth = 1; //sometimes the function called with depth=0 which cause crash + BOOL dither; + + /* assume DXTn formats, else NULL */ + pre_convert = get_dxtn_conversion_func(src_format_desc->format, FALSE); /* decompress */ + post_convert = get_dxtn_conversion_func(dst_format_desc->format, TRUE); /* compress */ + /* and ARGBF16 is not supported :( */ + if ((!pre_convert && (src_format_desc->type != FORMAT_ARGB) && (src_format_desc->type != FORMAT_INDEX)) || + (!post_convert && (dst_format_desc->type != FORMAT_ARGB))) { FIXME("Pixel format conversion is not implemented %#x -> %#x\n", src_format_desc->format, dst_format_desc->format); return E_NOTIMPL; } + TRACE("convert volume tex from 0x%x to 0x%x\n", src_format_desc->format, dst_format_desc->format); + if (!dst_box) { + hr = IDirect3DVolume9_LockBox(dst_volume, &locked_box, &tmp_box, 0); + } else + hr = IDirect3DVolume9_LockBox(dst_volume, &locked_box, dst_box, 0); + if (FAILED(hr)) { + ERR("fail to LockBox\n"); + return hr; + } - 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; + TRACE("src_memory %p, src_addr %p, src_row_pitch=%d src_slice_pitch=%d\n", + src_memory, src_addr, src_row_pitch, src_slice_pitch); - hr = IDirect3DVolume9_LockBox(dst_volume, &locked_box, dst_box, 0); - if (FAILED(hr)) return hr; - - if ((filter & 0xf) == D3DX_FILTER_NONE) + /* handle pre-conversion from src_fmt to D3DFMT_A8R8G8B8 */ + tmp_format_desc = get_format_info(D3DFMT_A8R8G8B8); + tmp_src_row_pitch = src_size.width * tmp_format_desc->bytes_per_pixel; + tmp_src_slice_pitch = tmp_src_row_pitch * src_size.height; + tmp_src_byte_size = tmp_src_slice_pitch * src_size.depth; + tmp_src_memory = HeapAlloc(GetProcessHeap(), 0, tmp_src_byte_size); + if (!tmp_src_memory) + { + hr = E_OUTOFMEMORY; + goto error; + } + tmp_memory = tmp_src_memory; + if (pre_convert) { - 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); + //calculate_dds - for reference + for (depth_i = 0; depth_i < src_size.depth; depth_i++) + { + if (!pre_convert(src_addr, tmp_memory, src_row_pitch, tmp_src_row_pitch, + WINED3DFMT_B8G8R8A8_UNORM, src_size.width, src_size.height)) + { + hr = E_FAIL; + ERR("fail to pre_convert\n"); + goto error; + } + src_addr += src_slice_pitch / src_format_desc->block_byte_count; + tmp_memory += tmp_src_slice_pitch; + } } else { - if ((filter & 0xf) != D3DX_FILTER_POINT) - FIXME("Unhandled filter %#x.\n", filter); + convert_argb_pixels(src_addr, src_row_pitch, src_slice_pitch, &src_size, src_format_desc, + tmp_src_memory, tmp_src_row_pitch, tmp_src_slice_pitch, &src_size, tmp_format_desc, + color_key, src_palette); + } - 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); + /* calculation for dst_size */ + tmp_depth = dst_size.depth?dst_size.depth:src_size.depth; + tmp_dst_row_pitch = dst_size.width * tmp_format_desc->bytes_per_pixel; /* bytes */ + tmp_dst_slice_pitch = tmp_dst_row_pitch * dst_size.height; /* bytes */ + tmp_dst_byte_size = tmp_dst_slice_pitch * tmp_depth; + tmp_dst_memory = HeapAlloc(GetProcessHeap(), 0, tmp_dst_byte_size); + TRACE("allocated memory %p size=%d\n", tmp_dst_memory, tmp_dst_byte_size); + if (!tmp_dst_memory) + { + hr = E_OUTOFMEMORY; + goto error; + } + tmp_memory = tmp_dst_memory; + dither = filter & D3DX_FILTER_DITHER; + /* Resize/Filtering */ + switch (filter & 0xf) { + case D3DX_FILTER_NONE: + convert_argb_pixels(tmp_src_memory, tmp_src_row_pitch, tmp_src_slice_pitch, &src_size, tmp_format_desc, + tmp_dst_memory, tmp_dst_row_pitch, tmp_dst_slice_pitch, &dst_size, + tmp_format_desc, color_key, src_palette); + + break; + case D3DX_FILTER_TRIANGLE: + smooth_filter_argb_pixels(tmp_src_memory, tmp_src_row_pitch, tmp_src_slice_pitch, &src_size, tmp_format_desc, + tmp_dst_memory, tmp_dst_row_pitch, tmp_dst_slice_pitch, &dst_size, + tmp_format_desc, color_key, dither); + break; + case D3DX_FILTER_POINT: + case D3DX_FILTER_BOX: + default: + point_filter_argb_pixels(tmp_src_memory, tmp_src_row_pitch, tmp_src_slice_pitch, &src_size, tmp_format_desc, + tmp_dst_memory, tmp_dst_row_pitch, tmp_dst_slice_pitch, &dst_size, + tmp_format_desc, color_key, src_palette); + break; + } + + src_addr = tmp_dst_memory; + tmp_memory = locked_box.pBits; + /* handle post-conversion from D3DFMT_A8R8G8B8 to dst_fmt*/ + if (post_convert) + { + for (depth_i = 0; depth_i < tmp_depth; depth_i++) + { + if (!post_convert(src_addr, tmp_memory, tmp_dst_row_pitch, locked_box.RowPitch, + WINED3DFMT_B8G8R8A8_UNORM, + dst_size.width, dst_size.height)) + { + hr = E_FAIL; + ERR("fail to post_convert\n"); + goto error; + } + src_addr += tmp_dst_slice_pitch; + tmp_memory += locked_box.SlicePitch / dst_format_desc->block_byte_count; + } + } + else + { + //convert from WINED3DFMT_B8G8R8A8_UNORM to dst_fmt if not DXTn + convert_argb_pixels(src_addr, tmp_dst_row_pitch, tmp_dst_slice_pitch, &dst_size, tmp_format_desc, + locked_box.pBits, locked_box.RowPitch, locked_box.SlicePitch, + &dst_size, dst_format_desc, color_key, src_palette); } + + TRACE("format converted from 0x%x to 0x%x\n", + src_format_desc->format, dst_format_desc->format); + + error: + if (tmp_dst_memory) { + HeapFree(GetProcessHeap(), 0, tmp_dst_memory); + } + if (tmp_src_memory) { + HeapFree(GetProcessHeap(), 0, tmp_src_memory); + } IDirect3DVolume9_UnlockBox(dst_volume); } - - return D3D_OK; + return hr; } HRESULT WINAPI D3DXLoadVolumeFromFileInMemory(IDirect3DVolume9 *dst_volume,