VirtualBox

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

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

Additions/3D/win/VBoxGL: another format. bugref:9845

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