From 5d4bc533434a1ab717efa71bca488ebf1bdb0772 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=B3zef=20Kucia?= Date: Fri, 13 Jul 2012 17:21:52 +0200 Subject: [PATCH] d3dx9: Implement pixel format conversion for volume textures. --- dlls/d3dx9_36/d3dx9_36_private.h | 4 ++ dlls/d3dx9_36/surface.c | 121 +++++++++++++++++++++------------------ dlls/d3dx9_36/tests/volume.c | 17 +++++- dlls/d3dx9_36/volume.c | 39 ++++++++++++- 4 files changed, 122 insertions(+), 59 deletions(-) diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h index d10cea00c76..fec9ede9d40 100644 --- a/dlls/d3dx9_36/d3dx9_36_private.h +++ b/dlls/d3dx9_36/d3dx9_36_private.h @@ -64,6 +64,10 @@ HRESULT write_buffer_to_file(const WCHAR *filename, ID3DXBuffer *buffer) DECLSPE const PixelFormatDesc *get_format_info(D3DFORMAT format) DECLSPEC_HIDDEN; const PixelFormatDesc *get_format_info_idx(int idx) DECLSPEC_HIDDEN; +void copy_simple_data(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, SIZE src_size, UINT src_depth, const PixelFormatDesc *src_format, + BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, SIZE dst_size, UINT dst_depth, const PixelFormatDesc *dst_format, + D3DCOLOR color_key) 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) DECLSPEC_HIDDEN; HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data, diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index c1835b782fe..433c2514510 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1255,85 +1255,94 @@ static void format_from_vec4(const PixelFormatDesc *format, const struct vec4 *s * Pixels outsize the source rect are blacked out. * Works only for ARGB formats with 1 - 4 bytes per pixel. */ -static void copy_simple_data(const BYTE *src, UINT srcpitch, SIZE src_size, const PixelFormatDesc *srcformat, - BYTE *dest, UINT destpitch, SIZE dst_size, const PixelFormatDesc *destformat, D3DCOLOR colorkey) +void copy_simple_data(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, SIZE src_size, UINT src_depth, const PixelFormatDesc *src_format, + BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, SIZE dst_size, UINT dst_depth, const PixelFormatDesc *dst_format, D3DCOLOR color_key) { struct argb_conversion_info conv_info, ck_conv_info; const PixelFormatDesc *ck_format = NULL; DWORD channels[4], pixel; - UINT minwidth, minheight; - UINT x, y; + UINT min_width, min_height, min_depth; + UINT x, y, z; ZeroMemory(channels, sizeof(channels)); - init_argb_conversion_info(srcformat, destformat, &conv_info); + init_argb_conversion_info(src_format, dst_format, &conv_info); - minwidth = (src_size.cx < dst_size.cx) ? src_size.cx : dst_size.cx; - minheight = (src_size.cy < dst_size.cy) ? src_size.cy : dst_size.cy; + min_width = min(src_size.cx, dst_size.cx); + min_height = min(src_size.cy, dst_size.cy); + min_depth = min(src_depth, dst_depth); - if (colorkey) + if (color_key) { /* Color keys are always represented in D3DFMT_A8R8G8B8 format. */ ck_format = get_format_info(D3DFMT_A8R8G8B8); - init_argb_conversion_info(srcformat, ck_format, &ck_conv_info); + init_argb_conversion_info(src_format, ck_format, &ck_conv_info); } - for(y = 0;y < minheight;y++) { - const BYTE *srcptr = src + y * srcpitch; - BYTE *destptr = dest + y * destpitch; - DWORD val; + for (z = 0; z < min_depth; z++) { + const BYTE *src_slice_ptr = src + z * src_slice_pitch; + BYTE *dst_slice_ptr = dst + z * dst_slice_pitch; - for(x = 0;x < minwidth;x++) { - /* extract source color components */ - pixel = dword_from_bytes(srcptr, srcformat->bytes_per_pixel); + for (y = 0; y < min_height; y++) { + const BYTE *src_ptr = src_slice_ptr + y * src_row_pitch; + BYTE *dst_ptr = dst_slice_ptr + y * dst_row_pitch; + DWORD val; - if (!srcformat->to_rgba && !destformat->from_rgba) - { - get_relevant_argb_components(&conv_info, pixel, channels); - val = make_argb_color(&conv_info, channels); + for (x = 0; x < min_width; x++) { + /* extract source color components */ + pixel = dword_from_bytes(src_ptr, src_format->bytes_per_pixel); - if (colorkey) + if (!src_format->to_rgba && !dst_format->from_rgba) { - get_relevant_argb_components(&ck_conv_info, pixel, channels); - pixel = make_argb_color(&ck_conv_info, channels); - if (pixel == colorkey) - val &= ~conv_info.destmask[0]; + get_relevant_argb_components(&conv_info, pixel, channels); + val = make_argb_color(&conv_info, channels); + + if (color_key) + { + get_relevant_argb_components(&ck_conv_info, pixel, channels); + pixel = make_argb_color(&ck_conv_info, channels); + if (pixel == color_key) + val &= ~conv_info.destmask[0]; + } } - } - else - { - struct vec4 color, tmp; - - format_to_vec4(srcformat, &pixel, &color); - if (srcformat->to_rgba) - srcformat->to_rgba(&color, &tmp); else - tmp = color; - - if (ck_format) { - format_from_vec4(ck_format, &tmp, &pixel); - if (pixel == colorkey) - tmp.w = 0.0f; - } + struct vec4 color, tmp; + + format_to_vec4(src_format, &pixel, &color); + if (src_format->to_rgba) + src_format->to_rgba(&color, &tmp); + else + tmp = color; + + if (ck_format) + { + format_from_vec4(ck_format, &tmp, &pixel); + if (pixel == color_key) + tmp.w = 0.0f; + } - if (destformat->from_rgba) - destformat->from_rgba(&tmp, &color); - else - color = tmp; + if (dst_format->from_rgba) + dst_format->from_rgba(&tmp, &color); + else + color = tmp; - format_from_vec4(destformat, &color, &val); + format_from_vec4(dst_format, &color, &val); + } + + dword_to_bytes(dst_ptr, val, dst_format->bytes_per_pixel); + src_ptr += src_format->bytes_per_pixel; + dst_ptr += dst_format->bytes_per_pixel; } - dword_to_bytes(destptr, val, destformat->bytes_per_pixel); - srcptr += srcformat->bytes_per_pixel; - destptr += destformat->bytes_per_pixel; + if (src_size.cx < dst_size.cx) /* black out remaining pixels */ + memset(dst_ptr, 0, dst_format->bytes_per_pixel * (dst_size.cx - src_size.cx)); } - if (src_size.cx < dst_size.cx) /* black out remaining pixels */ - memset(destptr, 0, destformat->bytes_per_pixel * (dst_size.cx - src_size.cx)); + if (src_size.cy < dst_size.cy) /* black out remaining pixels */ + memset(dst + src_size.cy * dst_row_pitch, 0, dst_row_pitch * (dst_size.cy - src_size.cy)); } - if (src_size.cy < dst_size.cy) /* black out remaining pixels */ - memset(dest + src_size.cy * destpitch, 0, destpitch * (dst_size.cy - src_size.cy)); + if (src_depth < dst_depth) /* black out remaining pixels */ + memset(dst + src_depth * dst_slice_pitch, 0, dst_slice_pitch * (dst_depth - src_depth)); } /************************************************************ @@ -1562,8 +1571,8 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, if ((filter & 0xf) == D3DX_FILTER_NONE) { - copy_simple_data(src_memory, src_pitch, src_size, srcformatdesc, - lockrect.pBits, lockrect.Pitch, dst_size, destformatdesc, color_key); + copy_simple_data(src_memory, src_pitch, 0, src_size, 1, srcformatdesc, + lockrect.pBits, lockrect.Pitch, 0, dst_size, 1, destformatdesc, color_key); } else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */ { @@ -1854,8 +1863,8 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE hr = IDirect3DSurface9_LockRect(src_surface, &locked_rect, src_rect, D3DLOCK_READONLY); if (SUCCEEDED(hr)) { - copy_simple_data(locked_rect.pBits, locked_rect.Pitch, size, src_format_desc, - dst_data, dst_pitch, size, dst_format_desc, 0); + copy_simple_data(locked_rect.pBits, locked_rect.Pitch, 0, size, 1, src_format_desc, + dst_data, dst_pitch, 0, size, 1, dst_format_desc, 0); IDirect3DSurface9_UnlockRect(src_surface); } diff --git a/dlls/d3dx9_36/tests/volume.c b/dlls/d3dx9_36/tests/volume.c index a4c94316517..f49a6341983 100644 --- a/dlls/d3dx9_36/tests/volume.c +++ b/dlls/d3dx9_36/tests/volume.c @@ -58,7 +58,7 @@ static inline void set_box(D3DBOX *box, UINT left, UINT top, UINT right, UINT bo static void test_D3DXLoadVolumeFromMemory(IDirect3DDevice9 *device) { - int i; + int i, x, y, z; HRESULT hr; D3DBOX src_box, dst_box; D3DLOCKED_BOX locked_box; @@ -110,6 +110,21 @@ static void test_D3DXLoadVolumeFromMemory(IDirect3DDevice9 *device) for (i = 0; i < 16; i++) check_pixel_4bpp(&locked_box, i % 4, i / 4, 0, pixels[i]); IDirect3DVolume9_UnlockBox(volume); + hr = D3DXLoadVolumeFromMemory(volume, NULL, NULL, pixels, D3DFMT_A8R8G8B8, 16, sizeof(pixels), NULL, &src_box, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + + IDirect3DVolume9_LockBox(volume, &locked_box, NULL, D3DLOCK_READONLY); + for (i = 0; i < 16; i++) check_pixel_4bpp(&locked_box, i % 4, i / 4, 0, pixels[i]); + for (z = 0; z < 4; z++) + { + for (y = 0; y < 256; y++) + { + for (x = 0; x < 256; x++) + if (z != 0 || y >= 4 || x >= 4) check_pixel_4bpp(&locked_box, x, y, z, 0); + } + } + IDirect3DVolume9_UnlockBox(volume); + set_box(&src_box, 0, 0, 2, 2, 1, 2); set_box(&dst_box, 0, 0, 2, 2, 0, 1); hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 8, 16, NULL, &src_box, D3DX_DEFAULT, 0); diff --git a/dlls/d3dx9_36/volume.c b/dlls/d3dx9_36/volume.c index 6164cc37460..90dbd29c921 100644 --- a/dlls/d3dx9_36/volume.c +++ b/dlls/d3dx9_36/volume.c @@ -194,8 +194,43 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, } else { - FIXME("Stretching or format conversion not implemented\n"); - return E_NOTIMPL; + const BYTE *src_addr; + SIZE src_size, dst_size; + + if (src_format_desc->bytes_per_pixel > 4 || dst_format_desc->bytes_per_pixel > 4 + || src_format_desc->block_height != 1 || src_format_desc->block_width != 1 + || dst_format_desc->block_height != 1 || dst_format_desc->block_width != 1) + { + FIXME("Pixel format conversion not implemented %#x -> %#x\n", + src_format_desc->format, dst_format_desc->format); + return E_NOTIMPL; + } + + src_size.cx = src_width; + src_size.cy = src_height; + dst_size.cx = dst_width; + dst_size.cy = dst_height; + + 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) + { + copy_simple_data(src_memory, src_row_pitch, src_slice_pitch, src_size, src_depth, src_format_desc, + locked_box.pBits, locked_box.RowPitch, locked_box.SlicePitch, dst_size, dst_depth, dst_format_desc, color_key); + } + else + { + FIXME("Filtering for volume textures not implemented\n"); + return E_NOTIMPL; + } + + IDirect3DVolume9_UnlockBox(dst_volume); } return D3D_OK; -- 2.11.4.GIT