VirtualBox

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

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

wddm: more on new comand mechanism, guest side almost done, some cleanup

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