[PATCH 1/7] mfplat: Implement MFCreateDXSurfaceBuffer().
Nikolay Sivov
nsivov at codeweavers.com
Fri Oct 30 08:50:41 CDT 2020
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mfplat/buffer.c | 308 +++++++++++++++++++++++++++++++++++++
dlls/mfplat/mfplat.spec | 1 +
dlls/mfplat/tests/mfplat.c | 11 +-
3 files changed, 319 insertions(+), 1 deletion(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c
index 5e969e14ec9..3d1d2abdf88 100644
--- a/dlls/mfplat/buffer.c
+++ b/dlls/mfplat/buffer.c
@@ -21,6 +21,10 @@
#include "mfplat_private.h"
#include "rtworkq.h"
+#include "initguid.h"
+#include "d3d9.h"
+#include "evr.h"
+
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
@@ -50,6 +54,11 @@ struct memory_buffer
unsigned int locks;
} _2d;
+ struct
+ {
+ IDirect3DSurface9 *surface;
+ D3DLOCKED_RECT rect;
+ } d3d9_surface;
CRITICAL_SECTION cs;
};
@@ -142,6 +151,8 @@ static ULONG WINAPI memory_buffer_Release(IMFMediaBuffer *iface)
if (!refcount)
{
+ if (buffer->d3d9_surface.surface)
+ IDirect3DSurface9_Release(buffer->d3d9_surface.surface);
DeleteCriticalSection(&buffer->cs);
heap_free(buffer->_2d.linear_buffer);
heap_free(buffer->data);
@@ -333,6 +344,97 @@ static const IMFMediaBufferVtbl memory_1d_2d_buffer_vtbl =
memory_buffer_GetMaxLength,
};
+static HRESULT WINAPI d3d9_surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length, DWORD *current_length)
+{
+ struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
+ HRESULT hr = S_OK;
+
+ TRACE("%p, %p, %p, %p.\n", iface, data, max_length, current_length);
+
+ if (!data)
+ return E_POINTER;
+
+ EnterCriticalSection(&buffer->cs);
+
+ if (!buffer->_2d.linear_buffer && buffer->_2d.locks)
+ hr = MF_E_INVALIDREQUEST;
+ else if (!buffer->_2d.linear_buffer)
+ {
+ D3DLOCKED_RECT rect;
+
+ if (!(buffer->_2d.linear_buffer = heap_alloc(ALIGN_SIZE(buffer->_2d.plane_size, MF_64_BYTE_ALIGNMENT))))
+ hr = E_OUTOFMEMORY;
+
+ if (SUCCEEDED(hr))
+ {
+ hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &rect, NULL, 0);
+ if (SUCCEEDED(hr))
+ {
+ MFCopyImage(buffer->_2d.linear_buffer, buffer->_2d.width, rect.pBits, rect.Pitch,
+ buffer->_2d.width, buffer->_2d.height);
+ IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface);
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ ++buffer->_2d.locks;
+ *data = buffer->_2d.linear_buffer;
+ if (max_length)
+ *max_length = buffer->_2d.plane_size;
+ if (current_length)
+ *current_length = buffer->_2d.plane_size;
+ }
+
+ LeaveCriticalSection(&buffer->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI d3d9_surface_buffer_Unlock(IMFMediaBuffer *iface)
+{
+ struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
+ HRESULT hr = S_OK;
+
+ TRACE("%p.\n", iface);
+
+ EnterCriticalSection(&buffer->cs);
+
+ if (!buffer->_2d.linear_buffer)
+ hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
+ else if (!--buffer->_2d.locks)
+ {
+ D3DLOCKED_RECT rect;
+
+ if (SUCCEEDED(hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &rect, NULL, 0)))
+ {
+ MFCopyImage(rect.pBits, rect.Pitch, buffer->_2d.linear_buffer, buffer->_2d.width,
+ buffer->_2d.width, buffer->_2d.height);
+ IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface);
+ }
+
+ heap_free(buffer->_2d.linear_buffer);
+ buffer->_2d.linear_buffer = NULL;
+ }
+
+ LeaveCriticalSection(&buffer->cs);
+
+ return hr;
+}
+
+static const IMFMediaBufferVtbl d3d9_surface_1d_buffer_vtbl =
+{
+ memory_1d_2d_buffer_QueryInterface,
+ memory_buffer_AddRef,
+ memory_buffer_Release,
+ d3d9_surface_buffer_Lock,
+ d3d9_surface_buffer_Unlock,
+ memory_buffer_GetCurrentLength,
+ memory_buffer_SetCurrentLength,
+ memory_buffer_GetMaxLength,
+};
+
static HRESULT WINAPI memory_2d_buffer_QueryInterface(IMF2DBuffer2 *iface, REFIID riid, void **obj)
{
struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
@@ -521,6 +623,144 @@ static const IMF2DBuffer2Vtbl memory_2d_buffer_vtbl =
memory_2d_buffer_Copy2DTo,
};
+static HRESULT WINAPI d3d9_surface_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
+{
+ struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
+ HRESULT hr = S_OK;
+
+ TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
+
+ if (!scanline0 || !pitch)
+ return E_POINTER;
+
+ EnterCriticalSection(&buffer->cs);
+
+ if (buffer->_2d.linear_buffer)
+ hr = MF_E_UNEXPECTED;
+ else if (!buffer->_2d.locks++)
+ {
+ hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &buffer->d3d9_surface.rect, NULL, 0);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *scanline0 = buffer->d3d9_surface.rect.pBits;
+ *pitch = buffer->d3d9_surface.rect.Pitch;
+ }
+
+ LeaveCriticalSection(&buffer->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI d3d9_surface_buffer_Unlock2D(IMF2DBuffer2 *iface)
+{
+ struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
+ HRESULT hr = S_OK;
+
+ TRACE("%p.\n", iface);
+
+ EnterCriticalSection(&buffer->cs);
+
+ if (buffer->_2d.locks)
+ {
+ if (!--buffer->_2d.locks)
+ {
+ IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface);
+ memset(&buffer->d3d9_surface.rect, 0, sizeof(buffer->d3d9_surface.rect));
+ }
+ }
+ else
+ hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
+
+ LeaveCriticalSection(&buffer->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI d3d9_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
+{
+ struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
+ HRESULT hr = S_OK;
+
+ TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
+
+ if (!scanline0 || !pitch)
+ return E_POINTER;
+
+ EnterCriticalSection(&buffer->cs);
+
+ if (!buffer->_2d.locks)
+ hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
+ else
+ {
+ *scanline0 = buffer->d3d9_surface.rect.pBits;
+ *pitch = buffer->d3d9_surface.rect.Pitch;
+ }
+
+ LeaveCriticalSection(&buffer->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI d3d9_surface_buffer_GetContiguousLength(IMF2DBuffer2 *iface, DWORD *length)
+{
+ FIXME("%p, %p.\n", iface, length);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3d9_surface_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags, BYTE **scanline0,
+ LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
+{
+ struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
+ HRESULT hr = S_OK;
+
+ TRACE("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length);
+
+ if (!scanline0 || !pitch || !buffer_start || !buffer_length)
+ return E_POINTER;
+
+ EnterCriticalSection(&buffer->cs);
+
+ if (buffer->_2d.linear_buffer)
+ hr = MF_E_UNEXPECTED;
+ else if (!buffer->_2d.locks++)
+ {
+ hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &buffer->d3d9_surface.rect, NULL, 0);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *scanline0 = buffer->d3d9_surface.rect.pBits;
+ *pitch = buffer->d3d9_surface.rect.Pitch;
+ if (buffer_start)
+ *buffer_start = *scanline0;
+ if (buffer_length)
+ *buffer_length = buffer->d3d9_surface.rect.Pitch * buffer->_2d.height;
+ }
+
+ LeaveCriticalSection(&buffer->cs);
+
+ return hr;
+}
+
+static const IMF2DBuffer2Vtbl d3d9_surface_buffer_vtbl =
+{
+ memory_2d_buffer_QueryInterface,
+ memory_2d_buffer_AddRef,
+ memory_2d_buffer_Release,
+ d3d9_surface_buffer_Lock2D,
+ d3d9_surface_buffer_Unlock2D,
+ d3d9_surface_buffer_GetScanline0AndPitch,
+ memory_2d_buffer_IsContiguousFormat,
+ d3d9_surface_buffer_GetContiguousLength,
+ memory_2d_buffer_ContiguousCopyTo,
+ memory_2d_buffer_ContiguousCopyFrom,
+ d3d9_surface_buffer_Lock2DSize,
+ memory_2d_buffer_Copy2DTo,
+};
+
static HRESULT WINAPI memory_2d_buffer_gs_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
{
struct memory_buffer *buffer = impl_from_IMFGetService(iface);
@@ -554,6 +794,28 @@ static const IMFGetServiceVtbl memory_2d_buffer_gs_vtbl =
memory_2d_buffer_gs_GetService,
};
+static HRESULT WINAPI d3d9_surface_buffer_gs_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
+{
+ struct memory_buffer *buffer = impl_from_IMFGetService(iface);
+
+ TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
+
+ if (IsEqualGUID(service, &MR_BUFFER_SERVICE))
+ {
+ return IDirect3DSurface9_QueryInterface(buffer->d3d9_surface.surface, riid, obj);
+ }
+
+ return E_NOTIMPL;
+}
+
+static const IMFGetServiceVtbl d3d9_surface_buffer_gs_vtbl =
+{
+ memory_2d_buffer_gs_QueryInterface,
+ memory_2d_buffer_gs_AddRef,
+ memory_2d_buffer_gs_Release,
+ d3d9_surface_buffer_gs_GetService,
+};
+
static HRESULT memory_buffer_init(struct memory_buffer *buffer, DWORD max_length, DWORD alignment,
const IMFMediaBufferVtbl *vtbl)
{
@@ -675,6 +937,36 @@ static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, BOOL bo
return S_OK;
}
+static HRESULT create_d3d9_surface_buffer(IUnknown *surface, BOOL bottom_up, IMFMediaBuffer **buffer)
+{
+ struct memory_buffer *object;
+ D3DSURFACE_DESC desc;
+
+ object = heap_alloc_zero(sizeof(*object));
+ if (!object)
+ return E_OUTOFMEMORY;
+
+ object->IMFMediaBuffer_iface.lpVtbl = &d3d9_surface_1d_buffer_vtbl;
+ object->IMF2DBuffer2_iface.lpVtbl = &d3d9_surface_buffer_vtbl;
+ object->IMFGetService_iface.lpVtbl = &d3d9_surface_buffer_gs_vtbl;
+ object->refcount = 1;
+ InitializeCriticalSection(&object->cs);
+ object->d3d9_surface.surface = (IDirect3DSurface9 *)surface;
+ IUnknown_AddRef(surface);
+
+ IDirect3DSurface9_GetDesc(object->d3d9_surface.surface, &desc);
+ TRACE("format %#x, %u x %u.\n", desc.Format, desc.Width, desc.Height);
+
+ MFGetPlaneSize(desc.Format, desc.Width, desc.Height, &object->_2d.plane_size);
+ object->_2d.width = desc.Width;
+ object->_2d.height = desc.Height;
+ object->max_length = object->_2d.plane_size;
+
+ *buffer = &object->IMFMediaBuffer_iface;
+
+ return S_OK;
+}
+
/***********************************************************************
* MFCreateMemoryBuffer (mfplat.@)
*/
@@ -695,6 +987,9 @@ HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IM
return create_1d_buffer(max_length, alignment, buffer);
}
+/***********************************************************************
+ * MFCreate2DMediaBuffer (mfplat.@)
+ */
HRESULT WINAPI MFCreate2DMediaBuffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer)
{
TRACE("%u, %u, %s, %d, %p.\n", width, height, debugstr_fourcc(fourcc), bottom_up, buffer);
@@ -702,6 +997,19 @@ HRESULT WINAPI MFCreate2DMediaBuffer(DWORD width, DWORD height, DWORD fourcc, BO
return create_2d_buffer(width, height, fourcc, bottom_up, buffer);
}
+/***********************************************************************
+ * MFCreateDXSurfaceBuffer (mfplat.@)
+ */
+HRESULT WINAPI MFCreateDXSurfaceBuffer(REFIID riid, IUnknown *surface, BOOL bottom_up, IMFMediaBuffer **buffer)
+{
+ TRACE("%s, %p, %d, %p.\n", debugstr_guid(riid), surface, bottom_up, buffer);
+
+ if (!IsEqualIID(riid, &IID_IDirect3DSurface9))
+ return E_INVALIDARG;
+
+ return create_d3d9_surface_buffer(surface, bottom_up, buffer);
+}
+
static unsigned int buffer_get_aligned_length(unsigned int length, unsigned int alignment)
{
length = (length + alignment) / alignment;
diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec
index 5f4735cd6f7..80064e1980e 100644
--- a/dlls/mfplat/mfplat.spec
+++ b/dlls/mfplat/mfplat.spec
@@ -46,6 +46,7 @@
@ stub MFCreateAudioMediaType
@ stdcall MFCreateCollection(ptr)
@ stdcall MFCreateDXGIDeviceManager(ptr ptr)
+@ stdcall MFCreateDXSurfaceBuffer(ptr ptr long ptr)
@ stdcall MFCreateEventQueue(ptr)
@ stdcall MFCreateFile(long long long wstr ptr)
@ stub MFCreateLegacyMediaBufferOnMFMediaBuffer
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 8c6cbf74661..711a712da0d 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -5649,7 +5649,7 @@ static void test_MFCreateDXSurfaceBuffer(void)
if (!pMFCreateDXSurfaceBuffer)
{
- skip("MFCreateDXSurfaceBuffer is not available.\n");
+ win_skip("MFCreateDXSurfaceBuffer is not available.\n");
return;
}
@@ -5671,6 +5671,9 @@ static void test_MFCreateDXSurfaceBuffer(void)
IDirect3DSwapChain9_Release(swapchain);
+ hr = pMFCreateDXSurfaceBuffer(&IID_IUnknown, (IUnknown *)backbuffer, FALSE, &buffer);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
hr = pMFCreateDXSurfaceBuffer(&IID_IDirect3DSurface9, (IUnknown *)backbuffer, FALSE, &buffer);
ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr);
@@ -5764,6 +5767,12 @@ static void test_MFCreateDXSurfaceBuffer(void)
ok(data[0] == 0xab, "Unexpected leading byte.\n");
IMF2DBuffer2_Unlock2D(_2dbuffer2);
+ hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(data[0] == 0xab, "Unexpected leading byte.\n");
+ hr = IMFMediaBuffer_Unlock(buffer);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
hr = IMF2DBuffer2_Lock2DSize(_2dbuffer2, MF2DBuffer_LockFlags_ReadWrite, &data, &pitch, &data2, &length);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
IMF2DBuffer2_Unlock2D(_2dbuffer2);
--
2.28.0
More information about the wine-devel
mailing list