Mostly to show that D3DKMTCheckOcclusion is mainly composed of ownership checks rather than actually window occlusion. Also composition status doesn't affect its behavior despite MSDN say so.
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/gdi32/tests/Makefile.in | 2 +- dlls/gdi32/tests/driver.c | 382 +++++++++++++++++++++++++++++++++++ 2 files changed, 383 insertions(+), 1 deletion(-)
diff --git a/dlls/gdi32/tests/Makefile.in b/dlls/gdi32/tests/Makefile.in index 9d82c278e9..6c32f22c1d 100644 --- a/dlls/gdi32/tests/Makefile.in +++ b/dlls/gdi32/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = gdi32.dll -IMPORTS = user32 gdi32 advapi32 +IMPORTS = user32 gdi32 advapi32 d3d10_1 dxgi
C_SRCS = \ bitmap.c \ diff --git a/dlls/gdi32/tests/driver.c b/dlls/gdi32/tests/driver.c index 81c41a1454..b4564c58ee 100644 --- a/dlls/gdi32/tests/driver.c +++ b/dlls/gdi32/tests/driver.c @@ -27,12 +27,18 @@ #include "wingdi.h" #include "winuser.h" #include "winternl.h" +#include "dwmapi.h" +#define COBJMACROS +#include "initguid.h" +#include "dxgi1_6.h" +#include <d3d11.h> #include "ddk/d3dkmthk.h"
#include "wine/test.h"
static const WCHAR display1W[] = {'\','\','.','\','D','I','S','P','L','A','Y','1',0};
+static NTSTATUS (WINAPI *pD3DKMTCheckOcclusion)(const D3DKMT_CHECKOCCLUSION *); static NTSTATUS (WINAPI *pD3DKMTCheckVidPnExclusiveOwnership)(const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *); static NTSTATUS (WINAPI *pD3DKMTCloseAdapter)(const D3DKMT_CLOSEADAPTER *); static NTSTATUS (WINAPI *pD3DKMTCreateDevice)(D3DKMT_CREATEDEVICE *); @@ -40,6 +46,59 @@ static NTSTATUS (WINAPI *pD3DKMTDestroyDevice)(const D3DKMT_DESTROYDEVICE *); static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromGdiDisplayName)(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *); static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromHdc)(D3DKMT_OPENADAPTERFROMHDC *); static NTSTATUS (WINAPI *pD3DKMTSetVidPnSourceOwner)(const D3DKMT_SETVIDPNSOURCEOWNER *); +static HRESULT (WINAPI *pDwmEnableComposition)(UINT); + +static IDXGIAdapter *create_adapter(void) +{ + IDXGIFactory *factory; + IDXGIAdapter *adapter; + HRESULT hr; + + if (FAILED(hr = CreateDXGIFactory(&IID_IDXGIFactory, (void **)&factory))) + { + trace("Failed to create IDXGIFactory, hr %#x.\n", hr); + return NULL; + } + + adapter = NULL; + hr = IDXGIFactory_EnumAdapters(factory, 0, &adapter); + IDXGIFactory_Release(factory); + if (FAILED(hr)) + trace("Failed to get adapter, hr %#x.\n", hr); + return adapter; +} + +static IDXGIDevice *create_device(unsigned int flags) +{ + IDXGIDevice *dxgi_device; + ID3D10Device1 *device; + IDXGIAdapter *adapter; + HRESULT hr; + + adapter = create_adapter(); + hr = D3D10CreateDevice1(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, flags, D3D10_FEATURE_LEVEL_10_0, + D3D10_1_SDK_VERSION, &device); + if (adapter) + IDXGIAdapter_Release(adapter); + if (SUCCEEDED(hr)) + goto success; + + if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_WARP, NULL, flags, D3D10_FEATURE_LEVEL_10_0, + D3D10_1_SDK_VERSION, &device))) + goto success; + if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL, flags, D3D10_FEATURE_LEVEL_10_0, + D3D10_1_SDK_VERSION, &device))) + goto success; + + return NULL; + +success: + hr = ID3D10Device1_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device); + ok(SUCCEEDED(hr), "Created device does not implement IDXGIDevice\n"); + ID3D10Device1_Release(device); + + return dxgi_device; +}
static void test_D3DKMTOpenAdapterFromGdiDisplayName(void) { @@ -603,10 +662,328 @@ static void test_D3DKMTSetVidPnSourceOwner(void) ok(status == STATUS_INVALID_PARAMETER, "Got unexpected return code %#x.\n", status); }
+static void test_D3DKMTCheckOcclusion(void) +{ + static const DWORD timeout = 2000; + 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; + DXGI_SWAP_CHAIN_DESC swapchain_desc; + NTSTATUS expected_occlusion, status; + INT i, adapter_count = 0; + IDXGISwapChain *swapchain; + IDXGIFactory *factory; + IDXGIAdapter *adapter; + IDXGIDevice *device; + 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"); + + DestroyWindow(hwnd2); + + if (!(pD3DKMTCheckVidPnExclusiveOwnership && pD3DKMTCloseAdapter && pD3DKMTCreateDevice && pD3DKMTDestroyDevice + && pD3DKMTOpenAdapterFromGdiDisplayName && pD3DKMTSetVidPnSourceOwner)) + { + skip("Required functions are unavailable.\n"); + goto done; + } + + 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); + ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status); + + /* Test swapchain fullscreen mode relationship with D3DKMTCheckOcclusion */ + if (!(device = create_device(0))) + { + skip("Failed to create device.\n"); + goto done; + } + + hr = IDXGIDevice_GetAdapter(device, &adapter); + ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr); + + hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory); + ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr); + + memset(&swapchain_desc, 0, sizeof(swapchain_desc)); + swapchain_desc.BufferDesc.Width = 800; + swapchain_desc.BufferDesc.Height = 600; + swapchain_desc.BufferDesc.RefreshRate.Numerator = 60; + swapchain_desc.BufferDesc.RefreshRate.Denominator = 60; + swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapchain_desc.SampleDesc.Count = 1; + swapchain_desc.SampleDesc.Quality = 0; + swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapchain_desc.BufferCount = 1; + swapchain_desc.OutputWindow = hwnd; + swapchain_desc.Windowed = TRUE; + swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swapchain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + + hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain); + ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr); + + 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 == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status); + + hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); + ok(SUCCEEDED(hr), "Failed to SetFullscreenState.\n"); + + 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); + + hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); + ok(SUCCEEDED(hr), "Failed to SetFullscreenState.\n"); + /* Leaving fullscreen could take several seconds to complete, wait a while to get accurate results for + * D3DKMTCheckOcclusion and D3DKMTCheckVidPnExclusiveOwnership. */ + Sleep(timeout); + + 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, "Got unexpected return code %#x.\n", status); + + hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); + ok(SUCCEEDED(hr), "Failed to SetFullscreenState.\n"); + + /* Invisible window, even HWND_TOP, doesn't break swapchain out of fullscreen, and doesn't change video present + * network ownership */ + hwnd2 = CreateWindowA("static", "static2", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, 0); + ok(hwnd2 != NULL, "Failed to create window.\n"); + SetWindowPos(hwnd2, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + + 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); + + /* Visible window, even with HWND_BOTTOM, breaks swapchain out of fullscreen */ + SetWindowPos(hwnd2, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + ShowWindow(hwnd2, SW_SHOW); + Sleep(timeout); + 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, "Got unexpected return code %#x.\n", status); + + hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); + ok(SUCCEEDED(hr), "Failed to SetFullscreenState.\n"); + Sleep(timeout); + + 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, "Got unexpected return code %#x.\n", status); + + IDXGISwapChain_Release(swapchain); + IDXGIAdapter_Release(adapter); + IDXGIDevice_Release(device); + IDXGIFactory_Release(factory); + + /* 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); + + 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); + /* 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); + + destroy_device_desc.hDevice = create_device_desc.hDevice; + status = pD3DKMTDestroyDevice(&destroy_device_desc); + ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status); + +done: + if (pD3DKMTCloseAdapter) + { + 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); +} + START_TEST(driver) { HMODULE gdi32 = LoadLibraryA("gdi32.dll"); + HMODULE dwmapi = LoadLibraryA("dwmapi.dll");
+ pD3DKMTCheckOcclusion = (void *)GetProcAddress(gdi32, "D3DKMTCheckOcclusion"); pD3DKMTCheckVidPnExclusiveOwnership = (void *)GetProcAddress(gdi32, "D3DKMTCheckVidPnExclusiveOwnership"); pD3DKMTCloseAdapter = (void *)GetProcAddress(gdi32, "D3DKMTCloseAdapter"); pD3DKMTCreateDevice = (void *)GetProcAddress(gdi32, "D3DKMTCreateDevice"); @@ -615,6 +992,10 @@ START_TEST(driver) pD3DKMTOpenAdapterFromHdc = (void *)GetProcAddress(gdi32, "D3DKMTOpenAdapterFromHdc"); pD3DKMTSetVidPnSourceOwner = (void *)GetProcAddress(gdi32, "D3DKMTSetVidPnSourceOwner");
+ if (dwmapi) + pDwmEnableComposition = (void *)GetProcAddress(dwmapi, "DwmEnableComposition"); + + test_D3DKMTCheckOcclusion(); test_D3DKMTCheckVidPnExclusiveOwnership(); test_D3DKMTCloseAdapter(); test_D3DKMTCreateDevice(); @@ -624,4 +1005,5 @@ START_TEST(driver) test_D3DKMTSetVidPnSourceOwner();
FreeLibrary(gdi32); + FreeLibrary(dwmapi); }