VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxUhgsmiKmt.cpp@ 33676

Last change on this file since 33676 was 33530, checked in by vboxsync, 14 years ago

wddm/3d: chromium hgsmi: better alloc/submit engine

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.7 KB
Line 
1/** @file
2 *
3 * VBoxVideo Display D3D User mode dll
4 *
5 * Copyright (C) 2010 Oracle Corporation
6 *
7 * This file is part of VirtualBox Open Source Edition (OSE), as
8 * available from http://www.virtualbox.org. This file is free software;
9 * you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License (GPL) as published by the Free Software
11 * Foundation, in version 2 as it comes in the "COPYING" file of the
12 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
14 */
15#include "VBoxDispD3DCmn.h"
16
17#include <iprt/mem.h>
18#include <iprt/err.h>
19
20typedef struct VBOXUHGSMI_BUFFER_PRIVATE_KMT
21{
22 VBOXUHGSMI_BUFFER_PRIVATE_BASE BasePrivate;
23 PVBOXUHGSMI_PRIVATE_KMT pHgsmi;
24 CRITICAL_SECTION CritSect;
25 UINT aLockPageIndices[1];
26} VBOXUHGSMI_BUFFER_PRIVATE_KMT, *PVBOXUHGSMI_BUFFER_PRIVATE_KMT;
27
28typedef struct VBOXUHGSMI_BUFFER_PRIVATE_KMT_ESC
29{
30 VBOXUHGSMI_BUFFER Base;
31 PVBOXUHGSMI_PRIVATE_KMT pHgsmi;
32 VBOXVIDEOCM_UM_ALLOC Alloc;
33} VBOXUHGSMI_BUFFER_PRIVATE_KMT_ESC, *PVBOXUHGSMI_BUFFER_PRIVATE_KMT_ESC;
34
35#define VBOXUHGSMIKMT_GET_BUFFER(_p) VBOXUHGSMIKMT_GET_PRIVATE(_p, VBOXUHGSMI_BUFFER_PRIVATE_KMT)
36#define VBOXUHGSMIKMTESC_GET_PRIVATE(_p, _t) ((_t*)(((uint8_t*)_p) - RT_OFFSETOF(_t, Base)))
37#define VBOXUHGSMIKMTESC_GET_BUFFER(_p) VBOXUHGSMIKMTESC_GET_PRIVATE(_p, VBOXUHGSMI_BUFFER_PRIVATE_KMT_ESC)
38
39DECLCALLBACK(int) vboxUhgsmiKmtBufferDestroy(PVBOXUHGSMI_BUFFER pBuf)
40{
41 PVBOXUHGSMI_BUFFER_PRIVATE_KMT pBuffer = VBOXUHGSMIKMT_GET_BUFFER(pBuf);
42 D3DKMT_DESTROYALLOCATION DdiDealloc;
43 DdiDealloc.hDevice = pBuffer->pHgsmi->Device.hDevice;
44 DdiDealloc.hResource = NULL;
45 DdiDealloc.phAllocationList = &pBuffer->BasePrivate.hAllocation;
46 DdiDealloc.AllocationCount = 1;
47 NTSTATUS Status = pBuffer->pHgsmi->Callbacks.pfnD3DKMTDestroyAllocation(&DdiDealloc);
48 Assert(!Status);
49 if (!Status)
50 {
51 if (pBuffer->BasePrivate.Base.bSynchCreated)
52 {
53 CloseHandle(pBuffer->BasePrivate.Base.hSynch);
54 }
55 RTMemFree(pBuffer);
56 return VINF_SUCCESS;
57 }
58 return VERR_GENERAL_FAILURE;
59}
60
61DECLCALLBACK(int) vboxUhgsmiKmtBufferLock(PVBOXUHGSMI_BUFFER pBuf, uint32_t offLock, uint32_t cbLock, VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags, void**pvLock)
62{
63 PVBOXUHGSMI_BUFFER_PRIVATE_KMT pBuffer = VBOXUHGSMIKMT_GET_BUFFER(pBuf);
64 D3DKMT_LOCK DdiLock = {0};
65 DdiLock.hDevice = pBuffer->pHgsmi->Device.hDevice;
66 DdiLock.hAllocation = pBuffer->BasePrivate.hAllocation;
67 DdiLock.PrivateDriverData = NULL;
68
69 EnterCriticalSection(&pBuffer->CritSect);
70
71 int rc = vboxUhgsmiBaseLockData(pBuf, offLock, cbLock, fFlags,
72 &DdiLock.Flags, &DdiLock.NumPages, pBuffer->aLockPageIndices);
73 AssertRC(rc);
74 if (RT_FAILURE(rc))
75 return rc;
76
77 if (DdiLock.NumPages)
78 DdiLock.pPages = pBuffer->aLockPageIndices;
79 else
80 DdiLock.pPages = NULL;
81
82 NTSTATUS Status = pBuffer->pHgsmi->Callbacks.pfnD3DKMTLock(&DdiLock);
83 Assert(!Status);
84 LeaveCriticalSection(&pBuffer->CritSect);
85 if (!Status)
86 {
87 *pvLock = (void*)(((uint8_t*)DdiLock.pData) + (offLock & 0xfff));
88 return VINF_SUCCESS;
89 }
90 return VERR_GENERAL_FAILURE;
91}
92
93DECLCALLBACK(int) vboxUhgsmiKmtBufferUnlock(PVBOXUHGSMI_BUFFER pBuf)
94{
95 PVBOXUHGSMI_BUFFER_PRIVATE_KMT pBuffer = VBOXUHGSMIKMT_GET_BUFFER(pBuf);
96 D3DKMT_UNLOCK DdiUnlock;
97
98 DdiUnlock.hDevice = pBuffer->pHgsmi->Device.hDevice;
99 DdiUnlock.NumAllocations = 1;
100 DdiUnlock.phAllocations = &pBuffer->BasePrivate.hAllocation;
101 NTSTATUS Status = pBuffer->pHgsmi->Callbacks.pfnD3DKMTUnlock(&DdiUnlock);
102 Assert(!Status);
103 if (!Status)
104 return VINF_SUCCESS;
105 return VERR_GENERAL_FAILURE;
106}
107
108DECLCALLBACK(int) vboxUhgsmiKmtBufferCreate(PVBOXUHGSMI pHgsmi, uint32_t cbBuf,
109 VBOXUHGSMI_SYNCHOBJECT_TYPE enmSynchType, HVBOXUHGSMI_SYNCHOBJECT hSynch,
110 PVBOXUHGSMI_BUFFER* ppBuf)
111{
112 bool bSynchCreated = false;
113 if (!cbBuf)
114 return VERR_INVALID_PARAMETER;
115
116 int rc = vboxUhgsmiBaseEventChkCreate(enmSynchType, &hSynch, &bSynchCreated);
117 AssertRC(rc);
118 if (RT_FAILURE(rc))
119 return rc;
120
121 cbBuf = VBOXWDDM_ROUNDBOUND(cbBuf, 0x1000);
122 Assert(cbBuf);
123 uint32_t cPages = cbBuf >> 12;
124 Assert(cPages);
125
126 PVBOXUHGSMI_PRIVATE_KMT pPrivate = VBOXUHGSMIKMT_GET(pHgsmi);
127 PVBOXUHGSMI_BUFFER_PRIVATE_KMT pBuf = (PVBOXUHGSMI_BUFFER_PRIVATE_KMT)RTMemAllocZ(RT_OFFSETOF(VBOXUHGSMI_BUFFER_PRIVATE_KMT, aLockPageIndices[cPages]));
128 Assert(pBuf);
129 if (pBuf)
130 {
131 struct
132 {
133 D3DKMT_CREATEALLOCATION DdiAlloc;
134 D3DDDI_ALLOCATIONINFO DdiAllocInfo;
135 VBOXWDDM_ALLOCINFO AllocInfo;
136 } Buf;
137 memset(&Buf, 0, sizeof (Buf));
138 Buf.DdiAlloc.hDevice = pPrivate->Device.hDevice;
139 Buf.DdiAlloc.NumAllocations = 1;
140 Buf.DdiAlloc.pAllocationInfo = &Buf.DdiAllocInfo;
141 Buf.DdiAllocInfo.pPrivateDriverData = &Buf.AllocInfo;
142 Buf.DdiAllocInfo.PrivateDriverDataSize = sizeof (Buf.AllocInfo);
143 Buf.AllocInfo.enmType = VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER;
144 Buf.AllocInfo.cbBuffer = cbBuf;
145 Buf.AllocInfo.hSynch = hSynch;
146 Buf.AllocInfo.enmSynchType = enmSynchType;
147
148 HRESULT hr = pPrivate->Callbacks.pfnD3DKMTCreateAllocation(&Buf.DdiAlloc);
149 Assert(hr == S_OK);
150 if (hr == S_OK)
151 {
152 InitializeCriticalSection(&pBuf->CritSect);
153
154 Assert(Buf.DdiAllocInfo.hAllocation);
155 pBuf->BasePrivate.Base.pfnLock = vboxUhgsmiKmtBufferLock;
156 pBuf->BasePrivate.Base.pfnUnlock = vboxUhgsmiKmtBufferUnlock;
157// pBuf->Base.pfnAdjustValidDataRange = vboxUhgsmiKmtBufferAdjustValidDataRange;
158 pBuf->BasePrivate.Base.pfnDestroy = vboxUhgsmiKmtBufferDestroy;
159
160 pBuf->BasePrivate.Base.hSynch = hSynch;
161 pBuf->BasePrivate.Base.enmSynchType = enmSynchType;
162 pBuf->BasePrivate.Base.cbBuffer = cbBuf;
163 pBuf->BasePrivate.Base.bSynchCreated = bSynchCreated;
164
165 pBuf->pHgsmi = pPrivate;
166 pBuf->BasePrivate.hAllocation = Buf.DdiAllocInfo.hAllocation;
167
168 *ppBuf = &pBuf->BasePrivate.Base;
169
170 return VINF_SUCCESS;
171 }
172
173 RTMemFree(pBuf);
174 }
175 else
176 rc = VERR_NO_MEMORY;
177
178 if (bSynchCreated)
179 CloseHandle(hSynch);
180
181 return rc;
182}
183
184DECLCALLBACK(int) vboxUhgsmiKmtBufferSubmitAsynch(PVBOXUHGSMI pHgsmi, PVBOXUHGSMI_BUFFER_SUBMIT aBuffers, uint32_t cBuffers)
185{
186 PVBOXUHGSMI_PRIVATE_KMT pHg = VBOXUHGSMIKMT_GET(pHgsmi);
187 UINT cbDmaCmd = pHg->Context.CommandBufferSize;
188 int rc = vboxUhgsmiBaseDmaFill(aBuffers, cBuffers,
189 pHg->Context.pCommandBuffer, &cbDmaCmd,
190 pHg->Context.pAllocationList, pHg->Context.AllocationListSize,
191 pHg->Context.pPatchLocationList, pHg->Context.PatchLocationListSize);
192 AssertRC(rc);
193 if (RT_FAILURE(rc))
194 return rc;
195
196 D3DKMT_RENDER DdiRender = {0};
197 DdiRender.hContext = pHg->Context.hContext;
198 DdiRender.CommandLength = cbDmaCmd;
199 DdiRender.AllocationCount = cBuffers;
200 Assert(DdiRender.CommandLength);
201 Assert(DdiRender.CommandLength < UINT32_MAX/2);
202
203 HRESULT hr = pHg->Callbacks.pfnD3DKMTRender(&DdiRender);
204 Assert(hr == S_OK);
205 if (hr == S_OK)
206 {
207 pHg->Context.CommandBufferSize = DdiRender.NewCommandBufferSize;
208 pHg->Context.pCommandBuffer = DdiRender.pNewCommandBuffer;
209 pHg->Context.AllocationListSize = DdiRender.NewAllocationListSize;
210 pHg->Context.pAllocationList = DdiRender.pNewAllocationList;
211 pHg->Context.PatchLocationListSize = DdiRender.NewPatchLocationListSize;
212 pHg->Context.pPatchLocationList = DdiRender.pNewPatchLocationList;
213
214 return VINF_SUCCESS;
215 }
216
217 return VERR_GENERAL_FAILURE;
218}
219
220
221DECLCALLBACK(int) vboxUhgsmiKmtEscBufferLock(PVBOXUHGSMI_BUFFER pBuf, uint32_t offLock, uint32_t cbLock, VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags, void**pvLock)
222{
223 PVBOXUHGSMI_BUFFER_PRIVATE_KMT_ESC pBuffer = VBOXUHGSMIKMTESC_GET_BUFFER(pBuf);
224 *pvLock = pBuffer->Alloc.pvData + offLock;
225 return VINF_SUCCESS;
226}
227
228DECLCALLBACK(int) vboxUhgsmiKmtEscBufferUnlock(PVBOXUHGSMI_BUFFER pBuf)
229{
230 return VINF_SUCCESS;
231}
232
233DECLCALLBACK(int) vboxUhgsmiKmtEscBufferDestroy(PVBOXUHGSMI_BUFFER pBuf)
234{
235 PVBOXUHGSMI_BUFFER_PRIVATE_KMT_ESC pBuffer = VBOXUHGSMIKMTESC_GET_BUFFER(pBuf);
236 PVBOXUHGSMI_PRIVATE_KMT pPrivate = pBuffer->pHgsmi;
237 D3DKMT_ESCAPE DdiEscape = {0};
238 VBOXDISPIFESCAPE_UHGSMI_DEALLOCATE DeallocInfo = {0};
239 DdiEscape.hAdapter = pPrivate->Adapter.hAdapter;
240 DdiEscape.hDevice = pPrivate->Device.hDevice;
241 DdiEscape.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
242 //Buf.DdiEscape.Flags.HardwareAccess = 1;
243 DdiEscape.pPrivateDriverData = &DeallocInfo;
244 DdiEscape.PrivateDriverDataSize = sizeof (DeallocInfo);
245 DdiEscape.hContext = pPrivate->Context.hContext;
246
247 DeallocInfo.EscapeHdr.escapeCode = VBOXESC_UHGSMI_DEALLOCATE;
248 DeallocInfo.hAlloc = pBuffer->Alloc.hAlloc;
249
250 HRESULT hr = pPrivate->Callbacks.pfnD3DKMTEscape(&DdiEscape);
251 Assert(hr == S_OK);
252 if (hr == S_OK)
253 {
254 if (pBuffer->Base.bSynchCreated)
255 {
256 CloseHandle(pBuffer->Base.hSynch);
257 }
258 RTMemFree(pBuffer);
259 return VINF_SUCCESS;
260 }
261
262 return VERR_GENERAL_FAILURE;
263}
264
265DECLCALLBACK(int) vboxUhgsmiKmtEscBufferCreate(PVBOXUHGSMI pHgsmi, uint32_t cbBuf,
266 VBOXUHGSMI_SYNCHOBJECT_TYPE enmSynchType, HVBOXUHGSMI_SYNCHOBJECT hSynch,
267 PVBOXUHGSMI_BUFFER* ppBuf)
268{
269 bool bSynchCreated = false;
270 if (!cbBuf)
271 return VERR_INVALID_PARAMETER;
272
273 int rc = vboxUhgsmiBaseEventChkCreate(enmSynchType, &hSynch, &bSynchCreated);
274 AssertRC(rc);
275 if (RT_FAILURE(rc))
276 return rc;
277
278 cbBuf = VBOXWDDM_ROUNDBOUND(cbBuf, 0x1000);
279 Assert(cbBuf);
280 uint32_t cPages = cbBuf >> 12;
281 Assert(cPages);
282
283 PVBOXUHGSMI_PRIVATE_KMT pPrivate = VBOXUHGSMIKMT_GET(pHgsmi);
284 PVBOXUHGSMI_BUFFER_PRIVATE_KMT_ESC pBuf = (PVBOXUHGSMI_BUFFER_PRIVATE_KMT_ESC)RTMemAllocZ(RT_OFFSETOF(VBOXUHGSMI_BUFFER_PRIVATE_KMT, aLockPageIndices[cPages]));
285 Assert(pBuf);
286 if (pBuf)
287 {
288 struct
289 {
290 D3DKMT_ESCAPE DdiEscape;
291 VBOXDISPIFESCAPE_UHGSMI_ALLOCATE AllocInfo;
292 } Buf;
293 memset(&Buf, 0, sizeof (Buf));
294 Buf.DdiEscape.hAdapter = pPrivate->Adapter.hAdapter;
295 Buf.DdiEscape.hDevice = pPrivate->Device.hDevice;
296 Buf.DdiEscape.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
297 //Buf.DdiEscape.Flags.HardwareAccess = 1;
298 Buf.DdiEscape.pPrivateDriverData = &Buf.AllocInfo;
299 Buf.DdiEscape.PrivateDriverDataSize = sizeof (Buf.AllocInfo);
300 Buf.DdiEscape.hContext = pPrivate->Context.hContext;
301
302 Buf.AllocInfo.EscapeHdr.escapeCode = VBOXESC_UHGSMI_ALLOCATE;
303 Buf.AllocInfo.Alloc.cbData = cbBuf;
304 Buf.AllocInfo.Alloc.hSynch = hSynch;
305 Buf.AllocInfo.Alloc.enmSynchType = enmSynchType;
306
307 HRESULT hr = pPrivate->Callbacks.pfnD3DKMTEscape(&Buf.DdiEscape);
308 Assert(hr == S_OK);
309 if (hr == S_OK)
310 {
311 pBuf->Alloc = Buf.AllocInfo.Alloc;
312 Assert(pBuf->Alloc.pvData);
313 pBuf->pHgsmi = pPrivate;
314 pBuf->Base.pfnLock = vboxUhgsmiKmtEscBufferLock;
315 pBuf->Base.pfnUnlock = vboxUhgsmiKmtEscBufferUnlock;
316// pBuf->Base.pfnAdjustValidDataRange = vboxUhgsmiKmtBufferAdjustValidDataRange;
317 pBuf->Base.pfnDestroy = vboxUhgsmiKmtEscBufferDestroy;
318
319 pBuf->Base.hSynch = hSynch;
320 pBuf->Base.enmSynchType = enmSynchType;
321 pBuf->Base.cbBuffer = Buf.AllocInfo.Alloc.cbData;
322 pBuf->Base.bSynchCreated = bSynchCreated;
323
324 *ppBuf = &pBuf->Base;
325
326 return VINF_SUCCESS;
327 }
328
329 RTMemFree(pBuf);
330 }
331 else
332 rc = VERR_NO_MEMORY;
333
334 if (bSynchCreated)
335 CloseHandle(hSynch);
336
337 return rc;
338}
339
340DECLCALLBACK(int) vboxUhgsmiKmtEscBufferSubmitAsynch(PVBOXUHGSMI pHgsmi, PVBOXUHGSMI_BUFFER_SUBMIT aBuffers, uint32_t cBuffers)
341{
342 /* we no chromium will not submit more than three buffers actually,
343 * for simplicity allocate it statically on the stack */
344 struct
345 {
346 VBOXDISPIFESCAPE_UHGSMI_SUBMIT SubmitInfo;
347 VBOXWDDM_UHGSMI_BUFFER_UI_INFO_ESCAPE aBufInfos[3];
348 } Buf;
349
350 if (cBuffers > RT_ELEMENTS(Buf.aBufInfos) + 1)
351 {
352 Assert(0);
353 return VERR_INVALID_PARAMETER;
354 }
355
356
357 PVBOXUHGSMI_PRIVATE_KMT pPrivate = VBOXUHGSMIKMT_GET(pHgsmi);
358 D3DKMT_ESCAPE DdiEscape = {0};
359
360 DdiEscape.hAdapter = pPrivate->Adapter.hAdapter;
361 DdiEscape.hDevice = pPrivate->Device.hDevice;
362 DdiEscape.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
363 //Buf.DdiEscape.Flags.HardwareAccess = 1;
364 DdiEscape.pPrivateDriverData = &Buf.SubmitInfo;
365 DdiEscape.PrivateDriverDataSize = RT_OFFSETOF(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[cBuffers]);
366 DdiEscape.hContext = pPrivate->Context.hContext;
367
368 Buf.SubmitInfo.EscapeHdr.escapeCode = VBOXESC_UHGSMI_SUBMIT;
369 Buf.SubmitInfo.EscapeHdr.u32CmdSpecific = cBuffers;
370 for (UINT i = 0; i < cBuffers; ++i)
371 {
372 VBOXWDDM_UHGSMI_BUFFER_UI_INFO_ESCAPE *pSubmInfo = &Buf.SubmitInfo.aBuffers[i];
373 PVBOXUHGSMI_BUFFER_SUBMIT pBufInfo = &aBuffers[i];
374 PVBOXUHGSMI_BUFFER_PRIVATE_KMT_ESC pBuf = VBOXUHGSMIKMTESC_GET_BUFFER(pBufInfo->pBuf);
375 pSubmInfo->hAlloc = pBuf->Alloc.hAlloc;
376 pSubmInfo->Info.fSubFlags = pBufInfo->fFlags;
377 if (pBufInfo->fFlags.bEntireBuffer)
378 {
379 pSubmInfo->Info.offData = 0;
380 pSubmInfo->Info.cbData = pBuf->Base.cbBuffer;
381 }
382 else
383 {
384 pSubmInfo->Info.offData = pBufInfo->offData;
385 pSubmInfo->Info.cbData = pBufInfo->cbData;
386 }
387 }
388
389 HRESULT hr = pPrivate->Callbacks.pfnD3DKMTEscape(&DdiEscape);
390 Assert(hr == S_OK);
391 if (hr == S_OK)
392 {
393 return VINF_SUCCESS;
394 }
395
396 return VERR_GENERAL_FAILURE;
397}
398
399static HRESULT vboxUhgsmiKmtEngineCreate(PVBOXUHGSMI_PRIVATE_KMT pHgsmi, BOOL bD3D)
400{
401 HRESULT hr = vboxDispKmtCallbacksInit(&pHgsmi->Callbacks);
402 Assert(hr == S_OK);
403 if (hr == S_OK)
404 {
405 hr = vboxDispKmtOpenAdapter(&pHgsmi->Callbacks, &pHgsmi->Adapter);
406 Assert(hr == S_OK);
407 if (hr == S_OK)
408 {
409 hr = vboxDispKmtCreateDevice(&pHgsmi->Adapter, &pHgsmi->Device);
410 Assert(hr == S_OK);
411 if (hr == S_OK)
412 {
413 hr = vboxDispKmtCreateContext(&pHgsmi->Device, &pHgsmi->Context, bD3D);
414 Assert(hr == S_OK);
415 if (hr == S_OK)
416 {
417 return S_OK;
418 }
419 vboxDispKmtDestroyDevice(&pHgsmi->Device);
420 }
421 vboxDispKmtCloseAdapter(&pHgsmi->Adapter);
422 }
423 vboxDispKmtCallbacksTerm(&pHgsmi->Callbacks);
424 }
425 return hr;
426}
427HRESULT vboxUhgsmiKmtCreate(PVBOXUHGSMI_PRIVATE_KMT pHgsmi, BOOL bD3D)
428{
429 pHgsmi->BasePrivate.Base.pfnBufferCreate = vboxUhgsmiKmtBufferCreate;
430 pHgsmi->BasePrivate.Base.pfnBufferSubmitAsynch = vboxUhgsmiKmtBufferSubmitAsynch;
431 pHgsmi->BasePrivate.hClient = NULL;
432 return vboxUhgsmiKmtEngineCreate(pHgsmi, bD3D);
433}
434
435HRESULT vboxUhgsmiKmtEscCreate(PVBOXUHGSMI_PRIVATE_KMT pHgsmi, BOOL bD3D)
436{
437 pHgsmi->BasePrivate.Base.pfnBufferCreate = vboxUhgsmiKmtEscBufferCreate;
438 pHgsmi->BasePrivate.Base.pfnBufferSubmitAsynch = vboxUhgsmiKmtEscBufferSubmitAsynch;
439 pHgsmi->BasePrivate.hClient = NULL;
440 return vboxUhgsmiKmtEngineCreate(pHgsmi, bD3D);
441}
442
443HRESULT vboxUhgsmiKmtDestroy(PVBOXUHGSMI_PRIVATE_KMT pHgsmi)
444{
445 Assert(0);
446 HRESULT hr = vboxDispKmtDestroyContext(&pHgsmi->Context);
447 Assert(hr == S_OK);
448 if (hr == S_OK)
449 {
450 hr = vboxDispKmtDestroyDevice(&pHgsmi->Device);
451 Assert(hr == S_OK);
452 if (hr == S_OK)
453 {
454 hr = vboxDispKmtCloseAdapter(&pHgsmi->Adapter);
455 Assert(hr == S_OK);
456 if (hr == S_OK)
457 {
458 hr = vboxDispKmtCallbacksTerm(&pHgsmi->Callbacks);
459 Assert(hr == S_OK);
460 if (hr == S_OK)
461 return S_OK;
462 }
463 }
464 }
465 return hr;
466}
467
468HRESULT vboxDispKmtCallbacksInit(PVBOXDISPKMT_CALLBACKS pCallbacks)
469{
470 HRESULT hr = S_OK;
471
472 memset(pCallbacks, 0, sizeof (*pCallbacks));
473
474 pCallbacks->hGdi32 = LoadLibraryW(L"gdi32.dll");
475 if (pCallbacks->hGdi32 != NULL)
476 {
477 bool bSupported = true;
478 pCallbacks->pfnD3DKMTOpenAdapterFromHdc = (PFND3DKMT_OPENADAPTERFROMHDC)GetProcAddress(pCallbacks->hGdi32, "D3DKMTOpenAdapterFromHdc");
479 Log((__FUNCTION__"pfnD3DKMTOpenAdapterFromHdc = %p\n", pCallbacks->pfnD3DKMTOpenAdapterFromHdc));
480 bSupported &= !!(pCallbacks->pfnD3DKMTOpenAdapterFromHdc);
481
482 pCallbacks->pfnD3DKMTOpenAdapterFromGdiDisplayName = (PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME)GetProcAddress(pCallbacks->hGdi32, "D3DKMTOpenAdapterFromGdiDisplayName");
483 Log((__FUNCTION__": pfnD3DKMTOpenAdapterFromGdiDisplayName = %p\n", pCallbacks->pfnD3DKMTOpenAdapterFromGdiDisplayName));
484 bSupported &= !!(pCallbacks->pfnD3DKMTOpenAdapterFromGdiDisplayName);
485
486 pCallbacks->pfnD3DKMTCloseAdapter = (PFND3DKMT_CLOSEADAPTER)GetProcAddress(pCallbacks->hGdi32, "D3DKMTCloseAdapter");
487 Log((__FUNCTION__": pfnD3DKMTCloseAdapter = %p\n", pCallbacks->pfnD3DKMTCloseAdapter));
488 bSupported &= !!(pCallbacks->pfnD3DKMTCloseAdapter);
489
490 pCallbacks->pfnD3DKMTEscape = (PFND3DKMT_ESCAPE)GetProcAddress(pCallbacks->hGdi32, "D3DKMTEscape");
491 Log((__FUNCTION__": pfnD3DKMTEscape = %p\n", pCallbacks->pfnD3DKMTEscape));
492 bSupported &= !!(pCallbacks->pfnD3DKMTEscape);
493
494 pCallbacks->pfnD3DKMTCreateDevice = (PFND3DKMT_CREATEDEVICE)GetProcAddress(pCallbacks->hGdi32, "D3DKMTCreateDevice");
495 Log((__FUNCTION__": pfnD3DKMTCreateDevice = %p\n", pCallbacks->pfnD3DKMTCreateDevice));
496 bSupported &= !!(pCallbacks->pfnD3DKMTCreateDevice);
497
498 pCallbacks->pfnD3DKMTDestroyDevice = (PFND3DKMT_DESTROYDEVICE)GetProcAddress(pCallbacks->hGdi32, "D3DKMTDestroyDevice");
499 Log((__FUNCTION__": pfnD3DKMTDestroyDevice = %p\n", pCallbacks->pfnD3DKMTDestroyDevice));
500 bSupported &= !!(pCallbacks->pfnD3DKMTDestroyDevice);
501
502 pCallbacks->pfnD3DKMTCreateContext = (PFND3DKMT_CREATECONTEXT)GetProcAddress(pCallbacks->hGdi32, "D3DKMTCreateContext");
503 Log((__FUNCTION__": pfnD3DKMTCreateContext = %p\n", pCallbacks->pfnD3DKMTCreateContext));
504 bSupported &= !!(pCallbacks->pfnD3DKMTCreateContext);
505
506 pCallbacks->pfnD3DKMTDestroyContext = (PFND3DKMT_DESTROYCONTEXT)GetProcAddress(pCallbacks->hGdi32, "D3DKMTDestroyContext");
507 Log((__FUNCTION__": pfnD3DKMTDestroyContext = %p\n", pCallbacks->pfnD3DKMTDestroyContext));
508 bSupported &= !!(pCallbacks->pfnD3DKMTDestroyContext);
509
510 pCallbacks->pfnD3DKMTRender = (PFND3DKMT_RENDER)GetProcAddress(pCallbacks->hGdi32, "D3DKMTRender");
511 Log((__FUNCTION__": pfnD3DKMTRender = %p\n", pCallbacks->pfnD3DKMTRender));
512 bSupported &= !!(pCallbacks->pfnD3DKMTRender);
513
514 pCallbacks->pfnD3DKMTCreateAllocation = (PFND3DKMT_CREATEALLOCATION)GetProcAddress(pCallbacks->hGdi32, "D3DKMTCreateAllocation");
515 Log((__FUNCTION__": pfnD3DKMTCreateAllocation = %p\n", pCallbacks->pfnD3DKMTCreateAllocation));
516 bSupported &= !!(pCallbacks->pfnD3DKMTCreateAllocation);
517
518 pCallbacks->pfnD3DKMTDestroyAllocation = (PFND3DKMT_DESTROYALLOCATION)GetProcAddress(pCallbacks->hGdi32, "D3DKMTDestroyAllocation");
519 Log((__FUNCTION__": pfnD3DKMTDestroyAllocation = %p\n", pCallbacks->pfnD3DKMTDestroyAllocation));
520 bSupported &= !!(pCallbacks->pfnD3DKMTDestroyAllocation);
521
522 pCallbacks->pfnD3DKMTLock = (PFND3DKMT_LOCK)GetProcAddress(pCallbacks->hGdi32, "D3DKMTLock");
523 Log((__FUNCTION__": pfnD3DKMTLock = %p\n", pCallbacks->pfnD3DKMTLock));
524 bSupported &= !!(pCallbacks->pfnD3DKMTLock);
525
526 pCallbacks->pfnD3DKMTUnlock = (PFND3DKMT_UNLOCK)GetProcAddress(pCallbacks->hGdi32, "D3DKMTUnlock");
527 Log((__FUNCTION__": pfnD3DKMTUnlock = %p\n", pCallbacks->pfnD3DKMTUnlock));
528 bSupported &= !!(pCallbacks->pfnD3DKMTUnlock);
529
530 Assert(bSupported);
531 if (bSupported)
532 {
533 return S_OK;
534 }
535 else
536 {
537 Log((__FUNCTION__": one of pfnD3DKMT function pointers failed to initialize\n"));
538 hr = E_NOINTERFACE;
539 }
540
541 FreeLibrary(pCallbacks->hGdi32);
542 }
543 else
544 {
545 DWORD winEr = GetLastError();
546 hr = HRESULT_FROM_WIN32(winEr);
547 Assert(0);
548 Assert(hr != S_OK);
549 Assert(hr != S_FALSE);
550 if (hr == S_OK || hr == S_FALSE)
551 hr = E_FAIL;
552 }
553
554 return hr;
555}
556
557HRESULT vboxDispKmtCallbacksTerm(PVBOXDISPKMT_CALLBACKS pCallbacks)
558{
559 FreeLibrary(pCallbacks->hGdi32);
560 return S_OK;
561}
562
563HRESULT vboxDispKmtOpenAdapter(PVBOXDISPKMT_CALLBACKS pCallbacks, PVBOXDISPKMT_ADAPTER pAdapter)
564{
565 D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME OpenAdapterData = {0};
566 wcsncpy(OpenAdapterData.DeviceName, L"\\\\.\\DISPLAY1", RT_ELEMENTS(OpenAdapterData.DeviceName) - 1 /* the last one is always \0 */);
567 HRESULT hr = S_OK;
568 NTSTATUS Status = pCallbacks->pfnD3DKMTOpenAdapterFromGdiDisplayName(&OpenAdapterData);
569 Assert(!Status);
570 if (!Status)
571 {
572 pAdapter->hAdapter = OpenAdapterData.hAdapter;
573 pAdapter->pCallbacks = pCallbacks;
574 return S_OK;
575 }
576 else
577 {
578 Log((__FUNCTION__": pfnD3DKMTOpenAdapterFromGdiDisplayName failed, Status (0x%x)\n", Status));
579 hr = E_FAIL;
580 }
581
582 return hr;
583
584}
585
586HRESULT vboxDispKmtCloseAdapter(PVBOXDISPKMT_ADAPTER pAdapter)
587{
588 D3DKMT_CLOSEADAPTER ClosaAdapterData = {0};
589 ClosaAdapterData.hAdapter = pAdapter->hAdapter;
590 NTSTATUS Status = pAdapter->pCallbacks->pfnD3DKMTCloseAdapter(&ClosaAdapterData);
591 Assert(!Status);
592 if (!Status)
593 {
594 return S_OK;
595 }
596
597 Log((__FUNCTION__": pfnD3DKMTCloseAdapter failed, Status (0x%x)\n", Status));
598 /* ignore */
599 Status = 0;
600 return E_FAIL;
601}
602
603HRESULT vboxDispKmtCreateDevice(PVBOXDISPKMT_ADAPTER pAdapter, PVBOXDISPKMT_DEVICE pDevice)
604{
605 D3DKMT_CREATEDEVICE CreateDeviceData = {0};
606 CreateDeviceData.hAdapter = pAdapter->hAdapter;
607 NTSTATUS Status = pAdapter->pCallbacks->pfnD3DKMTCreateDevice(&CreateDeviceData);
608 Assert(!Status);
609 if (!Status)
610 {
611 pDevice->pAdapter = pAdapter;
612 pDevice->hDevice = CreateDeviceData.hDevice;
613 pDevice->pCommandBuffer = CreateDeviceData.pCommandBuffer;
614 pDevice->CommandBufferSize = CreateDeviceData.CommandBufferSize;
615 pDevice->pAllocationList = CreateDeviceData.pAllocationList;
616 pDevice->AllocationListSize = CreateDeviceData.AllocationListSize;
617 pDevice->pPatchLocationList = CreateDeviceData.pPatchLocationList;
618 pDevice->PatchLocationListSize = CreateDeviceData.PatchLocationListSize;
619
620 return S_OK;
621 }
622
623 return E_FAIL;
624}
625
626HRESULT vboxDispKmtDestroyDevice(PVBOXDISPKMT_DEVICE pDevice)
627{
628 D3DKMT_DESTROYDEVICE DestroyDeviceData = {0};
629 DestroyDeviceData.hDevice = pDevice->hDevice;
630 NTSTATUS Status = pDevice->pAdapter->pCallbacks->pfnD3DKMTDestroyDevice(&DestroyDeviceData);
631 Assert(!Status);
632 if (!Status)
633 {
634 return S_OK;
635 }
636 return E_FAIL;
637}
638
639HRESULT vboxDispKmtCreateContext(PVBOXDISPKMT_DEVICE pDevice, PVBOXDISPKMT_CONTEXT pContext, BOOL bD3D)
640{
641 VBOXWDDM_CREATECONTEXT_INFO Info = {0};
642 Info.u32IfVersion = 9;
643 Info.enmType = bD3D ? VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_3D : VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL;
644 D3DKMT_CREATECONTEXT ContextData = {0};
645 ContextData.hDevice = pDevice->hDevice;
646 ContextData.NodeOrdinal = 0;
647 ContextData.EngineAffinity = 0;
648 ContextData.pPrivateDriverData = &Info;
649 ContextData.PrivateDriverDataSize = sizeof (Info);
650 ContextData.ClientHint = bD3D ? D3DKMT_CLIENTHINT_DX9 : D3DKMT_CLIENTHINT_OPENGL;
651 NTSTATUS Status = pDevice->pAdapter->pCallbacks->pfnD3DKMTCreateContext(&ContextData);
652 Assert(!Status);
653 if (!Status)
654 {
655 pContext->pDevice = pDevice;
656 pContext->hContext = ContextData.hContext;
657 pContext->pCommandBuffer = ContextData.pCommandBuffer;
658 pContext->CommandBufferSize = ContextData.CommandBufferSize;
659 pContext->pAllocationList = ContextData.pAllocationList;
660 pContext->AllocationListSize = ContextData.AllocationListSize;
661 pContext->pPatchLocationList = ContextData.pPatchLocationList;
662 pContext->PatchLocationListSize = ContextData.PatchLocationListSize;
663 return S_OK;
664 }
665 return E_FAIL;
666}
667
668HRESULT vboxDispKmtDestroyContext(PVBOXDISPKMT_CONTEXT pContext)
669{
670 D3DKMT_DESTROYCONTEXT DestroyContextData = {0};
671 DestroyContextData.hContext = pContext->hContext;
672 NTSTATUS Status = pContext->pDevice->pAdapter->pCallbacks->pfnD3DKMTDestroyContext(&DestroyContextData);
673 Assert(!Status);
674 if (!Status)
675 return S_OK;
676 return E_FAIL;
677}
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