VirtualBox

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

Last change on this file since 76376 was 76376, checked in by vboxsync, 6 years ago

VBoxUhgsmi.h: GCC doesn't like unnamed sub-structures in C++ code, so ditched them for VBOXUHGSMI_BUFFER_TYPE_FLAGS, VBOXUHGSMI_BUFFER_LOCK_FLAGS and VBOXUHGSMI_BUFFER_SUBMIT_FLAGS. Also skipped the outer wrapper structures for each of these types as all it contained was an unnamed union, so just make the typedefs unions straight away. Fixed some hungarian inconsistency between the three types ('b' == byte, not boolean in VBox, don't forget).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.3 KB
Line 
1/* $Id: VBoxUhgsmiKmt.cpp 76376 2018-12-22 22:32:24Z vboxsync $ */
2/** @file
3 * VBoxVideo Display D3D User mode dll
4 */
5
6/*
7 * Copyright (C) 2011-2017 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 "VBoxDispD3DCmn.h"
19
20#include <iprt/mem.h>
21#include <iprt/err.h>
22
23#include <cr_protocol.h>
24
25#ifndef NT_SUCCESS
26# define NT_SUCCESS(_Status) (((NTSTATUS)(_Status)) >= 0)
27#endif
28
29
30DECLCALLBACK(int) vboxUhgsmiKmtBufferDestroy(PVBOXUHGSMI_BUFFER pBuf)
31{
32 PVBOXUHGSMI_BUFFER_PRIVATE_DX_ALLOC_BASE pBuffer = VBOXUHGSMDXALLOCBASE_GET_BUFFER(pBuf);
33 PVBOXUHGSMI_PRIVATE_KMT pPrivate = VBOXUHGSMIKMT_GET(pBuffer->BasePrivate.pHgsmi);
34
35 D3DKMT_DESTROYALLOCATION DdiDealloc;
36 DdiDealloc.hDevice = pPrivate->Device.hDevice;
37 DdiDealloc.hResource = NULL;
38 DdiDealloc.phAllocationList = &pBuffer->hAllocation;
39 DdiDealloc.AllocationCount = 1;
40 NTSTATUS Status = pPrivate->Callbacks.pfnD3DKMTDestroyAllocation(&DdiDealloc);
41 if (NT_SUCCESS(Status))
42 {
43#ifdef DEBUG_misha
44 memset(pBuffer, 0, sizeof(*pBuffer));
45#endif
46 RTMemFree(pBuffer);
47 return VINF_SUCCESS;
48 }
49 else
50 {
51 WARN(("pfnD3DKMTDestroyAllocation failed, Status (0x%x)", Status));
52 }
53 return VERR_GENERAL_FAILURE;
54}
55
56DECLCALLBACK(int) vboxUhgsmiKmtBufferLock(PVBOXUHGSMI_BUFFER pBuf, uint32_t offLock, uint32_t cbLock,
57 VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags, void**pvLock)
58{
59 PVBOXUHGSMI_BUFFER_PRIVATE_DX_ALLOC_BASE pBuffer = VBOXUHGSMDXALLOCBASE_GET_BUFFER(pBuf);
60 PVBOXUHGSMI_PRIVATE_KMT pPrivate = VBOXUHGSMIKMT_GET(pBuffer->BasePrivate.pHgsmi);
61 D3DKMT_LOCK DdiLock = {0};
62 DdiLock.hDevice = pPrivate->Device.hDevice;
63 DdiLock.hAllocation = pBuffer->hAllocation;
64 DdiLock.PrivateDriverData = NULL;
65
66 int rc = vboxUhgsmiBaseDxLockData(pBuffer, offLock, cbLock, fFlags,
67 &DdiLock.Flags, &DdiLock.NumPages);
68 if (!RT_SUCCESS(rc))
69 {
70 WARN(("vboxUhgsmiBaseDxLockData failed rc %d", rc));
71 return rc;
72 }
73
74
75 if (DdiLock.NumPages)
76 DdiLock.pPages = pBuffer->aLockPageIndices;
77 else
78 DdiLock.pPages = NULL;
79
80 NTSTATUS Status = pPrivate->Callbacks.pfnD3DKMTLock(&DdiLock);
81 if (NT_SUCCESS(Status))
82 {
83 *pvLock = (void*)(((uint8_t*)DdiLock.pData) + (offLock & 0xfff));
84 return VINF_SUCCESS;
85 }
86 else
87 {
88 WARN(("pfnD3DKMTLock failed, Status (0x%x)", Status));
89 }
90
91 return VERR_GENERAL_FAILURE;
92}
93
94DECLCALLBACK(int) vboxUhgsmiKmtBufferUnlock(PVBOXUHGSMI_BUFFER pBuf)
95{
96 PVBOXUHGSMI_BUFFER_PRIVATE_DX_ALLOC_BASE pBuffer = VBOXUHGSMDXALLOCBASE_GET_BUFFER(pBuf);
97 D3DKMT_UNLOCK DdiUnlock;
98
99 PVBOXUHGSMI_PRIVATE_KMT pPrivate = VBOXUHGSMIKMT_GET(pBuffer->BasePrivate.pHgsmi);
100 DdiUnlock.hDevice = pPrivate->Device.hDevice;
101 DdiUnlock.NumAllocations = 1;
102 DdiUnlock.phAllocations = &pBuffer->hAllocation;
103 NTSTATUS Status = pPrivate->Callbacks.pfnD3DKMTUnlock(&DdiUnlock);
104 if (NT_SUCCESS(Status))
105 return VINF_SUCCESS;
106 else
107 WARN(("pfnD3DKMTUnlock failed, Status (0x%x)", Status));
108
109 return VERR_GENERAL_FAILURE;
110}
111
112DECLCALLBACK(int) vboxUhgsmiKmtBufferCreate(PVBOXUHGSMI pHgsmi, uint32_t cbBuf, VBOXUHGSMI_BUFFER_TYPE_FLAGS fType, PVBOXUHGSMI_BUFFER* ppBuf)
113{
114 if (!cbBuf)
115 return VERR_INVALID_PARAMETER;
116
117 int rc = VINF_SUCCESS;
118
119 cbBuf = VBOXWDDM_ROUNDBOUND(cbBuf, 0x1000);
120 Assert(cbBuf);
121 uint32_t cPages = cbBuf >> 12;
122 Assert(cPages);
123
124 PVBOXUHGSMI_PRIVATE_KMT pPrivate = VBOXUHGSMIKMT_GET(pHgsmi);
125 PVBOXUHGSMI_BUFFER_PRIVATE_DX_ALLOC_BASE pBuf;
126 pBuf = (PVBOXUHGSMI_BUFFER_PRIVATE_DX_ALLOC_BASE)RTMemAllocZ(RT_UOFFSETOF_DYN(VBOXUHGSMI_BUFFER_PRIVATE_DX_ALLOC_BASE,
127 aLockPageIndices[cPages]));
128 if (!pBuf)
129 {
130 WARN(("RTMemAllocZ failed"));
131 return VERR_NO_MEMORY;
132 }
133
134 D3DKMT_CREATEALLOCATION DdiAlloc;
135 D3DDDI_ALLOCATIONINFO DdiAllocInfo;
136 VBOXWDDM_ALLOCINFO AllocInfo;
137
138 memset(&DdiAlloc, 0, sizeof (DdiAlloc));
139 DdiAlloc.hDevice = pPrivate->Device.hDevice;
140 DdiAlloc.NumAllocations = 1;
141 DdiAlloc.pAllocationInfo = &DdiAllocInfo;
142
143 vboxUhgsmiBaseDxAllocInfoFill(&DdiAllocInfo, &AllocInfo, cbBuf, fType);
144
145 NTSTATUS Status = pPrivate->Callbacks.pfnD3DKMTCreateAllocation(&DdiAlloc);
146 if (NT_SUCCESS(Status))
147 {
148 Assert(DdiAllocInfo.hAllocation);
149 pBuf->BasePrivate.Base.pfnLock = vboxUhgsmiKmtBufferLock;
150 pBuf->BasePrivate.Base.pfnUnlock = vboxUhgsmiKmtBufferUnlock;
151 pBuf->BasePrivate.Base.pfnDestroy = vboxUhgsmiKmtBufferDestroy;
152
153 pBuf->BasePrivate.Base.fType = fType;
154 pBuf->BasePrivate.Base.cbBuffer = cbBuf;
155
156 pBuf->BasePrivate.pHgsmi = &pPrivate->BasePrivate;
157
158 pBuf->hAllocation = DdiAllocInfo.hAllocation;
159
160
161 *ppBuf = &pBuf->BasePrivate.Base;
162
163 return VINF_SUCCESS;
164 }
165 else
166 {
167 WARN(("pfnD3DKMTCreateAllocation failes, Status(0x%x)", Status));
168 rc = VERR_OUT_OF_RESOURCES;
169 }
170
171 RTMemFree(pBuf);
172
173 return rc;
174}
175
176DECLCALLBACK(int) vboxUhgsmiKmtBufferSubmit(PVBOXUHGSMI pHgsmi, PVBOXUHGSMI_BUFFER_SUBMIT aBuffers, uint32_t cBuffers)
177{
178 PVBOXUHGSMI_PRIVATE_KMT pHg = VBOXUHGSMIKMT_GET(pHgsmi);
179 UINT cbDmaCmd = pHg->Context.CommandBufferSize;
180 int rc = vboxUhgsmiBaseDxDmaFill(aBuffers, cBuffers,
181 pHg->Context.pCommandBuffer, &cbDmaCmd,
182 pHg->Context.pAllocationList, pHg->Context.AllocationListSize,
183 pHg->Context.pPatchLocationList, pHg->Context.PatchLocationListSize);
184 if (RT_FAILURE(rc))
185 {
186 WARN(("vboxUhgsmiBaseDxDmaFill failed, rc %d", rc));
187 return rc;
188 }
189
190 D3DKMT_RENDER DdiRender = {0};
191 DdiRender.hContext = pHg->Context.hContext;
192 DdiRender.CommandLength = cbDmaCmd;
193 DdiRender.AllocationCount = cBuffers;
194 Assert(DdiRender.CommandLength);
195 Assert(DdiRender.CommandLength < UINT32_MAX/2);
196
197 NTSTATUS Status = pHg->Callbacks.pfnD3DKMTRender(&DdiRender);
198 if (NT_SUCCESS(Status))
199 {
200 pHg->Context.CommandBufferSize = DdiRender.NewCommandBufferSize;
201 pHg->Context.pCommandBuffer = DdiRender.pNewCommandBuffer;
202 pHg->Context.AllocationListSize = DdiRender.NewAllocationListSize;
203 pHg->Context.pAllocationList = DdiRender.pNewAllocationList;
204 pHg->Context.PatchLocationListSize = DdiRender.NewPatchLocationListSize;
205 pHg->Context.pPatchLocationList = DdiRender.pNewPatchLocationList;
206
207 return VINF_SUCCESS;
208 }
209 else
210 {
211 WARN(("pfnD3DKMTRender failed, Status (0x%x)", Status));
212 }
213
214 return VERR_GENERAL_FAILURE;
215}
216
217
218static HRESULT vboxUhgsmiKmtEngineCreate(PVBOXUHGSMI_PRIVATE_KMT pHgsmi, BOOL bD3D)
219{
220 HRESULT hr = vboxDispKmtCallbacksInit(&pHgsmi->Callbacks);
221 if (hr == S_OK)
222 {
223 hr = vboxDispKmtOpenAdapter(&pHgsmi->Callbacks, &pHgsmi->Adapter);
224 if (hr == S_OK)
225 {
226 hr = vboxDispKmtCreateDevice(&pHgsmi->Adapter, &pHgsmi->Device);
227 if (hr == S_OK)
228 {
229 hr = vboxDispKmtCreateContext(&pHgsmi->Device, &pHgsmi->Context,
230 bD3D ? VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_3D : VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL,
231 CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR,
232 NULL, 0);
233 if (hr == S_OK)
234 {
235 return S_OK;
236 }
237 else
238 {
239 WARN(("vboxDispKmtCreateContext failed, hr(0x%x)", hr));
240 }
241 vboxDispKmtDestroyDevice(&pHgsmi->Device);
242 }
243 else
244 {
245 WARN(("vboxDispKmtCreateDevice failed, hr(0x%x)", hr));
246 }
247 vboxDispKmtCloseAdapter(&pHgsmi->Adapter);
248 }
249 else
250 {
251// WARN(("vboxDispKmtOpenAdapter failed, hr(0x%x)", hr));
252 }
253
254 vboxDispKmtCallbacksTerm(&pHgsmi->Callbacks);
255 }
256 else
257 {
258 WARN(("vboxDispKmtCallbacksInit failed, hr(0x%x)", hr));
259 }
260 return hr;
261}
262
263static DECLCALLBACK(int) vboxCrHhgsmiKmtEscape(struct VBOXUHGSMI_PRIVATE_BASE *pHgsmi, void *pvData, uint32_t cbData, BOOL fHwAccess)
264{
265 PVBOXUHGSMI_PRIVATE_KMT pPrivate = VBOXUHGSMIKMT_GET(pHgsmi);
266 D3DKMT_ESCAPE DdiEscape = {0};
267 DdiEscape.hAdapter = pPrivate->Adapter.hAdapter;
268 DdiEscape.hDevice = pPrivate->Device.hDevice;
269 DdiEscape.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
270 DdiEscape.Flags.HardwareAccess = !!fHwAccess;
271 DdiEscape.pPrivateDriverData = pvData;
272 DdiEscape.PrivateDriverDataSize = cbData;
273 DdiEscape.hContext = pPrivate->Context.hContext;
274
275 NTSTATUS Status = pPrivate->Callbacks.pfnD3DKMTEscape(&DdiEscape);
276 if (NT_SUCCESS(Status))
277 {
278 return VINF_SUCCESS;
279 }
280
281 WARN(("pfnD3DKMTEscape failed, Status (0x%x)", Status));
282 return VERR_GENERAL_FAILURE;
283}
284
285static void vboxUhgsmiKmtSetupCallbacks(PVBOXUHGSMI_PRIVATE_KMT pHgsmi)
286{
287 pHgsmi->BasePrivate.Base.pfnBufferCreate = vboxUhgsmiKmtBufferCreate;
288 pHgsmi->BasePrivate.Base.pfnBufferSubmit = vboxUhgsmiKmtBufferSubmit;
289 /* escape is still needed, since Ugfsmi uses it e.g. to query connection id */
290 pHgsmi->BasePrivate.pfnEscape = vboxCrHhgsmiKmtEscape;
291}
292
293static void vboxUhgsmiKmtEscSetupCallbacks(PVBOXUHGSMI_PRIVATE_KMT pHgsmi)
294{
295 vboxUhgsmiBaseInit(&pHgsmi->BasePrivate, vboxCrHhgsmiKmtEscape);
296}
297
298#if 0
299HRESULT vboxUhgsmiKmtCreate(PVBOXUHGSMI_PRIVATE_KMT pHgsmi, BOOL bD3D)
300{
301 vboxUhgsmiKmtSetupCallbacks(pHgsmi);
302 return vboxUhgsmiKmtEngineCreate(pHgsmi, bD3D);
303}
304
305HRESULT vboxUhgsmiKmtEscCreate(PVBOXUHGSMI_PRIVATE_KMT pHgsmi, BOOL bD3D)
306{
307 vboxUhgsmiKmtEscSetupCallbacks(pHgsmi);
308 return vboxUhgsmiKmtEngineCreate(pHgsmi, bD3D);
309}
310#endif
311
312static HRESULT vboxUhgsmiKmtQueryCaps(PVBOXUHGSMI_PRIVATE_KMT pHgsmi, uint32_t *pu32Caps)
313{
314 VBOXWDDM_QAI Query;
315 D3DKMT_QUERYADAPTERINFO Info;
316 Info.hAdapter = pHgsmi->Adapter.hAdapter;
317 Info.Type = KMTQAITYPE_UMDRIVERPRIVATE;
318 Info.pPrivateDriverData = &Query;
319 Info.PrivateDriverDataSize = sizeof (Query);
320
321 NTSTATUS Status = pHgsmi->Callbacks.pfnD3DKMTQueryAdapterInfo(&Info);
322 if (!NT_SUCCESS(Status))
323 {
324 WARN(("pfnD3DKMTQueryAdapterInfo failed, Status %#x", Status));
325 return Status;
326 }
327
328 if (Query.u32Version != VBOXVIDEOIF_VERSION)
329 {
330 WARN(("Version mismatch"));
331 return E_FAIL;
332 }
333
334 if (Query.enmHwType == VBOXVIDEO_HWTYPE_VBOX)
335 *pu32Caps = Query.u.vbox.u32VBox3DCaps;
336#ifdef VBOX_WITH_MESA3D
337 /** @todo Remove the hack. u32VBox3DCaps should not be used with Gallium. */
338 else if (Query.enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
339 *pu32Caps = CR_VBOX_CAP_TEX_PRESENT | CR_VBOX_CAP_CMDVBVA;
340#endif
341 else
342 *pu32Caps = 0;
343
344 return S_OK;
345}
346
347HRESULT vboxUhgsmiKmtCreate(PVBOXUHGSMI_PRIVATE_KMT pHgsmi, BOOL bD3D)
348{
349 HRESULT hr = vboxUhgsmiKmtEngineCreate(pHgsmi, bD3D);
350 if (!SUCCEEDED(hr))
351 return hr;
352
353 uint32_t u32Caps = 0;
354 hr = vboxUhgsmiKmtQueryCaps(pHgsmi, &u32Caps);
355 if (!SUCCEEDED(hr))
356 {
357 WARN(("vboxUhgsmiKmtQueryCaps failed hr %#x", hr));
358 return hr;
359 }
360
361 if (u32Caps & CR_VBOX_CAP_CMDVBVA)
362 vboxUhgsmiKmtSetupCallbacks(pHgsmi);
363 else
364 vboxUhgsmiKmtEscSetupCallbacks(pHgsmi);
365
366 return S_OK;
367}
368
369HRESULT vboxUhgsmiKmtDestroy(PVBOXUHGSMI_PRIVATE_KMT pHgsmi)
370{
371 HRESULT hr = vboxDispKmtDestroyContext(&pHgsmi->Context);
372 Assert(hr == S_OK);
373 if (hr == S_OK)
374 {
375 hr = vboxDispKmtDestroyDevice(&pHgsmi->Device);
376 Assert(hr == S_OK);
377 if (hr == S_OK)
378 {
379 hr = vboxDispKmtCloseAdapter(&pHgsmi->Adapter);
380 Assert(hr == S_OK);
381 if (hr == S_OK)
382 {
383 hr = vboxDispKmtCallbacksTerm(&pHgsmi->Callbacks);
384 Assert(hr == S_OK);
385 if (hr == S_OK)
386 {
387#ifdef DEBUG_misha
388 memset(pHgsmi, 0, sizeof (*pHgsmi));
389#endif
390 return S_OK;
391 }
392 }
393 }
394 }
395 return hr;
396}
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