From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/surface.c | 126 ++++++++++++++++++++++------------ dlls/d3dx9_36/tests/surface.c | 59 ++++++++-------- 2 files changed, 110 insertions(+), 75 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index e5cf6b84bff..638bddf39ca 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -153,6 +153,33 @@ struct dds_header DWORD reserved2; };
+#define TGA_IMAGETYPE_COLORMAPPED 1 +#define TGA_IMAGETYPE_TRUECOLOR 2 +#define TGA_IMAGETYPE_GRAYSCALE 3 +#define TGA_IMAGETYPE_MASK 0x07 +#define TGA_IMAGETYPE_RLE 8 + +#define TGA_IMAGE_RIGHTTOLEFT 0x10 +#define TGA_IMAGE_TOPTOBOTTOM 0x20 + +#include "pshpack1.h" +struct tga_header +{ + uint8_t id_length; + uint8_t color_map_type; + uint8_t image_type; + uint16_t color_map_firstentry; + uint16_t color_map_length; + uint8_t color_map_entrysize; + uint16_t xorigin; + uint16_t yorigin; + uint16_t width; + uint16_t height; + uint8_t depth; + uint8_t image_descriptor; +}; +#include "poppack.h" + HRESULT lock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect, D3DLOCKED_RECT *lock, IDirect3DSurface9 **temp_surface, BOOL write) { @@ -501,23 +528,40 @@ static HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const uint8_t *pixels; HRESULT hr;
- *dst_buffer = NULL; + *dst_buffer = buffer = NULL; switch (file_format) { case D3DXIFF_DDS: - { - struct dds_header *header; - uint32_t header_size; - hr = dds_pixel_format_from_d3dx_pixel_format_id(NULL, dst_format); if (FAILED(hr)) return hr; + break;
- dst_fmt_desc = get_d3dx_pixel_format_info(dst_format); - hr = d3dx_calculate_pixels_size(dst_format, src_pixels->size.width, src_pixels->size.height, &dst_row_pitch, - &dst_slice_pitch); - if (FAILED(hr)) - return hr; + case D3DXIFF_TGA: + if ((dst_format != D3DX_PIXEL_FORMAT_B8G8R8_UNORM) && (dst_format != D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM)) + { + FIXME("Format replacement for TGA files is currently unimplemented.\n"); + return E_NOTIMPL; + } + break; + + default: + assert(0 && "Unexpected file format."); + return E_FAIL; + } + + dst_fmt_desc = get_d3dx_pixel_format_info(dst_format); + hr = d3dx_calculate_pixels_size(dst_format, src_pixels->size.width, src_pixels->size.height, &dst_row_pitch, + &dst_slice_pitch); + if (FAILED(hr)) + return hr; + + switch (file_format) + { + case D3DXIFF_DDS: + { + struct dds_header *header; + 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); @@ -535,9 +579,30 @@ static HRESULT d3dx_save_pixels_to_memory(struct d3dx_pixels *src_pixels, const break; }
+ case D3DXIFF_TGA: + { + struct tga_header *header; + + hr = D3DXCreateBuffer(dst_slice_pitch + sizeof(*header), &buffer); + if (FAILED(hr)) + return hr; + + header = ID3DXBuffer_GetBufferPointer(buffer); + pixels = (uint8_t *)ID3DXBuffer_GetBufferPointer(buffer) + sizeof(*header); + + memset(header, 0, sizeof(*header)); + header->image_type = TGA_IMAGETYPE_TRUECOLOR; + header->width = src_pixels->size.width; + header->height = src_pixels->size.height; + header->image_descriptor = TGA_IMAGE_TOPTOBOTTOM; + header->depth = dst_fmt_desc->bytes_per_pixel * 8; + if (dst_fmt_desc->format == D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM) + header->image_descriptor |= 0x08; + break; + } + default: - assert(0 && "Unexpected file format."); - return E_FAIL; + break; }
if (src_pixels->size.width != 0 && src_pixels->size.height != 0) @@ -559,8 +624,8 @@ exit: return hr; }
-static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSurface9 *src_surface, - const PALETTEENTRY *src_palette, const RECT *src_rect) +static HRESULT save_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSurface9 *src_surface, + const PALETTEENTRY *src_palette, const RECT *src_rect, D3DXIMAGE_FILEFORMAT file_format) { const struct pixel_format_desc *src_fmt_desc; D3DSURFACE_DESC src_surface_desc; @@ -610,7 +675,7 @@ static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSur return hr; }
- hr = d3dx_save_pixels_to_memory(&src_pixels, src_fmt_desc, D3DXIFF_DDS, &buffer); + hr = d3dx_save_pixels_to_memory(&src_pixels, src_fmt_desc, file_format, &buffer); if (FAILED(hr)) { unlock_surface(src_surface, NULL, temp_surface, FALSE); @@ -1085,33 +1150,6 @@ static enum d3dx_pixel_format_id d3dx_get_tga_format_for_bpp(uint8_t bpp) } }
-#define TGA_IMAGETYPE_COLORMAPPED 1 -#define TGA_IMAGETYPE_TRUECOLOR 2 -#define TGA_IMAGETYPE_GRAYSCALE 3 -#define TGA_IMAGETYPE_MASK 0x07 -#define TGA_IMAGETYPE_RLE 8 - -#define TGA_IMAGE_RIGHTTOLEFT 0x10 -#define TGA_IMAGE_TOPTOBOTTOM 0x20 - -#include "pshpack1.h" -struct tga_header -{ - uint8_t id_length; - uint8_t color_map_type; - uint8_t image_type; - uint16_t color_map_firstentry; - uint16_t color_map_length; - uint8_t color_map_entrysize; - uint16_t xorigin; - uint16_t yorigin; - uint16_t width; - uint16_t height; - uint8_t depth; - uint8_t image_descriptor; -}; -#include "poppack.h" - static HRESULT d3dx_image_tga_rle_decode_row(const uint8_t **src, uint32_t src_bytes_left, uint32_t row_width, uint32_t bytes_per_pixel, uint8_t *dst_row) { @@ -2993,10 +3031,10 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE container_format = &GUID_ContainerFormatJpeg; break; case D3DXIFF_DDS: - return save_dds_surface_to_memory(dst_buffer, src_surface, src_palette, src_rect); + case D3DXIFF_TGA: + return save_surface_to_memory(dst_buffer, src_surface, src_palette, src_rect, file_format); case D3DXIFF_HDR: case D3DXIFF_PFM: - case D3DXIFF_TGA: case D3DXIFF_PPM: FIXME("File format %#x is not supported yet\n", file_format); return E_NOTIMPL; diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 41f0ad9d68d..25152fc6a74 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -3923,7 +3923,7 @@ static void test_save_surface_iffs(IDirect3DDevice9 *device) { D3DFMT_R8G8B8, NULL, 0x00, { { D3D_OK, D3DFMT_R8G8B8, }, { D3D_OK, D3DFMT_X8R8G8B8 }, - { D3D_OK, D3DFMT_R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_R8G8B8 }, { D3D_OK, D3DFMT_X8R8G8B8 }, { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, { D3D_OK, D3DFMT_R8G8B8, }, @@ -3943,7 +3943,7 @@ static void test_save_surface_iffs(IDirect3DDevice9 *device) { D3DFMT_A8R8G8B8, NULL, 0x00, { { D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE }, { D3D_OK, D3DFMT_X8R8G8B8 }, - { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8 }, { D3D_OK, D3DFMT_A8R8G8B8, }, { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, { D3D_OK, D3DFMT_X8R8G8B8, .todo_format = TRUE }, @@ -3954,7 +3954,7 @@ static void test_save_surface_iffs(IDirect3DDevice9 *device) { D3DFMT_A8R8G8B8, NULL, 0xff, { { D3D_OK, D3DFMT_A8R8G8B8 }, { D3D_OK, D3DFMT_X8R8G8B8 }, - { D3D_OK, D3DFMT_A8R8G8B8, .todo_hr = TRUE }, + { D3D_OK, D3DFMT_A8R8G8B8 }, { D3D_OK, D3DFMT_A8R8G8B8, }, { D3D_OK, D3DFMT_X8R8G8B8, .todo_hr = TRUE }, { D3D_OK, D3DFMT_A8R8G8B8 }, @@ -4633,36 +4633,32 @@ static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device)
/* Test saved targa file headers. */ hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_TGA, surface, NULL, NULL); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - { - tga = ID3DXBuffer_GetBufferPointer(buffer); - ok(ID3DXBuffer_GetBufferSize(buffer) == (sizeof(tga->header) + tga->header.id_length + (4 * 4 * 4)), "Unexpected buffer size %lu.\n", - ID3DXBuffer_GetBufferSize(buffer)); - ok(tga->header.image_type == IMAGETYPE_TRUECOLOR, "Got unexpected image type %u.\n", tga->header.image_type); - ok(tga->header.height == 4, "Got unexpected height %u.\n", tga->header.height); - ok(tga->header.width == 4, "Got unexpected width %u.\n", tga->header.width); - ok(tga->header.depth == 32, "Got unexpected depth %u.\n", tga->header.depth); - ok(tga->header.image_descriptor == (IMAGE_TOPTOBOTTOM | 0x8), "Got unexpected image descriptor %#x.\n", tga->header.image_descriptor); - ID3DXBuffer_Release(buffer); - } + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + tga = ID3DXBuffer_GetBufferPointer(buffer); + ok(ID3DXBuffer_GetBufferSize(buffer) == (sizeof(tga->header) + tga->header.id_length + (4 * 4 * 4)), "Unexpected buffer size %lu.\n", + ID3DXBuffer_GetBufferSize(buffer)); + ok(tga->header.image_type == IMAGETYPE_TRUECOLOR, "Got unexpected image type %u.\n", tga->header.image_type); + ok(tga->header.height == 4, "Got unexpected height %u.\n", tga->header.height); + ok(tga->header.width == 4, "Got unexpected width %u.\n", tga->header.width); + ok(tga->header.depth == 32, "Got unexpected depth %u.\n", tga->header.depth); + ok(tga->header.image_descriptor == (IMAGE_TOPTOBOTTOM | 0x8), "Got unexpected image descriptor %#x.\n", tga->header.image_descriptor); + ID3DXBuffer_Release(buffer);
/* Size 0 rectangle. */ SetRectEmpty(&rect); hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_TGA, surface, NULL, &rect); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - { - tga = ID3DXBuffer_GetBufferPointer(buffer); - ok(ID3DXBuffer_GetBufferSize(buffer) == (sizeof(tga->header) + tga->header.id_length), "Unexpected buffer size %lu.\n", - ID3DXBuffer_GetBufferSize(buffer)); - ok(tga->header.image_type == IMAGETYPE_TRUECOLOR, "Got unexpected image type %u.\n", tga->header.image_type); - ok(!tga->header.height, "Got unexpected height %u.\n", tga->header.height); - ok(!tga->header.width, "Got unexpected width %u.\n", tga->header.width); - ok(tga->header.depth == 32, "Got unexpected depth %u.\n", tga->header.depth); - ok(tga->header.image_descriptor == (IMAGE_TOPTOBOTTOM | 0x8), "Got unexpected image descriptor %#x.\n", tga->header.image_descriptor); - ID3DXBuffer_Release(buffer); - } + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + tga = ID3DXBuffer_GetBufferPointer(buffer); + ok(ID3DXBuffer_GetBufferSize(buffer) == (sizeof(tga->header) + tga->header.id_length), "Unexpected buffer size %lu.\n", + ID3DXBuffer_GetBufferSize(buffer)); + ok(tga->header.image_type == IMAGETYPE_TRUECOLOR, "Got unexpected image type %u.\n", tga->header.image_type); + ok(!tga->header.height, "Got unexpected height %u.\n", tga->header.height); + ok(!tga->header.width, "Got unexpected width %u.\n", tga->header.width); + ok(tga->header.depth == 32, "Got unexpected depth %u.\n", tga->header.depth); + ok(tga->header.image_descriptor == (IMAGE_TOPTOBOTTOM | 0x8), "Got unexpected image descriptor %#x.\n", tga->header.image_descriptor); + ID3DXBuffer_Release(buffer);
/* Saving as D3DXIFF_DIB actually saves as a BMP. */ hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DIB, surface, NULL, NULL); @@ -4786,10 +4782,11 @@ static void test_D3DXSaveSurfaceToFile(IDirect3DDevice9 *device) { hr = D3DXSaveSurfaceToFileA("saved_surface.ppm", D3DXIFF_PPM, surface, NULL, NULL); ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); - hr = D3DXSaveSurfaceToFileA("saved_surface.tga", D3DXIFF_TGA, surface, NULL, NULL); - ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); }
+ hr = D3DXSaveSurfaceToFileA("saved_surface.tga", D3DXIFF_TGA, surface, NULL, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + hr = D3DXSaveSurfaceToFileA("saved_surface.dds", D3DXIFF_DDS, surface, NULL, NULL); ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);