VirtualBox

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

Last change on this file since 46606 was 46593, checked in by vboxsync, 11 years ago

updates

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

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