2019-05-24 10:23:26 +02:00
|
|
|
/*
|
|
|
|
* Unit test suite for kernel mode graphics driver
|
|
|
|
*
|
|
|
|
* Copyright 2019 Zhiyi Zhang
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#include "ntstatus.h"
|
|
|
|
#define WIN32_NO_STATUS
|
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "wingdi.h"
|
|
|
|
#include "winuser.h"
|
|
|
|
#include "winternl.h"
|
2019-05-25 05:55:07 +02:00
|
|
|
#include "dwmapi.h"
|
2019-05-24 10:23:26 +02:00
|
|
|
#include "ddk/d3dkmthk.h"
|
|
|
|
|
|
|
|
#include "wine/test.h"
|
|
|
|
|
|
|
|
static const WCHAR display1W[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y','1',0};
|
|
|
|
|
2019-05-25 05:55:07 +02:00
|
|
|
static NTSTATUS (WINAPI *pD3DKMTCheckOcclusion)(const D3DKMT_CHECKOCCLUSION *);
|
2019-05-24 10:23:31 +02:00
|
|
|
static NTSTATUS (WINAPI *pD3DKMTCheckVidPnExclusiveOwnership)(const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *);
|
2019-05-24 10:23:26 +02:00
|
|
|
static NTSTATUS (WINAPI *pD3DKMTCloseAdapter)(const D3DKMT_CLOSEADAPTER *);
|
2019-05-24 10:23:29 +02:00
|
|
|
static NTSTATUS (WINAPI *pD3DKMTCreateDevice)(D3DKMT_CREATEDEVICE *);
|
|
|
|
static NTSTATUS (WINAPI *pD3DKMTDestroyDevice)(const D3DKMT_DESTROYDEVICE *);
|
2019-05-24 10:23:26 +02:00
|
|
|
static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromGdiDisplayName)(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *);
|
2019-05-24 10:23:27 +02:00
|
|
|
static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromHdc)(D3DKMT_OPENADAPTERFROMHDC *);
|
2019-05-24 10:23:31 +02:00
|
|
|
static NTSTATUS (WINAPI *pD3DKMTSetVidPnSourceOwner)(const D3DKMT_SETVIDPNSOURCEOWNER *);
|
2019-05-25 05:55:07 +02:00
|
|
|
static HRESULT (WINAPI *pDwmEnableComposition)(UINT);
|
2019-05-24 10:23:26 +02:00
|
|
|
|
|
|
|
static void test_D3DKMTOpenAdapterFromGdiDisplayName(void)
|
|
|
|
{
|
|
|
|
D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc;
|
|
|
|
D3DKMT_CLOSEADAPTER close_adapter_desc;
|
|
|
|
DISPLAY_DEVICEW display_device = {sizeof(display_device)};
|
|
|
|
NTSTATUS status;
|
|
|
|
DWORD i;
|
|
|
|
|
|
|
|
lstrcpyW(open_adapter_gdi_desc.DeviceName, display1W);
|
|
|
|
if (!pD3DKMTOpenAdapterFromGdiDisplayName
|
|
|
|
|| pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc) == STATUS_PROCEDURE_NOT_FOUND)
|
|
|
|
{
|
2019-06-05 17:18:25 +02:00
|
|
|
win_skip("D3DKMTOpenAdapterFromGdiDisplayName() is unavailable.\n");
|
2019-05-24 10:23:26 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
|
|
|
|
status = pD3DKMTCloseAdapter(&close_adapter_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Invalid parameters */
|
|
|
|
status = pD3DKMTOpenAdapterFromGdiDisplayName(NULL);
|
|
|
|
ok(status == STATUS_UNSUCCESSFUL, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
memset(&open_adapter_gdi_desc, 0, sizeof(open_adapter_gdi_desc));
|
|
|
|
status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc);
|
|
|
|
ok(status == STATUS_UNSUCCESSFUL, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Open adapter */
|
|
|
|
for (i = 0; EnumDisplayDevicesW(NULL, i, &display_device, 0); ++i)
|
|
|
|
{
|
|
|
|
lstrcpyW(open_adapter_gdi_desc.DeviceName, display_device.DeviceName);
|
|
|
|
status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc);
|
|
|
|
if (display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ok(status == STATUS_UNSUCCESSFUL, "Got unexpected return code %#x.\n", status);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
ok(open_adapter_gdi_desc.hAdapter, "Expect not null.\n");
|
|
|
|
if (display_device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
|
|
|
ok(open_adapter_gdi_desc.VidPnSourceId == 0, "Got unexpected value %#x.\n",
|
|
|
|
open_adapter_gdi_desc.VidPnSourceId);
|
|
|
|
else
|
|
|
|
ok(open_adapter_gdi_desc.VidPnSourceId, "Got unexpected value %#x.\n", open_adapter_gdi_desc.VidPnSourceId);
|
|
|
|
|
|
|
|
close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
|
|
|
|
status = pD3DKMTCloseAdapter(&close_adapter_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-24 10:23:27 +02:00
|
|
|
static void test_D3DKMTOpenAdapterFromHdc(void)
|
|
|
|
{
|
|
|
|
DISPLAY_DEVICEW display_device = {sizeof(display_device)};
|
|
|
|
D3DKMT_OPENADAPTERFROMHDC open_adapter_hdc_desc;
|
|
|
|
D3DKMT_CLOSEADAPTER close_adapter_desc;
|
|
|
|
INT adapter_count = 0;
|
|
|
|
NTSTATUS status;
|
|
|
|
HDC hdc;
|
|
|
|
DWORD i;
|
|
|
|
|
|
|
|
if (!pD3DKMTOpenAdapterFromHdc || pD3DKMTOpenAdapterFromHdc(NULL) == STATUS_PROCEDURE_NOT_FOUND)
|
|
|
|
{
|
|
|
|
skip("D3DKMTOpenAdapterFromHdc() is unavailable.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Invalid parameters */
|
|
|
|
status = pD3DKMTOpenAdapterFromHdc(NULL);
|
|
|
|
todo_wine ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
memset(&open_adapter_hdc_desc, 0, sizeof(open_adapter_hdc_desc));
|
|
|
|
status = pD3DKMTOpenAdapterFromHdc(&open_adapter_hdc_desc);
|
|
|
|
todo_wine ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Open adapter */
|
|
|
|
for (i = 0; EnumDisplayDevicesW(NULL, i, &display_device, 0); ++i)
|
|
|
|
{
|
|
|
|
if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
adapter_count++;
|
|
|
|
|
|
|
|
hdc = CreateDCW(0, display_device.DeviceName, 0, NULL);
|
|
|
|
open_adapter_hdc_desc.hDc = hdc;
|
|
|
|
status = pD3DKMTOpenAdapterFromHdc(&open_adapter_hdc_desc);
|
|
|
|
todo_wine ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
todo_wine ok(open_adapter_hdc_desc.hAdapter, "Expect not null.\n");
|
|
|
|
if (display_device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
|
|
|
ok(open_adapter_hdc_desc.VidPnSourceId == 0, "Got unexpected value %#x.\n",
|
|
|
|
open_adapter_hdc_desc.VidPnSourceId);
|
|
|
|
else
|
|
|
|
todo_wine ok(open_adapter_hdc_desc.VidPnSourceId, "Got unexpected value %#x.\n",
|
|
|
|
open_adapter_hdc_desc.VidPnSourceId);
|
|
|
|
DeleteDC(hdc);
|
|
|
|
|
|
|
|
if (status == STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
close_adapter_desc.hAdapter = open_adapter_hdc_desc.hAdapter;
|
|
|
|
status = pD3DKMTCloseAdapter(&close_adapter_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* HDC covering more than two adapters is invalid for D3DKMTOpenAdapterFromHdc */
|
|
|
|
hdc = GetDC(0);
|
|
|
|
open_adapter_hdc_desc.hDc = hdc;
|
|
|
|
status = pD3DKMTOpenAdapterFromHdc(&open_adapter_hdc_desc);
|
|
|
|
ReleaseDC(0, hdc);
|
|
|
|
todo_wine ok(status == (adapter_count > 1 ? STATUS_INVALID_PARAMETER : STATUS_SUCCESS),
|
|
|
|
"Got unexpected return code %#x.\n", status);
|
|
|
|
if (status == STATUS_SUCCESS)
|
|
|
|
{
|
|
|
|
close_adapter_desc.hAdapter = open_adapter_hdc_desc.hAdapter;
|
|
|
|
status = pD3DKMTCloseAdapter(&close_adapter_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-24 10:23:28 +02:00
|
|
|
static void test_D3DKMTCloseAdapter(void)
|
|
|
|
{
|
|
|
|
D3DKMT_CLOSEADAPTER close_adapter_desc;
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
if (!pD3DKMTCloseAdapter || pD3DKMTCloseAdapter(NULL) == STATUS_PROCEDURE_NOT_FOUND)
|
|
|
|
{
|
|
|
|
win_skip("D3DKMTCloseAdapter() is unavailable.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Invalid parameters */
|
|
|
|
status = pD3DKMTCloseAdapter(NULL);
|
2019-06-05 17:18:44 +02:00
|
|
|
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status);
|
2019-05-24 10:23:28 +02:00
|
|
|
|
|
|
|
memset(&close_adapter_desc, 0, sizeof(close_adapter_desc));
|
|
|
|
status = pD3DKMTCloseAdapter(&close_adapter_desc);
|
2019-06-05 17:18:44 +02:00
|
|
|
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status);
|
2019-05-24 10:23:28 +02:00
|
|
|
}
|
|
|
|
|
2019-05-24 10:23:29 +02:00
|
|
|
static void test_D3DKMTCreateDevice(void)
|
|
|
|
{
|
|
|
|
D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc;
|
|
|
|
D3DKMT_CREATEDEVICE create_device_desc;
|
|
|
|
D3DKMT_CLOSEADAPTER close_adapter_desc;
|
|
|
|
D3DKMT_DESTROYDEVICE destroy_device_desc;
|
|
|
|
NTSTATUS status;
|
|
|
|
|
2019-06-05 17:19:09 +02:00
|
|
|
if (!pD3DKMTCreateDevice || pD3DKMTCreateDevice(NULL) == STATUS_PROCEDURE_NOT_FOUND)
|
2019-05-24 10:23:29 +02:00
|
|
|
{
|
2019-06-05 17:19:09 +02:00
|
|
|
win_skip("D3DKMTCreateDevice() is unavailable.\n");
|
2019-05-24 10:23:29 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Invalid parameters */
|
|
|
|
status = pD3DKMTCreateDevice(NULL);
|
|
|
|
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
memset(&create_device_desc, 0, sizeof(create_device_desc));
|
|
|
|
status = pD3DKMTCreateDevice(&create_device_desc);
|
|
|
|
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
lstrcpyW(open_adapter_gdi_desc.DeviceName, display1W);
|
|
|
|
status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Create device */
|
|
|
|
create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
|
|
|
|
status = pD3DKMTCreateDevice(&create_device_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
ok(create_device_desc.hDevice, "Expect not null.\n");
|
|
|
|
ok(create_device_desc.pCommandBuffer == NULL, "Expect null.\n");
|
|
|
|
ok(create_device_desc.CommandBufferSize == 0, "Got wrong value %#x.\n", create_device_desc.CommandBufferSize);
|
|
|
|
ok(create_device_desc.pAllocationList == NULL, "Expect null.\n");
|
|
|
|
ok(create_device_desc.AllocationListSize == 0, "Got wrong value %#x.\n", create_device_desc.AllocationListSize);
|
|
|
|
ok(create_device_desc.pPatchLocationList == NULL, "Expect null.\n");
|
|
|
|
ok(create_device_desc.PatchLocationListSize == 0, "Got wrong value %#x.\n", create_device_desc.PatchLocationListSize);
|
|
|
|
|
|
|
|
destroy_device_desc.hDevice = create_device_desc.hDevice;
|
|
|
|
status = pD3DKMTDestroyDevice(&destroy_device_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
|
|
|
|
status = pD3DKMTCloseAdapter(&close_adapter_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
}
|
|
|
|
|
2019-05-24 10:23:30 +02:00
|
|
|
static void test_D3DKMTDestroyDevice(void)
|
|
|
|
{
|
|
|
|
D3DKMT_DESTROYDEVICE destroy_device_desc;
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
if (!pD3DKMTDestroyDevice || pD3DKMTDestroyDevice(NULL) == STATUS_PROCEDURE_NOT_FOUND)
|
|
|
|
{
|
2019-06-05 17:19:09 +02:00
|
|
|
win_skip("D3DKMTDestroyDevice() is unavailable.\n");
|
2019-05-24 10:23:30 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Invalid parameters */
|
|
|
|
status = pD3DKMTDestroyDevice(NULL);
|
2019-06-05 17:19:09 +02:00
|
|
|
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status);
|
2019-05-24 10:23:30 +02:00
|
|
|
|
|
|
|
memset(&destroy_device_desc, 0, sizeof(destroy_device_desc));
|
|
|
|
status = pD3DKMTDestroyDevice(&destroy_device_desc);
|
2019-06-05 17:19:09 +02:00
|
|
|
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status);
|
2019-05-24 10:23:30 +02:00
|
|
|
}
|
|
|
|
|
2019-05-24 10:23:31 +02:00
|
|
|
static void test_D3DKMTCheckVidPnExclusiveOwnership(void)
|
|
|
|
{
|
|
|
|
static const DWORD timeout = 1000;
|
|
|
|
static const DWORD wait_step = 100;
|
|
|
|
D3DKMT_CREATEDEVICE create_device_desc, create_device_desc2;
|
|
|
|
D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc;
|
|
|
|
D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP check_owner_desc;
|
|
|
|
D3DKMT_DESTROYDEVICE destroy_device_desc;
|
|
|
|
D3DKMT_CLOSEADAPTER close_adapter_desc;
|
|
|
|
D3DKMT_VIDPNSOURCEOWNER_TYPE owner_type;
|
|
|
|
D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc;
|
|
|
|
DWORD total_time;
|
|
|
|
NTSTATUS status;
|
|
|
|
INT i;
|
|
|
|
|
|
|
|
/* Test cases using single device */
|
|
|
|
static const struct test_data1
|
|
|
|
{
|
|
|
|
D3DKMT_VIDPNSOURCEOWNER_TYPE owner_type;
|
|
|
|
NTSTATUS expected_set_status;
|
|
|
|
NTSTATUS expected_check_status;
|
|
|
|
} tests1[] = {
|
|
|
|
/* 0 */
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI, STATUS_INVALID_PARAMETER, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
/* 10 */
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
/* 20 */
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS},
|
|
|
|
/* 30 */
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_INVALID_PARAMETER, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
/* 40 */
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_INVALID_PARAMETER, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
/* 50 */
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_INVALID_PARAMETER, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{-1, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED + 1, STATUS_INVALID_PARAMETER, STATUS_SUCCESS},
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Test cases using two devices consecutively */
|
|
|
|
static const struct test_data2
|
|
|
|
{
|
|
|
|
D3DKMT_VIDPNSOURCEOWNER_TYPE set_owner_type1;
|
|
|
|
D3DKMT_VIDPNSOURCEOWNER_TYPE set_owner_type2;
|
|
|
|
NTSTATUS expected_set_status1;
|
|
|
|
NTSTATUS expected_set_status2;
|
|
|
|
NTSTATUS expected_check_status;
|
|
|
|
} tests2[] = {
|
|
|
|
/* 0 */
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_UNOWNED, D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_UNOWNED, D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_UNOWNED, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_UNOWNED, D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_SHARED, D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_SHARED, D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_SHARED, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_SHARED, D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
/* 10 */
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED, D3DKMT_VIDPNSOURCEOWNER_UNOWNED, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED, D3DKMT_VIDPNSOURCEOWNER_SHARED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EMULATED, D3DKMT_VIDPNSOURCEOWNER_EMULATED, STATUS_SUCCESS, STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, STATUS_SUCCESS},
|
|
|
|
{-1, D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, -1, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
{D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE, -1, STATUS_SUCCESS, STATUS_SUCCESS, STATUS_GRAPHICS_PRESENT_OCCLUDED},
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!pD3DKMTCheckVidPnExclusiveOwnership || pD3DKMTCheckVidPnExclusiveOwnership(NULL) == STATUS_PROCEDURE_NOT_FOUND)
|
|
|
|
{
|
2019-10-22 10:39:16 +02:00
|
|
|
win_skip("D3DKMTCheckVidPnExclusiveOwnership() is unavailable.\n");
|
2019-05-24 10:23:31 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Invalid parameters */
|
|
|
|
status = pD3DKMTCheckVidPnExclusiveOwnership(NULL);
|
|
|
|
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
memset(&check_owner_desc, 0, sizeof(check_owner_desc));
|
|
|
|
status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc);
|
|
|
|
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Test cases */
|
|
|
|
lstrcpyW(open_adapter_gdi_desc.DeviceName, display1W);
|
|
|
|
status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
memset(&create_device_desc, 0, sizeof(create_device_desc));
|
|
|
|
create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
|
|
|
|
status = pD3DKMTCreateDevice(&create_device_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
|
|
|
|
check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(tests1); ++i)
|
|
|
|
{
|
|
|
|
set_owner_desc.hDevice = create_device_desc.hDevice;
|
|
|
|
if (tests1[i].owner_type != -1)
|
|
|
|
{
|
|
|
|
owner_type = tests1[i].owner_type;
|
|
|
|
set_owner_desc.pType = &owner_type;
|
|
|
|
set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId;
|
|
|
|
set_owner_desc.VidPnSourceCount = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
set_owner_desc.pType = NULL;
|
|
|
|
set_owner_desc.pVidPnSourceId = NULL;
|
|
|
|
set_owner_desc.VidPnSourceCount = 0;
|
|
|
|
}
|
|
|
|
status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc);
|
|
|
|
ok(status == tests1[i].expected_set_status ||
|
|
|
|
/* win8 doesn't support D3DKMT_VIDPNSOURCEOWNER_EMULATED */
|
|
|
|
(status == STATUS_INVALID_PARAMETER && tests1[i].owner_type == D3DKMT_VIDPNSOURCEOWNER_EMULATED)
|
|
|
|
|| (status == STATUS_SUCCESS && tests1[i].owner_type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
|
|
|
|
&& tests1[i - 1].owner_type == D3DKMT_VIDPNSOURCEOWNER_EMULATED),
|
|
|
|
"Got unexpected return code %#x at test %d.\n", status, i);
|
|
|
|
|
|
|
|
status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc);
|
|
|
|
/* If don't sleep, D3DKMTCheckVidPnExclusiveOwnership may get STATUS_GRAPHICS_PRESENT_UNOCCLUDED instead
|
|
|
|
* of STATUS_SUCCESS */
|
|
|
|
if ((tests1[i].expected_check_status == STATUS_SUCCESS && status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED))
|
|
|
|
{
|
|
|
|
total_time = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Sleep(wait_step);
|
|
|
|
total_time += wait_step;
|
|
|
|
status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc);
|
|
|
|
} while (status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED && total_time < timeout);
|
|
|
|
}
|
|
|
|
ok(status == tests1[i].expected_check_status
|
|
|
|
|| (status == STATUS_GRAPHICS_PRESENT_OCCLUDED /* win8 */
|
|
|
|
&& tests1[i].owner_type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
|
|
|
|
&& tests1[i - 1].owner_type == D3DKMT_VIDPNSOURCEOWNER_EMULATED),
|
|
|
|
"Got unexpected return code %#x at test %d.\n", status, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set owner and unset owner using different devices */
|
|
|
|
memset(&create_device_desc2, 0, sizeof(create_device_desc2));
|
|
|
|
create_device_desc2.hAdapter = open_adapter_gdi_desc.hAdapter;
|
|
|
|
status = pD3DKMTCreateDevice(&create_device_desc2);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Set owner with the first device */
|
|
|
|
set_owner_desc.hDevice = create_device_desc.hDevice;
|
|
|
|
owner_type = D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE;
|
|
|
|
set_owner_desc.pType = &owner_type;
|
|
|
|
set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId;
|
|
|
|
set_owner_desc.VidPnSourceCount = 1;
|
|
|
|
status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc);
|
|
|
|
ok(status == STATUS_GRAPHICS_PRESENT_OCCLUDED, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Unset owner with the second device */
|
|
|
|
set_owner_desc.hDevice = create_device_desc2.hDevice;
|
|
|
|
set_owner_desc.pType = NULL;
|
|
|
|
set_owner_desc.pVidPnSourceId = NULL;
|
|
|
|
set_owner_desc.VidPnSourceCount = 0;
|
|
|
|
status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc);
|
|
|
|
/* No effect */
|
|
|
|
ok(status == STATUS_GRAPHICS_PRESENT_OCCLUDED, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Unset owner with the first device */
|
|
|
|
set_owner_desc.hDevice = create_device_desc.hDevice;
|
|
|
|
set_owner_desc.pType = NULL;
|
|
|
|
set_owner_desc.pVidPnSourceId = NULL;
|
|
|
|
set_owner_desc.VidPnSourceCount = 0;
|
|
|
|
status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc);
|
|
|
|
/* Proves that the correct device is needed to unset owner */
|
|
|
|
ok(status == STATUS_SUCCESS || status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED, "Got unexpected return code %#x.\n",
|
|
|
|
status);
|
|
|
|
|
|
|
|
/* Set owner with the first device, set owner again with the second device */
|
|
|
|
for (i = 0; i < ARRAY_SIZE(tests2); ++i)
|
|
|
|
{
|
|
|
|
if (tests2[i].set_owner_type1 != -1)
|
|
|
|
{
|
|
|
|
set_owner_desc.hDevice = create_device_desc.hDevice;
|
|
|
|
owner_type = tests2[i].set_owner_type1;
|
|
|
|
set_owner_desc.pType = &owner_type;
|
|
|
|
set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId;
|
|
|
|
set_owner_desc.VidPnSourceCount = 1;
|
|
|
|
/* If don't sleep, D3DKMTSetVidPnSourceOwner may return STATUS_OK for D3DKMT_VIDPNSOURCEOWNER_SHARED.
|
|
|
|
* Other owner type doesn't seems to be affected. */
|
|
|
|
if (tests2[i].set_owner_type1 == D3DKMT_VIDPNSOURCEOWNER_SHARED)
|
|
|
|
Sleep(timeout);
|
|
|
|
status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc);
|
|
|
|
ok(status == tests2[i].expected_set_status1
|
|
|
|
|| (status == STATUS_INVALID_PARAMETER /* win8 */
|
|
|
|
&& tests2[i].set_owner_type1 == D3DKMT_VIDPNSOURCEOWNER_EMULATED),
|
|
|
|
"Got unexpected return code %#x at test %d.\n", status, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tests2[i].set_owner_type2 != -1)
|
|
|
|
{
|
|
|
|
set_owner_desc.hDevice = create_device_desc2.hDevice;
|
|
|
|
owner_type = tests2[i].set_owner_type2;
|
|
|
|
set_owner_desc.pType = &owner_type;
|
|
|
|
set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId;
|
|
|
|
set_owner_desc.VidPnSourceCount = 1;
|
|
|
|
status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc);
|
|
|
|
ok(status == tests2[i].expected_set_status2
|
|
|
|
|| (status == STATUS_INVALID_PARAMETER /* win8 */
|
|
|
|
&& tests2[i].set_owner_type2 == D3DKMT_VIDPNSOURCEOWNER_EMULATED)
|
|
|
|
|| (status == STATUS_SUCCESS && tests2[i].set_owner_type1 == D3DKMT_VIDPNSOURCEOWNER_EMULATED
|
|
|
|
&& tests2[i].set_owner_type2 == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE),
|
|
|
|
"Got unexpected return code %#x at test %d.\n", status, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc);
|
|
|
|
if ((tests2[i].expected_check_status == STATUS_SUCCESS && status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED))
|
|
|
|
{
|
|
|
|
total_time = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Sleep(wait_step);
|
|
|
|
total_time += wait_step;
|
|
|
|
status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc);
|
|
|
|
} while (status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED && total_time < timeout);
|
|
|
|
}
|
|
|
|
ok(status == tests2[i].expected_check_status
|
|
|
|
|| (status == STATUS_GRAPHICS_PRESENT_OCCLUDED /* win8 */
|
|
|
|
&& tests2[i].set_owner_type2 == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
|
|
|
|
&& tests2[i].set_owner_type1 == D3DKMT_VIDPNSOURCEOWNER_EMULATED),
|
|
|
|
"Got unexpected return code %#x at test %d.\n", status, i);
|
|
|
|
|
|
|
|
/* Unset owner with first device */
|
|
|
|
if (tests2[i].set_owner_type1 != -1)
|
|
|
|
{
|
|
|
|
set_owner_desc.hDevice = create_device_desc.hDevice;
|
|
|
|
set_owner_desc.pType = NULL;
|
|
|
|
set_owner_desc.pVidPnSourceId = NULL;
|
|
|
|
set_owner_desc.VidPnSourceCount = 0;
|
|
|
|
status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x at test %d.\n", status, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unset owner with second device */
|
|
|
|
if (tests2[i].set_owner_type2 != -1)
|
|
|
|
{
|
|
|
|
set_owner_desc.hDevice = create_device_desc2.hDevice;
|
|
|
|
set_owner_desc.pType = NULL;
|
|
|
|
set_owner_desc.pVidPnSourceId = NULL;
|
|
|
|
set_owner_desc.VidPnSourceCount = 0;
|
|
|
|
status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x at test %d.\n", status, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Destroy devices holding ownership */
|
|
|
|
set_owner_desc.hDevice = create_device_desc.hDevice;
|
|
|
|
owner_type = D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE;
|
|
|
|
set_owner_desc.pType = &owner_type;
|
|
|
|
set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId;
|
|
|
|
set_owner_desc.VidPnSourceCount = 1;
|
|
|
|
status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
destroy_device_desc.hDevice = create_device_desc.hDevice;
|
|
|
|
status = pD3DKMTDestroyDevice(&destroy_device_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
set_owner_desc.hDevice = create_device_desc2.hDevice;
|
|
|
|
owner_type = D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE;
|
|
|
|
set_owner_desc.pType = &owner_type;
|
|
|
|
set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId;
|
|
|
|
set_owner_desc.VidPnSourceCount = 1;
|
|
|
|
status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc);
|
|
|
|
/* So ownership is released when device is destroyed. otherwise the return code should be
|
|
|
|
* STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE */
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
destroy_device_desc.hDevice = create_device_desc2.hDevice;
|
|
|
|
status = pD3DKMTDestroyDevice(&destroy_device_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
|
|
|
|
status = pD3DKMTCloseAdapter(&close_adapter_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
}
|
|
|
|
|
2019-05-24 10:23:32 +02:00
|
|
|
static void test_D3DKMTSetVidPnSourceOwner(void)
|
|
|
|
{
|
|
|
|
D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc = {0};
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
if (!pD3DKMTSetVidPnSourceOwner || pD3DKMTSetVidPnSourceOwner(&set_owner_desc) == STATUS_PROCEDURE_NOT_FOUND)
|
|
|
|
{
|
2019-10-22 10:39:06 +02:00
|
|
|
win_skip("D3DKMTSetVidPnSourceOwner() is unavailable.\n");
|
2019-05-24 10:23:32 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Invalid parameters */
|
|
|
|
status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc);
|
|
|
|
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status);
|
|
|
|
}
|
|
|
|
|
2019-05-25 05:55:07 +02:00
|
|
|
static void test_D3DKMTCheckOcclusion(void)
|
|
|
|
{
|
|
|
|
DISPLAY_DEVICEW display_device = {sizeof(display_device)};
|
|
|
|
D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc;
|
|
|
|
D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP check_owner_desc;
|
|
|
|
D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc;
|
|
|
|
D3DKMT_DESTROYDEVICE destroy_device_desc;
|
|
|
|
D3DKMT_VIDPNSOURCEOWNER_TYPE owner_type;
|
|
|
|
D3DKMT_CLOSEADAPTER close_adapter_desc;
|
|
|
|
D3DKMT_CREATEDEVICE create_device_desc;
|
|
|
|
D3DKMT_CHECKOCCLUSION occlusion_desc;
|
|
|
|
NTSTATUS expected_occlusion, status;
|
|
|
|
INT i, adapter_count = 0;
|
|
|
|
HWND hwnd, hwnd2;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
if (!pD3DKMTCheckOcclusion || pD3DKMTCheckOcclusion(NULL) == STATUS_PROCEDURE_NOT_FOUND)
|
|
|
|
{
|
|
|
|
skip("D3DKMTCheckOcclusion() is unavailable.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* NULL parameter check */
|
|
|
|
status = pD3DKMTCheckOcclusion(NULL);
|
|
|
|
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
occlusion_desc.hWnd = NULL;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
hwnd = CreateWindowA("static", "static1", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 200, 200, 0, 0, 0, 0);
|
|
|
|
ok(hwnd != NULL, "Failed to create window.\n");
|
|
|
|
|
|
|
|
occlusion_desc.hWnd = hwnd;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Minimized state doesn't affect D3DKMTCheckOcclusion */
|
|
|
|
ShowWindow(hwnd, SW_MINIMIZE);
|
|
|
|
occlusion_desc.hWnd = hwnd;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
ShowWindow(hwnd, SW_SHOWNORMAL);
|
|
|
|
|
|
|
|
/* Invisible state doesn't affect D3DKMTCheckOcclusion */
|
|
|
|
ShowWindow(hwnd, SW_HIDE);
|
|
|
|
occlusion_desc.hWnd = hwnd;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
ShowWindow(hwnd, SW_SHOW);
|
|
|
|
|
|
|
|
/* hwnd2 covers hwnd */
|
|
|
|
hwnd2 = CreateWindowA("static", "static2", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, 0);
|
|
|
|
ok(hwnd2 != NULL, "Failed to create window.\n");
|
|
|
|
|
|
|
|
occlusion_desc.hWnd = hwnd;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
occlusion_desc.hWnd = hwnd2;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Composition doesn't affect D3DKMTCheckOcclusion */
|
|
|
|
if (pDwmEnableComposition)
|
|
|
|
{
|
|
|
|
hr = pDwmEnableComposition(DWM_EC_DISABLECOMPOSITION);
|
|
|
|
ok(hr == S_OK, "Failed to disable composition.\n");
|
|
|
|
|
|
|
|
occlusion_desc.hWnd = hwnd;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
/* This result means that D3DKMTCheckOcclusion doesn't check composition status despite MSDN says it will */
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
occlusion_desc.hWnd = hwnd2;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
ShowWindow(hwnd, SW_MINIMIZE);
|
|
|
|
occlusion_desc.hWnd = hwnd;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
ShowWindow(hwnd, SW_SHOWNORMAL);
|
|
|
|
|
|
|
|
ShowWindow(hwnd, SW_HIDE);
|
|
|
|
occlusion_desc.hWnd = hwnd;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
ShowWindow(hwnd, SW_SHOW);
|
|
|
|
|
|
|
|
hr = pDwmEnableComposition(DWM_EC_ENABLECOMPOSITION);
|
|
|
|
ok(hr == S_OK, "Failed to enable composition.\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
skip("Skip testing composition.\n");
|
|
|
|
|
|
|
|
lstrcpyW(open_adapter_gdi_desc.DeviceName, display1W);
|
|
|
|
status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
memset(&create_device_desc, 0, sizeof(create_device_desc));
|
|
|
|
create_device_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
|
|
|
|
status = pD3DKMTCreateDevice(&create_device_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
|
|
|
|
check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId;
|
|
|
|
status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc);
|
|
|
|
/* D3DKMTCheckVidPnExclusiveOwnership gets STATUS_GRAPHICS_PRESENT_UNOCCLUDED sometimes and with some delay,
|
|
|
|
* it will always return STATUS_SUCCESS. So there are some timing issues here. */
|
|
|
|
ok(status == STATUS_SUCCESS || status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Test D3DKMTCheckOcclusion relationship with video present source owner */
|
|
|
|
set_owner_desc.hDevice = create_device_desc.hDevice;
|
|
|
|
owner_type = D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE;
|
|
|
|
set_owner_desc.pType = &owner_type;
|
|
|
|
set_owner_desc.pVidPnSourceId = &open_adapter_gdi_desc.VidPnSourceId;
|
|
|
|
set_owner_desc.VidPnSourceCount = 1;
|
|
|
|
status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
for (i = 0; EnumDisplayDevicesW(NULL, i, &display_device, 0); ++i)
|
|
|
|
{
|
|
|
|
if ((display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
|
|
|
|
adapter_count++;
|
|
|
|
}
|
|
|
|
/* STATUS_GRAPHICS_PRESENT_OCCLUDED on single monitor system. STATUS_SUCCESS on multiple monitor system. */
|
|
|
|
expected_occlusion = adapter_count > 1 ? STATUS_SUCCESS : STATUS_GRAPHICS_PRESENT_OCCLUDED;
|
|
|
|
|
|
|
|
occlusion_desc.hWnd = hwnd;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == expected_occlusion, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Note hwnd2 is not actually occluded but D3DKMTCheckOcclusion reports STATUS_GRAPHICS_PRESENT_OCCLUDED as well */
|
|
|
|
SetWindowPos(hwnd2, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
|
|
|
ShowWindow(hwnd2, SW_SHOW);
|
|
|
|
occlusion_desc.hWnd = hwnd2;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == expected_occlusion, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Now hwnd is HWND_TOPMOST. Still reports STATUS_GRAPHICS_PRESENT_OCCLUDED */
|
|
|
|
ok(SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE), "Failed to SetWindowPos.\n");
|
|
|
|
ok(GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "No WS_EX_TOPMOST style.\n");
|
|
|
|
occlusion_desc.hWnd = hwnd;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == expected_occlusion, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
DestroyWindow(hwnd2);
|
|
|
|
occlusion_desc.hWnd = hwnd;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == expected_occlusion, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
|
|
|
|
check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId;
|
|
|
|
status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc);
|
|
|
|
ok(status == STATUS_GRAPHICS_PRESENT_OCCLUDED, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
/* Unset video present source owner */
|
|
|
|
set_owner_desc.hDevice = create_device_desc.hDevice;
|
|
|
|
set_owner_desc.pType = NULL;
|
|
|
|
set_owner_desc.pVidPnSourceId = NULL;
|
|
|
|
set_owner_desc.VidPnSourceCount = 0;
|
|
|
|
status = pD3DKMTSetVidPnSourceOwner(&set_owner_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
occlusion_desc.hWnd = hwnd;
|
|
|
|
status = pD3DKMTCheckOcclusion(&occlusion_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
check_owner_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
|
|
|
|
check_owner_desc.VidPnSourceId = open_adapter_gdi_desc.VidPnSourceId;
|
|
|
|
status = pD3DKMTCheckVidPnExclusiveOwnership(&check_owner_desc);
|
|
|
|
ok(status == STATUS_SUCCESS || status == STATUS_GRAPHICS_PRESENT_UNOCCLUDED, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
destroy_device_desc.hDevice = create_device_desc.hDevice;
|
|
|
|
status = pD3DKMTDestroyDevice(&destroy_device_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
|
|
|
|
close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
|
|
|
|
status = pD3DKMTCloseAdapter(&close_adapter_desc);
|
|
|
|
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
|
|
|
DestroyWindow(hwnd);
|
|
|
|
}
|
|
|
|
|
2019-05-24 10:23:26 +02:00
|
|
|
START_TEST(driver)
|
|
|
|
{
|
|
|
|
HMODULE gdi32 = GetModuleHandleA("gdi32.dll");
|
2019-05-25 05:55:07 +02:00
|
|
|
HMODULE dwmapi = LoadLibraryA("dwmapi.dll");
|
2019-05-24 10:23:26 +02:00
|
|
|
|
2019-05-25 05:55:07 +02:00
|
|
|
pD3DKMTCheckOcclusion = (void *)GetProcAddress(gdi32, "D3DKMTCheckOcclusion");
|
2019-05-24 10:23:31 +02:00
|
|
|
pD3DKMTCheckVidPnExclusiveOwnership = (void *)GetProcAddress(gdi32, "D3DKMTCheckVidPnExclusiveOwnership");
|
2019-05-24 10:23:26 +02:00
|
|
|
pD3DKMTCloseAdapter = (void *)GetProcAddress(gdi32, "D3DKMTCloseAdapter");
|
2019-05-24 10:23:29 +02:00
|
|
|
pD3DKMTCreateDevice = (void *)GetProcAddress(gdi32, "D3DKMTCreateDevice");
|
|
|
|
pD3DKMTDestroyDevice = (void *)GetProcAddress(gdi32, "D3DKMTDestroyDevice");
|
2019-05-24 10:23:26 +02:00
|
|
|
pD3DKMTOpenAdapterFromGdiDisplayName = (void *)GetProcAddress(gdi32, "D3DKMTOpenAdapterFromGdiDisplayName");
|
2019-05-24 10:23:27 +02:00
|
|
|
pD3DKMTOpenAdapterFromHdc = (void *)GetProcAddress(gdi32, "D3DKMTOpenAdapterFromHdc");
|
2019-05-24 10:23:31 +02:00
|
|
|
pD3DKMTSetVidPnSourceOwner = (void *)GetProcAddress(gdi32, "D3DKMTSetVidPnSourceOwner");
|
2019-05-24 10:23:26 +02:00
|
|
|
|
2019-05-25 05:55:07 +02:00
|
|
|
if (dwmapi)
|
|
|
|
pDwmEnableComposition = (void *)GetProcAddress(dwmapi, "DwmEnableComposition");
|
|
|
|
|
2019-05-24 10:23:26 +02:00
|
|
|
test_D3DKMTOpenAdapterFromGdiDisplayName();
|
2019-05-24 10:23:27 +02:00
|
|
|
test_D3DKMTOpenAdapterFromHdc();
|
2019-05-24 10:23:28 +02:00
|
|
|
test_D3DKMTCloseAdapter();
|
2019-05-24 10:23:29 +02:00
|
|
|
test_D3DKMTCreateDevice();
|
2019-05-24 10:23:30 +02:00
|
|
|
test_D3DKMTDestroyDevice();
|
2019-05-24 10:23:31 +02:00
|
|
|
test_D3DKMTCheckVidPnExclusiveOwnership();
|
2019-05-24 10:23:32 +02:00
|
|
|
test_D3DKMTSetVidPnSourceOwner();
|
2019-05-25 05:55:07 +02:00
|
|
|
test_D3DKMTCheckOcclusion();
|
|
|
|
|
|
|
|
FreeLibrary(dwmapi);
|
2019-05-24 10:23:26 +02:00
|
|
|
}
|