VirtualBox

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

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

wddm/DevVga/crOpenGL: new command submission working for 3D

  • 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 50928 2014-03-31 14:14:11Z 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#ifdef DEBUG_misha
45 memset(pBuffer, 0, sizeof(*pBuffer));
46#endif
47 RTMemFree(pBuffer);
48 return VINF_SUCCESS;
49 }
50 else
51 {
52 WARN(("pfnD3DKMTDestroyAllocation failed, Status (0x%x)", Status));
53 }
54 return VERR_GENERAL_FAILURE;
55}
56
57DECLCALLBACK(int) vboxUhgsmiKmtBufferLock(PVBOXUHGSMI_BUFFER pBuf, uint32_t offLock, uint32_t cbLock, 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 = (PVBOXUHGSMI_BUFFER_PRIVATE_DX_ALLOC_BASE)RTMemAllocZ(RT_OFFSETOF(VBOXUHGSMI_BUFFER_PRIVATE_DX_ALLOC_BASE, aLockPageIndices[cPages]));
126 if (!pBuf)
127 {
128 WARN(("RTMemAllocZ failed"));
129 return VERR_NO_MEMORY;
130 }
131
132 D3DKMT_CREATEALLOCATION DdiAlloc;
133 D3DDDI_ALLOCATIONINFO DdiAllocInfo;
134 VBOXWDDM_ALLOCINFO AllocInfo;
135
136 memset(&DdiAlloc, 0, sizeof (DdiAlloc));
137 DdiAlloc.hDevice = pPrivate->Device.hDevice;
138 DdiAlloc.NumAllocations = 1;
139 DdiAlloc.pAllocationInfo = &DdiAllocInfo;
140
141 vboxUhgsmiBaseDxAllocInfoFill(&DdiAllocInfo, &AllocInfo, cbBuf, fType);
142
143 NTSTATUS Status = pPrivate->Callbacks.pfnD3DKMTCreateAllocation(&DdiAlloc);
144 if (NT_SUCCESS(Status))
145 {
146 Assert(DdiAllocInfo.hAllocation);
147 pBuf->BasePrivate.Base.pfnLock = vboxUhgsmiKmtBufferLock;
148 pBuf->BasePrivate.Base.pfnUnlock = vboxUhgsmiKmtBufferUnlock;
149 pBuf->BasePrivate.Base.pfnDestroy = vboxUhgsmiKmtBufferDestroy;
150
151 pBuf->BasePrivate.Base.fType = fType;
152 pBuf->BasePrivate.Base.cbBuffer = cbBuf;
153
154 pBuf->BasePrivate.pHgsmi = &pPrivate->BasePrivate;
155
156 pBuf->hAllocation = DdiAllocInfo.hAllocation;
157
158
159 *ppBuf = &pBuf->BasePrivate.Base;
160
161 return VINF_SUCCESS;
162 }
163 else
164 {
165 WARN(("pfnD3DKMTCreateAllocation failes, Status(0x%x)", Status));
166 rc = VERR_OUT_OF_RESOURCES;
167 }
168
169 RTMemFree(pBuf);
170
171 return rc;
172}
173
174DECLCALLBACK(int) vboxUhgsmiKmtBufferSubmit(PVBOXUHGSMI pHgsmi, PVBOXUHGSMI_BUFFER_SUBMIT aBuffers, uint32_t cBuffers)
175{
176 PVBOXUHGSMI_PRIVATE_KMT pHg = VBOXUHGSMIKMT_GET(pHgsmi);
177 UINT cbDmaCmd = pHg->Context.CommandBufferSize;
178 int rc = vboxUhgsmiBaseDxDmaFill(aBuffers, cBuffers,
179 pHg->Context.pCommandBuffer, &cbDmaCmd,
180 pHg->Context.pAllocationList, pHg->Context.AllocationListSize,
181 pHg->Context.pPatchLocationList, pHg->Context.PatchLocationListSize);
182 if (RT_FAILURE(rc))
183 {
184 WARN(("vboxUhgsmiBaseDxDmaFill failed, rc %d", rc));
185 return rc;
186 }
187
188 D3DKMT_RENDER DdiRender = {0};
189 DdiRender.hContext = pHg->Context.hContext;
190 DdiRender.CommandLength = cbDmaCmd;
191 DdiRender.AllocationCount = cBuffers;
192 Assert(DdiRender.CommandLength);
193 Assert(DdiRender.CommandLength < UINT32_MAX/2);
194
195 NTSTATUS Status = pHg->Callbacks.pfnD3DKMTRender(&DdiRender);
196 if (NT_SUCCESS(Status))
197 {
198 pHg->Context.CommandBufferSize = DdiRender.NewCommandBufferSize;
199 pHg->Context.pCommandBuffer = DdiRender.pNewCommandBuffer;
200 pHg->Context.AllocationListSize = DdiRender.NewAllocationListSize;
201 pHg->Context.pAllocationList = DdiRender.pNewAllocationList;
202 pHg->Context.PatchLocationListSize = DdiRender.NewPatchLocationListSize;
203 pHg->Context.pPatchLocationList = DdiRender.pNewPatchLocationList;
204
205 return VINF_SUCCESS;
206 }
207 else
208 {
209 WARN(("pfnD3DKMTRender failed, Status (0x%x)", Status));
210 }
211
212 return VERR_GENERAL_FAILURE;
213}
214
215
216static HRESULT vboxUhgsmiKmtEngineCreate(PVBOXUHGSMI_PRIVATE_KMT pHgsmi, BOOL bD3D)
217{
218 HRESULT hr = vboxDispKmtCallbacksInit(&pHgsmi->Callbacks);
219 if (hr == S_OK)
220 {
221 hr = vboxDispKmtOpenAdapter(&pHgsmi->Callbacks, &pHgsmi->Adapter);
222 if (hr == S_OK)
223 {
224 hr = vboxDispKmtCreateDevice(&pHgsmi->Adapter, &pHgsmi->Device);
225 if (hr == S_OK)
226 {
227 hr = vboxDispKmtCreateContext(&pHgsmi->Device, &pHgsmi->Context,
228 bD3D ? VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_3D : VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL,
229 CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR,
230 NULL, 0);
231 if (hr == S_OK)
232 {
233 return S_OK;
234 }
235 else
236 {
237 WARN(("vboxDispKmtCreateContext failed, hr(0x%x)", hr));
238 }
239 vboxDispKmtDestroyDevice(&pHgsmi->Device);
240 }
241 else
242 {
243 WARN(("vboxDispKmtCreateDevice failed, hr(0x%x)", hr));
244 }
245 vboxDispKmtCloseAdapter(&pHgsmi->Adapter);
246 }
247 else
248 {
249// WARN(("vboxDispKmtOpenAdapter failed, hr(0x%x)", hr));
250 }
251
252 vboxDispKmtCallbacksTerm(&pHgsmi->Callbacks);
253 }
254 else
255 {
256 WARN(("vboxDispKmtCallbacksInit failed, hr(0x%x)", hr));
257 }
258 return hr;
259}
260
261static DECLCALLBACK(int) vboxCrHhgsmiKmtEscape(struct VBOXUHGSMI_PRIVATE_BASE *pHgsmi, void *pvData, uint32_t cbData, BOOL fHwAccess)
262{
263 PVBOXUHGSMI_PRIVATE_KMT pPrivate = VBOXUHGSMIKMT_GET(pHgsmi);
264 D3DKMT_ESCAPE DdiEscape = {0};
265 DdiEscape.hAdapter = pPrivate->Adapter.hAdapter;
266 DdiEscape.hDevice = pPrivate->Device.hDevice;
267 DdiEscape.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
268 DdiEscape.Flags.HardwareAccess = !!fHwAccess;
269 DdiEscape.pPrivateDriverData = pvData;
270 DdiEscape.PrivateDriverDataSize = cbData;
271 DdiEscape.hContext = pPrivate->Context.hContext;
272
273 NTSTATUS Status = pPrivate->Callbacks.pfnD3DKMTEscape(&DdiEscape);
274 if (NT_SUCCESS(Status))
275 {
276 return VINF_SUCCESS;
277 }
278
279 WARN(("pfnD3DKMTEscape failed, Status (0x%x)", Status));
280 return VERR_GENERAL_FAILURE;
281}
282
283static void vboxUhgsmiKmtSetupCallbacks(PVBOXUHGSMI_PRIVATE_KMT pHgsmi)
284{
285 pHgsmi->BasePrivate.Base.pfnBufferCreate = vboxUhgsmiKmtBufferCreate;
286 pHgsmi->BasePrivate.Base.pfnBufferSubmit = vboxUhgsmiKmtBufferSubmit;
287 /* escape is still needed, since Ugfsmi uses it e.g. to query connection id */
288 pHgsmi->BasePrivate.pfnEscape = vboxCrHhgsmiKmtEscape;
289}
290
291static void vboxUhgsmiKmtEscSetupCallbacks(PVBOXUHGSMI_PRIVATE_KMT pHgsmi)
292{
293 vboxUhgsmiBaseInit(&pHgsmi->BasePrivate, vboxCrHhgsmiKmtEscape);
294}
295
296#if 0
297HRESULT vboxUhgsmiKmtCreate(PVBOXUHGSMI_PRIVATE_KMT pHgsmi, BOOL bD3D)
298{
299 vboxUhgsmiKmtSetupCallbacks(pHgsmi);
300 return vboxUhgsmiKmtEngineCreate(pHgsmi, bD3D);
301}
302
303HRESULT vboxUhgsmiKmtEscCreate(PVBOXUHGSMI_PRIVATE_KMT pHgsmi, BOOL bD3D)
304{
305 vboxUhgsmiKmtEscSetupCallbacks(pHgsmi);
306 return vboxUhgsmiKmtEngineCreate(pHgsmi, bD3D);
307}
308#endif
309
310static HRESULT vboxUhgsmiKmtQueryCaps(PVBOXUHGSMI_PRIVATE_KMT pHgsmi, uint32_t *pu32Caps)
311{
312 VBOXWDDM_QI Query;
313 D3DKMT_QUERYADAPTERINFO Info;
314 Info.hAdapter = pHgsmi->Adapter.hAdapter;
315 Info.Type = KMTQAITYPE_UMDRIVERPRIVATE;
316 Info.pPrivateDriverData = &Query;
317 Info.PrivateDriverDataSize = sizeof (Query);
318
319 NTSTATUS Status = pHgsmi->Callbacks.pfnD3DKMTQueryAdapterInfo(&Info);
320 if (!NT_SUCCESS(Status))
321 {
322 WARN(("pfnD3DKMTQueryAdapterInfo failed, Status %#x", Status));
323 return Status;
324 }
325
326 if (Query.u32Version != VBOXVIDEOIF_VERSION)
327 {
328 WARN(("Version mismatch"));
329 return E_FAIL;
330 }
331
332 *pu32Caps = Query.u32VBox3DCaps;
333
334 return S_OK;
335}
336
337HRESULT vboxUhgsmiKmtCreate(PVBOXUHGSMI_PRIVATE_KMT pHgsmi, BOOL bD3D)
338{
339 HRESULT hr = vboxUhgsmiKmtEngineCreate(pHgsmi, bD3D);
340 if (!SUCCEEDED(hr))
341 return hr;
342
343 uint32_t u32Caps = 0;
344 hr = vboxUhgsmiKmtQueryCaps(pHgsmi, &u32Caps);
345 if (!SUCCEEDED(hr))
346 {
347 WARN(("vboxUhgsmiKmtQueryCaps failed hr %#x", hr));
348 return hr;
349 }
350
351 if (u32Caps & CR_VBOX_CAP_CMDVBVA)
352 vboxUhgsmiKmtSetupCallbacks(pHgsmi);
353 else
354 vboxUhgsmiKmtEscSetupCallbacks(pHgsmi);
355
356 return S_OK;
357}
358
359HRESULT vboxUhgsmiKmtDestroy(PVBOXUHGSMI_PRIVATE_KMT pHgsmi)
360{
361 HRESULT hr = vboxDispKmtDestroyContext(&pHgsmi->Context);
362 Assert(hr == S_OK);
363 if (hr == S_OK)
364 {
365 hr = vboxDispKmtDestroyDevice(&pHgsmi->Device);
366 Assert(hr == S_OK);
367 if (hr == S_OK)
368 {
369 hr = vboxDispKmtCloseAdapter(&pHgsmi->Adapter);
370 Assert(hr == S_OK);
371 if (hr == S_OK)
372 {
373 hr = vboxDispKmtCallbacksTerm(&pHgsmi->Callbacks);
374 Assert(hr == S_OK);
375 if (hr == S_OK)
376 {
377#ifdef DEBUG_misha
378 memset(pHgsmi, 0, sizeof (*pHgsmi));
379#endif
380 return S_OK;
381 }
382 }
383 }
384 }
385 return hr;
386}
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