d3dx9: Implement the support for saving a surface to a DDS file.

This commit is contained in:
Józef Kucia 2012-09-24 13:46:38 +02:00 committed by Alexandre Julliard
parent 8f00a63161
commit bf4201ea58
2 changed files with 95 additions and 1 deletions

View file

@ -275,6 +275,27 @@ static D3DFORMAT dds_pixel_format_to_d3dformat(const struct dds_pixel_format *pi
return D3DFMT_UNKNOWN;
}
static HRESULT d3dformat_to_dds_pixel_format(struct dds_pixel_format *pixel_format, D3DFORMAT d3dformat)
{
memset(pixel_format, 0, sizeof(*pixel_format));
pixel_format->size = sizeof(*pixel_format);
if (d3dformat == D3DFMT_R8G8B8)
{
pixel_format->flags = DDS_PF_RGB;
pixel_format->bpp = 24;
pixel_format->rmask = 0xff0000;
pixel_format->gmask = 0x00ff00;
pixel_format->bmask = 0x0000ff;
pixel_format->amask = 0x000000;
return D3D_OK;
}
WARN("Unknown pixel format %#x\n", d3dformat);
return E_NOTIMPL;
}
static HRESULT calculate_dds_surface_size(D3DFORMAT format, UINT width, UINT height,
UINT *pitch, UINT *size)
{
@ -410,6 +431,77 @@ static HRESULT load_surface_from_dds(IDirect3DSurface9 *dst_surface, const PALET
src_pitch, NULL, src_rect, filter, color_key);
}
static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSurface9 *src_surface, const RECT *src_rect)
{
HRESULT hr;
UINT dst_pitch, surface_size, file_size;
D3DSURFACE_DESC src_desc;
D3DLOCKED_RECT locked_rect;
ID3DXBuffer *buffer;
struct dds_header *header;
BYTE *pixels;
struct volume volume;
const struct pixel_format_desc *pixel_format;
if (src_rect)
{
FIXME("Saving a part of a surface to a DDS file is not implemented yet\n");
return E_NOTIMPL;
}
hr = IDirect3DSurface9_GetDesc(src_surface, &src_desc);
if (FAILED(hr)) return hr;
pixel_format = get_format_info(src_desc.Format);
if (pixel_format->type == FORMAT_UNKNOWN) return E_NOTIMPL;
file_size = calculate_dds_file_size(src_desc.Format, src_desc.Width, src_desc.Height, 1, 1, 1);
hr = calculate_dds_surface_size(src_desc.Format, src_desc.Width, src_desc.Height, &dst_pitch, &surface_size);
if (FAILED(hr)) return hr;
hr = D3DXCreateBuffer(file_size, &buffer);
if (FAILED(hr)) return hr;
header = ID3DXBuffer_GetBufferPointer(buffer);
pixels = (BYTE *)(header + 1);
memset(header, 0, sizeof(header));
header->signature = MAKEFOURCC('D','D','S',' ');
header->size = sizeof(*header);
header->flags = DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PITCH | DDS_PIXELFORMAT | DDS_MIPMAPCOUNT;
header->height = src_desc.Height;
header->width = src_desc.Width;
header->pitch_or_linear_size = dst_pitch;
header->depth = 1;
header->miplevels = 1;
header->caps = DDS_CAPS_TEXTURE;
hr = d3dformat_to_dds_pixel_format(&header->pixel_format, src_desc.Format);
if (FAILED(hr))
{
ID3DXBuffer_Release(buffer);
return hr;
}
hr = IDirect3DSurface9_LockRect(src_surface, &locked_rect, NULL, D3DLOCK_READONLY);
if (FAILED(hr))
{
ID3DXBuffer_Release(buffer);
return hr;
}
volume.width = src_desc.Width;
volume.height = src_desc.Height;
volume.depth = 1;
copy_simple_data(locked_rect.pBits, locked_rect.Pitch, 0, &volume, pixel_format,
pixels, dst_pitch, 0, &volume, pixel_format, 0);
IDirect3DSurface9_UnlockRect(src_surface);
*dst_buffer = buffer;
return D3D_OK;
}
HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette,
const D3DBOX *dst_box, const void *src_data, const D3DBOX *src_box, DWORD filter, D3DCOLOR color_key,
const D3DXIMAGE_INFO *src_info)
@ -1761,6 +1853,7 @@ HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE
encoder_clsid = &CLSID_WICJpegEncoder;
break;
case D3DXIFF_DDS:
return save_dds_surface_to_memory(dst_buffer, src_surface, src_rect);
case D3DXIFF_DIB:
case D3DXIFF_HDR:
case D3DXIFF_PFM:

View file

@ -1156,9 +1156,10 @@ next_tests:
ok(hr == D3D_OK, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3D_OK);
hr = D3DXSaveSurfaceToFileA("saved_surface.tga", D3DXIFF_TGA, surface, NULL, NULL);
ok(hr == D3D_OK, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3D_OK);
}
hr = D3DXSaveSurfaceToFileA("saved_surface.dds", D3DXIFF_DDS, surface, NULL, NULL);
ok(hr == D3D_OK, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3D_OK);
}
hr = D3DXSaveSurfaceToFileA("saved_surface", D3DXIFF_PFM + 1, surface, NULL, NULL);
ok(hr == D3DERR_INVALIDCALL, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);