VirtualBox

source: vbox/trunk/src/VBox/Additions/3D/win/VBoxGL/GaDrvEnvKMT.cpp@ 98103

Last change on this file since 98103 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 47.6 KB
Line 
1/* $Id: GaDrvEnvKMT.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VirtualBox Windows Guest Mesa3D - Gallium driver interface to the WDDM miniport driver using Kernel Mode Thunks.
4 */
5
6/*
7 * Copyright (C) 2016-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include "GaDrvEnvKMT.h"
29
30#include <UmHlpInternal.h>
31
32#include "svga3d_reg.h"
33
34#include <common/wddm/VBoxMPIf.h>
35
36#include <iprt/assertcompile.h>
37#include <iprt/param.h> /* For PAGE_SIZE */
38
39AssertCompile(sizeof(HANDLE) >= sizeof(D3DKMT_HANDLE));
40
41
42/*
43 * AVL configuration.
44 */
45#define KAVL_FN(a) RTAvlU32##a
46#define KAVL_MAX_STACK 27 /* Up to 2^24 nodes. */
47#define KAVL_CHECK_FOR_EQUAL_INSERT 1 /* No duplicate keys! */
48#define KAVLNODECORE AVLU32NODECORE
49#define PKAVLNODECORE PAVLU32NODECORE
50#define PPKAVLNODECORE PPAVLU32NODECORE
51#define KAVLKEY AVLU32KEY
52#define PKAVLKEY PAVLU32KEY
53#define KAVLENUMDATA AVLU32ENUMDATA
54#define PKAVLENUMDATA PAVLU32ENUMDATA
55#define PKAVLCALLBACK PAVLU32CALLBACK
56
57
58/*
59 * AVL Compare macros
60 */
61#define KAVL_G(key1, key2) ( (key1) > (key2) )
62#define KAVL_E(key1, key2) ( (key1) == (key2) )
63#define KAVL_NE(key1, key2) ( (key1) != (key2) )
64
65
66#include <iprt/avl.h>
67
68/*
69 * Include the code.
70 */
71#define SSToDS(ptr) ptr
72#define KMAX RT_MAX
73#define kASSERT(_e) do { } while (0)
74#include "avl_Base.cpp.h"
75#include "avl_Get.cpp.h"
76//#include "avl_GetBestFit.cpp.h"
77//#include "avl_RemoveBestFit.cpp.h"
78//#include "avl_DoWithAll.cpp.h"
79#include "avl_Destroy.cpp.h"
80
81
82typedef struct GaKmtCallbacks
83{
84 D3DKMT_HANDLE hAdapter;
85 D3DKMT_HANDLE hDevice;
86 D3DKMTFUNCTIONS const *d3dkmt;
87 LUID AdapterLuid;
88} GaKmtCallbacks;
89
90class GaDrvEnvKmt
91{
92 public:
93 GaDrvEnvKmt();
94 ~GaDrvEnvKmt();
95
96 HRESULT Init(void);
97
98 const WDDMGalliumDriverEnv *Env();
99
100 /*
101 * KMT specific helpers.
102 */
103 bool drvEnvKmtRenderCompose(uint32_t u32Cid,
104 void *pvCommands,
105 uint32_t cbCommands,
106 ULONGLONG PresentHistoryToken);
107 D3DKMT_HANDLE drvEnvKmtContextHandle(uint32_t u32Cid);
108 D3DKMT_HANDLE drvEnvKmtSurfaceHandle(uint32_t u32Sid);
109
110 GaKmtCallbacks mKmtCallbacks;
111
112 private:
113
114 VBOXGAHWINFO mHWInfo;
115
116 /* Map to convert context id (cid) to WDDM context information (GAWDDMCONTEXTINFO).
117 * Key is the 32 bit context id.
118 */
119 AVLU32TREE mContextTree;
120
121 /* Map to convert surface id (sid) to WDDM surface information (GAWDDMSURFACEINFO).
122 * Key is the 32 bit surface id.
123 */
124 AVLU32TREE mSurfaceTree;
125
126 WDDMGalliumDriverEnv mEnv;
127
128 static DECLCALLBACK(uint32_t) gaEnvContextCreate(void *pvEnv,
129 boolean extended,
130 boolean vgpu10);
131 static DECLCALLBACK(void) gaEnvContextDestroy(void *pvEnv,
132 uint32_t u32Cid);
133 static DECLCALLBACK(int) gaEnvSurfaceDefine(void *pvEnv,
134 GASURFCREATE *pCreateParms,
135 GASURFSIZE *paSizes,
136 uint32_t cSizes,
137 uint32_t *pu32Sid);
138 static DECLCALLBACK(void) gaEnvSurfaceDestroy(void *pvEnv,
139 uint32_t u32Sid);
140 static DECLCALLBACK(int) gaEnvRender(void *pvEnv,
141 uint32_t u32Cid,
142 void *pvCommands,
143 uint32_t cbCommands,
144 GAFENCEQUERY *pFenceQuery);
145 static DECLCALLBACK(void) gaEnvFenceUnref(void *pvEnv,
146 uint32_t u32FenceHandle);
147 static DECLCALLBACK(int) gaEnvFenceQuery(void *pvEnv,
148 uint32_t u32FenceHandle,
149 GAFENCEQUERY *pFenceQuery);
150 static DECLCALLBACK(int) gaEnvFenceWait(void *pvEnv,
151 uint32_t u32FenceHandle,
152 uint32_t u32TimeoutUS);
153 static DECLCALLBACK(int) gaEnvRegionCreate(void *pvEnv,
154 uint32_t u32RegionSize,
155 uint32_t *pu32GmrId,
156 void **ppvMap);
157 static DECLCALLBACK(void) gaEnvRegionDestroy(void *pvEnv,
158 uint32_t u32GmrId,
159 void *pvMap);
160
161 /* VGPU10 */
162 static DECLCALLBACK(int) gaEnvGBSurfaceDefine(void *pvEnv,
163 SVGAGBSURFCREATE *pCreateParms);
164
165 /*
166 * Internal.
167 */
168 bool doRender(uint32_t u32Cid, void *pvCommands, uint32_t cbCommands,
169 GAFENCEQUERY *pFenceQuery, ULONGLONG PresentHistoryToken, bool fPresentRedirected);
170};
171
172typedef struct GAWDDMCONTEXTINFO
173{
174 AVLU32NODECORE Core;
175 D3DKMT_HANDLE hContext;
176 VOID *pCommandBuffer;
177 UINT CommandBufferSize;
178 D3DDDI_ALLOCATIONLIST *pAllocationList;
179 UINT AllocationListSize;
180 D3DDDI_PATCHLOCATIONLIST *pPatchLocationList;
181 UINT PatchLocationListSize;
182} GAWDDMCONTEXTINFO;
183
184typedef struct GAWDDMSURFACEINFO
185{
186 AVLU32NODECORE Core;
187 D3DKMT_HANDLE hAllocation;
188} GAWDDMSURFACEINFO;
189
190
191/// @todo vboxDdi helpers must return a boof success indicator
192static bool
193vboxDdiQueryAdapterInfo(GaKmtCallbacks *pKmtCallbacks,
194 D3DKMT_HANDLE hAdapter,
195 VBOXWDDM_QAI *pAdapterInfo,
196 uint32_t cbAdapterInfo)
197{
198 D3DKMT_QUERYADAPTERINFO QAI;
199 memset(&QAI, 0, sizeof(QAI));
200 QAI.hAdapter = hAdapter;
201 QAI.Type = KMTQAITYPE_UMDRIVERPRIVATE;
202 QAI.pPrivateDriverData = pAdapterInfo;
203 QAI.PrivateDriverDataSize = cbAdapterInfo;
204
205 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTQueryAdapterInfo(&QAI);
206 return Status == STATUS_SUCCESS;
207}
208
209static void
210vboxDdiDeviceDestroy(GaKmtCallbacks *pKmtCallbacks,
211 D3DKMT_HANDLE hDevice)
212{
213 if (hDevice)
214 {
215 D3DKMT_DESTROYDEVICE DestroyDeviceData;
216 memset(&DestroyDeviceData, 0, sizeof(DestroyDeviceData));
217 DestroyDeviceData.hDevice = hDevice;
218 pKmtCallbacks->d3dkmt->pfnD3DKMTDestroyDevice(&DestroyDeviceData);
219 }
220}
221
222static bool
223vboxDdiDeviceCreate(GaKmtCallbacks *pKmtCallbacks,
224 D3DKMT_HANDLE *phDevice)
225{
226 D3DKMT_CREATEDEVICE CreateDeviceData;
227 memset(&CreateDeviceData, 0, sizeof(CreateDeviceData));
228 CreateDeviceData.hAdapter = pKmtCallbacks->hAdapter;
229 // CreateDeviceData.Flags = 0;
230
231 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTCreateDevice(&CreateDeviceData);
232 if (Status == STATUS_SUCCESS)
233 {
234 *phDevice = CreateDeviceData.hDevice;
235 return true;
236 }
237 return false;
238}
239
240static bool
241vboxDdiContextGetId(GaKmtCallbacks *pKmtCallbacks,
242 D3DKMT_HANDLE hContext,
243 uint32_t *pu32Cid)
244{
245 VBOXDISPIFESCAPE_GAGETCID data;
246 memset(&data, 0, sizeof(data));
247 data.EscapeHdr.escapeCode = VBOXESC_GAGETCID;
248 // data.EscapeHdr.cmdSpecific = 0;
249 // data.u32Cid = 0;
250
251 /* If the user-mode display driver sets hContext to a non-NULL value, the driver must
252 * have also set hDevice to a non-NULL value...
253 */
254 D3DKMT_ESCAPE EscapeData;
255 memset(&EscapeData, 0, sizeof(EscapeData));
256 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
257 EscapeData.hDevice = pKmtCallbacks->hDevice;
258 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
259 // EscapeData.Flags.HardwareAccess = 0;
260 EscapeData.pPrivateDriverData = &data;
261 EscapeData.PrivateDriverDataSize = sizeof(data);
262 EscapeData.hContext = hContext;
263
264 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
265 if (Status == STATUS_SUCCESS)
266 {
267 *pu32Cid = data.u32Cid;
268 return true;
269 }
270 return false;
271}
272
273static void
274vboxDdiContextDestroy(GaKmtCallbacks *pKmtCallbacks,
275 GAWDDMCONTEXTINFO *pContextInfo)
276{
277 if (pContextInfo->hContext)
278 {
279 D3DKMT_DESTROYCONTEXT DestroyContextData;
280 memset(&DestroyContextData, 0, sizeof(DestroyContextData));
281 DestroyContextData.hContext = pContextInfo->hContext;
282 pKmtCallbacks->d3dkmt->pfnD3DKMTDestroyContext(&DestroyContextData);
283 }
284}
285
286static bool
287vboxDdiContextCreate(GaKmtCallbacks *pKmtCallbacks,
288 void *pvPrivateData, uint32_t cbPrivateData,
289 GAWDDMCONTEXTINFO *pContextInfo)
290{
291 D3DKMT_CREATECONTEXT CreateContextData;
292 memset(&CreateContextData, 0, sizeof(CreateContextData));
293 CreateContextData.hDevice = pKmtCallbacks->hDevice;
294 // CreateContextData.NodeOrdinal = 0;
295 // CreateContextData.EngineAffinity = 0;
296 // CreateContextData.Flags.Value = 0;
297 CreateContextData.pPrivateDriverData = pvPrivateData;
298 CreateContextData.PrivateDriverDataSize = cbPrivateData;
299 CreateContextData.ClientHint = D3DKMT_CLIENTHINT_OPENGL;
300
301 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTCreateContext(&CreateContextData);
302 if (Status == STATUS_SUCCESS)
303 {
304 /* Query cid. */
305 uint32_t u32Cid = 0;
306 bool fSuccess = vboxDdiContextGetId(pKmtCallbacks, CreateContextData.hContext, &u32Cid);
307 if (fSuccess)
308 {
309 pContextInfo->Core.Key = u32Cid;
310 pContextInfo->hContext = CreateContextData.hContext;
311 pContextInfo->pCommandBuffer = CreateContextData.pCommandBuffer;
312 pContextInfo->CommandBufferSize = CreateContextData.CommandBufferSize;
313 pContextInfo->pAllocationList = CreateContextData.pAllocationList;
314 pContextInfo->AllocationListSize = CreateContextData.AllocationListSize;
315 pContextInfo->pPatchLocationList = CreateContextData.pPatchLocationList;
316 pContextInfo->PatchLocationListSize = CreateContextData.PatchLocationListSize;
317
318 return true;
319 }
320
321 vboxDdiContextDestroy(pKmtCallbacks, pContextInfo);
322 }
323
324 return false;
325}
326
327/* static */ DECLCALLBACK(void)
328GaDrvEnvKmt::gaEnvContextDestroy(void *pvEnv,
329 uint32_t u32Cid)
330{
331 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
332
333 GAWDDMCONTEXTINFO *pContextInfo = (GAWDDMCONTEXTINFO *)RTAvlU32Remove(&pThis->mContextTree, u32Cid);
334 if (pContextInfo)
335 {
336 vboxDdiContextDestroy(&pThis->mKmtCallbacks, pContextInfo);
337 memset(pContextInfo, 0, sizeof(*pContextInfo));
338 free(pContextInfo);
339 }
340}
341
342D3DKMT_HANDLE GaDrvEnvKmt::drvEnvKmtContextHandle(uint32_t u32Cid)
343{
344 GAWDDMCONTEXTINFO *pContextInfo = (GAWDDMCONTEXTINFO *)RTAvlU32Get(&mContextTree, u32Cid);
345 Assert(pContextInfo);
346 return pContextInfo ? pContextInfo->hContext : 0;
347}
348
349/* static */ DECLCALLBACK(uint32_t)
350GaDrvEnvKmt::gaEnvContextCreate(void *pvEnv,
351 boolean extended,
352 boolean vgpu10)
353{
354 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
355
356 GAWDDMCONTEXTINFO *pContextInfo;
357 pContextInfo = (GAWDDMCONTEXTINFO *)malloc(sizeof(GAWDDMCONTEXTINFO));
358 if (!pContextInfo)
359 return (uint32_t)-1;
360
361 VBOXWDDM_CREATECONTEXT_INFO privateData;
362 memset(&privateData, 0, sizeof(privateData));
363 privateData.u32IfVersion = 9;
364 privateData.enmType = VBOXWDDM_CONTEXT_TYPE_GA_3D;
365 privateData.u.vmsvga.u32Flags = extended? VBOXWDDM_F_GA_CONTEXT_EXTENDED: 0;
366 privateData.u.vmsvga.u32Flags |= vgpu10? VBOXWDDM_F_GA_CONTEXT_VGPU10: 0;
367
368 bool fSuccess = vboxDdiContextCreate(&pThis->mKmtCallbacks,
369 &privateData, sizeof(privateData), pContextInfo);
370 if (fSuccess)
371 {
372 if (RTAvlU32Insert(&pThis->mContextTree, &pContextInfo->Core))
373 {
374 return pContextInfo->Core.Key;
375 }
376
377 vboxDdiContextDestroy(&pThis->mKmtCallbacks,
378 pContextInfo);
379 }
380
381 Assert(0);
382 free(pContextInfo);
383 return (uint32_t)-1;
384}
385
386static D3DDDIFORMAT svgaToD3DDDIFormat(SVGA3dSurfaceFormat format)
387{
388 switch (format)
389 {
390 case SVGA3D_X8R8G8B8: return D3DDDIFMT_X8R8G8B8;
391 case SVGA3D_A8R8G8B8: return D3DDDIFMT_A8R8G8B8;
392 case SVGA3D_ALPHA8: return D3DDDIFMT_A8;
393 case SVGA3D_R8G8B8A8_UNORM: return D3DDDIFMT_A8B8G8R8;
394 case SVGA3D_A4R4G4B4: return D3DDDIFMT_A4R4G4B4;
395 case SVGA3D_LUMINANCE8: return D3DDDIFMT_L8;
396 case SVGA3D_A1R5G5B5: return D3DDDIFMT_A1R5G5B5;
397 case SVGA3D_LUMINANCE8_ALPHA8: return D3DDDIFMT_A8L8;
398 case SVGA3D_R5G6B5: return D3DDDIFMT_R5G6B5;
399 case SVGA3D_ARGB_S10E5: return D3DDDIFMT_A16B16G16R16F;
400 case SVGA3D_ARGB_S23E8: return D3DDDIFMT_A32B32G32R32F;
401 case SVGA3D_B8G8R8A8_UNORM: return D3DDDIFMT_A8R8G8B8;
402 case SVGA3D_B8G8R8X8_UNORM: return D3DDDIFMT_X8R8G8B8;
403 case SVGA3D_R8_UNORM: /* R8->A8 conversion is not correct, but it does not matter here,
404 * because the D3DDDIFMT_ value is used only to compute bpp, pitch, etc. */
405 case SVGA3D_A8_UNORM: return D3DDDIFMT_A8;
406 case SVGA3D_B5G5R5A1_UNORM: return D3DDDIFMT_A1R5G5B5;
407 default: break;
408 }
409
410 VBoxDispMpLoggerLogF("WDDM: EnvKMT: unsupported surface format %d\n", format);
411 Assert(0);
412 return D3DDDIFMT_UNKNOWN;
413}
414
415/* static */ DECLCALLBACK(int)
416GaDrvEnvKmt::gaEnvSurfaceDefine(void *pvEnv,
417 GASURFCREATE *pCreateParms,
418 GASURFSIZE *paSizes,
419 uint32_t cSizes,
420 uint32_t *pu32Sid)
421{
422 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
423
424 D3DKMT_ESCAPE EscapeData;
425 VBOXDISPIFESCAPE_GASURFACEDEFINE *pData;
426 uint32_t cbAlloc;
427 uint8_t *pu8Req;
428 uint32_t cbReq;
429
430 /* Size of the SVGA request data */
431 cbReq = sizeof(GASURFCREATE) + cSizes * sizeof(GASURFSIZE);
432 /* How much to allocate for WDDM escape data. */
433 cbAlloc = sizeof(VBOXDISPIFESCAPE_GASURFACEDEFINE)
434 + cbReq;
435
436 pData = (VBOXDISPIFESCAPE_GASURFACEDEFINE *)malloc(cbAlloc);
437 if (!pData)
438 return -1;
439
440 pData->EscapeHdr.escapeCode = VBOXESC_GASURFACEDEFINE;
441 // pData->EscapeHdr.cmdSpecific = 0;
442 // pData->u32Sid = 0;
443 pData->cbReq = cbReq;
444 pData->cSizes = cSizes;
445
446 pu8Req = (uint8_t *)&pData[1];
447 memcpy(pu8Req, pCreateParms, sizeof(GASURFCREATE));
448 memcpy(&pu8Req[sizeof(GASURFCREATE)], paSizes, cSizes * sizeof(GASURFSIZE));
449
450 memset(&EscapeData, 0, sizeof(EscapeData));
451 EscapeData.hAdapter = pThis->mKmtCallbacks.hAdapter;
452 EscapeData.hDevice = pThis->mKmtCallbacks.hDevice;
453 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
454 EscapeData.Flags.HardwareAccess = 1;
455 EscapeData.pPrivateDriverData = pData;
456 EscapeData.PrivateDriverDataSize = cbAlloc;
457 // EscapeData.hContext = 0;
458
459 NTSTATUS Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTEscape(&EscapeData);
460 if (Status == STATUS_SUCCESS)
461 {
462 /* Create a kernel mode allocation for render targets,
463 * because we will need kernel mode handles for Present.
464 */
465 if (pCreateParms->flags & SVGA3D_SURFACE_HINT_RENDERTARGET)
466 {
467 /* First check if the format is supported. */
468 D3DDDIFORMAT const ddiFormat = svgaToD3DDDIFormat((SVGA3dSurfaceFormat)pCreateParms->format);
469 if (ddiFormat != D3DDDIFMT_UNKNOWN)
470 {
471 GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)malloc(sizeof(GAWDDMSURFACEINFO));
472 if (pSurfaceInfo)
473 {
474 memset(pSurfaceInfo, 0, sizeof(GAWDDMSURFACEINFO));
475
476 VBOXWDDM_ALLOCINFO wddmAllocInfo;
477 memset(&wddmAllocInfo, 0, sizeof(wddmAllocInfo));
478
479 wddmAllocInfo.enmType = VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC;
480 wddmAllocInfo.fFlags.RenderTarget = 1;
481 wddmAllocInfo.hSharedHandle = 0;
482 wddmAllocInfo.hostID = pData->u32Sid;
483 wddmAllocInfo.SurfDesc.slicePitch = 0;
484 wddmAllocInfo.SurfDesc.depth = paSizes[0].cDepth;
485 wddmAllocInfo.SurfDesc.width = paSizes[0].cWidth;
486 wddmAllocInfo.SurfDesc.height = paSizes[0].cHeight;
487 wddmAllocInfo.SurfDesc.format = ddiFormat;
488 wddmAllocInfo.SurfDesc.VidPnSourceId = 0;
489 wddmAllocInfo.SurfDesc.bpp = vboxWddmCalcBitsPerPixel(wddmAllocInfo.SurfDesc.format);
490 wddmAllocInfo.SurfDesc.pitch = vboxWddmCalcPitch(wddmAllocInfo.SurfDesc.width,
491 wddmAllocInfo.SurfDesc.format);
492 wddmAllocInfo.SurfDesc.cbSize = vboxWddmCalcSize(wddmAllocInfo.SurfDesc.pitch,
493 wddmAllocInfo.SurfDesc.height,
494 wddmAllocInfo.SurfDesc.format);
495 wddmAllocInfo.SurfDesc.d3dWidth = vboxWddmCalcWidthForPitch(wddmAllocInfo.SurfDesc.pitch,
496 wddmAllocInfo.SurfDesc.format);
497
498 D3DDDI_ALLOCATIONINFO AllocationInfo;
499 memset(&AllocationInfo, 0, sizeof(AllocationInfo));
500 // AllocationInfo.hAllocation = NULL;
501 // AllocationInfo.pSystemMem = NULL;
502 AllocationInfo.pPrivateDriverData = &wddmAllocInfo;
503 AllocationInfo.PrivateDriverDataSize = sizeof(wddmAllocInfo);
504
505 D3DKMT_CREATEALLOCATION CreateAllocation;
506 memset(&CreateAllocation, 0, sizeof(CreateAllocation));
507 CreateAllocation.hDevice = pThis->mKmtCallbacks.hDevice;
508 CreateAllocation.NumAllocations = 1;
509 CreateAllocation.pAllocationInfo = &AllocationInfo;
510
511 Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTCreateAllocation(&CreateAllocation);
512 if (Status == STATUS_SUCCESS)
513 {
514 pSurfaceInfo->Core.Key = pData->u32Sid;
515 pSurfaceInfo->hAllocation = AllocationInfo.hAllocation;
516 if (!RTAvlU32Insert(&pThis->mSurfaceTree, &pSurfaceInfo->Core))
517 {
518 Status = STATUS_NOT_SUPPORTED;
519 }
520 }
521
522 if (Status != STATUS_SUCCESS)
523 {
524 free(pSurfaceInfo);
525 }
526 }
527 else
528 {
529 Status = STATUS_NOT_SUPPORTED;
530 }
531 }
532 else
533 {
534 /* Unsupported render target format. */
535 Status = STATUS_NOT_SUPPORTED;
536 }
537 }
538
539 if (Status != STATUS_SUCCESS)
540 {
541 gaEnvSurfaceDestroy(pvEnv, pData->u32Sid);
542 }
543 }
544
545 if (Status == STATUS_SUCCESS)
546 {
547 *pu32Sid = pData->u32Sid;
548 free(pData);
549 return 0;
550 }
551
552 Assert(0);
553 free(pData);
554 return -1;
555}
556
557/* static */ DECLCALLBACK(void)
558GaDrvEnvKmt::gaEnvSurfaceDestroy(void *pvEnv,
559 uint32_t u32Sid)
560{
561 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
562
563 VBOXDISPIFESCAPE_GASURFACEDESTROY data;
564 memset(&data, 0, sizeof(data));
565 data.EscapeHdr.escapeCode = VBOXESC_GASURFACEDESTROY;
566 // data.EscapeHdr.cmdSpecific = 0;
567 data.u32Sid = u32Sid;
568
569 D3DKMT_ESCAPE EscapeData;
570 memset(&EscapeData, 0, sizeof(EscapeData));
571 EscapeData.hAdapter = pThis->mKmtCallbacks.hAdapter;
572 EscapeData.hDevice = pThis->mKmtCallbacks.hDevice;
573 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
574 EscapeData.Flags.HardwareAccess = 1;
575 EscapeData.pPrivateDriverData = &data;
576 EscapeData.PrivateDriverDataSize = sizeof(data);
577 // EscapeData.hContext = 0;
578
579 NTSTATUS Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTEscape(&EscapeData);
580 Assert(Status == STATUS_SUCCESS);
581
582 /* Try to remove from sid -> hAllocation map. */
583 GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)RTAvlU32Remove(&pThis->mSurfaceTree, u32Sid);
584 if (pSurfaceInfo)
585 {
586 D3DKMT_DESTROYALLOCATION DestroyAllocation;
587 memset(&DestroyAllocation, 0, sizeof(DestroyAllocation));
588 DestroyAllocation.hDevice = pThis->mKmtCallbacks.hDevice;
589 // DestroyAllocation.hResource = 0;
590 DestroyAllocation.phAllocationList = &pSurfaceInfo->hAllocation;
591 DestroyAllocation.AllocationCount = 1;
592
593 Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTDestroyAllocation(&DestroyAllocation);
594 Assert(Status == STATUS_SUCCESS);
595
596 free(pSurfaceInfo);
597 }
598}
599
600D3DKMT_HANDLE GaDrvEnvKmt::drvEnvKmtSurfaceHandle(uint32_t u32Sid)
601{
602 GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)RTAvlU32Get(&mSurfaceTree, u32Sid);
603 return pSurfaceInfo ? pSurfaceInfo->hAllocation : 0;
604}
605
606static bool
607vboxDdiFenceCreate(GaKmtCallbacks *pKmtCallbacks,
608 GAWDDMCONTEXTINFO *pContextInfo,
609 uint32_t *pu32FenceHandle)
610{
611 VBOXDISPIFESCAPE_GAFENCECREATE fenceCreate;
612 memset(&fenceCreate, 0, sizeof(fenceCreate));
613 fenceCreate.EscapeHdr.escapeCode = VBOXESC_GAFENCECREATE;
614 // fenceCreate.EscapeHdr.cmdSpecific = 0;
615
616 /* If the user-mode display driver sets hContext to a non-NULL value, the driver must
617 * have also set hDevice to a non-NULL value...
618 */
619 D3DKMT_ESCAPE EscapeData;
620 memset(&EscapeData, 0, sizeof(EscapeData));
621 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
622 EscapeData.hDevice = pKmtCallbacks->hDevice;
623 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
624 // EscapeData.Flags.HardwareAccess = 0;
625 EscapeData.pPrivateDriverData = &fenceCreate;
626 EscapeData.PrivateDriverDataSize = sizeof(fenceCreate);
627 EscapeData.hContext = pContextInfo->hContext;
628
629 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
630 if (Status == STATUS_SUCCESS)
631 {
632 *pu32FenceHandle = fenceCreate.u32FenceHandle;
633 return true;
634 }
635
636 Assert(0);
637 return false;
638}
639
640static bool
641vboxDdiFenceQuery(GaKmtCallbacks *pKmtCallbacks,
642 uint32_t u32FenceHandle,
643 GAFENCEQUERY *pFenceQuery)
644{
645 VBOXDISPIFESCAPE_GAFENCEQUERY fenceQuery;
646 memset(&fenceQuery, 0, sizeof(fenceQuery));
647 fenceQuery.EscapeHdr.escapeCode = VBOXESC_GAFENCEQUERY;
648 // fenceQuery.EscapeHdr.cmdSpecific = 0;
649 fenceQuery.u32FenceHandle = u32FenceHandle;
650
651 D3DKMT_ESCAPE EscapeData;
652 memset(&EscapeData, 0, sizeof(EscapeData));
653 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
654 EscapeData.hDevice = pKmtCallbacks->hDevice;
655 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
656 // EscapeData.Flags.HardwareAccess = 0;
657 EscapeData.pPrivateDriverData = &fenceQuery;
658 EscapeData.PrivateDriverDataSize = sizeof(fenceQuery);
659 EscapeData.hContext = 0;
660
661 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
662 if (Status == STATUS_SUCCESS)
663 {
664 pFenceQuery->u32FenceHandle = fenceQuery.u32FenceHandle;
665 pFenceQuery->u32SubmittedSeqNo = fenceQuery.u32SubmittedSeqNo;
666 pFenceQuery->u32ProcessedSeqNo = fenceQuery.u32ProcessedSeqNo;
667 pFenceQuery->u32FenceStatus = fenceQuery.u32FenceStatus;
668 return true;
669 }
670
671 Assert(0);
672 return false;
673}
674
675/* static */ DECLCALLBACK(int)
676GaDrvEnvKmt::gaEnvFenceQuery(void *pvEnv,
677 uint32_t u32FenceHandle,
678 GAFENCEQUERY *pFenceQuery)
679{
680 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
681
682 if (!pThis->mKmtCallbacks.hDevice)
683 {
684 pFenceQuery->u32FenceStatus = GA_FENCE_STATUS_NULL;
685 return 0;
686 }
687
688 bool fSuccess = vboxDdiFenceQuery(&pThis->mKmtCallbacks, u32FenceHandle, pFenceQuery);
689 return fSuccess ? 0: -1;
690}
691
692static bool
693vboxDdiFenceWait(GaKmtCallbacks *pKmtCallbacks,
694 uint32_t u32FenceHandle,
695 uint32_t u32TimeoutUS)
696{
697 VBOXDISPIFESCAPE_GAFENCEWAIT fenceWait;
698 memset(&fenceWait, 0, sizeof(fenceWait));
699 fenceWait.EscapeHdr.escapeCode = VBOXESC_GAFENCEWAIT;
700 // pFenceWait->EscapeHdr.cmdSpecific = 0;
701 fenceWait.u32FenceHandle = u32FenceHandle;
702 fenceWait.u32TimeoutUS = u32TimeoutUS;
703
704 D3DKMT_ESCAPE EscapeData;
705 memset(&EscapeData, 0, sizeof(EscapeData));
706 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
707 EscapeData.hDevice = pKmtCallbacks->hDevice;
708 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
709 // EscapeData.Flags.HardwareAccess = 0;
710 EscapeData.pPrivateDriverData = &fenceWait;
711 EscapeData.PrivateDriverDataSize = sizeof(fenceWait);
712 EscapeData.hContext = 0;
713
714 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
715 Assert(Status == STATUS_SUCCESS);
716 return Status == STATUS_SUCCESS;
717}
718
719/* static */ DECLCALLBACK(int)
720GaDrvEnvKmt::gaEnvFenceWait(void *pvEnv,
721 uint32_t u32FenceHandle,
722 uint32_t u32TimeoutUS)
723{
724 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
725
726 if (!pThis->mKmtCallbacks.hDevice)
727 return 0;
728
729 bool fSuccess = vboxDdiFenceWait(&pThis->mKmtCallbacks, u32FenceHandle, u32TimeoutUS);
730 return fSuccess ? 0 : -1;
731}
732
733static bool
734vboxDdiFenceUnref(GaKmtCallbacks *pKmtCallbacks,
735 uint32_t u32FenceHandle)
736{
737 VBOXDISPIFESCAPE_GAFENCEUNREF fenceUnref;
738 memset(&fenceUnref, 0, sizeof(fenceUnref));
739 fenceUnref.EscapeHdr.escapeCode = VBOXESC_GAFENCEUNREF;
740 // pFenceUnref->EscapeHdr.cmdSpecific = 0;
741 fenceUnref.u32FenceHandle = u32FenceHandle;
742
743 D3DKMT_ESCAPE EscapeData;
744 memset(&EscapeData, 0, sizeof(EscapeData));
745 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
746 EscapeData.hDevice = pKmtCallbacks->hDevice;
747 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
748 // EscapeData.Flags.HardwareAccess = 0;
749 EscapeData.pPrivateDriverData = &fenceUnref;
750 EscapeData.PrivateDriverDataSize = sizeof(fenceUnref);
751 EscapeData.hContext = 0;
752
753 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
754 Assert(Status == STATUS_SUCCESS);
755 return Status == STATUS_SUCCESS;
756}
757
758/* static */ DECLCALLBACK(void)
759GaDrvEnvKmt::gaEnvFenceUnref(void *pvEnv,
760 uint32_t u32FenceHandle)
761{
762 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
763
764 if (!pThis->mKmtCallbacks.hDevice)
765 return;
766
767 vboxDdiFenceUnref(&pThis->mKmtCallbacks, u32FenceHandle);
768}
769
770/** Calculate how many commands will fit in the buffer.
771 *
772 * @param pu8Commands Command buffer.
773 * @param cbCommands Size of command buffer.
774 * @param cbAvail Available buffer size..
775 * @param pu32Length Size of commands which will fit in cbAvail bytes.
776 */
777static bool
778vboxCalcCommandLength(const uint8_t *pu8Commands, uint32_t cbCommands, uint32_t cbAvail, uint32_t *pu32Length)
779{
780 uint32_t u32Length = 0;
781 const uint8_t *pu8Src = pu8Commands;
782 const uint8_t *pu8SrcEnd = pu8Commands + cbCommands;
783
784 while (pu8SrcEnd > pu8Src)
785 {
786 const uint32_t cbSrcLeft = pu8SrcEnd - pu8Src;
787 if (cbSrcLeft < sizeof(uint32_t))
788 {
789 return false;
790 }
791
792 /* Get the command id and command length. */
793 const uint32_t u32CmdId = *(uint32_t *)pu8Src;
794 uint32_t cbCmd = 0;
795
796 if (SVGA_3D_CMD_BASE <= u32CmdId && u32CmdId < SVGA_3D_CMD_MAX)
797 {
798 if (cbSrcLeft < sizeof(SVGA3dCmdHeader))
799 {
800 return false;
801 }
802
803 const SVGA3dCmdHeader *pHeader = (SVGA3dCmdHeader *)pu8Src;
804 cbCmd = sizeof(SVGA3dCmdHeader) + pHeader->size;
805 if (cbCmd % sizeof(uint32_t) != 0)
806 {
807 return false;
808 }
809 if (cbSrcLeft < cbCmd)
810 {
811 return false;
812 }
813 }
814 else
815 {
816 /* It is not expected that any of common SVGA commands will be in the command buffer
817 * because the SVGA gallium driver does not use them.
818 */
819 return false;
820 }
821
822 if (u32Length + cbCmd > cbAvail)
823 {
824 if (u32Length == 0)
825 {
826 /* No commands fit into the buffer. */
827 return false;
828 }
829 break;
830 }
831
832 pu8Src += cbCmd;
833 u32Length += cbCmd;
834 }
835
836 *pu32Length = u32Length;
837 return true;
838}
839
840static bool
841vboxDdiRender(GaKmtCallbacks *pKmtCallbacks,
842 GAWDDMCONTEXTINFO *pContextInfo, uint32_t u32FenceHandle, void *pvCommands, uint32_t cbCommands,
843 ULONGLONG PresentHistoryToken, bool fPresentRedirected)
844{
845 uint32_t cbLeft;
846 const uint8_t *pu8Src;
847
848 cbLeft = cbCommands;
849 pu8Src = (uint8_t *)pvCommands;
850 /* Even when cbCommands is 0, submit the fence. The following code deals with this. */
851 do
852 {
853 /* Actually available space. */
854 const uint32_t cbAvail = pContextInfo->CommandBufferSize;
855 if (cbAvail <= sizeof(u32FenceHandle))
856 {
857 return false;
858 }
859
860 /* How many bytes of command data still to copy. */
861 uint32_t cbCommandChunk = cbLeft;
862
863 /* How many bytes still to copy. */
864 uint32_t cbToCopy = sizeof(u32FenceHandle) + cbCommandChunk;
865
866 /* Copy the buffer identifier. */
867 if (cbToCopy <= cbAvail)
868 {
869 /* Command buffer is big enough. */
870 *(uint32_t *)pContextInfo->pCommandBuffer = u32FenceHandle;
871 }
872 else
873 {
874 /* Split. Write zero as buffer identifier. */
875 *(uint32_t *)pContextInfo->pCommandBuffer = 0;
876
877 /* Get how much commands data will fit in the buffer. */
878 if (!vboxCalcCommandLength(pu8Src, cbCommandChunk, cbAvail - sizeof(u32FenceHandle), &cbCommandChunk))
879 {
880 return false;
881 }
882
883 cbToCopy = sizeof(u32FenceHandle) + cbCommandChunk;
884 }
885
886 if (cbCommandChunk)
887 {
888 /* Copy the command data. */
889 memcpy((uint8_t *)pContextInfo->pCommandBuffer + sizeof(u32FenceHandle), pu8Src, cbCommandChunk);
890 }
891
892 /* Advance the command position. */
893 pu8Src += cbCommandChunk;
894 cbLeft -= cbCommandChunk;
895
896 D3DKMT_RENDER RenderData;
897 memset(&RenderData, 0, sizeof(RenderData));
898 RenderData.hContext = pContextInfo->hContext;
899 // RenderData.CommandOffset = 0;
900 RenderData.CommandLength = cbToCopy;
901 // RenderData.AllocationCount = 0;
902 // RenderData.PatchLocationCount = 0;
903 RenderData.PresentHistoryToken = PresentHistoryToken;
904 RenderData.Flags.PresentRedirected = fPresentRedirected;
905
906 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTRender(&RenderData);
907 Assert(Status == STATUS_SUCCESS);
908 if (Status != STATUS_SUCCESS)
909 {
910 return false;
911 }
912
913 pContextInfo->pCommandBuffer = RenderData.pNewCommandBuffer;
914 pContextInfo->CommandBufferSize = RenderData.NewCommandBufferSize;
915 pContextInfo->pAllocationList = RenderData.pNewAllocationList;
916 pContextInfo->AllocationListSize = RenderData.NewAllocationListSize;
917 pContextInfo->pPatchLocationList = RenderData.pNewPatchLocationList;
918 pContextInfo->PatchLocationListSize = RenderData.NewPatchLocationListSize;
919 } while (cbLeft);
920
921 return true;
922}
923
924bool GaDrvEnvKmt::doRender(uint32_t u32Cid, void *pvCommands, uint32_t cbCommands,
925 GAFENCEQUERY *pFenceQuery, ULONGLONG PresentHistoryToken, bool fPresentRedirected)
926{
927 uint32_t u32FenceHandle;
928 GAWDDMCONTEXTINFO *pContextInfo = (GAWDDMCONTEXTINFO *)RTAvlU32Get(&mContextTree, u32Cid);
929 if (!pContextInfo)
930 return false;
931
932 bool fSuccess = true;
933 u32FenceHandle = 0;
934 if (pFenceQuery)
935 {
936 fSuccess = vboxDdiFenceCreate(&mKmtCallbacks, pContextInfo, &u32FenceHandle);
937 }
938
939 if (fSuccess)
940 {
941 fSuccess = vboxDdiRender(&mKmtCallbacks, pContextInfo, u32FenceHandle,
942 pvCommands, cbCommands, PresentHistoryToken, fPresentRedirected);
943 if (fSuccess)
944 {
945 if (pFenceQuery)
946 {
947 if (!vboxDdiFenceQuery(&mKmtCallbacks, u32FenceHandle, pFenceQuery))
948 {
949 pFenceQuery->u32FenceStatus = GA_FENCE_STATUS_NULL;
950 }
951 }
952 }
953 }
954 return fSuccess;
955}
956
957/* static */ DECLCALLBACK(int)
958GaDrvEnvKmt::gaEnvRender(void *pvEnv,
959 uint32_t u32Cid,
960 void *pvCommands,
961 uint32_t cbCommands,
962 GAFENCEQUERY *pFenceQuery)
963{
964 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
965 return pThis->doRender(u32Cid, pvCommands, cbCommands, pFenceQuery, 0, false) ? 1 : 0;
966}
967
968bool GaDrvEnvKmt::drvEnvKmtRenderCompose(uint32_t u32Cid,
969 void *pvCommands,
970 uint32_t cbCommands,
971 ULONGLONG PresentHistoryToken)
972{
973 return doRender(u32Cid, pvCommands, cbCommands, NULL, PresentHistoryToken, true);
974}
975
976
977static bool
978vboxDdiRegionCreate(GaKmtCallbacks *pKmtCallbacks,
979 uint32_t u32RegionSize,
980 uint32_t *pu32GmrId,
981 void **ppvMap)
982{
983 VBOXDISPIFESCAPE_GAREGION data;
984 memset(&data, 0, sizeof(data));
985 data.EscapeHdr.escapeCode = VBOXESC_GAREGION;
986 // data.EscapeHdr.cmdSpecific = 0;
987 data.u32Command = GA_REGION_CMD_CREATE;
988 data.u32NumPages = (u32RegionSize + PAGE_SIZE - 1) / PAGE_SIZE;
989 // data.u32GmrId = 0;
990 // data.u64UserAddress = 0;
991
992 D3DKMT_ESCAPE EscapeData;
993 memset(&EscapeData, 0, sizeof(EscapeData));
994 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
995 EscapeData.hDevice = pKmtCallbacks->hDevice;
996 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
997 // EscapeData.Flags.HardwareAccess = 0;
998 EscapeData.pPrivateDriverData = &data;
999 EscapeData.PrivateDriverDataSize = sizeof(data);
1000 // EscapeData.hContext = 0;
1001
1002 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
1003 if (Status == STATUS_SUCCESS)
1004 {
1005 *pu32GmrId = data.u32GmrId;
1006 *ppvMap = (void *)(uintptr_t)data.u64UserAddress;
1007 return true;
1008 }
1009
1010 Assert(0);
1011 return false;
1012}
1013
1014/* static */ DECLCALLBACK(int)
1015GaDrvEnvKmt::gaEnvRegionCreate(void *pvEnv,
1016 uint32_t u32RegionSize,
1017 uint32_t *pu32GmrId,
1018 void **ppvMap)
1019{
1020 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
1021
1022 if (pThis->mKmtCallbacks.hDevice)
1023 {
1024 /* That is a real device */
1025 bool fSuccess = vboxDdiRegionCreate(&pThis->mKmtCallbacks, u32RegionSize, pu32GmrId, ppvMap);
1026 return fSuccess ? 0: -1;
1027 }
1028
1029 /* That is a fake device, created when WDDM adapter is initialized. */
1030 *ppvMap = malloc(u32RegionSize);
1031 if (*ppvMap)
1032 {
1033 *pu32GmrId = 0;
1034 return 0;
1035 }
1036
1037 return -1;
1038}
1039
1040static bool
1041vboxDdiRegionDestroy(GaKmtCallbacks *pKmtCallbacks,
1042 uint32_t u32GmrId)
1043{
1044 VBOXDISPIFESCAPE_GAREGION data;
1045 memset(&data, 0, sizeof(data));
1046 data.EscapeHdr.escapeCode = VBOXESC_GAREGION;
1047 // data.EscapeHdr.cmdSpecific = 0;
1048 data.u32Command = GA_REGION_CMD_DESTROY;
1049 // data.u32NumPages = 0;
1050 data.u32GmrId = u32GmrId;
1051 // data.u64UserAddress = 0;
1052
1053 D3DKMT_ESCAPE EscapeData;
1054 memset(&EscapeData, 0, sizeof(EscapeData));
1055 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
1056 EscapeData.hDevice = pKmtCallbacks->hDevice;
1057 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
1058 // EscapeData.Flags.HardwareAccess = 0;
1059 EscapeData.pPrivateDriverData = &data;
1060 EscapeData.PrivateDriverDataSize = sizeof(data);
1061 // EscapeData.hContext = 0;
1062
1063 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
1064 Assert(Status == STATUS_SUCCESS);
1065 return Status == STATUS_SUCCESS;
1066}
1067
1068/* static */ DECLCALLBACK(void)
1069GaDrvEnvKmt::gaEnvRegionDestroy(void *pvEnv,
1070 uint32_t u32GmrId,
1071 void *pvMap)
1072{
1073 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
1074
1075 if (pThis->mKmtCallbacks.hDevice)
1076 {
1077 vboxDdiRegionDestroy(&pThis->mKmtCallbacks, u32GmrId);
1078 }
1079 else
1080 {
1081 free(pvMap);
1082 }
1083}
1084
1085/* static */ DECLCALLBACK(int)
1086GaDrvEnvKmt::gaEnvGBSurfaceDefine(void *pvEnv,
1087 SVGAGBSURFCREATE *pCreateParms)
1088{
1089 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
1090
1091 VBOXDISPIFESCAPE_SVGAGBSURFACEDEFINE data;
1092 data.EscapeHdr.escapeCode = VBOXESC_SVGAGBSURFACEDEFINE;
1093 data.EscapeHdr.u32CmdSpecific = 0;
1094 data.CreateParms = *pCreateParms;
1095
1096 D3DKMT_ESCAPE EscapeData;
1097 memset(&EscapeData, 0, sizeof(EscapeData));
1098 EscapeData.hAdapter = pThis->mKmtCallbacks.hAdapter;
1099 EscapeData.hDevice = pThis->mKmtCallbacks.hDevice;
1100 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
1101 EscapeData.Flags.HardwareAccess = 1;
1102 EscapeData.pPrivateDriverData = &data;
1103 EscapeData.PrivateDriverDataSize = sizeof(data);
1104 // EscapeData.hContext = 0;
1105
1106 NTSTATUS Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTEscape(&EscapeData);
1107 if (Status == STATUS_SUCCESS)
1108 {
1109 pCreateParms->gmrid = data.CreateParms.gmrid;
1110 pCreateParms->cbGB = data.CreateParms.cbGB;
1111 pCreateParms->u64UserAddress = data.CreateParms.u64UserAddress;
1112 pCreateParms->u32Sid = data.CreateParms.u32Sid;
1113
1114 /* Create a kernel mode allocation for render targets,
1115 * because we will need kernel mode handles for Present.
1116 */
1117 if (pCreateParms->s.flags & SVGA3D_SURFACE_HINT_RENDERTARGET)
1118 {
1119 /* First check if the format is supported. */
1120 D3DDDIFORMAT const ddiFormat = svgaToD3DDDIFormat((SVGA3dSurfaceFormat)pCreateParms->s.format);
1121 if (ddiFormat != D3DDDIFMT_UNKNOWN)
1122 {
1123 GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)malloc(sizeof(GAWDDMSURFACEINFO));
1124 if (pSurfaceInfo)
1125 {
1126 memset(pSurfaceInfo, 0, sizeof(GAWDDMSURFACEINFO));
1127
1128 VBOXWDDM_ALLOCINFO wddmAllocInfo;
1129 memset(&wddmAllocInfo, 0, sizeof(wddmAllocInfo));
1130
1131 wddmAllocInfo.enmType = VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC;
1132 wddmAllocInfo.fFlags.RenderTarget = 1;
1133 wddmAllocInfo.hSharedHandle = 0;
1134 wddmAllocInfo.hostID = pCreateParms->u32Sid;
1135 wddmAllocInfo.SurfDesc.slicePitch = 0;
1136 wddmAllocInfo.SurfDesc.depth = pCreateParms->s.size.depth;
1137 wddmAllocInfo.SurfDesc.width = pCreateParms->s.size.width;
1138 wddmAllocInfo.SurfDesc.height = pCreateParms->s.size.height;
1139 wddmAllocInfo.SurfDesc.format = ddiFormat;
1140 wddmAllocInfo.SurfDesc.VidPnSourceId = 0;
1141 wddmAllocInfo.SurfDesc.bpp = vboxWddmCalcBitsPerPixel(wddmAllocInfo.SurfDesc.format);
1142 wddmAllocInfo.SurfDesc.pitch = vboxWddmCalcPitch(wddmAllocInfo.SurfDesc.width,
1143 wddmAllocInfo.SurfDesc.format);
1144 wddmAllocInfo.SurfDesc.cbSize = vboxWddmCalcSize(wddmAllocInfo.SurfDesc.pitch,
1145 wddmAllocInfo.SurfDesc.height,
1146 wddmAllocInfo.SurfDesc.format);
1147 wddmAllocInfo.SurfDesc.d3dWidth = vboxWddmCalcWidthForPitch(wddmAllocInfo.SurfDesc.pitch,
1148 wddmAllocInfo.SurfDesc.format);
1149
1150 D3DDDI_ALLOCATIONINFO AllocationInfo;
1151 memset(&AllocationInfo, 0, sizeof(AllocationInfo));
1152 // AllocationInfo.hAllocation = NULL;
1153 // AllocationInfo.pSystemMem = NULL;
1154 AllocationInfo.pPrivateDriverData = &wddmAllocInfo;
1155 AllocationInfo.PrivateDriverDataSize = sizeof(wddmAllocInfo);
1156
1157 D3DKMT_CREATEALLOCATION CreateAllocation;
1158 memset(&CreateAllocation, 0, sizeof(CreateAllocation));
1159 CreateAllocation.hDevice = pThis->mKmtCallbacks.hDevice;
1160 CreateAllocation.NumAllocations = 1;
1161 CreateAllocation.pAllocationInfo = &AllocationInfo;
1162
1163 Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTCreateAllocation(&CreateAllocation);
1164 if (Status == STATUS_SUCCESS)
1165 {
1166 pSurfaceInfo->Core.Key = pCreateParms->u32Sid;
1167 pSurfaceInfo->hAllocation = AllocationInfo.hAllocation;
1168 if (!RTAvlU32Insert(&pThis->mSurfaceTree, &pSurfaceInfo->Core))
1169 {
1170 Status = STATUS_NOT_SUPPORTED;
1171 }
1172 }
1173
1174 if (Status != STATUS_SUCCESS)
1175 {
1176 free(pSurfaceInfo);
1177 }
1178 }
1179 else
1180 {
1181 Status = STATUS_NOT_SUPPORTED;
1182 }
1183 }
1184 else
1185 {
1186 /* Unsupported render target format. */
1187 Assert(0);
1188 Status = STATUS_NOT_SUPPORTED;
1189 }
1190 }
1191
1192 if (Status != STATUS_SUCCESS)
1193 {
1194 gaEnvSurfaceDestroy(pvEnv, pCreateParms->u32Sid);
1195 }
1196 }
1197
1198 if (Status == STATUS_SUCCESS)
1199 return 0;
1200
1201 Assert(0);
1202 return -1;
1203}
1204
1205GaDrvEnvKmt::GaDrvEnvKmt()
1206 :
1207 mContextTree(0),
1208 mSurfaceTree(0)
1209{
1210 RT_ZERO(mKmtCallbacks);
1211 RT_ZERO(mHWInfo);
1212 RT_ZERO(mEnv);
1213}
1214
1215GaDrvEnvKmt::~GaDrvEnvKmt()
1216{
1217}
1218
1219HRESULT GaDrvEnvKmt::Init(void)
1220{
1221 mKmtCallbacks.d3dkmt = D3DKMTFunctions();
1222
1223 /* Figure out which adapter to use. */
1224 NTSTATUS Status = vboxDispKmtOpenAdapter2(&mKmtCallbacks.hAdapter, &mKmtCallbacks.AdapterLuid);
1225 Assert(Status == STATUS_SUCCESS);
1226 if (Status == STATUS_SUCCESS)
1227 {
1228 VBOXWDDM_QAI adapterInfo;
1229 bool fSuccess = vboxDdiQueryAdapterInfo(&mKmtCallbacks, mKmtCallbacks.hAdapter, &adapterInfo, sizeof(adapterInfo));
1230 Assert(fSuccess);
1231 if (fSuccess)
1232 {
1233 fSuccess = vboxDdiDeviceCreate(&mKmtCallbacks, &mKmtCallbacks.hDevice);
1234 Assert(fSuccess);
1235 if (fSuccess)
1236 {
1237 mHWInfo = adapterInfo.u.vmsvga.HWInfo;
1238
1239 /*
1240 * Success.
1241 */
1242 return S_OK;
1243 }
1244
1245 vboxDdiDeviceDestroy(&mKmtCallbacks, mKmtCallbacks.hDevice);
1246 }
1247
1248 vboxDispKmtCloseAdapter(mKmtCallbacks.hAdapter);
1249 }
1250
1251 return E_FAIL;
1252}
1253
1254const WDDMGalliumDriverEnv *GaDrvEnvKmt::Env()
1255{
1256 if (mEnv.cb == 0)
1257 {
1258 mEnv.cb = sizeof(WDDMGalliumDriverEnv);
1259 mEnv.pHWInfo = &mHWInfo;
1260 mEnv.pvEnv = this;
1261 mEnv.pfnContextCreate = gaEnvContextCreate;
1262 mEnv.pfnContextDestroy = gaEnvContextDestroy;
1263 mEnv.pfnSurfaceDefine = gaEnvSurfaceDefine;
1264 mEnv.pfnSurfaceDestroy = gaEnvSurfaceDestroy;
1265 mEnv.pfnRender = gaEnvRender;
1266 mEnv.pfnFenceUnref = gaEnvFenceUnref;
1267 mEnv.pfnFenceQuery = gaEnvFenceQuery;
1268 mEnv.pfnFenceWait = gaEnvFenceWait;
1269 mEnv.pfnRegionCreate = gaEnvRegionCreate;
1270 mEnv.pfnRegionDestroy = gaEnvRegionDestroy;
1271 /* VGPU10 */
1272 mEnv.pfnGBSurfaceDefine = gaEnvGBSurfaceDefine;
1273 }
1274
1275 return &mEnv;
1276}
1277
1278RT_C_DECLS_BEGIN
1279
1280const WDDMGalliumDriverEnv *GaDrvEnvKmtCreate(void)
1281{
1282 GaDrvEnvKmt *p = new GaDrvEnvKmt();
1283 if (p)
1284 {
1285 HRESULT hr = p->Init();
1286 if (hr != S_OK)
1287 {
1288 delete p;
1289 p = NULL;
1290 }
1291 }
1292 return p ? p->Env() : NULL;
1293}
1294
1295void GaDrvEnvKmtDelete(const WDDMGalliumDriverEnv *pEnv)
1296{
1297 if (pEnv)
1298 {
1299 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1300 delete p;
1301 }
1302}
1303
1304D3DKMT_HANDLE GaDrvEnvKmtContextHandle(const WDDMGalliumDriverEnv *pEnv, uint32_t u32Cid)
1305{
1306 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1307 return p->drvEnvKmtContextHandle(u32Cid);
1308}
1309
1310D3DKMT_HANDLE GaDrvEnvKmtSurfaceHandle(const WDDMGalliumDriverEnv *pEnv, uint32_t u32Sid)
1311{
1312 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1313 return p->drvEnvKmtSurfaceHandle(u32Sid);
1314}
1315
1316void GaDrvEnvKmtAdapterLUID(const WDDMGalliumDriverEnv *pEnv, LUID *pAdapterLuid)
1317{
1318 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1319 *pAdapterLuid = p->mKmtCallbacks.AdapterLuid;
1320}
1321
1322D3DKMT_HANDLE GaDrvEnvKmtAdapterHandle(const WDDMGalliumDriverEnv *pEnv)
1323{
1324 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1325 return p->mKmtCallbacks.hAdapter;
1326}
1327
1328D3DKMT_HANDLE GaDrvEnvKmtDeviceHandle(const WDDMGalliumDriverEnv *pEnv)
1329{
1330 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1331 return p->mKmtCallbacks.hDevice;
1332}
1333
1334void GaDrvEnvKmtRenderCompose(const WDDMGalliumDriverEnv *pEnv,
1335 uint32_t u32Cid,
1336 void *pvCommands,
1337 uint32_t cbCommands,
1338 ULONGLONG PresentHistoryToken)
1339{
1340 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1341 p->drvEnvKmtRenderCompose(u32Cid, pvCommands, cbCommands, PresentHistoryToken);
1342}
1343
1344RT_C_DECLS_END
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