evr/presenter: Create a swapchain for given output window.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2020-11-13 15:31:32 +03:00 committed by Alexandre Julliard
parent e19938f9db
commit 02d982de38
2 changed files with 139 additions and 43 deletions

View file

@ -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)

View file

@ -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();