From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/surface.c | 54 ++++++++++++++++++++++++++--------- dlls/d3dx9_36/tests/surface.c | 43 +++++++++++----------------- 2 files changed, 57 insertions(+), 40 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index cfe6e525bff..e635d46a2b3 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -32,9 +32,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory**);
-/* Wine-specific WIC GUIDs */ -DEFINE_GUID(GUID_WineContainerFormatTga, 0x0c44fda1,0xa5c5,0x4298,0x96,0x85,0x47,0x3f,0xc1,0x7c,0xd3,0x22); - static const struct { const GUID *wic_guid; @@ -755,8 +752,7 @@ static BOOL image_is_argb(IWICBitmapFrameDecode *frame, struct d3dx_image *image BYTE *buffer; HRESULT hr;
- if (image->format != D3DFMT_X8R8G8B8 || (image->image_file_format != D3DXIFF_BMP - && image->image_file_format != D3DXIFF_TGA)) + if (image->format != D3DFMT_X8R8G8B8 || image->image_file_format != D3DXIFF_BMP) return FALSE;
size = image->size.width * image->size.height * 4; @@ -794,7 +790,6 @@ static const GUID *d3dx_file_format_to_wic_container_guid(D3DXIMAGE_FILEFORMAT i switch (iff) { case D3DXIFF_BMP: return &GUID_ContainerFormatBmp; - case D3DXIFF_TGA: return &GUID_WineContainerFormatTga; case D3DXIFF_JPG: return &GUID_ContainerFormatJpeg; case D3DXIFF_PNG: return &GUID_ContainerFormatPng; default: @@ -1078,12 +1073,10 @@ static HRESULT d3dx_image_tga_decode(const void *src_data, uint32_t src_data_siz const BOOL is_rle = !!(header->image_type & IMAGETYPE_RLE); uint32_t row_pitch, slice_pitch, i; uint8_t *img_buf = NULL, *src_row; + PALETTEENTRY *palette = NULL; const uint8_t *src_pos; HRESULT hr;
- if (image->format == D3DFMT_P8) - return E_NOTIMPL; - hr = d3dx_calculate_pixels_size(image->format, image->size.width, image->size.height, &row_pitch, &slice_pitch); if (FAILED(hr)) return hr; @@ -1092,15 +1085,48 @@ static HRESULT d3dx_image_tga_decode(const void *src_data, uint32_t src_data_siz if (!is_rle && (src_header_size + slice_pitch) > src_data_size) return D3DXERR_INVALIDDATA;
+ if (image->format == D3DFMT_P8) + { + const uint8_t *src_palette = ((const uint8_t *)src_data) + sizeof(*header) + header->id_length; + const struct volume image_map_size = { header->color_map_length, 1, 1 }; + uint32_t src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch; + const struct pixel_format_desc *src_desc, *dst_desc; + + if (!(palette = malloc(sizeof(*palette) * 256))) + return E_OUTOFMEMORY; + + /* + * Convert from a TGA colormap to PALETTEENTRY. TGA is BGRA, + * PALETTEENTRY is RGBA. + */ + src_desc = get_format_info(d3dx_get_tga_format_for_bpp(header->color_map_entrysize)); + hr = d3dx_calculate_pixels_size(src_desc->format, header->color_map_length, 1, &src_row_pitch, &src_slice_pitch); + if (FAILED(hr)) + goto exit; + + dst_desc = get_format_info(D3DFMT_A8B8G8R8); + d3dx_calculate_pixels_size(dst_desc->format, 256, 1, &dst_row_pitch, &dst_slice_pitch); + convert_argb_pixels(src_palette, src_row_pitch, src_slice_pitch, &image_map_size, src_desc, (BYTE *)palette, + dst_row_pitch, dst_slice_pitch, &image_map_size, dst_desc, 0, NULL); + + /* Initialize unused palette entries to 0xff. */ + if (header->color_map_length < 256) + memset(&palette[header->color_map_length], 0xff, sizeof(*palette) * (256 - header->color_map_length)); + } + if (!is_rle && !bottom_to_top && !right_to_left) { image->pixels = (uint8_t *)src_data + src_header_size; + image->image_palette = image->palette = palette; return D3D_OK; }
/* Allocate an extra row to use as a temporary buffer. */ if (!(img_buf = malloc(slice_pitch + row_pitch))) - return E_OUTOFMEMORY; + { + hr = E_OUTOFMEMORY; + goto exit; + }
src_row = img_buf + slice_pitch; src_pos = (const uint8_t *)src_data + src_header_size; @@ -1142,10 +1168,13 @@ static HRESULT d3dx_image_tga_decode(const void *src_data, uint32_t src_data_siz }
image->image_buf = image->pixels = img_buf; + image->image_palette = image->palette = palette;
exit: if (img_buf && (image->image_buf != img_buf)) free(img_buf); + if (palette && (image->image_palette != palette)) + free(palette);
return hr; } @@ -1227,10 +1256,7 @@ HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3d }
/* Last resort, try TGA. */ - hr = d3dx_initialize_image_from_tga(src_data, src_data_size, image, flags); - if (hr == E_NOTIMPL) - hr = d3dx_initialize_image_from_wic(src_data, src_data_size, image, D3DXIFF_TGA, flags); - return hr; + return d3dx_initialize_image_from_tga(src_data, src_data_size, image, flags); }
switch (iff) diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 691c4011fd0..d87d68836b0 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -1887,12 +1887,12 @@ static const uint8_t test_tga_grayscale_8bpp_rle_expected[] = 0x00,0x10,0x20,0x30,0x40,0x40,0x40,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0, };
-#define check_tga_surface_load(surface, expected, right_to_left, bottom_to_top, todo) \ - check_tga_surface_load_(__LINE__, surface, expected, right_to_left, bottom_to_top, todo) +#define check_tga_surface_load(surface, expected, right_to_left, bottom_to_top) \ + check_tga_surface_load_(__LINE__, surface, expected, right_to_left, bottom_to_top) static void check_tga_surface_load_(uint32_t line, IDirect3DSurface9 *surface, const uint8_t *expected, BOOL right_to_left, - BOOL bottom_to_top, BOOL todo) + BOOL bottom_to_top) { - uint32_t x, y, fmt_bpp, fmt_pitch, mismatch_count; + uint32_t x, y, fmt_bpp, fmt_pitch; D3DLOCKED_RECT lock_rect; D3DSURFACE_DESC desc; HRESULT hr; @@ -1903,7 +1903,6 @@ static void check_tga_surface_load_(uint32_t line, IDirect3DSurface9 *surface, c fmt_bpp = get_bpp_for_d3dformat(desc.Format); fmt_pitch = fmt_bpp * desc.Width; IDirect3DSurface9_LockRect(surface, &lock_rect, NULL, D3DLOCK_READONLY); - mismatch_count = 0; for (y = 0; y < desc.Height; ++y) { const uint32_t expected_row_idx = bottom_to_top ? (desc.Height - y - 1) : y; @@ -1917,11 +1916,9 @@ static void check_tga_surface_load_(uint32_t line, IDirect3DSurface9 *surface, c const uint8_t *pixel = row + (fmt_bpp * x); BOOL pixel_match = !memcmp(pixel, expected_pixel, fmt_bpp);
- if (!pixel_match) - mismatch_count++; + ok_(__FILE__, line)(pixel_match, "Pixel mismatch at (%u,%u).\n", x, y); } } - todo_wine_if(todo) ok_(__FILE__, line)(!mismatch_count, "%u mismatched pixels.\n", mismatch_count); IDirect3DSurface9_UnlockRect(surface); }
@@ -1936,8 +1933,6 @@ static void test_load_surface_from_tga(IDirect3DDevice9 *device) uint32_t pixels_size;
const uint8_t *expected; - BOOL todo_hr; - BOOL todo_surface; } tga_tests[] = { { { 0, COLORMAP_TYPE_ONE, IMAGETYPE_COLORMAPPED, 0, 256, 15, 0, 0, 4, 4, 8, 0 }, @@ -1953,22 +1948,22 @@ static void test_load_surface_from_tga(IDirect3DDevice9 *device) { { 0, COLORMAP_TYPE_ONE, IMAGETYPE_COLORMAPPED, 0, 256, 16, 0, 0, 4, 4, 8, 0 }, test_tga_color_map_16bpp, sizeof(test_tga_color_map_16bpp), test_tga_color_map_index_4_4, sizeof(test_tga_color_map_index_4_4), - test_tga_color_map_16bpp_expected, .todo_surface = TRUE + test_tga_color_map_16bpp_expected }, { { 0, COLORMAP_TYPE_ONE, IMAGETYPE_COLORMAPPED, 0, 256, 24, 0, 0, 4, 4, 8, 0 }, test_tga_color_map_24bpp, sizeof(test_tga_color_map_24bpp), test_tga_color_map_index_4_4, sizeof(test_tga_color_map_index_4_4), - test_tga_color_map_24bpp_expected, .todo_surface = TRUE + test_tga_color_map_24bpp_expected }, { { 0, COLORMAP_TYPE_ONE, IMAGETYPE_COLORMAPPED, 0, 256, 32, 0, 0, 4, 4, 8, 0 }, test_tga_color_map_32bpp, sizeof(test_tga_color_map_32bpp), test_tga_color_map_index_4_4, sizeof(test_tga_color_map_index_4_4), - test_tga_color_map_32bpp_expected, .todo_surface = TRUE + test_tga_color_map_32bpp_expected }, { { 0, COLORMAP_TYPE_ONE, IMAGETYPE_COLORMAPPED, 0, 128, 32, 0, 0, 4, 4, 8, 0 }, test_tga_color_map_32bpp, sizeof(test_tga_color_map_32bpp) / 2, test_tga_color_map_index_4_4, sizeof(test_tga_color_map_index_4_4), - test_tga_color_map_half_32bpp_expected, .todo_surface = TRUE + test_tga_color_map_half_32bpp_expected }, { { 0, COLORMAP_TYPE_NONE, IMAGETYPE_TRUECOLOR, 0, 0, 0, 0, 0, 4, 4, 15, 0 }, NULL, 0, @@ -2067,30 +2062,26 @@ static void test_load_surface_from_tga(IDirect3DDevice9 *device)
/* Read as default, bottom to top, left to right. */ hr = D3DXLoadSurfaceFromFileInMemory(surface, NULL, NULL, tga, file_size, NULL, D3DX_FILTER_NONE, 0, NULL); - todo_wine_if(tga_tests[i].todo_hr) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - check_tga_surface_load(surface, tga_tests[i].expected, FALSE, TRUE, tga_tests[i].todo_surface); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + check_tga_surface_load(surface, tga_tests[i].expected, FALSE, TRUE);
/* Read as top to bottom, left to right. */ tga->header.image_descriptor = IMAGE_TOPTOBOTTOM; hr = D3DXLoadSurfaceFromFileInMemory(surface, NULL, NULL, tga, file_size, NULL, D3DX_FILTER_NONE, 0, NULL); - todo_wine_if(tga_tests[i].todo_hr) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - check_tga_surface_load(surface, tga_tests[i].expected, FALSE, FALSE, tga_tests[i].todo_surface); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + check_tga_surface_load(surface, tga_tests[i].expected, FALSE, FALSE);
/* Read as bottom to top, right to left. */ tga->header.image_descriptor = IMAGE_RIGHTTOLEFT; hr = D3DXLoadSurfaceFromFileInMemory(surface, NULL, NULL, tga, file_size, NULL, D3DX_FILTER_NONE, 0, NULL); - todo_wine_if(tga_tests[i].color_map) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - check_tga_surface_load(surface, tga_tests[i].expected, TRUE, TRUE, FALSE); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + check_tga_surface_load(surface, tga_tests[i].expected, TRUE, TRUE);
/* Read as top to bottom, right to left. */ tga->header.image_descriptor = IMAGE_TOPTOBOTTOM | IMAGE_RIGHTTOLEFT; hr = D3DXLoadSurfaceFromFileInMemory(surface, NULL, NULL, tga, file_size, NULL, D3DX_FILTER_NONE, 0, NULL); - todo_wine_if(tga_tests[i].color_map) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - check_tga_surface_load(surface, tga_tests[i].expected, TRUE, FALSE, FALSE); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + check_tga_surface_load(surface, tga_tests[i].expected, TRUE, FALSE);
check_release((IUnknown *)surface, 0); winetest_pop_context();