Commit edb01d26 authored by Christian Costa's avatar Christian Costa Committed by Alexandre Julliard

d3dx9_36: Add support for D3DFMT_P8 and conversion to other ARGB formats + tests.

parent a047b2cb
......@@ -50,6 +50,7 @@ enum format_type {
FORMAT_ARGBF16,/* float 16 */
FORMAT_ARGBF, /* float */
FORMAT_DXT,
FORMAT_INDEX,
FORMAT_UNKNOWN
};
......@@ -63,7 +64,7 @@ struct pixel_format_desc {
UINT block_byte_count;
enum format_type type;
void (*from_rgba)(const struct vec4 *src, struct vec4 *dst);
void (*to_rgba)(const struct vec4 *src, struct vec4 *dst);
void (*to_rgba)(const struct vec4 *src, struct vec4 *dst, const PALETTEENTRY *palette);
};
HRESULT map_view_of_file(LPCWSTR filename, LPVOID *buffer, DWORD *length) DECLSPEC_HIDDEN;
......@@ -80,11 +81,11 @@ void copy_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch,
void convert_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) DECLSPEC_HIDDEN;
const struct pixel_format_desc *dst_format, D3DCOLOR color_key, const PALETTEENTRY *palette) DECLSPEC_HIDDEN;
void point_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) DECLSPEC_HIDDEN;
const struct pixel_format_desc *dst_format, D3DCOLOR color_key, const PALETTEENTRY *palette) 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;
......
......@@ -1025,7 +1025,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface,
D3DXIMAGE_INFO imginfo;
HRESULT hr;
IWICImagingFactory *factory;
IWICImagingFactory *factory = NULL;
IWICBitmapDecoder *decoder;
IWICBitmapFrameDecode *bitmapframe;
IWICStream *stream;
......@@ -1084,6 +1084,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface,
if (FAILED(IWICImagingFactory_CreateStream(factory, &stream)))
{
IWICImagingFactory_Release(factory);
factory = NULL;
goto cleanup_err;
}
......@@ -1092,7 +1093,6 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface,
hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream*)stream, NULL, 0, &decoder);
IWICStream_Release(stream);
IWICImagingFactory_Release(factory);
if (FAILED(hr))
goto cleanup_err;
......@@ -1113,6 +1113,8 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface,
{
BYTE *buffer;
DWORD pitch;
PALETTEENTRY *palette = NULL;
WICColor *colors = NULL;
pitch = formatdesc->bytes_per_pixel * wicrect.Width;
buffer = HeapAlloc(GetProcessHeap(), 0, pitch * wicrect.Height);
......@@ -1120,13 +1122,51 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface,
hr = IWICBitmapFrameDecode_CopyPixels(bitmapframe, &wicrect, pitch,
pitch * wicrect.Height, buffer);
if (SUCCEEDED(hr) && (formatdesc->type == FORMAT_INDEX))
{
IWICPalette *wic_palette = NULL;
UINT nb_colors;
hr = IWICImagingFactory_CreatePalette(factory, &wic_palette);
if (SUCCEEDED(hr))
hr = IWICBitmapFrameDecode_CopyPalette(bitmapframe, wic_palette);
if (SUCCEEDED(hr))
hr = IWICPalette_GetColorCount(wic_palette, &nb_colors);
if (SUCCEEDED(hr))
{
colors = HeapAlloc(GetProcessHeap(), 0, nb_colors * sizeof(colors));
palette = HeapAlloc(GetProcessHeap(), 0, nb_colors * sizeof(palette));
if (!colors || !palette)
hr = E_OUTOFMEMORY;
}
if (SUCCEEDED(hr))
hr = IWICPalette_GetColors(wic_palette, nb_colors, colors, &nb_colors);
if (SUCCEEDED(hr))
{
UINT i;
/* Convert colors from WICColor (ARGB) to PALETTEENTRY (ABGR) */
for (i = 0; i < nb_colors; i++)
{
palette[i].peRed = (colors[i] >> 16) & 0xff;
palette[i].peGreen = (colors[i] >> 8) & 0xff;
palette[i].peBlue = colors[i] & 0xff;
palette[i].peFlags = (colors[i] >> 24) & 0xff; /* peFlags is the alpha component in DX8 and higher */
}
}
if (wic_palette)
IWICPalette_Release(wic_palette);
}
if (SUCCEEDED(hr))
{
hr = D3DXLoadSurfaceFromMemory(pDestSurface, pDestPalette, pDestRect,
buffer, imginfo.Format, pitch,
NULL, &rect, dwFilter, Colorkey);
palette, &rect, dwFilter, Colorkey);
}
HeapFree(GetProcessHeap(), 0, colors);
HeapFree(GetProcessHeap(), 0, palette);
HeapFree(GetProcessHeap(), 0, buffer);
}
......@@ -1136,6 +1176,9 @@ cleanup_bmp:
IWICBitmapDecoder_Release(decoder);
cleanup_err:
if (factory)
IWICImagingFactory_Release(factory);
CoUninitialize();
if (imginfo.ImageFileFormat == D3DXIFF_DIB)
......@@ -1466,7 +1509,8 @@ void copy_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch,
*/
void convert_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)
const struct volume *dst_size, const struct pixel_format_desc *dst_format, D3DCOLOR color_key,
const PALETTEENTRY *palette)
{
struct argb_conversion_info conv_info, ck_conv_info;
const struct pixel_format_desc *ck_format = NULL;
......@@ -1520,7 +1564,7 @@ void convert_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pit
format_to_vec4(src_format, &pixel, &color);
if (src_format->to_rgba)
src_format->to_rgba(&color, &tmp);
src_format->to_rgba(&color, &tmp, palette);
else
tmp = color;
......@@ -1565,7 +1609,8 @@ void convert_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pit
*/
void point_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)
const struct volume *dst_size, const struct pixel_format_desc *dst_format, D3DCOLOR color_key,
const PALETTEENTRY *palette)
{
struct argb_conversion_info conv_info, ck_conv_info;
const struct pixel_format_desc *ck_format = NULL;
......@@ -1619,7 +1664,7 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic
format_to_vec4(src_format, &pixel, &color);
if (src_format->to_rgba)
src_format->to_rgba(&color, &tmp);
src_format->to_rgba(&color, &tmp, palette);
else
tmp = color;
......@@ -1767,7 +1812,8 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
}
else /* Stretching or format conversion. */
{
if (srcformatdesc->type != FORMAT_ARGB || destformatdesc->type != FORMAT_ARGB)
if (((srcformatdesc->type != FORMAT_ARGB) && (srcformatdesc->type != FORMAT_INDEX)) ||
(destformatdesc->type != FORMAT_ARGB))
{
FIXME("Format conversion missing %#x -> %#x\n", src_format, surfdesc.Format);
return E_NOTIMPL;
......@@ -1779,7 +1825,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
if ((filter & 0xf) == D3DX_FILTER_NONE)
{
convert_argb_pixels(src_memory, src_pitch, 0, &src_size, srcformatdesc,
lockrect.pBits, lockrect.Pitch, 0, &dst_size, destformatdesc, color_key);
lockrect.pBits, lockrect.Pitch, 0, &dst_size, destformatdesc, color_key, src_palette);
}
else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */
{
......@@ -1789,7 +1835,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
/* 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);
lockrect.pBits, lockrect.Pitch, 0, &dst_size, destformatdesc, color_key, src_palette);
}
IDirect3DSurface9_UnlockRect(dst_surface);
......@@ -2064,7 +2110,7 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE
if (SUCCEEDED(hr))
{
convert_argb_pixels(locked_rect.pBits, locked_rect.Pitch, 0, &size, src_format_desc,
dst_data, dst_pitch, 0, &size, dst_format_desc, 0);
dst_data, dst_pitch, 0, &size, dst_format_desc, 0, NULL);
IDirect3DSurface9_UnlockRect(src_surface);
}
......
......@@ -49,7 +49,7 @@ static const unsigned char bmp_1bpp[] = {
0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
0x00,0x00,0x02,0x00,0x00,0x00,0xf1,0xf2,0xf3,0x80,0xf4,0xf5,0xf6,0x81,0x00,0x00,
0x00,0x00
};
......@@ -58,7 +58,7 @@ static const unsigned char bmp_2bpp[] = {
0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00,
0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
0x00,0x00,0x02,0x00,0x00,0x00,0xf1,0xf2,0xf3,0x80,0xf4,0xf5,0xf6,0x81,0x00,0x00,
0x00,0x00
};
......@@ -67,7 +67,7 @@ static const unsigned char bmp_4bpp[] = {
0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x00,
0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
0x00,0x00,0x02,0x00,0x00,0x00,0xf1,0xf2,0xf3,0x80,0xf4,0xf5,0xf6,0x81,0x00,0x00,
0x00,0x00
};
......@@ -76,7 +76,7 @@ static const unsigned char bmp_8bpp[] = {
0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x00,0x00,
0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
0x00,0x00,0x02,0x00,0x00,0x00,0xf1,0xf2,0xf3,0x80,0xf4,0xf5,0xf6,0x81,0x00,0x00,
0x00,0x00
};
......@@ -646,7 +646,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
/* D3DXLoadSurfaceFromFile */
if(testbitmap_ok) {
hr = D3DXLoadSurfaceFromFileA(surf, NULL, NULL, "testbitmap.bmp", NULL, D3DX_DEFAULT, 0, NULL);
todo_wine ok(hr == D3D_OK, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3D_OK);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3D_OK);
hr = D3DXLoadSurfaceFromFileA(NULL, NULL, NULL, "testbitmap.bmp", NULL, D3DX_DEFAULT, 0, NULL);
ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
......@@ -683,7 +683,7 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
/* D3DXLoadSurfaceFromFileInMemory */
hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, bmp_1bpp, sizeof(bmp_1bpp), NULL, D3DX_DEFAULT, 0, NULL);
todo_wine ok(hr == D3D_OK, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, noimage, sizeof(noimage), NULL, D3DX_DEFAULT, 0, NULL);
ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
......@@ -800,6 +800,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, 2, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf, NULL);
if(FAILED(hr)) skip("Failed to create a surface (%#x)\n", hr);
else {
PALETTEENTRY palette;
hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8r3g3b2, D3DFMT_A8R3G3B2, 4, NULL, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
......@@ -870,6 +872,28 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
hr = IDirect3DSurface9_UnlockRect(surf);
ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
/* Test D3DXLoadSurfaceFromMemory with indexed color image */
palette.peRed = bmp_1bpp[56];
palette.peGreen = bmp_1bpp[55];
palette.peBlue = bmp_1bpp[54];
palette.peFlags = bmp_1bpp[57]; /* peFlags is the alpha component in DX8 and higher */
hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, &bmp_1bpp[62], D3DFMT_P8, 4, (const PALETTEENTRY*)&palette, &rect, D3DX_FILTER_NONE, 0);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x\n", hr);
ok(*(DWORD*)lockrect.pBits == 0x80f3f2f1, "Pixel color mismatch: got %#x, expected 0x80f3f2f1\n", *(DWORD*)lockrect.pBits);
hr = IDirect3DSurface9_UnlockRect(surf);
ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x\n", hr);
/* Test D3DXLoadSurfaceFromFileInMemory with indexed color image (alpha is not taken into account for bmp file) */
hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, bmp_1bpp, sizeof(bmp_1bpp), NULL, D3DX_FILTER_NONE, 0, NULL);
ok(hr == D3D_OK, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY);
ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x\n", hr);
ok(*(DWORD*)lockrect.pBits == 0xfff3f2f1, "Pixel color mismatch: got %#x, expected 0xfff3f2f1\n", *(DWORD*)lockrect.pBits);
hr = IDirect3DSurface9_UnlockRect(surf);
ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x\n", hr);
check_release((IUnknown*)surf, 0);
}
......
......@@ -28,7 +28,7 @@ static void la_from_rgba(const struct vec4 *rgba, struct vec4 *la)
la->w = rgba->w;
}
static void la_to_rgba(const struct vec4 *la, struct vec4 *rgba)
static void la_to_rgba(const struct vec4 *la, struct vec4 *rgba, const PALETTEENTRY *palette)
{
rgba->x = la->x;
rgba->y = la->x;
......@@ -36,6 +36,16 @@ static void la_to_rgba(const struct vec4 *la, struct vec4 *rgba)
rgba->w = la->w;
}
static void index_to_rgba(const struct vec4 *index, struct vec4 *rgba, const PALETTEENTRY *palette)
{
ULONG idx = (ULONG)(index->x * 255.0f + 0.5f);
rgba->x = palette[idx].peRed / 255.0f;
rgba->y = palette[idx].peGreen / 255.0f;
rgba->z = palette[idx].peBlue / 255.0f;
rgba->w = palette[idx].peFlags / 255.0f; /* peFlags is the alpha component in DX8 and higher */
}
/************************************************************
* pixel format table providing info about number of bytes per pixel,
* number of bits per channel and format type.
......@@ -73,7 +83,7 @@ static const struct pixel_format_desc formats[] =
{D3DFMT_DXT5, { 0, 0, 0, 0}, { 0, 0, 0, 0}, 1, 4, 4, 16, FORMAT_DXT, NULL, NULL },
{D3DFMT_A16B16G16R16F, {16, 16, 16, 16}, {48, 0, 16, 32}, 8, 1, 1, 8, FORMAT_ARGBF16, NULL, NULL },
{D3DFMT_A32B32G32R32F, {32, 32, 32, 32}, {96, 0, 32, 64}, 16, 1, 1, 16, FORMAT_ARGBF, NULL, NULL },
{D3DFMT_P8, { 8, 8, 8, 8}, { 0, 0, 0, 0}, 1, 1, 1, 1, FORMAT_UNKNOWN, NULL, NULL },
{D3DFMT_P8, { 8, 8, 8, 8}, { 0, 0, 0, 0}, 1, 1, 1, 1, FORMAT_INDEX, NULL, index_to_rgba},
/* marks last element */
{D3DFMT_UNKNOWN, { 0, 0, 0, 0}, { 0, 0, 0, 0}, 0, 1, 1, 0, FORMAT_UNKNOWN, NULL, NULL },
};
......
......@@ -185,7 +185,9 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume,
{
const BYTE *src_addr;
if (src_format_desc->type != FORMAT_ARGB || dst_format_desc->type != FORMAT_ARGB)
if (((src_format_desc->type != FORMAT_ARGB) && (src_format_desc->type != FORMAT_INDEX)) ||
(dst_format_desc->type != FORMAT_ARGB))
{
FIXME("Pixel format conversion not implemented %#x -> %#x\n",
src_format_desc->format, dst_format_desc->format);
......@@ -203,7 +205,8 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume,
if ((filter & 0xf) == D3DX_FILTER_NONE)
{
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);
locked_box.pBits, locked_box.RowPitch, locked_box.SlicePitch, &dst_size, dst_format_desc, color_key,
src_palette);
}
else
{
......@@ -211,7 +214,8 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume,
FIXME("Unhandled filter %#x.\n", filter);
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);
locked_box.pBits, locked_box.RowPitch, locked_box.SlicePitch, &dst_size, dst_format_desc, color_key,
src_palette);
}
IDirect3DVolume9_UnlockBox(dst_volume);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment