d3dx9: Implement D3DXSaveSurfaceToFileInMemory.
This commit is contained in:
parent
d770297c37
commit
70b1bff695
|
@ -264,7 +264,7 @@
|
||||||
@ stub D3DXSavePRTCompBufferToFileA(ptr ptr)
|
@ stub D3DXSavePRTCompBufferToFileA(ptr ptr)
|
||||||
@ stub D3DXSavePRTCompBufferToFileW(ptr ptr)
|
@ stub D3DXSavePRTCompBufferToFileW(ptr ptr)
|
||||||
@ stdcall D3DXSaveSurfaceToFileA(ptr long ptr ptr ptr)
|
@ stdcall D3DXSaveSurfaceToFileA(ptr long ptr ptr ptr)
|
||||||
@ stub D3DXSaveSurfaceToFileInMemory(ptr long ptr ptr ptr)
|
@ stdcall D3DXSaveSurfaceToFileInMemory(ptr long ptr ptr ptr)
|
||||||
@ stdcall D3DXSaveSurfaceToFileW(ptr long ptr ptr ptr)
|
@ stdcall D3DXSaveSurfaceToFileW(ptr long ptr ptr ptr)
|
||||||
@ stub D3DXSaveTextureToFileA(ptr long ptr ptr)
|
@ stub D3DXSaveTextureToFileA(ptr long ptr ptr)
|
||||||
@ stub D3DXSaveTextureToFileInMemory(ptr long ptr ptr)
|
@ stub D3DXSaveTextureToFileInMemory(ptr long ptr ptr)
|
||||||
|
|
|
@ -59,6 +59,8 @@ typedef struct _PixelFormatDesc {
|
||||||
HRESULT map_view_of_file(LPCWSTR filename, LPVOID *buffer, DWORD *length) DECLSPEC_HIDDEN;
|
HRESULT map_view_of_file(LPCWSTR filename, LPVOID *buffer, DWORD *length) DECLSPEC_HIDDEN;
|
||||||
HRESULT load_resource_into_memory(HMODULE module, HRSRC resinfo, LPVOID *buffer, DWORD *length) DECLSPEC_HIDDEN;
|
HRESULT load_resource_into_memory(HMODULE module, HRSRC resinfo, LPVOID *buffer, DWORD *length) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
HRESULT write_buffer_to_file(const WCHAR *filename, ID3DXBuffer *buffer) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
const PixelFormatDesc *get_format_info(D3DFORMAT format) DECLSPEC_HIDDEN;
|
const PixelFormatDesc *get_format_info(D3DFORMAT format) DECLSPEC_HIDDEN;
|
||||||
const PixelFormatDesc *get_format_info_idx(int idx) DECLSPEC_HIDDEN;
|
const PixelFormatDesc *get_format_info_idx(int idx) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "d3dx9_36_private.h"
|
#include "d3dx9_36_private.h"
|
||||||
|
|
||||||
#include "initguid.h"
|
#include "initguid.h"
|
||||||
|
#include "ole2.h"
|
||||||
#include "wincodec.h"
|
#include "wincodec.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
|
WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
|
||||||
|
@ -1584,6 +1585,7 @@ HRESULT WINAPI D3DXSaveSurfaceToFileA(const char *dst_filename, D3DXIMAGE_FILEFO
|
||||||
int len;
|
int len;
|
||||||
WCHAR *filename;
|
WCHAR *filename;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
ID3DXBuffer *buffer;
|
||||||
|
|
||||||
TRACE("(%s, %#x, %p, %p, %s): relay\n",
|
TRACE("(%s, %#x, %p, %p, %s): relay\n",
|
||||||
wine_dbgstr_a(dst_filename), file_format, src_surface, src_palette, wine_dbgstr_rect(src_rect));
|
wine_dbgstr_a(dst_filename), file_format, src_surface, src_palette, wine_dbgstr_rect(src_rect));
|
||||||
|
@ -1595,7 +1597,12 @@ HRESULT WINAPI D3DXSaveSurfaceToFileA(const char *dst_filename, D3DXIMAGE_FILEFO
|
||||||
if (!filename) return E_OUTOFMEMORY;
|
if (!filename) return E_OUTOFMEMORY;
|
||||||
MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, filename, len);
|
MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, filename, len);
|
||||||
|
|
||||||
hr = D3DXSaveSurfaceToFileW(filename, file_format, src_surface, src_palette, src_rect);
|
hr = D3DXSaveSurfaceToFileInMemory(&buffer, file_format, src_surface, src_palette, src_rect);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = write_buffer_to_file(filename, buffer);
|
||||||
|
ID3DXBuffer_Release(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, filename);
|
HeapFree(GetProcessHeap(), 0, filename);
|
||||||
return hr;
|
return hr;
|
||||||
|
@ -1604,11 +1611,31 @@ HRESULT WINAPI D3DXSaveSurfaceToFileA(const char *dst_filename, D3DXIMAGE_FILEFO
|
||||||
HRESULT WINAPI D3DXSaveSurfaceToFileW(const WCHAR *dst_filename, D3DXIMAGE_FILEFORMAT file_format,
|
HRESULT WINAPI D3DXSaveSurfaceToFileW(const WCHAR *dst_filename, D3DXIMAGE_FILEFORMAT file_format,
|
||||||
IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
|
IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
|
||||||
{
|
{
|
||||||
IWICImagingFactory *factory;
|
HRESULT hr;
|
||||||
|
ID3DXBuffer *buffer;
|
||||||
|
|
||||||
|
TRACE("(%s, %#x, %p, %p, %s): relay\n",
|
||||||
|
wine_dbgstr_w(dst_filename), file_format, src_surface, src_palette, wine_dbgstr_rect(src_rect));
|
||||||
|
|
||||||
|
if (!dst_filename) return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
|
hr = D3DXSaveSurfaceToFileInMemory(&buffer, file_format, src_surface, src_palette, src_rect);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = write_buffer_to_file(dst_filename, buffer);
|
||||||
|
ID3DXBuffer_Release(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE_FILEFORMAT file_format,
|
||||||
|
IDirect3DSurface9 *src_surface, const PALETTEENTRY *src_palette, const RECT *src_rect)
|
||||||
|
{
|
||||||
IWICBitmapEncoder *encoder = NULL;
|
IWICBitmapEncoder *encoder = NULL;
|
||||||
IWICBitmapFrameEncode *frame = NULL;
|
IWICBitmapFrameEncode *frame = NULL;
|
||||||
IPropertyBag2 *encoder_options = NULL;
|
IPropertyBag2 *encoder_options = NULL;
|
||||||
IWICStream *stream = NULL;
|
IStream *stream = NULL;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
HRESULT initresult;
|
HRESULT initresult;
|
||||||
const CLSID *encoder_clsid;
|
const CLSID *encoder_clsid;
|
||||||
|
@ -1618,11 +1645,15 @@ HRESULT WINAPI D3DXSaveSurfaceToFileW(const WCHAR *dst_filename, D3DXIMAGE_FILEF
|
||||||
D3DSURFACE_DESC src_surface_desc;
|
D3DSURFACE_DESC src_surface_desc;
|
||||||
D3DLOCKED_RECT locked_rect;
|
D3DLOCKED_RECT locked_rect;
|
||||||
int width, height;
|
int width, height;
|
||||||
|
STATSTG stream_stats;
|
||||||
|
HGLOBAL stream_hglobal;
|
||||||
|
ID3DXBuffer *buffer;
|
||||||
|
DWORD size;
|
||||||
|
|
||||||
TRACE("(%s, %#x, %p, %p, %s)\n",
|
TRACE("(%p, %#x, %p, %p, %s)\n",
|
||||||
wine_dbgstr_w(dst_filename), file_format, src_surface, src_palette, wine_dbgstr_rect(src_rect));
|
dst_buffer, file_format, src_surface, src_palette, wine_dbgstr_rect(src_rect));
|
||||||
|
|
||||||
if (!dst_filename || !src_surface) return D3DERR_INVALIDCALL;
|
if (!dst_buffer || !src_surface) return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
if (src_palette)
|
if (src_palette)
|
||||||
{
|
{
|
||||||
|
@ -1657,7 +1688,10 @@ HRESULT WINAPI D3DXSaveSurfaceToFileW(const WCHAR *dst_filename, D3DXIMAGE_FILEF
|
||||||
if (src_rect)
|
if (src_rect)
|
||||||
{
|
{
|
||||||
if (src_rect->left == src_rect->right || src_rect->top == src_rect->bottom)
|
if (src_rect->left == src_rect->right || src_rect->top == src_rect->bottom)
|
||||||
return D3D_OK;
|
{
|
||||||
|
WARN("Invalid rectangle with 0 area\n");
|
||||||
|
return D3DXCreateBuffer(64, dst_buffer);
|
||||||
|
}
|
||||||
if (src_rect->left < 0 || src_rect->top < 0)
|
if (src_rect->left < 0 || src_rect->top < 0)
|
||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
if (src_rect->left > src_rect->right || src_rect->top > src_rect->bottom)
|
if (src_rect->left > src_rect->right || src_rect->top > src_rect->bottom)
|
||||||
|
@ -1676,24 +1710,14 @@ HRESULT WINAPI D3DXSaveSurfaceToFileW(const WCHAR *dst_filename, D3DXIMAGE_FILEF
|
||||||
|
|
||||||
initresult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
initresult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||||
|
|
||||||
hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
|
|
||||||
&IID_IWICImagingFactory, (void **)&factory);
|
|
||||||
if (FAILED(hr)) goto cleanup_err;
|
|
||||||
|
|
||||||
hr = IWICImagingFactory_CreateStream(factory, &stream);
|
|
||||||
IWICImagingFactory_Release(factory);
|
|
||||||
if (FAILED(hr)) goto cleanup_err;
|
|
||||||
|
|
||||||
hr = IWICStream_InitializeFromFilename(stream, dst_filename, GENERIC_WRITE);
|
|
||||||
if (FAILED(hr)) goto cleanup_err;
|
|
||||||
|
|
||||||
hr = CoCreateInstance(encoder_clsid, NULL, CLSCTX_INPROC_SERVER,
|
hr = CoCreateInstance(encoder_clsid, NULL, CLSCTX_INPROC_SERVER,
|
||||||
&IID_IWICBitmapEncoder, (void **)&encoder);
|
&IID_IWICBitmapEncoder, (void **)&encoder);
|
||||||
if (FAILED(hr)) goto cleanup_err;
|
if (FAILED(hr)) goto cleanup_err;
|
||||||
|
|
||||||
hr = IWICBitmapEncoder_Initialize(encoder, (IStream *)stream, WICBitmapEncoderNoCache);
|
hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
|
||||||
IStream_Release((IStream *)stream);
|
if (FAILED(hr)) goto cleanup_err;
|
||||||
stream = NULL;
|
|
||||||
|
hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
|
||||||
if (FAILED(hr)) goto cleanup_err;
|
if (FAILED(hr)) goto cleanup_err;
|
||||||
|
|
||||||
hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frame, &encoder_options);
|
hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frame, &encoder_options);
|
||||||
|
@ -1783,11 +1807,37 @@ HRESULT WINAPI D3DXSaveSurfaceToFileW(const WCHAR *dst_filename, D3DXIMAGE_FILEF
|
||||||
}
|
}
|
||||||
else WARN("Unsupported pixel format %#x\n", src_surface_desc.Format);
|
else WARN("Unsupported pixel format %#x\n", src_surface_desc.Format);
|
||||||
|
|
||||||
|
/* copy data from stream to ID3DXBuffer */
|
||||||
|
hr = IStream_Stat(stream, &stream_stats, STATFLAG_NONAME);
|
||||||
|
if (FAILED(hr)) goto cleanup_err;
|
||||||
|
|
||||||
|
if (stream_stats.cbSize.u.HighPart != 0)
|
||||||
|
{
|
||||||
|
hr = D3DXERR_INVALIDDATA;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
size = stream_stats.cbSize.u.LowPart;
|
||||||
|
|
||||||
|
hr = D3DXCreateBuffer(size, &buffer);
|
||||||
|
if (FAILED(hr)) goto cleanup;
|
||||||
|
|
||||||
|
hr = GetHGlobalFromStream(stream, &stream_hglobal);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
void *buffer_pointer = ID3DXBuffer_GetBufferPointer(buffer);
|
||||||
|
void *stream_data = GlobalLock(stream_hglobal);
|
||||||
|
memcpy(buffer_pointer, stream_data, size);
|
||||||
|
GlobalUnlock(stream_hglobal);
|
||||||
|
*dst_buffer = buffer;
|
||||||
|
}
|
||||||
|
else ID3DXBuffer_Release(buffer);
|
||||||
|
|
||||||
cleanup_err:
|
cleanup_err:
|
||||||
if (FAILED(hr)) hr = D3DERR_INVALIDCALL;
|
if (FAILED(hr) && hr != E_OUTOFMEMORY)
|
||||||
|
hr = D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (stream) IStream_Release((IStream *)stream);
|
if (stream) IStream_Release(stream);
|
||||||
|
|
||||||
if (frame) IWICBitmapFrameEncode_Release(frame);
|
if (frame) IWICBitmapFrameEncode_Release(frame);
|
||||||
if (encoder_options) IPropertyBag2_Release(encoder_options);
|
if (encoder_options) IPropertyBag2_Release(encoder_options);
|
||||||
|
|
|
@ -920,6 +920,32 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
|
||||||
if(testbitmap_ok) DeleteFileA("testbitmap.bmp");
|
if(testbitmap_ok) DeleteFileA("testbitmap.bmp");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
RECT rect;
|
||||||
|
ID3DXBuffer *buffer;
|
||||||
|
IDirect3DSurface9 *surface;
|
||||||
|
|
||||||
|
hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
skip("Couldn't create surface\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetRect(&rect, 0, 0, 0, 0);
|
||||||
|
hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_BMP, surface, NULL, &rect);
|
||||||
|
/* fails with the debug version of d3d9 */
|
||||||
|
ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL), "D3DXSaveSurfaceToFileInMemory returned %#x, expected %#x\n", hr, D3D_OK);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
DWORD size = ID3DXBuffer_GetBufferSize(buffer);
|
||||||
|
ok(size > 0, "ID3DXBuffer_GetBufferSize returned %u, expected > 0\n", size);
|
||||||
|
ID3DXBuffer_Release(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
IDirect3DSurface9_Release(surface);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_D3DXSaveSurfaceToFile(IDirect3DDevice9 *device)
|
static void test_D3DXSaveSurfaceToFile(IDirect3DDevice9 *device)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -1037,6 +1063,7 @@ START_TEST(surface)
|
||||||
|
|
||||||
test_D3DXGetImageInfo();
|
test_D3DXGetImageInfo();
|
||||||
test_D3DXLoadSurface(device);
|
test_D3DXLoadSurface(device);
|
||||||
|
test_D3DXSaveSurfaceToFileInMemory(device);
|
||||||
test_D3DXSaveSurfaceToFile(device);
|
test_D3DXSaveSurfaceToFile(device);
|
||||||
|
|
||||||
check_release((IUnknown*)device, 0);
|
check_release((IUnknown*)device, 0);
|
||||||
|
|
|
@ -158,6 +158,25 @@ HRESULT load_resource_into_memory(HMODULE module, HRSRC resinfo, LPVOID *buffer,
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT write_buffer_to_file(const WCHAR *dst_filename, ID3DXBuffer *buffer)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
void *buffer_pointer;
|
||||||
|
DWORD buffer_size;
|
||||||
|
HANDLE file = CreateFileW(dst_filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (file == INVALID_HANDLE_VALUE)
|
||||||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
|
||||||
|
buffer_pointer = ID3DXBuffer_GetBufferPointer(buffer);
|
||||||
|
buffer_size = ID3DXBuffer_GetBufferSize(buffer);
|
||||||
|
|
||||||
|
if (!WriteFile(file, buffer_pointer, buffer_size, NULL, NULL))
|
||||||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
|
||||||
|
CloseHandle(file);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* get_format_info
|
* get_format_info
|
||||||
|
|
|
@ -168,6 +168,12 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
|
||||||
D3DFORMAT src_format, UINT src_pitch, const PALETTEENTRY *src_palette, const RECT *src_rect,
|
D3DFORMAT src_format, UINT src_pitch, const PALETTEENTRY *src_palette, const RECT *src_rect,
|
||||||
DWORD filter, D3DCOLOR color_key);
|
DWORD filter, D3DCOLOR color_key);
|
||||||
|
|
||||||
|
HRESULT WINAPI D3DXSaveSurfaceToFileInMemory( LPD3DXBUFFER *destbuffer,
|
||||||
|
D3DXIMAGE_FILEFORMAT destformat,
|
||||||
|
LPDIRECT3DSURFACE9 srcsurface,
|
||||||
|
CONST PALETTEENTRY *srcpalette,
|
||||||
|
CONST RECT *srcrect);
|
||||||
|
|
||||||
HRESULT WINAPI D3DXSaveSurfaceToFileA( LPCSTR destfile,
|
HRESULT WINAPI D3DXSaveSurfaceToFileA( LPCSTR destfile,
|
||||||
D3DXIMAGE_FILEFORMAT destformat,
|
D3DXIMAGE_FILEFORMAT destformat,
|
||||||
LPDIRECT3DSURFACE9 srcsurface,
|
LPDIRECT3DSURFACE9 srcsurface,
|
||||||
|
|
Loading…
Reference in New Issue