VirtualBox

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

Last change on this file since 69498 was 69498, checked in by vboxsync, 7 years ago

backed out r118835 as it incorrectly updated the 'This file is based on' file headers.

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