=?UTF-8?Q?J=C3=B3zef=20Kucia=20?=: d3dx9: Implement the support for saving a surface to a DDS file.

Alexandre Julliard julliard at winehq.org
Mon Sep 24 16:04:28 CDT 2012


Module: wine
Branch: master
Commit: bf4201ea58efb099f0d9f4fe8669d68d74f2a633
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=bf4201ea58efb099f0d9f4fe8669d68d74f2a633

Author: Józef Kucia <joseph.kucia at gmail.com>
Date:   Mon Sep 24 13:46:38 2012 +0200

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

---

 dlls/d3dx9_36/surface.c       |   93 +++++++++++++++++++++++++++++++++++++++++
 dlls/d3dx9_36/tests/surface.c |    3 +-
 2 files changed, 95 insertions(+), 1 deletions(-)

diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c
index 3bf8cb1..770a2e5 100644
--- a/dlls/d3dx9_36/surface.c
+++ b/dlls/d3dx9_36/surface.c
@@ -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:
diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c
index 5a01200..50ed2b2 100644
--- a/dlls/d3dx9_36/tests/surface.c
+++ b/dlls/d3dx9_36/tests/surface.c
@@ -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);




More information about the wine-cvs mailing list