[PATCH 2/6] evr/presenter: Create a swapchain for given output window.

Nikolay Sivov nsivov at codeweavers.com
Fri Nov 13 06:31:32 CST 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/evr/presenter.c |  54 +++++++++++++++++-
 dlls/evr/tests/evr.c | 128 +++++++++++++++++++++++++++++--------------
 2 files changed, 139 insertions(+), 43 deletions(-)

diff --git a/dlls/evr/presenter.c b/dlls/evr/presenter.c
index c1f29d41e4e..fc3a1b52c51 100644
--- a/dlls/evr/presenter.c
+++ b/dlls/evr/presenter.c
@@ -77,6 +77,9 @@ struct video_presenter
     IMediaEventSink *event_sink;
 
     IDirect3DDeviceManager9 *device_manager;
+    IDirect3DSwapChain9 *swapchain;
+    HANDLE hdevice;
+
     IMFVideoSampleAllocator *allocator;
     struct streaming_thread thread;
     IMFMediaType *media_type;
@@ -164,6 +167,19 @@ static unsigned int get_gcd(unsigned int a, unsigned int b)
     return a;
 }
 
+static HRESULT video_presenter_get_device(struct video_presenter *presenter, IDirect3DDevice9 **device)
+{
+    HRESULT hr;
+
+    if (!presenter->hdevice)
+    {
+        if (FAILED(hr = IDirect3DDeviceManager9_OpenDeviceHandle(presenter->device_manager, &presenter->hdevice)))
+            return hr;
+    }
+
+    return IDirect3DDeviceManager9_LockDevice(presenter->device_manager, presenter->hdevice, device, TRUE);
+}
+
 static void video_presenter_get_native_video_size(struct video_presenter *presenter)
 {
     IMFMediaType *media_type;
@@ -501,8 +517,13 @@ static ULONG WINAPI video_presenter_inner_Release(IUnknown *iface)
         video_presenter_clear_container(presenter);
         video_presenter_reset_media_type(presenter);
         DeleteCriticalSection(&presenter->cs);
+        if (presenter->swapchain)
+            IDirect3DSwapChain9_Release(presenter->swapchain);
         if (presenter->device_manager)
+        {
+            IDirect3DDeviceManager9_CloseDeviceHandle(presenter->device_manager, presenter->hdevice);
             IDirect3DDeviceManager9_Release(presenter->device_manager);
+        }
         if (presenter->allocator)
             IMFVideoSampleAllocator_Release(presenter->allocator);
         heap_free(presenter);
@@ -995,9 +1016,32 @@ static HRESULT WINAPI video_presenter_control_GetAspectRatioMode(IMFVideoDisplay
     return S_OK;
 }
 
+static HRESULT video_presenter_create_swapchain(struct video_presenter *presenter)
+{
+    D3DPRESENT_PARAMETERS present_params = { 0 };
+    IDirect3DDevice9 *d3d_device;
+    HRESULT hr;
+
+    if (SUCCEEDED(hr = video_presenter_get_device(presenter, &d3d_device)))
+    {
+        present_params.hDeviceWindow = presenter->video_window;
+        present_params.Windowed = TRUE;
+        present_params.SwapEffect = D3DSWAPEFFECT_COPY;
+        present_params.Flags = D3DPRESENTFLAG_VIDEO;
+        present_params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+        hr = IDirect3DDevice9_CreateAdditionalSwapChain(d3d_device, &present_params, &presenter->swapchain);
+
+        IDirect3DDevice9_Release(d3d_device);
+        IDirect3DDeviceManager9_UnlockDevice(presenter->device_manager, presenter->hdevice, FALSE);
+    }
+
+    return hr;
+}
+
 static HRESULT WINAPI video_presenter_control_SetVideoWindow(IMFVideoDisplayControl *iface, HWND window)
 {
     struct video_presenter *presenter = impl_from_IMFVideoDisplayControl(iface);
+    HRESULT hr = S_OK;
 
     TRACE("%p, %p.\n", iface, window);
 
@@ -1005,10 +1049,16 @@ static HRESULT WINAPI video_presenter_control_SetVideoWindow(IMFVideoDisplayCont
         return E_INVALIDARG;
 
     EnterCriticalSection(&presenter->cs);
-    presenter->video_window = window;
+    if (presenter->video_window != window)
+    {
+        if (presenter->swapchain)
+            IDirect3DSwapChain9_Release(presenter->swapchain);
+        presenter->video_window = window;
+        hr = video_presenter_create_swapchain(presenter);
+    }
     LeaveCriticalSection(&presenter->cs);
 
-    return S_OK;
+    return hr;
 }
 
 static HRESULT WINAPI video_presenter_control_GetVideoWindow(IMFVideoDisplayControl *iface, HWND *window)
diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c
index bdf3154c7e5..d4c2ffb0480 100644
--- a/dlls/evr/tests/evr.c
+++ b/dlls/evr/tests/evr.c
@@ -1096,18 +1096,13 @@ done:
 
 static void test_default_presenter(void)
 {
-    D3DDEVICE_CREATION_PARAMETERS device_params = { 0 };
-    D3DPRESENT_PARAMETERS present_params = { 0 };
     IMFVideoDisplayControl *display_control;
-    IDirect3DSwapChain9 *swapchain;
     IMFVideoPresenter *presenter;
     IMFRateSupport *rate_support;
-    IDirect3DDevice9 *d3d_device;
     IDirect3DDeviceManager9 *dm;
     IMFVideoDeviceID *deviceid;
     IMFGetService *gs;
     HWND hwnd, hwnd2;
-    HANDLE handle;
     IUnknown *unk;
     DWORD flags;
     float rate;
@@ -1176,33 +1171,6 @@ static void test_default_presenter(void)
     hr = IMFVideoPresenter_QueryInterface(presenter, &IID_IMFVideoDisplayControl, (void **)&display_control);
     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
 
-    hr = IDirect3DDeviceManager9_OpenDeviceHandle(dm, &handle);
-    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
-
-    hr = IDirect3DDeviceManager9_LockDevice(dm, handle, &d3d_device, FALSE);
-    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
-
-    hr = IDirect3DDevice9_GetCreationParameters(d3d_device, &device_params);
-    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
-    ok(device_params.hFocusWindow == GetDesktopWindow(), "Unexpected window %p.\n", device_params.hFocusWindow);
-
-    hr = IDirect3DDevice9_GetSwapChain(d3d_device, 0, &swapchain);
-    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
-
-    hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_params);
-    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
-
-    ok(present_params.hDeviceWindow == GetDesktopWindow(), "Unexpected device window.\n");
-    ok(present_params.Windowed, "Unexpected windowed mode.\n");
-    ok(present_params.SwapEffect == D3DSWAPEFFECT_COPY, "Unexpected swap effect.\n");
-    ok(present_params.Flags & D3DPRESENTFLAG_VIDEO, "Unexpected flags %#x.\n", present_params.Flags);
-    ok(present_params.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE, "Unexpected present interval.\n");
-
-    IDirect3DDevice9_Release(d3d_device);
-
-    hr = IDirect3DDeviceManager9_UnlockDevice(dm, handle, FALSE);
-    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
-
     /* Video window */
     hwnd = create_window();
     ok(!!hwnd, "Failed to create a test window.\n");
@@ -1229,15 +1197,6 @@ static void test_default_presenter(void)
     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
     ok(hwnd2 == hwnd, "Unexpected window %p.\n", hwnd2);
 
-    /* Video position */
-    hr = IDirect3DDeviceManager9_CloseDeviceHandle(dm, handle);
-    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
-
-    IDirect3DDeviceManager9_Release(dm);
-
-    IMFVideoDisplayControl_Release(display_control);
-    IMFGetService_Release(gs);
-
     /* Rate support. */
     hr = IMFVideoPresenter_QueryInterface(presenter, &IID_IMFRateSupport, (void **)&rate_support);
     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
@@ -1920,6 +1879,92 @@ static void test_presenter_ar_mode(void)
     IMFVideoDisplayControl_Release(display_control);
 }
 
+static void test_presenter_video_window(void)
+{
+    D3DDEVICE_CREATION_PARAMETERS device_params = { 0 };
+    IMFVideoDisplayControl *display_control;
+    IDirect3DDeviceManager9 *dm;
+    IDirect3DDevice9 *d3d_device;
+    HANDLE hdevice;
+    HRESULT hr;
+    IDirect3DSwapChain9 *swapchain;
+    D3DPRESENT_PARAMETERS present_params = { 0 };
+    HWND window;
+
+    hr = MFCreateVideoPresenter(NULL, &IID_IDirect3DDevice9, &IID_IMFVideoDisplayControl, (void **)&display_control);
+    ok(hr == S_OK, "Failed to create default presenter, hr %#x.\n", hr);
+
+    hr = MFGetService((IUnknown *)display_control, &MR_VIDEO_ACCELERATION_SERVICE,
+         &IID_IDirect3DDeviceManager9, (void **)&dm);
+
+    hr = IDirect3DDeviceManager9_OpenDeviceHandle(dm, &hdevice);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DDeviceManager9_LockDevice(dm, hdevice, &d3d_device, FALSE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DDevice9_GetCreationParameters(d3d_device, &device_params);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(device_params.hFocusWindow == GetDesktopWindow(), "Unexpected window %p.\n", device_params.hFocusWindow);
+
+    hr = IDirect3DDevice9_GetSwapChain(d3d_device, 0, &swapchain);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_params);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    ok(present_params.hDeviceWindow == GetDesktopWindow(), "Unexpected device window.\n");
+    ok(present_params.Windowed, "Unexpected windowed mode.\n");
+    ok(present_params.SwapEffect == D3DSWAPEFFECT_COPY, "Unexpected swap effect.\n");
+    ok(present_params.Flags & D3DPRESENTFLAG_VIDEO, "Unexpected flags %#x.\n", present_params.Flags);
+    ok(present_params.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE, "Unexpected present interval.\n");
+
+    IDirect3DSwapChain9_Release(swapchain);
+    IDirect3DDevice9_Release(d3d_device);
+
+    hr = IDirect3DDeviceManager9_UnlockDevice(dm, hdevice, FALSE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    /* Setting window. */
+    hr = IMFVideoDisplayControl_GetVideoWindow(display_control, &window);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(!window, "Unexpected window %p.\n", window);
+
+    window = create_window();
+
+    hr = IMFVideoDisplayControl_SetVideoWindow(display_control, window);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    /* Device is not recreated or reset on window change. */
+    hr = IDirect3DDeviceManager9_LockDevice(dm, hdevice, &d3d_device, FALSE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DDevice9_GetSwapChain(d3d_device, 0, &swapchain);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_params);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    ok(present_params.hDeviceWindow == GetDesktopWindow(), "Unexpected device window.\n");
+    ok(present_params.Windowed, "Unexpected windowed mode.\n");
+    ok(present_params.SwapEffect == D3DSWAPEFFECT_COPY, "Unexpected swap effect.\n");
+    ok(present_params.Flags & D3DPRESENTFLAG_VIDEO, "Unexpected flags %#x.\n", present_params.Flags);
+    ok(present_params.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE, "Unexpected present interval.\n");
+
+    IDirect3DSwapChain9_Release(swapchain);
+    IDirect3DDevice9_Release(d3d_device);
+
+    hr = IDirect3DDeviceManager9_UnlockDevice(dm, hdevice, FALSE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DDeviceManager9_CloseDeviceHandle(dm, hdevice);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    IMFVideoDisplayControl_Release(display_control);
+
+    DestroyWindow(window);
+}
+
 static void test_mixer_output_rectangle(void)
 {
     IMFVideoMixerControl *mixer_control;
@@ -2370,6 +2415,7 @@ START_TEST(evr)
     test_presenter_video_position();
     test_presenter_native_video_size();
     test_presenter_ar_mode();
+    test_presenter_video_window();
     test_mixer_output_rectangle();
     test_mixer_zorder();
     test_mixer_samples();
-- 
2.29.2




More information about the wine-devel mailing list