VirtualBox

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

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

wddm/graphics/crogl: more new command submission fixes

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