VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispKmt.cpp@ 63105

Last change on this file since 63105 was 63033, checked in by vboxsync, 9 years ago

GA/NT/Graphics: warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.6 KB
Line 
1/* $Id: VBoxDispKmt.cpp 63033 2016-08-05 11:19:40Z vboxsync $ */
2/** @file
3 * VBoxVideo Display D3D User Mode Dll.
4 */
5
6/*
7 * Copyright (C) 2011-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "VBoxDispD3DBase.h"
19#include "VBoxDispKmt.h"
20
21#include <iprt/assert.h>
22#include <iprt/log.h>
23
24
25/**
26 * Loads a system DLL.
27 *
28 * @returns Module handle or NULL
29 * @param pszName The DLL name.
30 */
31static HMODULE loadSystemDll(const char *pszName)
32{
33 char szPath[MAX_PATH];
34 UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath));
35 size_t cbName = strlen(pszName) + 1;
36 if (cchPath + 1 + cbName > sizeof(szPath))
37 return NULL;
38 szPath[cchPath] = '\\';
39 memcpy(&szPath[cchPath + 1], pszName, cbName);
40 return LoadLibraryA(szPath);
41}
42
43HRESULT vboxDispKmtCallbacksInit(PVBOXDISPKMT_CALLBACKS pCallbacks)
44{
45 HRESULT hr = S_OK;
46
47 memset(pCallbacks, 0, sizeof (*pCallbacks));
48
49 pCallbacks->hGdi32 = loadSystemDll("gdi32.dll");
50 if (pCallbacks->hGdi32 != NULL)
51 {
52 bool bSupported = true;
53 bool bSupportedWin8 = true;
54 pCallbacks->pfnD3DKMTOpenAdapterFromHdc = (PFND3DKMT_OPENADAPTERFROMHDC)GetProcAddress(pCallbacks->hGdi32, "D3DKMTOpenAdapterFromHdc");
55 LogFunc(("pfnD3DKMTOpenAdapterFromHdc = %p\n", pCallbacks->pfnD3DKMTOpenAdapterFromHdc));
56 bSupported &= !!(pCallbacks->pfnD3DKMTOpenAdapterFromHdc);
57
58 pCallbacks->pfnD3DKMTOpenAdapterFromGdiDisplayName = (PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME)GetProcAddress(pCallbacks->hGdi32, "D3DKMTOpenAdapterFromGdiDisplayName");
59 LogFunc(("pfnD3DKMTOpenAdapterFromGdiDisplayName = %p\n", pCallbacks->pfnD3DKMTOpenAdapterFromGdiDisplayName));
60 bSupported &= !!(pCallbacks->pfnD3DKMTOpenAdapterFromGdiDisplayName);
61
62 pCallbacks->pfnD3DKMTCloseAdapter = (PFND3DKMT_CLOSEADAPTER)GetProcAddress(pCallbacks->hGdi32, "D3DKMTCloseAdapter");
63 LogFunc(("pfnD3DKMTCloseAdapter = %p\n", pCallbacks->pfnD3DKMTCloseAdapter));
64 bSupported &= !!(pCallbacks->pfnD3DKMTCloseAdapter);
65
66 pCallbacks->pfnD3DKMTEscape = (PFND3DKMT_ESCAPE)GetProcAddress(pCallbacks->hGdi32, "D3DKMTEscape");
67 LogFunc(("pfnD3DKMTEscape = %p\n", pCallbacks->pfnD3DKMTEscape));
68 bSupported &= !!(pCallbacks->pfnD3DKMTEscape);
69
70 pCallbacks->pfnD3DKMTQueryAdapterInfo = (PFND3DKMT_QUERYADAPTERINFO)GetProcAddress(pCallbacks->hGdi32, "D3DKMTQueryAdapterInfo");
71 LogFunc(("pfnD3DKMTQueryAdapterInfo = %p\n", pCallbacks->pfnD3DKMTQueryAdapterInfo));
72 bSupported &= !!(pCallbacks->pfnD3DKMTQueryAdapterInfo);
73
74 pCallbacks->pfnD3DKMTCreateDevice = (PFND3DKMT_CREATEDEVICE)GetProcAddress(pCallbacks->hGdi32, "D3DKMTCreateDevice");
75 LogFunc(("pfnD3DKMTCreateDevice = %p\n", pCallbacks->pfnD3DKMTCreateDevice));
76 bSupported &= !!(pCallbacks->pfnD3DKMTCreateDevice);
77
78 pCallbacks->pfnD3DKMTDestroyDevice = (PFND3DKMT_DESTROYDEVICE)GetProcAddress(pCallbacks->hGdi32, "D3DKMTDestroyDevice");
79 LogFunc(("pfnD3DKMTDestroyDevice = %p\n", pCallbacks->pfnD3DKMTDestroyDevice));
80 bSupported &= !!(pCallbacks->pfnD3DKMTDestroyDevice);
81
82 pCallbacks->pfnD3DKMTCreateContext = (PFND3DKMT_CREATECONTEXT)GetProcAddress(pCallbacks->hGdi32, "D3DKMTCreateContext");
83 LogFunc(("pfnD3DKMTCreateContext = %p\n", pCallbacks->pfnD3DKMTCreateContext));
84 bSupported &= !!(pCallbacks->pfnD3DKMTCreateContext);
85
86 pCallbacks->pfnD3DKMTDestroyContext = (PFND3DKMT_DESTROYCONTEXT)GetProcAddress(pCallbacks->hGdi32, "D3DKMTDestroyContext");
87 LogFunc(("pfnD3DKMTDestroyContext = %p\n", pCallbacks->pfnD3DKMTDestroyContext));
88 bSupported &= !!(pCallbacks->pfnD3DKMTDestroyContext);
89
90 pCallbacks->pfnD3DKMTRender = (PFND3DKMT_RENDER)GetProcAddress(pCallbacks->hGdi32, "D3DKMTRender");
91 LogFunc(("pfnD3DKMTRender = %p\n", pCallbacks->pfnD3DKMTRender));
92 bSupported &= !!(pCallbacks->pfnD3DKMTRender);
93
94 pCallbacks->pfnD3DKMTCreateAllocation = (PFND3DKMT_CREATEALLOCATION)GetProcAddress(pCallbacks->hGdi32, "D3DKMTCreateAllocation");
95 LogFunc(("pfnD3DKMTCreateAllocation = %p\n", pCallbacks->pfnD3DKMTCreateAllocation));
96 bSupported &= !!(pCallbacks->pfnD3DKMTCreateAllocation);
97
98 pCallbacks->pfnD3DKMTDestroyAllocation = (PFND3DKMT_DESTROYALLOCATION)GetProcAddress(pCallbacks->hGdi32, "D3DKMTDestroyAllocation");
99 LogFunc(("pfnD3DKMTDestroyAllocation = %p\n", pCallbacks->pfnD3DKMTDestroyAllocation));
100 bSupported &= !!(pCallbacks->pfnD3DKMTDestroyAllocation);
101
102 pCallbacks->pfnD3DKMTLock = (PFND3DKMT_LOCK)GetProcAddress(pCallbacks->hGdi32, "D3DKMTLock");
103 LogFunc(("pfnD3DKMTLock = %p\n", pCallbacks->pfnD3DKMTLock));
104 bSupported &= !!(pCallbacks->pfnD3DKMTLock);
105
106 pCallbacks->pfnD3DKMTUnlock = (PFND3DKMT_UNLOCK)GetProcAddress(pCallbacks->hGdi32, "D3DKMTUnlock");
107 LogFunc(("pfnD3DKMTUnlock = %p\n", pCallbacks->pfnD3DKMTUnlock));
108 bSupported &= !!(pCallbacks->pfnD3DKMTUnlock);
109
110 pCallbacks->pfnD3DKMTInvalidateActiveVidPn = (PFND3DKMT_INVALIDATEACTIVEVIDPN)GetProcAddress(pCallbacks->hGdi32, "D3DKMTInvalidateActiveVidPn");
111 LogFunc(("pfnD3DKMTInvalidateActiveVidPn = %p\n", pCallbacks->pfnD3DKMTInvalidateActiveVidPn));
112 bSupported &= !!(pCallbacks->pfnD3DKMTInvalidateActiveVidPn);
113
114 pCallbacks->pfnD3DKMTPollDisplayChildren = (PFND3DKMT_POLLDISPLAYCHILDREN)GetProcAddress(pCallbacks->hGdi32, "D3DKMTPollDisplayChildren");
115 LogFunc(("pfnD3DKMTPollDisplayChildren = %p\n", pCallbacks->pfnD3DKMTPollDisplayChildren));
116 bSupported &= !!(pCallbacks->pfnD3DKMTPollDisplayChildren);
117
118 pCallbacks->pfnD3DKMTEnumAdapters = (PFND3DKMT_ENUMADAPTERS)GetProcAddress(pCallbacks->hGdi32, "D3DKMTEnumAdapters");
119 LogFunc(("pfnD3DKMTEnumAdapters = %p\n", pCallbacks->pfnD3DKMTEnumAdapters));
120 /* this present starting win8 release preview only, so keep going if it is not available,
121 * i.e. do not clear the bSupported on its absence */
122 bSupportedWin8 &= !!(pCallbacks->pfnD3DKMTEnumAdapters);
123
124 pCallbacks->pfnD3DKMTOpenAdapterFromLuid = (PFND3DKMT_OPENADAPTERFROMLUID)GetProcAddress(pCallbacks->hGdi32, "D3DKMTOpenAdapterFromLuid");
125 LogFunc(("pfnD3DKMTOpenAdapterFromLuid = %p\n", pCallbacks->pfnD3DKMTOpenAdapterFromLuid));
126 /* this present starting win8 release preview only, so keep going if it is not available,
127 * i.e. do not clear the bSupported on its absence */
128 bSupportedWin8 &= !!(pCallbacks->pfnD3DKMTOpenAdapterFromLuid);
129
130 /*Assert(bSupported);*/
131 if (bSupported)
132 {
133 if (bSupportedWin8)
134 pCallbacks->enmVersion = VBOXDISPKMT_CALLBACKS_VERSION_WIN8;
135 else
136 pCallbacks->enmVersion = VBOXDISPKMT_CALLBACKS_VERSION_VISTA_WIN7;
137 return S_OK;
138 }
139 else
140 {
141 LogFunc(("one of pfnD3DKMT function pointers failed to initialize\n"));
142 hr = E_NOINTERFACE;
143 }
144
145 FreeLibrary(pCallbacks->hGdi32);
146 }
147 else
148 {
149 DWORD winEr = GetLastError();
150 hr = HRESULT_FROM_WIN32(winEr);
151 Assert(0);
152 Assert(hr != S_OK);
153 Assert(hr != S_FALSE);
154 if (hr == S_OK || hr == S_FALSE)
155 hr = E_FAIL;
156 }
157
158 return hr;
159}
160
161HRESULT vboxDispKmtCallbacksTerm(PVBOXDISPKMT_CALLBACKS pCallbacks)
162{
163 FreeLibrary(pCallbacks->hGdi32);
164#ifdef DEBUG_misha
165 memset(pCallbacks, 0, sizeof (*pCallbacks));
166#endif
167 return S_OK;
168}
169
170HRESULT vboxDispKmtAdpHdcCreate(HDC *phDc)
171{
172 HRESULT hr = E_FAIL;
173 DISPLAY_DEVICE DDev;
174 memset(&DDev, 0, sizeof (DDev));
175 DDev.cb = sizeof (DDev);
176
177 *phDc = NULL;
178
179 for (int i = 0; ; ++i)
180 {
181 if (EnumDisplayDevices(NULL, /* LPCTSTR lpDevice */ i, /* DWORD iDevNum */
182 &DDev, 0 /* DWORD dwFlags*/))
183 {
184 if (DDev.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
185 {
186 HDC hDc = CreateDC(NULL, DDev.DeviceName, NULL, NULL);
187 if (hDc)
188 {
189 *phDc = hDc;
190 return S_OK;
191 }
192 else
193 {
194 DWORD winEr = GetLastError();
195 Assert(0);
196 hr = HRESULT_FROM_WIN32(winEr);
197 Assert(FAILED(hr));
198 break;
199 }
200 }
201 }
202 else
203 {
204 DWORD winEr = GetLastError();
205// BP_WARN();
206 hr = HRESULT_FROM_WIN32(winEr);
207#ifdef DEBUG_misha
208 Assert(FAILED(hr));
209#endif
210 if (!FAILED(hr))
211 {
212 hr = E_FAIL;
213 }
214 break;
215 }
216 }
217
218 return hr;
219}
220
221static HRESULT vboxDispKmtOpenAdapterViaHdc(const VBOXDISPKMT_CALLBACKS *pCallbacks, PVBOXDISPKMT_ADAPTER pAdapter)
222{
223 D3DKMT_OPENADAPTERFROMHDC OpenAdapterData = {0};
224 HRESULT hr = vboxDispKmtAdpHdcCreate(&OpenAdapterData.hDc);
225 if (!SUCCEEDED(hr))
226 return hr;
227
228 Assert(OpenAdapterData.hDc);
229 NTSTATUS Status = pCallbacks->pfnD3DKMTOpenAdapterFromHdc(&OpenAdapterData);
230 if (NT_SUCCESS(Status))
231 {
232 pAdapter->hAdapter = OpenAdapterData.hAdapter;
233 pAdapter->hDc = OpenAdapterData.hDc;
234 pAdapter->pCallbacks = pCallbacks;
235 memset(&pAdapter->Luid, 0, sizeof (pAdapter->Luid));
236 return S_OK;
237 }
238 else
239 {
240 LogFunc(("pfnD3DKMTOpenAdapterFromGdiDisplayName failed, Status (0x%x)\n", Status));
241 hr = E_FAIL;
242 }
243
244 DeleteDC(OpenAdapterData.hDc);
245
246 return hr;
247}
248
249static HRESULT vboxDispKmtOpenAdapterViaLuid(const VBOXDISPKMT_CALLBACKS *pCallbacks, PVBOXDISPKMT_ADAPTER pAdapter)
250{
251 if (pCallbacks->enmVersion < VBOXDISPKMT_CALLBACKS_VERSION_WIN8)
252 return E_NOTIMPL;
253
254 D3DKMT_ENUMADAPTERS EnumAdapters = {0};
255 EnumAdapters.NumAdapters = RT_ELEMENTS(EnumAdapters.Adapters);
256
257 NTSTATUS Status = pCallbacks->pfnD3DKMTEnumAdapters(&EnumAdapters);
258#ifdef DEBUG_misha
259 Assert(!Status);
260#endif
261 if (!NT_SUCCESS(Status))
262 return E_FAIL;
263
264 Assert(EnumAdapters.NumAdapters);
265
266 /* try the same twice: if we fail to open the adapter containing present sources,
267 * try to open any adapter */
268 for (ULONG f = 0; f < 2; ++f)
269 {
270 for (ULONG i = 0; i < EnumAdapters.NumAdapters; ++i)
271 {
272 if (f || EnumAdapters.Adapters[i].NumOfSources)
273 {
274 D3DKMT_OPENADAPTERFROMLUID OpenAdapterData = {0};
275 OpenAdapterData.AdapterLuid = EnumAdapters.Adapters[i].AdapterLuid;
276 Status = pCallbacks->pfnD3DKMTOpenAdapterFromLuid(&OpenAdapterData);
277 #ifdef DEBUG_misha
278 Assert(!Status);
279 #endif
280 if (NT_SUCCESS(Status))
281 {
282 pAdapter->hAdapter = OpenAdapterData.hAdapter;
283 pAdapter->hDc = NULL;
284 pAdapter->Luid = EnumAdapters.Adapters[i].AdapterLuid;
285 pAdapter->pCallbacks = pCallbacks;
286 return S_OK;
287 }
288 }
289 }
290 }
291
292#ifdef DEBUG_misha
293 Assert(0);
294#endif
295 return E_FAIL;
296}
297
298HRESULT vboxDispKmtOpenAdapter(const VBOXDISPKMT_CALLBACKS *pCallbacks, PVBOXDISPKMT_ADAPTER pAdapter)
299{
300 HRESULT hr = vboxDispKmtOpenAdapterViaHdc(pCallbacks, pAdapter);
301 if (SUCCEEDED(hr))
302 return S_OK;
303
304 hr = vboxDispKmtOpenAdapterViaLuid(pCallbacks, pAdapter);
305 if (SUCCEEDED(hr))
306 return S_OK;
307
308 return hr;
309}
310
311HRESULT vboxDispKmtCloseAdapter(PVBOXDISPKMT_ADAPTER pAdapter)
312{
313 D3DKMT_CLOSEADAPTER ClosaAdapterData = {0};
314 ClosaAdapterData.hAdapter = pAdapter->hAdapter;
315 NTSTATUS Status = pAdapter->pCallbacks->pfnD3DKMTCloseAdapter(&ClosaAdapterData);
316 Assert(!Status);
317 if (!Status)
318 {
319 DeleteDC(pAdapter->hDc);
320#ifdef DEBUG_misha
321 memset(pAdapter, 0, sizeof (*pAdapter));
322#endif
323 return S_OK;
324 }
325
326 LogFunc(("pfnD3DKMTCloseAdapter failed, Status (0x%x)\n", Status));
327
328 return E_FAIL;
329}
330
331HRESULT vboxDispKmtCreateDevice(PVBOXDISPKMT_ADAPTER pAdapter, PVBOXDISPKMT_DEVICE pDevice)
332{
333 D3DKMT_CREATEDEVICE CreateDeviceData = {0};
334 CreateDeviceData.hAdapter = pAdapter->hAdapter;
335 NTSTATUS Status = pAdapter->pCallbacks->pfnD3DKMTCreateDevice(&CreateDeviceData);
336 Assert(!Status);
337 if (!Status)
338 {
339 pDevice->pAdapter = pAdapter;
340 pDevice->hDevice = CreateDeviceData.hDevice;
341 pDevice->pCommandBuffer = CreateDeviceData.pCommandBuffer;
342 pDevice->CommandBufferSize = CreateDeviceData.CommandBufferSize;
343 pDevice->pAllocationList = CreateDeviceData.pAllocationList;
344 pDevice->AllocationListSize = CreateDeviceData.AllocationListSize;
345 pDevice->pPatchLocationList = CreateDeviceData.pPatchLocationList;
346 pDevice->PatchLocationListSize = CreateDeviceData.PatchLocationListSize;
347
348 return S_OK;
349 }
350
351 return E_FAIL;
352}
353
354HRESULT vboxDispKmtDestroyDevice(PVBOXDISPKMT_DEVICE pDevice)
355{
356 D3DKMT_DESTROYDEVICE DestroyDeviceData = {0};
357 DestroyDeviceData.hDevice = pDevice->hDevice;
358 NTSTATUS Status = pDevice->pAdapter->pCallbacks->pfnD3DKMTDestroyDevice(&DestroyDeviceData);
359 Assert(!Status);
360 if (!Status)
361 {
362#ifdef DEBUG_misha
363 memset(pDevice, 0, sizeof (*pDevice));
364#endif
365 return S_OK;
366 }
367 return E_FAIL;
368}
369
370HRESULT vboxDispKmtCreateContext(PVBOXDISPKMT_DEVICE pDevice, PVBOXDISPKMT_CONTEXT pContext,
371 VBOXWDDM_CONTEXT_TYPE enmType,
372 uint32_t crVersionMajor, uint32_t crVersionMinor,
373 HANDLE hEvent, uint64_t u64UmInfo)
374{
375 VBOXWDDM_CREATECONTEXT_INFO Info = {0};
376 Info.u32IfVersion = 9;
377 Info.enmType = enmType;
378 Info.crVersionMajor = crVersionMajor;
379 Info.crVersionMinor = crVersionMinor;
380 Info.hUmEvent = (uintptr_t)hEvent;
381 Info.u64UmInfo = u64UmInfo;
382 D3DKMT_CREATECONTEXT ContextData = {0};
383 ContextData.hDevice = pDevice->hDevice;
384 ContextData.NodeOrdinal = VBOXWDDM_NODE_ID_3D_KMT;
385 ContextData.EngineAffinity = VBOXWDDM_ENGINE_ID_3D_KMT;
386 ContextData.pPrivateDriverData = &Info;
387 ContextData.PrivateDriverDataSize = sizeof (Info);
388 ContextData.ClientHint = enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL ? D3DKMT_CLIENTHINT_OPENGL : D3DKMT_CLIENTHINT_DX9;
389 NTSTATUS Status = pDevice->pAdapter->pCallbacks->pfnD3DKMTCreateContext(&ContextData);
390 Assert(!Status);
391 if (!Status)
392 {
393 pContext->pDevice = pDevice;
394 pContext->hContext = ContextData.hContext;
395 pContext->pCommandBuffer = ContextData.pCommandBuffer;
396 pContext->CommandBufferSize = ContextData.CommandBufferSize;
397 pContext->pAllocationList = ContextData.pAllocationList;
398 pContext->AllocationListSize = ContextData.AllocationListSize;
399 pContext->pPatchLocationList = ContextData.pPatchLocationList;
400 pContext->PatchLocationListSize = ContextData.PatchLocationListSize;
401 return S_OK;
402 }
403 return E_FAIL;
404}
405
406HRESULT vboxDispKmtDestroyContext(PVBOXDISPKMT_CONTEXT pContext)
407{
408 D3DKMT_DESTROYCONTEXT DestroyContextData = {0};
409 DestroyContextData.hContext = pContext->hContext;
410 NTSTATUS Status = pContext->pDevice->pAdapter->pCallbacks->pfnD3DKMTDestroyContext(&DestroyContextData);
411 Assert(!Status);
412 if (!Status)
413 {
414#ifdef DEBUG_misha
415 memset(pContext, 0, sizeof (*pContext));
416#endif
417 return S_OK;
418 }
419 return E_FAIL;
420}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette