Wine incorrectly inserts a sample copier. D3D awareness is handled per node, and each node will have their own sample allocator created from the D3D device manager provided by the session.
-- v5: mf/tests: Test device manager handling in the topology loader. mf/tests: Test D3D awareness handling in the topology loader. include: Add MFTOPOLOGY_DXVA_MODE enum definition.
From: Rémi Bernon rbernon@codeweavers.com
--- include/mfidl.idl | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/include/mfidl.idl b/include/mfidl.idl index b3201b12d84..666af53c6e3 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -131,6 +131,13 @@ typedef enum _MF_VIDEO_PROCESSOR_ALGORITHM_TYPE MF_VIDEO_PROCESSOR_ALGORITHM_MRF_CRF_444 = 1, } MF_VIDEO_PROCESSOR_ALGORITHM_TYPE;
+typedef enum MFTOPOLOGY_DXVA_MODE +{ + MFTOPOLOGY_DXVA_DEFAULT = 0, + MFTOPOLOGY_DXVA_NONE = 1, + MFTOPOLOGY_DXVA_FULL = 2, +} MFTOPOLOGY_DXVA_MODE; + [ object, uuid(2eb1e945-18b8-4139-9b1a-d5d584818530),
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 501 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 501 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index fece60d37a7..86076a158a0 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -271,6 +271,315 @@ static void init_sink_node(IMFStreamSink *stream_sink, MF_CONNECT_METHOD method, } }
+struct test_transform +{ + IMFTransform IMFTransform_iface; + LONG refcount; + + IMFAttributes *attributes; + + UINT input_count; + IMFMediaType **input_types; + IMFMediaType *input_type; + + UINT output_count; + IMFMediaType **output_types; + IMFMediaType *output_type; +}; + +static struct test_transform *test_transform_from_IMFTransform(IMFTransform *iface) +{ + return CONTAINING_RECORD(iface, struct test_transform, IMFTransform_iface); +} + +static HRESULT WINAPI test_transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + + if (IsEqualGUID(iid, &IID_IUnknown) + || IsEqualGUID(iid, &IID_IMFTransform)) + { + IMFTransform_AddRef(&transform->IMFTransform_iface); + *out = &transform->IMFTransform_iface; + return S_OK; + } + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI test_transform_AddRef(IMFTransform *iface) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + ULONG refcount = InterlockedIncrement(&transform->refcount); + return refcount; +} + +static ULONG WINAPI test_transform_Release(IMFTransform *iface) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + ULONG refcount = InterlockedDecrement(&transform->refcount); + + if (!refcount) + { + if (transform->input_type) + IMFMediaType_Release(transform->input_type); + if (transform->output_type) + IMFMediaType_Release(transform->output_type); + if (transform->attributes) + IMFAttributes_Release(transform->attributes); + free(transform); + } + + return refcount; +} + +static HRESULT WINAPI test_transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, + DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) +{ + *inputs = *outputs = 1; + return S_OK; +} + +static HRESULT WINAPI test_transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs, + DWORD output_size, DWORD *outputs) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) +{ + ok(0, "Unexpected %s call.\n", __func__); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info) +{ + ok(0, "Unexpected %s call.\n", __func__); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + if (!(*attributes = transform->attributes)) + return E_NOTIMPL; + IMFAttributes_AddRef(*attributes); + return S_OK; +} + +static HRESULT WINAPI test_transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_DeleteInputStream(IMFTransform *iface, DWORD id) +{ + ok(0, "Unexpected %s call.\n", __func__); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) +{ + ok(0, "Unexpected %s call.\n", __func__); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, + IMFMediaType **type) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + + if (index >= transform->input_count) + { + *type = NULL; + return MF_E_NO_MORE_TYPES; + } + + *type = transform->input_types[index]; + IMFMediaType_AddRef(*type); + return S_OK; +} + +static HRESULT WINAPI test_transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, + DWORD index, IMFMediaType **type) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + + if (index >= transform->output_count) + { + *type = NULL; + return MF_E_NO_MORE_TYPES; + } + + *type = transform->output_types[index]; + IMFMediaType_AddRef(*type); + return S_OK; +} + +static HRESULT WINAPI test_transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + if (flags & MFT_SET_TYPE_TEST_ONLY) + { + todo_wine ok(0, "Unexpected %s call.\n", __func__); + return winetest_platform_is_wine ? S_OK : E_NOTIMPL; + } + if (transform->input_type) + IMFMediaType_Release(transform->input_type); + if ((transform->input_type = type)) + IMFMediaType_AddRef(transform->input_type); + return S_OK; +} + +static HRESULT WINAPI test_transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + if (flags & MFT_SET_TYPE_TEST_ONLY) + { + todo_wine ok(0, "Unexpected %s call.\n", __func__); + return winetest_platform_is_wine ? S_OK : E_NOTIMPL; + } + if (transform->output_type) + IMFMediaType_Release(transform->output_type); + if ((transform->output_type = type)) + IMFMediaType_AddRef(transform->output_type); + return S_OK; +} + +static HRESULT WINAPI test_transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + if (!(*type = transform->input_type)) + return MF_E_TRANSFORM_TYPE_NOT_SET; + IMFMediaType_AddRef(*type); + return S_OK; +} + +static HRESULT WINAPI test_transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + if (!(*type = transform->output_type)) + return MF_E_TRANSFORM_TYPE_NOT_SET; + IMFMediaType_AddRef(*type); + return S_OK; +} + +static HRESULT WINAPI test_transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) +{ + ok(0, "Unexpected %s call.\n", __func__); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_GetOutputStatus(IMFTransform *iface, DWORD *flags) +{ + ok(0, "Unexpected %s call.\n", __func__); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper) +{ + ok(0, "Unexpected %s call.\n", __func__); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event) +{ + ok(0, "Unexpected %s call.\n", __func__); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) +{ + ok(0, "Unexpected %s call.\n", __func__); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) +{ + ok(0, "Unexpected %s call.\n", __func__); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, + MFT_OUTPUT_DATA_BUFFER *data, DWORD *status) +{ + ok(0, "Unexpected %s call.\n", __func__); + return E_NOTIMPL; +} + +static const IMFTransformVtbl test_transform_vtbl = +{ + test_transform_QueryInterface, + test_transform_AddRef, + test_transform_Release, + test_transform_GetStreamLimits, + test_transform_GetStreamCount, + test_transform_GetStreamIDs, + test_transform_GetInputStreamInfo, + test_transform_GetOutputStreamInfo, + test_transform_GetAttributes, + test_transform_GetInputStreamAttributes, + test_transform_GetOutputStreamAttributes, + test_transform_DeleteInputStream, + test_transform_AddInputStreams, + test_transform_GetInputAvailableType, + test_transform_GetOutputAvailableType, + test_transform_SetInputType, + test_transform_SetOutputType, + test_transform_GetInputCurrentType, + test_transform_GetOutputCurrentType, + test_transform_GetInputStatus, + test_transform_GetOutputStatus, + test_transform_SetOutputBounds, + test_transform_ProcessEvent, + test_transform_ProcessMessage, + test_transform_ProcessInput, + test_transform_ProcessOutput, +}; + +static HRESULT WINAPI test_transform_create(UINT input_count, IMFMediaType **input_types, + UINT output_count, IMFMediaType **output_types, BOOL d3d_aware, IMFTransform **out) +{ + struct test_transform *transform; + HRESULT hr; + + if (!(transform = calloc(1, sizeof(*transform)))) + return E_OUTOFMEMORY; + transform->IMFTransform_iface.lpVtbl = &test_transform_vtbl; + transform->refcount = 1; + + transform->input_count = input_count; + transform->input_types = input_types; + transform->input_type = input_types[0]; + IMFMediaType_AddRef(transform->input_type); + transform->output_count = output_count; + transform->output_types = output_types; + transform->output_type = output_types[0]; + IMFMediaType_AddRef(transform->output_type); + + hr = MFCreateAttributes(&transform->attributes, 1); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFAttributes_SetUINT32(transform->attributes, &MF_SA_D3D_AWARE, d3d_aware); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFAttributes_SetUINT32(transform->attributes, &MF_SA_D3D11_AWARE, d3d_aware); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + *out = &transform->IMFTransform_iface; + return S_OK; +} + DEFINE_EXPECT(test_source_BeginGetEvent); DEFINE_EXPECT(test_source_QueueEvent); DEFINE_EXPECT(test_source_Start); @@ -1730,6 +2039,8 @@ struct test_stream_sink IMFStreamSink IMFStreamSink_iface; IMFMediaTypeHandler *handler; IMFMediaSink *media_sink; + + IMFAttributes *attributes; };
static struct test_stream_sink *impl_from_IMFStreamSink(IMFStreamSink *iface) @@ -1739,6 +2050,8 @@ static struct test_stream_sink *impl_from_IMFStreamSink(IMFStreamSink *iface)
static HRESULT WINAPI test_stream_sink_QueryInterface(IMFStreamSink *iface, REFIID riid, void **obj) { + struct test_stream_sink *impl = impl_from_IMFStreamSink(iface); + if (IsEqualIID(riid, &IID_IMFStreamSink) || IsEqualIID(riid, &IID_IMFMediaEventGenerator) || IsEqualIID(riid, &IID_IUnknown)) @@ -1747,6 +2060,12 @@ static HRESULT WINAPI test_stream_sink_QueryInterface(IMFStreamSink *iface, REFI return S_OK; }
+ if (IsEqualIID(riid, &IID_IMFAttributes) && impl->attributes) + { + IMFAttributes_AddRef((*obj = impl->attributes)); + return S_OK; + } + *obj = NULL; return E_NOINTERFACE; } @@ -4582,6 +4901,187 @@ static void test_topology_loader_evr(void) CoUninitialize(); }
+static void test_topology_loader_d3d_init(IMFTopology *topology, IMFMediaSource *source, IMFPresentationDescriptor *pd, IMFStreamDescriptor *sd, + UINT transform_count, IMFTransform **transforms, IMFStreamSink *sink) +{ + IMFTopologyNode *prev_node, *node; + HRESULT hr; + UINT i; + + hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node); + ok(hr == S_OK, "got hr %#lx.\n", hr); + init_source_node(source, MF_CONNECT_DIRECT, node, pd, sd); + hr = IMFTopology_AddNode(topology, node); + ok(hr == S_OK, "got hr %#lx.\n", hr); + prev_node = node; + + for (i = 0; i < transform_count; i++) + { + hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopologyNode_SetObject(node, (IUnknown *)transforms[i]); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopology_AddNode(topology, node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopologyNode_ConnectOutput(prev_node, 0, node, 0); + ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr); + IMFTopologyNode_Release(prev_node); + prev_node = node; + } + + hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node); + ok(hr == S_OK, "got hr %#lx.\n", hr); + init_sink_node(sink, MF_CONNECT_DIRECT, node); + hr = IMFTopology_AddNode(topology, node); + ok(hr == S_OK, "got hr %#lx.\n", hr); + hr = IMFTopologyNode_ConnectOutput(prev_node, 0, node, 0); + ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr); + IMFTopologyNode_Release(prev_node); + IMFTopologyNode_Release(node); +} + +static void test_topology_loader_d3d(void) +{ + static const media_type_desc video_media_type_desc = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), + ATTR_RATIO(MF_MT_FRAME_SIZE, 1280, 720), + }; + + struct test_stream_sink stream_sink = test_stream_sink; + struct test_handler handler = test_handler; + IMFTopology *topology, *full_topology; + IMFPresentationDescriptor *pd; + IMFTransform *transforms[4]; + IMFMediaType *media_type; + IMFStreamDescriptor *sd; + IMFMediaSource *source; + IMFTopoLoader *loader; + HRESULT hr; + WORD count; + LONG ref; + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "got hr %#lx.\n", hr); + init_media_type(media_type, video_media_type_desc, -1); + + stream_sink.handler = &handler.IMFMediaTypeHandler_iface; + hr = MFCreateAttributes(&stream_sink.attributes, 1); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + handler.media_types_count = 1; + handler.media_types = &media_type; + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + hr = MFCreateTopoLoader(&loader); + ok(hr == S_OK, "got hr %#lx.\n", hr); + hr = MFCreateTopology(&topology); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + create_descriptors(1, &media_type, &video_media_type_desc, &pd, &sd); + source = create_test_source(pd); + + test_topology_loader_d3d_init(topology, source, pd, sd, 0, NULL, &stream_sink.IMFStreamSink_iface); + + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ref = IMFTopology_GetNodeCount(full_topology, &count); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ok(count == 2, "got count %u.\n", count); + ref = IMFTopology_Release(full_topology); + ok(ref == 0, "Release returned %ld\n", ref); + + + /* sink D3D aware attribute doesn't change the resolved topology */ + + hr = IMFAttributes_SetUINT32(stream_sink.attributes, &MF_SA_D3D11_AWARE, 1); + ok(hr == S_OK, "got hr %#lx.\n", hr); + hr = IMFAttributes_SetUINT32(stream_sink.attributes, &MF_SA_D3D_AWARE, 1); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ref = IMFTopology_GetNodeCount(full_topology, &count); + ok(hr == S_OK, "got hr %#lx.\n", hr); + todo_wine ok(count == 2, "got count %u.\n", count); + ref = IMFTopology_Release(full_topology); + ok(ref == 0, "Release returned %ld\n", ref); + + + /* source D3D aware attribute doesn't change the resolved topology */ + + hr = IMFStreamDescriptor_SetUINT32(sd, &MF_SA_D3D11_AWARE, 1); + ok(hr == S_OK, "got hr %#lx.\n", hr); + hr = IMFStreamDescriptor_SetUINT32(sd, &MF_SA_D3D_AWARE, 1); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ref = IMFTopology_GetNodeCount(full_topology, &count); + ok(hr == S_OK, "got hr %#lx.\n", hr); + todo_wine ok(count == 2, "got count %u.\n", count); + ref = IMFTopology_Release(full_topology); + ok(ref == 0, "Release returned %ld\n", ref); + + ref = IMFTopology_Release(topology); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFTopoLoader_Release(loader); + ok(ref == 0, "Release returned %ld\n", ref); + + + /* transform D3D aware attribute doesn't change the resolved topology */ + + hr = MFCreateTopoLoader(&loader); + ok(hr == S_OK, "got hr %#lx.\n", hr); + hr = MFCreateTopology(&topology); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + test_transform_create(1, &media_type, 1, &media_type, FALSE, &transforms[0]); + test_transform_create(1, &media_type, 1, &media_type, TRUE, &transforms[1]); + test_transform_create(1, &media_type, 1, &media_type, FALSE, &transforms[2]); + test_transform_create(1, &media_type, 1, &media_type, TRUE, &transforms[3]); + + test_topology_loader_d3d_init(topology, source, pd, sd, 4, transforms, &stream_sink.IMFStreamSink_iface); + + IMFTransform_Release(transforms[0]); + IMFTransform_Release(transforms[1]); + IMFTransform_Release(transforms[2]); + IMFTransform_Release(transforms[3]); + + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ref = IMFTopology_GetNodeCount(full_topology, &count); + ok(hr == S_OK, "got hr %#lx.\n", hr); + todo_wine ok(count == 6, "got count %u.\n", count); + ref = IMFTopology_Release(full_topology); + ok(ref == 0, "Release returned %ld\n", ref); + + ref = IMFTopology_Release(topology); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFTopoLoader_Release(loader); + ok(ref == 0, "Release returned %ld\n", ref); + + + ref = IMFMediaSource_Release(source); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFPresentationDescriptor_Release(pd); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFStreamDescriptor_Release(sd); + ok(ref == 0, "Release returned %ld\n", ref); + + hr = MFShutdown(); + ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr); + + + IMFAttributes_Release(stream_sink.attributes); + IMFMediaType_Release(media_type); + + winetest_pop_context(); +} + static HRESULT WINAPI testshutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IMFShutdown) || @@ -8254,6 +8754,7 @@ START_TEST(mf) test_topology_tee_node(); test_topology_loader(); test_topology_loader_evr(); + test_topology_loader_d3d(); test_MFGetService(); test_sequencer_source(); test_media_session();
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/Makefile.in | 2 +- dlls/mf/tests/mf.c | 604 +++++++++++++++++++++++++++++++++++++- 2 files changed, 600 insertions(+), 6 deletions(-)
diff --git a/dlls/mf/tests/Makefile.in b/dlls/mf/tests/Makefile.in index 3bb0c66de0a..cdd5e4a6af8 100644 --- a/dlls/mf/tests/Makefile.in +++ b/dlls/mf/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = mf.dll -IMPORTS = mf mfplat dmoguids mfuuid strmiids uuid wmcodecdspuuid ole32 user32 propsys msdmo d3d11 msvfw32 +IMPORTS = mf mfplat dmoguids mfuuid strmiids uuid wmcodecdspuuid ole32 user32 propsys msdmo d3d9 d3d11 dxva2 msvfw32
SOURCES = \ mf.c \ diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 86076a158a0..fd37b9520d5 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -34,6 +34,7 @@ #include "uuids.h" #include "wmcodecdsp.h" #include "nserror.h" +#include "d3d11_4.h"
#include "mf_test.h"
@@ -137,6 +138,27 @@ static HWND create_window(void) 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL); }
+static IDirect3DDevice9 *create_d3d9_device(IDirect3D9 *d3d9, HWND focus_window) +{ + D3DPRESENT_PARAMETERS present_parameters = {0}; + IDirect3DDevice9 *device = NULL; + + present_parameters.BackBufferWidth = 640; + present_parameters.BackBufferHeight = 480; + present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8; + present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + present_parameters.hDeviceWindow = focus_window; + present_parameters.Windowed = TRUE; + present_parameters.EnableAutoDepthStencil = TRUE; + present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8; + present_parameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; + + IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device); + + return device; +} + static IMFSample *create_sample(const BYTE *data, ULONG size) { IMFMediaBuffer *media_buffer; @@ -277,6 +299,7 @@ struct test_transform LONG refcount;
IMFAttributes *attributes; + const MFT_OUTPUT_STREAM_INFO *output_stream_info;
UINT input_count; IMFMediaType **input_types; @@ -285,6 +308,11 @@ struct test_transform UINT output_count; IMFMediaType **output_types; IMFMediaType *output_type; + + IDirect3DDeviceManager9 *expect_d3d9_device_manager; + BOOL got_d3d9_device_manager; + IMFDXGIDeviceManager *expect_dxgi_device_manager; + BOOL got_dxgi_device_manager; };
static struct test_transform *test_transform_from_IMFTransform(IMFTransform *iface) @@ -359,10 +387,22 @@ static HRESULT WINAPI test_transform_GetInputStreamInfo(IMFTransform *iface, DWO return E_NOTIMPL; }
+static void test_transform_set_output_stream_info(IMFTransform *iface, const MFT_OUTPUT_STREAM_INFO *info) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + transform->output_stream_info = info; +} + static HRESULT WINAPI test_transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info) { - ok(0, "Unexpected %s call.\n", __func__); - return E_NOTIMPL; + struct test_transform *transform = test_transform_from_IMFTransform(iface); + + ok(!!transform->output_stream_info, "Unexpected %s iface %p call.\n", __func__, iface); + if (!transform->output_stream_info) + return E_NOTIMPL; + + *info = *transform->output_stream_info; + return S_OK; }
static HRESULT WINAPI test_transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) @@ -500,10 +540,75 @@ static HRESULT WINAPI test_transform_ProcessEvent(IMFTransform *iface, DWORD id, return E_NOTIMPL; }
+static void test_transform_set_expect_d3d9_device_manager(IMFTransform *iface, IDirect3DDeviceManager9 *manager) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + transform->expect_d3d9_device_manager = manager; +} + +static void test_transform_set_expect_dxgi_device_manager(IMFTransform *iface, IMFDXGIDeviceManager *manager) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + transform->expect_dxgi_device_manager = manager; +} + static HRESULT WINAPI test_transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) { - ok(0, "Unexpected %s call.\n", __func__); - return E_NOTIMPL; + struct test_transform *transform = test_transform_from_IMFTransform(iface); + switch (message) + { + case MFT_MESSAGE_SET_D3D_MANAGER: + ok(!!param, "Unexpected param.\n"); + ok(transform->expect_d3d9_device_manager || transform->expect_dxgi_device_manager, "Unexpected %s call.\n", __func__); + + if (transform->expect_d3d9_device_manager) + { + IDirect3DDeviceManager9 *manager; + HRESULT hr; + + check_interface((IUnknown *)param, &IID_IMFDXGIDeviceManager, FALSE); + hr = IUnknown_QueryInterface((IUnknown *)param, &IID_IDirect3DDeviceManager9, (void **)&manager); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(manager == transform->expect_d3d9_device_manager, "got manager %p\n", manager); + IDirect3DDeviceManager9_Release(manager); + + transform->got_d3d9_device_manager = TRUE; + } + if (transform->expect_dxgi_device_manager) + { + IMFDXGIDeviceManager *manager; + HRESULT hr; + + check_interface((IUnknown *)param, &IID_IDirect3DDeviceManager9, FALSE); + hr = IUnknown_QueryInterface((IUnknown *)param, &IID_IMFDXGIDeviceManager, (void **)&manager); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(manager == transform->expect_dxgi_device_manager, "got manager %p\n", manager); + if (manager) IMFDXGIDeviceManager_Release(manager); + + transform->got_dxgi_device_manager = TRUE; + } + return S_OK; + + default: + ok(0, "Unexpected %s call.\n", __func__); + return E_NOTIMPL; + } +} + +static BOOL test_transform_got_d3d9_device_manager(IMFTransform *iface) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + BOOL ret = transform->got_d3d9_device_manager; + transform->got_d3d9_device_manager = FALSE; + return ret; +} + +static BOOL test_transform_got_dxgi_device_manager(IMFTransform *iface) +{ + struct test_transform *transform = test_transform_from_IMFTransform(iface); + BOOL ret = transform->got_dxgi_device_manager; + transform->got_dxgi_device_manager = FALSE; + return ret; }
static HRESULT WINAPI test_transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) @@ -2037,10 +2142,12 @@ static const struct test_media_sink test_media_sink = {.IMFMediaSink_iface.lpVtb struct test_stream_sink { IMFStreamSink IMFStreamSink_iface; + IMFGetService IMFGetService_iface; IMFMediaTypeHandler *handler; IMFMediaSink *media_sink;
IMFAttributes *attributes; + IUnknown *device_manager; };
static struct test_stream_sink *impl_from_IMFStreamSink(IMFStreamSink *iface) @@ -2066,6 +2173,13 @@ static HRESULT WINAPI test_stream_sink_QueryInterface(IMFStreamSink *iface, REFI return S_OK; }
+ if (IsEqualIID(riid, &IID_IMFGetService)) + { + *obj = &impl->IMFGetService_iface; + IMFGetService_AddRef(&impl->IMFGetService_iface); + return S_OK; + } + *obj = NULL; return E_NOINTERFACE; } @@ -2177,7 +2291,52 @@ static const IMFStreamSinkVtbl test_stream_sink_vtbl = test_stream_sink_Flush, };
-static const struct test_stream_sink test_stream_sink = {.IMFStreamSink_iface.lpVtbl = &test_stream_sink_vtbl}; +static struct test_stream_sink *impl_from_IMFGetService(IMFGetService *iface) +{ + return CONTAINING_RECORD(iface, struct test_stream_sink, IMFGetService_iface); +} + +static HRESULT WINAPI test_stream_sink_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj) +{ + struct test_stream_sink *stream = impl_from_IMFGetService(iface); + return IMFStreamSink_QueryInterface(&stream->IMFStreamSink_iface, riid, obj); +} + +static ULONG WINAPI test_stream_sink_get_service_AddRef(IMFGetService *iface) +{ + struct test_stream_sink *stream = impl_from_IMFGetService(iface); + return IMFStreamSink_AddRef(&stream->IMFStreamSink_iface); +} + +static ULONG WINAPI test_stream_sink_get_service_Release(IMFGetService *iface) +{ + struct test_stream_sink *stream = impl_from_IMFGetService(iface); + return IMFStreamSink_Release(&stream->IMFStreamSink_iface); +} + +static HRESULT WINAPI test_stream_sink_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj) +{ + struct test_stream_sink *stream = impl_from_IMFGetService(iface); + + if (IsEqualGUID(service, &MR_VIDEO_ACCELERATION_SERVICE) && stream->device_manager) + return IUnknown_QueryInterface(stream->device_manager, riid, obj); + + return E_NOINTERFACE; +} + +static const IMFGetServiceVtbl test_stream_sink_get_service_vtbl = +{ + test_stream_sink_get_service_QueryInterface, + test_stream_sink_get_service_AddRef, + test_stream_sink_get_service_Release, + test_stream_sink_get_service_GetService, +}; + +static const struct test_stream_sink test_stream_sink = +{ + .IMFStreamSink_iface.lpVtbl = &test_stream_sink_vtbl, + .IMFGetService_iface.lpVtbl = &test_stream_sink_get_service_vtbl, +};
struct test_callback { @@ -5082,6 +5241,435 @@ static void test_topology_loader_d3d(void) winetest_pop_context(); }
+static void test_topology_loader_d3d9(MFTOPOLOGY_DXVA_MODE mode) +{ + static const media_type_desc video_media_type_desc = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), + ATTR_RATIO(MF_MT_FRAME_SIZE, 1280, 720), + }; + + struct test_stream_sink stream_sink = test_stream_sink; + MFT_OUTPUT_STREAM_INFO output_stream_info = {0}; + struct test_handler handler = test_handler; + IMFTopology *topology, *full_topology; + IDirect3DDeviceManager9 *d3d9_manager; + IMFPresentationDescriptor *pd; + IDirect3DDevice9 *d3d9_device; + IMFTransform *transforms[4]; + IMFMediaType *media_type; + IMFStreamDescriptor *sd; + IMFMediaSource *source; + IMFTopoLoader *loader; + IDirect3D9 *d3d9; + UINT token; + HRESULT hr; + WORD count; + HWND hwnd; + BOOL ret; + LONG ref; + + winetest_push_context("d3d9 mode %d", mode); + + hwnd = create_window(); + + if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION))) + { + skip("Failed to create a D3D9 object, skipping tests.\n"); + goto skip_d3d9; + } + if (!(d3d9_device = create_d3d9_device(d3d9, hwnd))) + { + skip("Failed to create a D3D9 device, skipping tests.\n"); + IDirect3D9_Release(d3d9); + goto skip_d3d9; + } + IDirect3D9_Release(d3d9); + + hr = DXVA2CreateDirect3DDeviceManager9(&token, &d3d9_manager); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IDirect3DDeviceManager9_ResetDevice(d3d9_manager, d3d9_device, token); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IDirect3DDevice9_Release(d3d9_device); + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "got hr %#lx.\n", hr); + init_media_type(media_type, video_media_type_desc, -1); + + stream_sink.handler = &handler.IMFMediaTypeHandler_iface; + hr = MFCreateAttributes(&stream_sink.attributes, 1); + ok(hr == S_OK, "got hr %#lx.\n", hr); + hr = IMFAttributes_SetUINT32(stream_sink.attributes, &MF_SA_D3D_AWARE, 1); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + stream_sink.device_manager = (IUnknown *)d3d9_manager; + + handler.media_types_count = 1; + handler.media_types = &media_type; + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + + hr = MFCreateTopoLoader(&loader); + ok(hr == S_OK, "got hr %#lx.\n", hr); + hr = MFCreateTopology(&topology); + ok(hr == S_OK, "got hr %#lx.\n", hr); + hr = IMFTopology_SetUINT32(topology, &MF_TOPOLOGY_DXVA_MODE, mode); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + create_descriptors(1, &media_type, &video_media_type_desc, &pd, &sd); + hr = IMFStreamDescriptor_SetUINT32(sd, &MF_SA_D3D_AWARE, 1); + ok(hr == S_OK, "got hr %#lx.\n", hr); + source = create_test_source(pd); + + + /* D3D aware transforms connected to downstream non-D3D-aware transforms don't receive a device manager */ + + test_transform_create(1, &media_type, 1, &media_type, FALSE, &transforms[0]); + test_transform_create(1, &media_type, 1, &media_type, TRUE, &transforms[1]); + test_transform_create(1, &media_type, 1, &media_type, FALSE, &transforms[2]); + test_transform_create(1, &media_type, 1, &media_type, TRUE, &transforms[3]); + + test_topology_loader_d3d_init(topology, source, pd, sd, 4, transforms, &stream_sink.IMFStreamSink_iface); + + IMFMediaSource_Release(source); + IMFPresentationDescriptor_Release(pd); + IMFStreamDescriptor_Release(sd); + + test_transform_set_output_stream_info(transforms[3], &output_stream_info); + + if (mode == MFTOPOLOGY_DXVA_FULL) + { + test_transform_set_expect_d3d9_device_manager(transforms[1], d3d9_manager); + test_transform_set_expect_d3d9_device_manager(transforms[3], d3d9_manager); + } + + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ref = IMFTopology_GetNodeCount(full_topology, &count); + ok(hr == S_OK, "got hr %#lx.\n", hr); + todo_wine ok(count == 6, "got count %u.\n", count); + ref = IMFTopology_Release(full_topology); + ok(ref == 0, "Release returned %ld\n", ref); + + if (mode == MFTOPOLOGY_DXVA_FULL) + { + ret = test_transform_got_d3d9_device_manager(transforms[0]); + ok(!ret, "got d3d9 device manager\n"); + ret = test_transform_got_d3d9_device_manager(transforms[1]); + ok(!ret, "got d3d9 device manager\n"); + ret = test_transform_got_d3d9_device_manager(transforms[2]); + ok(!ret, "got d3d9 device manager\n"); + ret = test_transform_got_d3d9_device_manager(transforms[3]); + todo_wine ok(!!ret, "got d3d9 device manager\n"); + } + + /* copier is inserted before the sink if preceding node may allocate samples without a device manager */ + + output_stream_info.dwFlags = MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES; + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ref = IMFTopology_GetNodeCount(full_topology, &count); + ok(hr == S_OK, "got hr %#lx.\n", hr); + if (mode == MFTOPOLOGY_DXVA_NONE || mode == MFTOPOLOGY_DXVA_FULL) + todo_wine ok(count == 6, "got count %u.\n", count); + else + ok(count == 7, "got count %u.\n", count); + ref = IMFTopology_Release(full_topology); + ok(ref == 0, "Release returned %ld\n", ref); + + if (mode == MFTOPOLOGY_DXVA_FULL) + { + ret = test_transform_got_d3d9_device_manager(transforms[0]); + ok(!ret, "got d3d9 device manager\n"); + ret = test_transform_got_d3d9_device_manager(transforms[1]); + ok(!ret, "got d3d9 device manager\n"); + ret = test_transform_got_d3d9_device_manager(transforms[2]); + ok(!ret, "got d3d9 device manager\n"); + ret = test_transform_got_d3d9_device_manager(transforms[3]); + todo_wine ok(!!ret, "got d3d9 device manager\n"); + } + + output_stream_info.dwFlags = MFT_OUTPUT_STREAM_PROVIDES_SAMPLES; + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ref = IMFTopology_GetNodeCount(full_topology, &count); + ok(hr == S_OK, "got hr %#lx.\n", hr); + if (mode == MFTOPOLOGY_DXVA_NONE || mode == MFTOPOLOGY_DXVA_FULL) + todo_wine ok(count == 6, "got count %u.\n", count); + else + ok(count == 7, "got count %u.\n", count); + ref = IMFTopology_Release(full_topology); + ok(ref == 0, "Release returned %ld\n", ref); + + if (mode == MFTOPOLOGY_DXVA_FULL) + { + ret = test_transform_got_d3d9_device_manager(transforms[0]); + ok(!ret, "got d3d9 device manager\n"); + ret = test_transform_got_d3d9_device_manager(transforms[1]); + ok(!ret, "got d3d9 device manager\n"); + ret = test_transform_got_d3d9_device_manager(transforms[2]); + ok(!ret, "got d3d9 device manager\n"); + ret = test_transform_got_d3d9_device_manager(transforms[3]); + todo_wine ok(!!ret, "got d3d9 device manager\n"); + } + + winetest_pop_context(); + + ref = IMFTopology_Release(topology); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFTopoLoader_Release(loader); + ok(ref == 0, "Release returned %ld\n", ref); + + IMFTransform_Release(transforms[0]); + IMFTransform_Release(transforms[1]); + IMFTransform_Release(transforms[2]); + IMFTransform_Release(transforms[3]); + + + IMFAttributes_Release(stream_sink.attributes); + IMFMediaType_Release(media_type); + + hr = MFShutdown(); + ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr); + + IDirect3DDeviceManager9_Release(d3d9_manager); + +skip_d3d9: + DestroyWindow(hwnd); + + winetest_pop_context(); +} + +static void test_topology_loader_d3d11(MFTOPOLOGY_DXVA_MODE mode) +{ + static const media_type_desc video_media_type_desc = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), + ATTR_RATIO(MF_MT_FRAME_SIZE, 1280, 720), + }; + + struct test_stream_sink stream_sink = test_stream_sink; + MFT_OUTPUT_STREAM_INFO output_stream_info = {0}; + struct test_handler handler = test_handler; + IMFTopology *topology, *full_topology; + IMFDXGIDeviceManager *dxgi_manager; + ID3D11Multithread *multithread; + IMFPresentationDescriptor *pd; + IMFTransform *transforms[4]; + IMFMediaType *media_type; + IMFStreamDescriptor *sd; + IMFMediaSource *source; + IMFTopoLoader *loader; + ID3D11Device *d3d11; + UINT token; + HRESULT hr; + WORD count; + BOOL ret; + LONG ref; + + winetest_push_context("d3d11 mode %d", mode); + + hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_VIDEO_SUPPORT, NULL, 0, + D3D11_SDK_VERSION, &d3d11, NULL, NULL); + if (FAILED(hr)) + { + skip("D3D11 device creation failed, skipping tests.\n"); + goto skip_d3d11; + } + + hr = ID3D11Device_QueryInterface(d3d11, &IID_ID3D11Multithread, (void **)&multithread); + ok(hr == S_OK, "got %#lx\n", hr); + ID3D11Multithread_SetMultithreadProtected(multithread, TRUE); + ID3D11Multithread_Release(multithread); + + hr = pMFCreateDXGIDeviceManager(&token, &dxgi_manager); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFDXGIDeviceManager_ResetDevice(dxgi_manager, (IUnknown *)d3d11, token); + ok(hr == S_OK, "got %#lx\n", hr); + ID3D11Device_Release(d3d11); + + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "got hr %#lx.\n", hr); + init_media_type(media_type, video_media_type_desc, -1); + + stream_sink.handler = &handler.IMFMediaTypeHandler_iface; + hr = MFCreateAttributes(&stream_sink.attributes, 1); + ok(hr == S_OK, "got hr %#lx.\n", hr); + hr = IMFAttributes_SetUINT32(stream_sink.attributes, &MF_SA_D3D11_AWARE, 1); + ok(hr == S_OK, "got hr %#lx.\n", hr); + stream_sink.device_manager = (IUnknown *)dxgi_manager; + + handler.media_types_count = 1; + handler.media_types = &media_type; + + create_descriptors(1, &media_type, &video_media_type_desc, &pd, &sd); + hr = IMFStreamDescriptor_SetUINT32(sd, &MF_SA_D3D11_AWARE, 1); + ok(hr == S_OK, "got hr %#lx.\n", hr); + source = create_test_source(pd); + + + /* D3D aware transforms connected to downstream non-D3D-aware transforms don't receive a device manager */ + + hr = MFCreateTopoLoader(&loader); + ok(hr == S_OK, "got hr %#lx.\n", hr); + hr = MFCreateTopology(&topology); + ok(hr == S_OK, "got hr %#lx.\n", hr); + hr = IMFTopology_SetUINT32(topology, &MF_TOPOLOGY_DXVA_MODE, mode); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + test_transform_create(1, &media_type, 1, &media_type, TRUE, &transforms[0]); + test_transform_create(1, &media_type, 1, &media_type, TRUE, &transforms[1]); + test_transform_create(1, &media_type, 1, &media_type, FALSE, &transforms[2]); + test_transform_create(1, &media_type, 1, &media_type, FALSE, &transforms[3]); + + test_topology_loader_d3d_init(topology, source, pd, sd, 4, transforms, &stream_sink.IMFStreamSink_iface); + + test_transform_set_output_stream_info(transforms[3], &output_stream_info); + + if (mode == MFTOPOLOGY_DXVA_FULL) + { + test_transform_set_expect_dxgi_device_manager(transforms[2], dxgi_manager); + test_transform_set_expect_dxgi_device_manager(transforms[3], dxgi_manager); + } + + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ref = IMFTopology_GetNodeCount(full_topology, &count); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ok(count == 6, "got count %u.\n", count); + ref = IMFTopology_Release(full_topology); + ok(ref == 0, "Release returned %ld\n", ref); + + if (mode == MFTOPOLOGY_DXVA_FULL) + { + ret = test_transform_got_dxgi_device_manager(transforms[0]); + ok(!ret, "got dxgi device manager\n"); + ret = test_transform_got_dxgi_device_manager(transforms[1]); + ok(!ret, "got dxgi device manager\n"); + ret = test_transform_got_dxgi_device_manager(transforms[2]); + ok(!ret, "got dxgi device manager\n"); + ret = test_transform_got_dxgi_device_manager(transforms[3]); + ok(!ret, "got dxgi device manager\n"); + } + + /* copier is never needed in MFTOPOLOGY_DXVA_NONE mode */ + + output_stream_info.dwFlags = MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES; + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ref = IMFTopology_GetNodeCount(full_topology, &count); + ok(hr == S_OK, "got hr %#lx.\n", hr); + if (mode == MFTOPOLOGY_DXVA_NONE) + ok(count == 6, "got count %u.\n", count); + else + todo_wine ok(count == 7, "got count %u.\n", count); + ref = IMFTopology_Release(full_topology); + ok(ref == 0, "Release returned %ld\n", ref); + + if (mode == MFTOPOLOGY_DXVA_FULL) + { + ret = test_transform_got_dxgi_device_manager(transforms[0]); + ok(!ret, "got dxgi device manager\n"); + ret = test_transform_got_dxgi_device_manager(transforms[1]); + ok(!ret, "got dxgi device manager\n"); + ret = test_transform_got_dxgi_device_manager(transforms[2]); + ok(!ret, "got dxgi device manager\n"); + ret = test_transform_got_dxgi_device_manager(transforms[3]); + ok(!ret, "got dxgi device manager\n"); + } + + output_stream_info.dwFlags = 0; + + ref = IMFTopology_Release(topology); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFTopoLoader_Release(loader); + ok(ref == 0, "Release returned %ld\n", ref); + + IMFTransform_Release(transforms[0]); + IMFTransform_Release(transforms[1]); + IMFTransform_Release(transforms[2]); + IMFTransform_Release(transforms[3]); + + + /* D3D aware transforms connected together to downstream D3D-aware sink receive a device manager */ + + hr = MFCreateTopoLoader(&loader); + ok(hr == S_OK, "got hr %#lx.\n", hr); + hr = MFCreateTopology(&topology); + ok(hr == S_OK, "got hr %#lx.\n", hr); + hr = IMFTopology_SetUINT32(topology, &MF_TOPOLOGY_DXVA_MODE, mode); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + test_transform_create(1, &media_type, 1, &media_type, FALSE, &transforms[0]); + test_transform_create(1, &media_type, 1, &media_type, FALSE, &transforms[1]); + test_transform_create(1, &media_type, 1, &media_type, TRUE, &transforms[2]); + test_transform_create(1, &media_type, 1, &media_type, TRUE, &transforms[3]); + + test_topology_loader_d3d_init(topology, source, pd, sd, 4, transforms, &stream_sink.IMFStreamSink_iface); + + test_transform_set_output_stream_info(transforms[3], &output_stream_info); + + if (mode == MFTOPOLOGY_DXVA_FULL) + { + test_transform_set_expect_dxgi_device_manager(transforms[2], dxgi_manager); + test_transform_set_expect_dxgi_device_manager(transforms[3], dxgi_manager); + } + + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ref = IMFTopology_GetNodeCount(full_topology, &count); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ok(count == 6, "got count %u.\n", count); + ref = IMFTopology_Release(full_topology); + ok(ref == 0, "Release returned %ld\n", ref); + + if (mode == MFTOPOLOGY_DXVA_FULL) + { + ret = test_transform_got_dxgi_device_manager(transforms[0]); + ok(!ret, "got dxgi device manager\n"); + ret = test_transform_got_dxgi_device_manager(transforms[1]); + ok(!ret, "got dxgi device manager\n"); + ret = test_transform_got_dxgi_device_manager(transforms[2]); + todo_wine ok(!!ret, "got dxgi device manager\n"); + ret = test_transform_got_dxgi_device_manager(transforms[3]); + todo_wine ok(!!ret, "got dxgi device manager\n"); + } + + ref = IMFTopology_Release(topology); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFTopoLoader_Release(loader); + ok(ref == 0, "Release returned %ld\n", ref); + + IMFTransform_Release(transforms[0]); + IMFTransform_Release(transforms[1]); + IMFTransform_Release(transforms[2]); + IMFTransform_Release(transforms[3]); + + + IMFMediaSource_Release(source); + IMFPresentationDescriptor_Release(pd); + IMFStreamDescriptor_Release(sd); + + IMFAttributes_Release(stream_sink.attributes); + IMFMediaType_Release(media_type); + + hr = MFShutdown(); + ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr); + + IMFDXGIDeviceManager_Release(dxgi_manager); + +skip_d3d11: + winetest_pop_context(); +} + static HRESULT WINAPI testshutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IMFShutdown) || @@ -8755,6 +9343,12 @@ START_TEST(mf) test_topology_loader(); test_topology_loader_evr(); test_topology_loader_d3d(); + test_topology_loader_d3d9(MFTOPOLOGY_DXVA_DEFAULT); + test_topology_loader_d3d9(MFTOPOLOGY_DXVA_NONE); + test_topology_loader_d3d9(MFTOPOLOGY_DXVA_FULL); + test_topology_loader_d3d11(MFTOPOLOGY_DXVA_DEFAULT); + test_topology_loader_d3d11(MFTOPOLOGY_DXVA_NONE); + test_topology_loader_d3d11(MFTOPOLOGY_DXVA_FULL); test_MFGetService(); test_sequencer_source(); test_media_session();
Added more tests with a sink device manager, showing cases where sample copier is supposed to be inserted.
This is not great. Do we need to this platform check? I think it's fine to implement TEST_ONLY even if only wine uses it.
Is this one needed?
This seems fine. Something to think about, maybe we'll split tests in more files, at this rate it grows quickly with number of stubs required.
On Tue Apr 9 09:24:59 2024 +0000, Nikolay Sivov wrote:
This seems fine. Something to think about, maybe we'll split tests in more files, at this rate it grows quickly with number of stubs required.
Yeah, I considered moving the mock components into dedicated files but I'm not very sure how to do it. I don't think winetest infrastructure let us have .c files without dedicated tests, so maybe something like `test_transform.h`, etc..., that could make them more easily copied and reused to other modules.
Or maybe split the topology tests.