VirtualBox

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

Last change on this file was 99587, checked in by vboxsync, 12 months ago

Additions/3D/win/VBoxGL: more formats. bugref:9845

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 49.9 KB
Line 
1/* $Id: GaDrvEnvKMT.cpp 99587 2023-05-03 15:45:16Z 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 /* The returning D3DDDIFMT_ value is used only to compute bpp, pitch, etc,
389 * so there is not need for an exact match.
390 */
391 switch (format)
392 {
393 case SVGA3D_X8R8G8B8: return D3DDDIFMT_X8R8G8B8;
394 case SVGA3D_A8R8G8B8: return D3DDDIFMT_A8R8G8B8;
395 case SVGA3D_ALPHA8: return D3DDDIFMT_A8;
396 case SVGA3D_A4R4G4B4: return D3DDDIFMT_A4R4G4B4;
397 case SVGA3D_LUMINANCE8: return D3DDDIFMT_L8;
398 case SVGA3D_A1R5G5B5: return D3DDDIFMT_A1R5G5B5;
399 case SVGA3D_LUMINANCE8_ALPHA8: return D3DDDIFMT_A8L8;
400 case SVGA3D_R5G6B5: return D3DDDIFMT_R5G6B5;
401 case SVGA3D_ARGB_S10E5: return D3DDDIFMT_A16B16G16R16F;
402 case SVGA3D_ARGB_S23E8: return D3DDDIFMT_A32B32G32R32F;
403 case SVGA3D_A8_UNORM: return D3DDDIFMT_A8;
404 case SVGA3D_B5G5R5A1_UNORM: return D3DDDIFMT_A1R5G5B5;
405
406 case SVGA3D_B8G8R8X8_TYPELESS:
407 case SVGA3D_B8G8R8X8_UNORM: return D3DDDIFMT_X8R8G8B8;
408 case SVGA3D_R16_FLOAT: return D3DDDIFMT_R16F;
409 case SVGA3D_R16G16_FLOAT: return D3DDDIFMT_G16R16F;
410 case SVGA3D_R16G16B16A16_FLOAT: return D3DDDIFMT_A16B16G16R16F;
411 case SVGA3D_R32_FLOAT: return D3DDDIFMT_R32F;
412 case SVGA3D_R32G32_FLOAT: return D3DDDIFMT_G32R32F;
413 case SVGA3D_R32G32B32A32_FLOAT: return D3DDDIFMT_A32B32G32R32F;
414 case SVGA3D_R8_TYPELESS:
415 case SVGA3D_R8_SINT:
416 case SVGA3D_R8_UINT:
417 case SVGA3D_R8_SNORM:
418 case SVGA3D_R8_UNORM: return D3DDDIFMT_L8;
419 case SVGA3D_R8G8_TYPELESS:
420 case SVGA3D_R8G8_SINT:
421 case SVGA3D_R8G8_UINT:
422 case SVGA3D_R8G8_SNORM:
423 case SVGA3D_R8G8_UNORM: return D3DDDIFMT_A8L8;
424 case SVGA3D_R8G8B8A8_TYPELESS:
425 case SVGA3D_R8G8B8A8_SINT:
426 case SVGA3D_R8G8B8A8_UINT:
427 case SVGA3D_R8G8B8A8_SNORM:
428 case SVGA3D_R8G8B8A8_UNORM: return D3DDDIFMT_A8R8G8B8;
429 case SVGA3D_R16_TYPELESS:
430 case SVGA3D_R16_SINT:
431 case SVGA3D_R16_UINT:
432 case SVGA3D_R16_SNORM:
433 case SVGA3D_R16_UNORM: return D3DDDIFMT_L16;
434 case SVGA3D_R16G16_TYPELESS:
435 case SVGA3D_R16G16_SINT:
436 case SVGA3D_R16G16_UINT:
437 case SVGA3D_R16G16_SNORM:
438 case SVGA3D_R16G16_UNORM: return D3DDDIFMT_G16R16;
439 case SVGA3D_R16G16B16A16_TYPELESS:
440 case SVGA3D_R16G16B16A16_SINT:
441 case SVGA3D_R16G16B16A16_UINT:
442 case SVGA3D_R16G16B16A16_SNORM:
443 case SVGA3D_R16G16B16A16_UNORM: return D3DDDIFMT_A16B16G16R16;
444 case SVGA3D_R32_TYPELESS:
445 case SVGA3D_R32_SINT:
446 case SVGA3D_R32_UINT: return D3DDDIFMT_R32F; /* Same size in bytes. */
447 case SVGA3D_R32G32_TYPELESS:
448 case SVGA3D_R32G32_SINT:
449 case SVGA3D_R32G32_UINT: return D3DDDIFMT_G32R32F; /* Same size in bytes. */
450 case SVGA3D_R32G32B32A32_TYPELESS:
451 case SVGA3D_R32G32B32A32_SINT:
452 case SVGA3D_R32G32B32A32_UINT: return D3DDDIFMT_A32B32G32R32F; /* Same size in bytes. */
453 case SVGA3D_R10G10B10A2_TYPELESS:
454 case SVGA3D_R10G10B10A2_UINT:
455 case SVGA3D_R10G10B10A2_UNORM: return D3DDDIFMT_A2B10G10R10;
456 case SVGA3D_B5G6R5_UNORM: return D3DDDIFMT_R5G6B5;
457 case SVGA3D_R11G11B10_FLOAT: return D3DDDIFMT_R32F;
458 case SVGA3D_B8G8R8A8_UNORM: return D3DDDIFMT_A8R8G8B8;
459 default: break;
460 }
461
462 VBoxDispMpLoggerLogF("WDDM: EnvKMT: unsupported surface format %d\n", format);
463 Assert(0);
464 return D3DDDIFMT_UNKNOWN;
465}
466
467/* static */ DECLCALLBACK(int)
468GaDrvEnvKmt::gaEnvSurfaceDefine(void *pvEnv,
469 GASURFCREATE *pCreateParms,
470 GASURFSIZE *paSizes,
471 uint32_t cSizes,
472 uint32_t *pu32Sid)
473{
474 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
475
476 D3DKMT_ESCAPE EscapeData;
477 VBOXDISPIFESCAPE_GASURFACEDEFINE *pData;
478 uint32_t cbAlloc;
479 uint8_t *pu8Req;
480 uint32_t cbReq;
481
482 /* Size of the SVGA request data */
483 cbReq = sizeof(GASURFCREATE) + cSizes * sizeof(GASURFSIZE);
484 /* How much to allocate for WDDM escape data. */
485 cbAlloc = sizeof(VBOXDISPIFESCAPE_GASURFACEDEFINE)
486 + cbReq;
487
488 pData = (VBOXDISPIFESCAPE_GASURFACEDEFINE *)malloc(cbAlloc);
489 if (!pData)
490 return -1;
491
492 pData->EscapeHdr.escapeCode = VBOXESC_GASURFACEDEFINE;
493 // pData->EscapeHdr.cmdSpecific = 0;
494 // pData->u32Sid = 0;
495 pData->cbReq = cbReq;
496 pData->cSizes = cSizes;
497
498 pu8Req = (uint8_t *)&pData[1];
499 memcpy(pu8Req, pCreateParms, sizeof(GASURFCREATE));
500 memcpy(&pu8Req[sizeof(GASURFCREATE)], paSizes, cSizes * sizeof(GASURFSIZE));
501
502 memset(&EscapeData, 0, sizeof(EscapeData));
503 EscapeData.hAdapter = pThis->mKmtCallbacks.hAdapter;
504 EscapeData.hDevice = pThis->mKmtCallbacks.hDevice;
505 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
506 EscapeData.Flags.HardwareAccess = 1;
507 EscapeData.pPrivateDriverData = pData;
508 EscapeData.PrivateDriverDataSize = cbAlloc;
509 // EscapeData.hContext = 0;
510
511 NTSTATUS Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTEscape(&EscapeData);
512 if (Status == STATUS_SUCCESS)
513 {
514 /* Create a kernel mode allocation for render targets,
515 * because we will need kernel mode handles for Present.
516 */
517 if (pCreateParms->flags & SVGA3D_SURFACE_HINT_RENDERTARGET)
518 {
519 /* First check if the format is supported. */
520 D3DDDIFORMAT const ddiFormat = svgaToD3DDDIFormat((SVGA3dSurfaceFormat)pCreateParms->format);
521 if (ddiFormat != D3DDDIFMT_UNKNOWN)
522 {
523 GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)malloc(sizeof(GAWDDMSURFACEINFO));
524 if (pSurfaceInfo)
525 {
526 memset(pSurfaceInfo, 0, sizeof(GAWDDMSURFACEINFO));
527
528 VBOXWDDM_ALLOCINFO wddmAllocInfo;
529 memset(&wddmAllocInfo, 0, sizeof(wddmAllocInfo));
530
531 wddmAllocInfo.enmType = VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC;
532 wddmAllocInfo.fFlags.RenderTarget = 1;
533 wddmAllocInfo.hSharedHandle = 0;
534 wddmAllocInfo.hostID = pData->u32Sid;
535 wddmAllocInfo.SurfDesc.slicePitch = 0;
536 wddmAllocInfo.SurfDesc.depth = paSizes[0].cDepth;
537 wddmAllocInfo.SurfDesc.width = paSizes[0].cWidth;
538 wddmAllocInfo.SurfDesc.height = paSizes[0].cHeight;
539 wddmAllocInfo.SurfDesc.format = ddiFormat;
540 wddmAllocInfo.SurfDesc.VidPnSourceId = 0;
541 wddmAllocInfo.SurfDesc.bpp = vboxWddmCalcBitsPerPixel(wddmAllocInfo.SurfDesc.format);
542 wddmAllocInfo.SurfDesc.pitch = vboxWddmCalcPitch(wddmAllocInfo.SurfDesc.width,
543 wddmAllocInfo.SurfDesc.format);
544 wddmAllocInfo.SurfDesc.cbSize = vboxWddmCalcSize(wddmAllocInfo.SurfDesc.pitch,
545 wddmAllocInfo.SurfDesc.height,
546 wddmAllocInfo.SurfDesc.format);
547 wddmAllocInfo.SurfDesc.d3dWidth = vboxWddmCalcWidthForPitch(wddmAllocInfo.SurfDesc.pitch,
548 wddmAllocInfo.SurfDesc.format);
549
550 D3DDDI_ALLOCATIONINFO AllocationInfo;
551 memset(&AllocationInfo, 0, sizeof(AllocationInfo));
552 // AllocationInfo.hAllocation = NULL;
553 // AllocationInfo.pSystemMem = NULL;
554 AllocationInfo.pPrivateDriverData = &wddmAllocInfo;
555 AllocationInfo.PrivateDriverDataSize = sizeof(wddmAllocInfo);
556
557 D3DKMT_CREATEALLOCATION CreateAllocation;
558 memset(&CreateAllocation, 0, sizeof(CreateAllocation));
559 CreateAllocation.hDevice = pThis->mKmtCallbacks.hDevice;
560 CreateAllocation.NumAllocations = 1;
561 CreateAllocation.pAllocationInfo = &AllocationInfo;
562
563 Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTCreateAllocation(&CreateAllocation);
564 if (Status == STATUS_SUCCESS)
565 {
566 pSurfaceInfo->Core.Key = pData->u32Sid;
567 pSurfaceInfo->hAllocation = AllocationInfo.hAllocation;
568 if (!RTAvlU32Insert(&pThis->mSurfaceTree, &pSurfaceInfo->Core))
569 {
570 Status = STATUS_NOT_SUPPORTED;
571 }
572 }
573
574 if (Status != STATUS_SUCCESS)
575 {
576 free(pSurfaceInfo);
577 }
578 }
579 else
580 {
581 Status = STATUS_NOT_SUPPORTED;
582 }
583 }
584 else
585 {
586 /* Unsupported render target format. */
587 Status = STATUS_NOT_SUPPORTED;
588 }
589 }
590
591 if (Status != STATUS_SUCCESS)
592 {
593 gaEnvSurfaceDestroy(pvEnv, pData->u32Sid);
594 }
595 }
596
597 if (Status == STATUS_SUCCESS)
598 {
599 *pu32Sid = pData->u32Sid;
600 free(pData);
601 return 0;
602 }
603
604 Assert(0);
605 free(pData);
606 return -1;
607}
608
609/* static */ DECLCALLBACK(void)
610GaDrvEnvKmt::gaEnvSurfaceDestroy(void *pvEnv,
611 uint32_t u32Sid)
612{
613 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
614
615 VBOXDISPIFESCAPE_GASURFACEDESTROY data;
616 memset(&data, 0, sizeof(data));
617 data.EscapeHdr.escapeCode = VBOXESC_GASURFACEDESTROY;
618 // data.EscapeHdr.cmdSpecific = 0;
619 data.u32Sid = u32Sid;
620
621 D3DKMT_ESCAPE EscapeData;
622 memset(&EscapeData, 0, sizeof(EscapeData));
623 EscapeData.hAdapter = pThis->mKmtCallbacks.hAdapter;
624 EscapeData.hDevice = pThis->mKmtCallbacks.hDevice;
625 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
626 EscapeData.Flags.HardwareAccess = 1;
627 EscapeData.pPrivateDriverData = &data;
628 EscapeData.PrivateDriverDataSize = sizeof(data);
629 // EscapeData.hContext = 0;
630
631 NTSTATUS Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTEscape(&EscapeData);
632 Assert(Status == STATUS_SUCCESS);
633
634 /* Try to remove from sid -> hAllocation map. */
635 GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)RTAvlU32Remove(&pThis->mSurfaceTree, u32Sid);
636 if (pSurfaceInfo)
637 {
638 D3DKMT_DESTROYALLOCATION DestroyAllocation;
639 memset(&DestroyAllocation, 0, sizeof(DestroyAllocation));
640 DestroyAllocation.hDevice = pThis->mKmtCallbacks.hDevice;
641 // DestroyAllocation.hResource = 0;
642 DestroyAllocation.phAllocationList = &pSurfaceInfo->hAllocation;
643 DestroyAllocation.AllocationCount = 1;
644
645 Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTDestroyAllocation(&DestroyAllocation);
646 Assert(Status == STATUS_SUCCESS);
647
648 free(pSurfaceInfo);
649 }
650}
651
652D3DKMT_HANDLE GaDrvEnvKmt::drvEnvKmtSurfaceHandle(uint32_t u32Sid)
653{
654 GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)RTAvlU32Get(&mSurfaceTree, u32Sid);
655 return pSurfaceInfo ? pSurfaceInfo->hAllocation : 0;
656}
657
658static bool
659vboxDdiFenceCreate(GaKmtCallbacks *pKmtCallbacks,
660 GAWDDMCONTEXTINFO *pContextInfo,
661 uint32_t *pu32FenceHandle)
662{
663 VBOXDISPIFESCAPE_GAFENCECREATE fenceCreate;
664 memset(&fenceCreate, 0, sizeof(fenceCreate));
665 fenceCreate.EscapeHdr.escapeCode = VBOXESC_GAFENCECREATE;
666 // fenceCreate.EscapeHdr.cmdSpecific = 0;
667
668 /* If the user-mode display driver sets hContext to a non-NULL value, the driver must
669 * have also set hDevice to a non-NULL value...
670 */
671 D3DKMT_ESCAPE EscapeData;
672 memset(&EscapeData, 0, sizeof(EscapeData));
673 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
674 EscapeData.hDevice = pKmtCallbacks->hDevice;
675 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
676 // EscapeData.Flags.HardwareAccess = 0;
677 EscapeData.pPrivateDriverData = &fenceCreate;
678 EscapeData.PrivateDriverDataSize = sizeof(fenceCreate);
679 EscapeData.hContext = pContextInfo->hContext;
680
681 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
682 if (Status == STATUS_SUCCESS)
683 {
684 *pu32FenceHandle = fenceCreate.u32FenceHandle;
685 return true;
686 }
687
688 Assert(0);
689 return false;
690}
691
692static bool
693vboxDdiFenceQuery(GaKmtCallbacks *pKmtCallbacks,
694 uint32_t u32FenceHandle,
695 GAFENCEQUERY *pFenceQuery)
696{
697 VBOXDISPIFESCAPE_GAFENCEQUERY fenceQuery;
698 memset(&fenceQuery, 0, sizeof(fenceQuery));
699 fenceQuery.EscapeHdr.escapeCode = VBOXESC_GAFENCEQUERY;
700 // fenceQuery.EscapeHdr.cmdSpecific = 0;
701 fenceQuery.u32FenceHandle = u32FenceHandle;
702
703 D3DKMT_ESCAPE EscapeData;
704 memset(&EscapeData, 0, sizeof(EscapeData));
705 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
706 EscapeData.hDevice = pKmtCallbacks->hDevice;
707 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
708 // EscapeData.Flags.HardwareAccess = 0;
709 EscapeData.pPrivateDriverData = &fenceQuery;
710 EscapeData.PrivateDriverDataSize = sizeof(fenceQuery);
711 EscapeData.hContext = 0;
712
713 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
714 if (Status == STATUS_SUCCESS)
715 {
716 pFenceQuery->u32FenceHandle = fenceQuery.u32FenceHandle;
717 pFenceQuery->u32SubmittedSeqNo = fenceQuery.u32SubmittedSeqNo;
718 pFenceQuery->u32ProcessedSeqNo = fenceQuery.u32ProcessedSeqNo;
719 pFenceQuery->u32FenceStatus = fenceQuery.u32FenceStatus;
720 return true;
721 }
722
723 Assert(0);
724 return false;
725}
726
727/* static */ DECLCALLBACK(int)
728GaDrvEnvKmt::gaEnvFenceQuery(void *pvEnv,
729 uint32_t u32FenceHandle,
730 GAFENCEQUERY *pFenceQuery)
731{
732 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
733
734 if (!pThis->mKmtCallbacks.hDevice)
735 {
736 pFenceQuery->u32FenceStatus = GA_FENCE_STATUS_NULL;
737 return 0;
738 }
739
740 bool fSuccess = vboxDdiFenceQuery(&pThis->mKmtCallbacks, u32FenceHandle, pFenceQuery);
741 return fSuccess ? 0: -1;
742}
743
744static bool
745vboxDdiFenceWait(GaKmtCallbacks *pKmtCallbacks,
746 uint32_t u32FenceHandle,
747 uint32_t u32TimeoutUS)
748{
749 VBOXDISPIFESCAPE_GAFENCEWAIT fenceWait;
750 memset(&fenceWait, 0, sizeof(fenceWait));
751 fenceWait.EscapeHdr.escapeCode = VBOXESC_GAFENCEWAIT;
752 // pFenceWait->EscapeHdr.cmdSpecific = 0;
753 fenceWait.u32FenceHandle = u32FenceHandle;
754 fenceWait.u32TimeoutUS = u32TimeoutUS;
755
756 D3DKMT_ESCAPE EscapeData;
757 memset(&EscapeData, 0, sizeof(EscapeData));
758 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
759 EscapeData.hDevice = pKmtCallbacks->hDevice;
760 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
761 // EscapeData.Flags.HardwareAccess = 0;
762 EscapeData.pPrivateDriverData = &fenceWait;
763 EscapeData.PrivateDriverDataSize = sizeof(fenceWait);
764 EscapeData.hContext = 0;
765
766 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
767 Assert(Status == STATUS_SUCCESS);
768 return Status == STATUS_SUCCESS;
769}
770
771/* static */ DECLCALLBACK(int)
772GaDrvEnvKmt::gaEnvFenceWait(void *pvEnv,
773 uint32_t u32FenceHandle,
774 uint32_t u32TimeoutUS)
775{
776 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
777
778 if (!pThis->mKmtCallbacks.hDevice)
779 return 0;
780
781 bool fSuccess = vboxDdiFenceWait(&pThis->mKmtCallbacks, u32FenceHandle, u32TimeoutUS);
782 return fSuccess ? 0 : -1;
783}
784
785static bool
786vboxDdiFenceUnref(GaKmtCallbacks *pKmtCallbacks,
787 uint32_t u32FenceHandle)
788{
789 VBOXDISPIFESCAPE_GAFENCEUNREF fenceUnref;
790 memset(&fenceUnref, 0, sizeof(fenceUnref));
791 fenceUnref.EscapeHdr.escapeCode = VBOXESC_GAFENCEUNREF;
792 // pFenceUnref->EscapeHdr.cmdSpecific = 0;
793 fenceUnref.u32FenceHandle = u32FenceHandle;
794
795 D3DKMT_ESCAPE EscapeData;
796 memset(&EscapeData, 0, sizeof(EscapeData));
797 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
798 EscapeData.hDevice = pKmtCallbacks->hDevice;
799 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
800 // EscapeData.Flags.HardwareAccess = 0;
801 EscapeData.pPrivateDriverData = &fenceUnref;
802 EscapeData.PrivateDriverDataSize = sizeof(fenceUnref);
803 EscapeData.hContext = 0;
804
805 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
806 Assert(Status == STATUS_SUCCESS);
807 return Status == STATUS_SUCCESS;
808}
809
810/* static */ DECLCALLBACK(void)
811GaDrvEnvKmt::gaEnvFenceUnref(void *pvEnv,
812 uint32_t u32FenceHandle)
813{
814 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
815
816 if (!pThis->mKmtCallbacks.hDevice)
817 return;
818
819 vboxDdiFenceUnref(&pThis->mKmtCallbacks, u32FenceHandle);
820}
821
822/** Calculate how many commands will fit in the buffer.
823 *
824 * @param pu8Commands Command buffer.
825 * @param cbCommands Size of command buffer.
826 * @param cbAvail Available buffer size..
827 * @param pu32Length Size of commands which will fit in cbAvail bytes.
828 */
829static bool
830vboxCalcCommandLength(const uint8_t *pu8Commands, uint32_t cbCommands, uint32_t cbAvail, uint32_t *pu32Length)
831{
832 uint32_t u32Length = 0;
833 const uint8_t *pu8Src = pu8Commands;
834 const uint8_t *pu8SrcEnd = pu8Commands + cbCommands;
835
836 while (pu8SrcEnd > pu8Src)
837 {
838 const uint32_t cbSrcLeft = pu8SrcEnd - pu8Src;
839 if (cbSrcLeft < sizeof(uint32_t))
840 {
841 return false;
842 }
843
844 /* Get the command id and command length. */
845 const uint32_t u32CmdId = *(uint32_t *)pu8Src;
846 uint32_t cbCmd = 0;
847
848 if (SVGA_3D_CMD_BASE <= u32CmdId && u32CmdId < SVGA_3D_CMD_MAX)
849 {
850 if (cbSrcLeft < sizeof(SVGA3dCmdHeader))
851 {
852 return false;
853 }
854
855 const SVGA3dCmdHeader *pHeader = (SVGA3dCmdHeader *)pu8Src;
856 cbCmd = sizeof(SVGA3dCmdHeader) + pHeader->size;
857 if (cbCmd % sizeof(uint32_t) != 0)
858 {
859 return false;
860 }
861 if (cbSrcLeft < cbCmd)
862 {
863 return false;
864 }
865 }
866 else
867 {
868 /* It is not expected that any of common SVGA commands will be in the command buffer
869 * because the SVGA gallium driver does not use them.
870 */
871 return false;
872 }
873
874 if (u32Length + cbCmd > cbAvail)
875 {
876 if (u32Length == 0)
877 {
878 /* No commands fit into the buffer. */
879 return false;
880 }
881 break;
882 }
883
884 pu8Src += cbCmd;
885 u32Length += cbCmd;
886 }
887
888 *pu32Length = u32Length;
889 return true;
890}
891
892static bool
893vboxDdiRender(GaKmtCallbacks *pKmtCallbacks,
894 GAWDDMCONTEXTINFO *pContextInfo, uint32_t u32FenceHandle, void *pvCommands, uint32_t cbCommands,
895 ULONGLONG PresentHistoryToken, bool fPresentRedirected)
896{
897 uint32_t cbLeft;
898 const uint8_t *pu8Src;
899
900 cbLeft = cbCommands;
901 pu8Src = (uint8_t *)pvCommands;
902 /* Even when cbCommands is 0, submit the fence. The following code deals with this. */
903 do
904 {
905 /* Actually available space. */
906 const uint32_t cbAvail = pContextInfo->CommandBufferSize;
907 if (cbAvail <= sizeof(u32FenceHandle))
908 {
909 return false;
910 }
911
912 /* How many bytes of command data still to copy. */
913 uint32_t cbCommandChunk = cbLeft;
914
915 /* How many bytes still to copy. */
916 uint32_t cbToCopy = sizeof(u32FenceHandle) + cbCommandChunk;
917
918 /* Copy the buffer identifier. */
919 if (cbToCopy <= cbAvail)
920 {
921 /* Command buffer is big enough. */
922 *(uint32_t *)pContextInfo->pCommandBuffer = u32FenceHandle;
923 }
924 else
925 {
926 /* Split. Write zero as buffer identifier. */
927 *(uint32_t *)pContextInfo->pCommandBuffer = 0;
928
929 /* Get how much commands data will fit in the buffer. */
930 if (!vboxCalcCommandLength(pu8Src, cbCommandChunk, cbAvail - sizeof(u32FenceHandle), &cbCommandChunk))
931 {
932 return false;
933 }
934
935 cbToCopy = sizeof(u32FenceHandle) + cbCommandChunk;
936 }
937
938 if (cbCommandChunk)
939 {
940 /* Copy the command data. */
941 memcpy((uint8_t *)pContextInfo->pCommandBuffer + sizeof(u32FenceHandle), pu8Src, cbCommandChunk);
942 }
943
944 /* Advance the command position. */
945 pu8Src += cbCommandChunk;
946 cbLeft -= cbCommandChunk;
947
948 D3DKMT_RENDER RenderData;
949 memset(&RenderData, 0, sizeof(RenderData));
950 RenderData.hContext = pContextInfo->hContext;
951 // RenderData.CommandOffset = 0;
952 RenderData.CommandLength = cbToCopy;
953 // RenderData.AllocationCount = 0;
954 // RenderData.PatchLocationCount = 0;
955 RenderData.PresentHistoryToken = PresentHistoryToken;
956 RenderData.Flags.PresentRedirected = fPresentRedirected;
957
958 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTRender(&RenderData);
959 Assert(Status == STATUS_SUCCESS);
960 if (Status != STATUS_SUCCESS)
961 {
962 return false;
963 }
964
965 pContextInfo->pCommandBuffer = RenderData.pNewCommandBuffer;
966 pContextInfo->CommandBufferSize = RenderData.NewCommandBufferSize;
967 pContextInfo->pAllocationList = RenderData.pNewAllocationList;
968 pContextInfo->AllocationListSize = RenderData.NewAllocationListSize;
969 pContextInfo->pPatchLocationList = RenderData.pNewPatchLocationList;
970 pContextInfo->PatchLocationListSize = RenderData.NewPatchLocationListSize;
971 } while (cbLeft);
972
973 return true;
974}
975
976bool GaDrvEnvKmt::doRender(uint32_t u32Cid, void *pvCommands, uint32_t cbCommands,
977 GAFENCEQUERY *pFenceQuery, ULONGLONG PresentHistoryToken, bool fPresentRedirected)
978{
979 uint32_t u32FenceHandle;
980 GAWDDMCONTEXTINFO *pContextInfo = (GAWDDMCONTEXTINFO *)RTAvlU32Get(&mContextTree, u32Cid);
981 if (!pContextInfo)
982 return false;
983
984 bool fSuccess = true;
985 u32FenceHandle = 0;
986 if (pFenceQuery)
987 {
988 fSuccess = vboxDdiFenceCreate(&mKmtCallbacks, pContextInfo, &u32FenceHandle);
989 }
990
991 if (fSuccess)
992 {
993 fSuccess = vboxDdiRender(&mKmtCallbacks, pContextInfo, u32FenceHandle,
994 pvCommands, cbCommands, PresentHistoryToken, fPresentRedirected);
995 if (fSuccess)
996 {
997 if (pFenceQuery)
998 {
999 if (!vboxDdiFenceQuery(&mKmtCallbacks, u32FenceHandle, pFenceQuery))
1000 {
1001 pFenceQuery->u32FenceStatus = GA_FENCE_STATUS_NULL;
1002 }
1003 }
1004 }
1005 }
1006 return fSuccess;
1007}
1008
1009/* static */ DECLCALLBACK(int)
1010GaDrvEnvKmt::gaEnvRender(void *pvEnv,
1011 uint32_t u32Cid,
1012 void *pvCommands,
1013 uint32_t cbCommands,
1014 GAFENCEQUERY *pFenceQuery)
1015{
1016 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
1017 return pThis->doRender(u32Cid, pvCommands, cbCommands, pFenceQuery, 0, false) ? 1 : 0;
1018}
1019
1020bool GaDrvEnvKmt::drvEnvKmtRenderCompose(uint32_t u32Cid,
1021 void *pvCommands,
1022 uint32_t cbCommands,
1023 ULONGLONG PresentHistoryToken)
1024{
1025 return doRender(u32Cid, pvCommands, cbCommands, NULL, PresentHistoryToken, true);
1026}
1027
1028
1029static bool
1030vboxDdiRegionCreate(GaKmtCallbacks *pKmtCallbacks,
1031 uint32_t u32RegionSize,
1032 uint32_t *pu32GmrId,
1033 void **ppvMap)
1034{
1035 VBOXDISPIFESCAPE_GAREGION data;
1036 memset(&data, 0, sizeof(data));
1037 data.EscapeHdr.escapeCode = VBOXESC_GAREGION;
1038 // data.EscapeHdr.cmdSpecific = 0;
1039 data.u32Command = GA_REGION_CMD_CREATE;
1040 data.u32NumPages = (u32RegionSize + PAGE_SIZE - 1) / PAGE_SIZE;
1041 // data.u32GmrId = 0;
1042 // data.u64UserAddress = 0;
1043
1044 D3DKMT_ESCAPE EscapeData;
1045 memset(&EscapeData, 0, sizeof(EscapeData));
1046 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
1047 EscapeData.hDevice = pKmtCallbacks->hDevice;
1048 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
1049 // EscapeData.Flags.HardwareAccess = 0;
1050 EscapeData.pPrivateDriverData = &data;
1051 EscapeData.PrivateDriverDataSize = sizeof(data);
1052 // EscapeData.hContext = 0;
1053
1054 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
1055 if (Status == STATUS_SUCCESS)
1056 {
1057 *pu32GmrId = data.u32GmrId;
1058 *ppvMap = (void *)(uintptr_t)data.u64UserAddress;
1059 return true;
1060 }
1061
1062 Assert(0);
1063 return false;
1064}
1065
1066/* static */ DECLCALLBACK(int)
1067GaDrvEnvKmt::gaEnvRegionCreate(void *pvEnv,
1068 uint32_t u32RegionSize,
1069 uint32_t *pu32GmrId,
1070 void **ppvMap)
1071{
1072 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
1073
1074 if (pThis->mKmtCallbacks.hDevice)
1075 {
1076 /* That is a real device */
1077 bool fSuccess = vboxDdiRegionCreate(&pThis->mKmtCallbacks, u32RegionSize, pu32GmrId, ppvMap);
1078 return fSuccess ? 0: -1;
1079 }
1080
1081 /* That is a fake device, created when WDDM adapter is initialized. */
1082 *ppvMap = malloc(u32RegionSize);
1083 if (*ppvMap)
1084 {
1085 *pu32GmrId = 0;
1086 return 0;
1087 }
1088
1089 return -1;
1090}
1091
1092static bool
1093vboxDdiRegionDestroy(GaKmtCallbacks *pKmtCallbacks,
1094 uint32_t u32GmrId)
1095{
1096 VBOXDISPIFESCAPE_GAREGION data;
1097 memset(&data, 0, sizeof(data));
1098 data.EscapeHdr.escapeCode = VBOXESC_GAREGION;
1099 // data.EscapeHdr.cmdSpecific = 0;
1100 data.u32Command = GA_REGION_CMD_DESTROY;
1101 // data.u32NumPages = 0;
1102 data.u32GmrId = u32GmrId;
1103 // data.u64UserAddress = 0;
1104
1105 D3DKMT_ESCAPE EscapeData;
1106 memset(&EscapeData, 0, sizeof(EscapeData));
1107 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
1108 EscapeData.hDevice = pKmtCallbacks->hDevice;
1109 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
1110 EscapeData.Flags.HardwareAccess = 1; /* Sync with submitted commands. */
1111 EscapeData.pPrivateDriverData = &data;
1112 EscapeData.PrivateDriverDataSize = sizeof(data);
1113 // EscapeData.hContext = 0;
1114
1115 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
1116 Assert(Status == STATUS_SUCCESS);
1117 return Status == STATUS_SUCCESS;
1118}
1119
1120/* static */ DECLCALLBACK(void)
1121GaDrvEnvKmt::gaEnvRegionDestroy(void *pvEnv,
1122 uint32_t u32GmrId,
1123 void *pvMap)
1124{
1125 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
1126
1127 if (pThis->mKmtCallbacks.hDevice)
1128 {
1129 vboxDdiRegionDestroy(&pThis->mKmtCallbacks, u32GmrId);
1130 }
1131 else
1132 {
1133 free(pvMap);
1134 }
1135}
1136
1137/* static */ DECLCALLBACK(int)
1138GaDrvEnvKmt::gaEnvGBSurfaceDefine(void *pvEnv,
1139 SVGAGBSURFCREATE *pCreateParms)
1140{
1141 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
1142
1143 VBOXDISPIFESCAPE_SVGAGBSURFACEDEFINE data;
1144 data.EscapeHdr.escapeCode = VBOXESC_SVGAGBSURFACEDEFINE;
1145 data.EscapeHdr.u32CmdSpecific = 0;
1146 data.CreateParms = *pCreateParms;
1147
1148 D3DKMT_ESCAPE EscapeData;
1149 memset(&EscapeData, 0, sizeof(EscapeData));
1150 EscapeData.hAdapter = pThis->mKmtCallbacks.hAdapter;
1151 EscapeData.hDevice = pThis->mKmtCallbacks.hDevice;
1152 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
1153 EscapeData.Flags.HardwareAccess = 1;
1154 EscapeData.pPrivateDriverData = &data;
1155 EscapeData.PrivateDriverDataSize = sizeof(data);
1156 // EscapeData.hContext = 0;
1157
1158 NTSTATUS Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTEscape(&EscapeData);
1159 if (Status == STATUS_SUCCESS)
1160 {
1161 pCreateParms->gmrid = data.CreateParms.gmrid;
1162 pCreateParms->cbGB = data.CreateParms.cbGB;
1163 pCreateParms->u64UserAddress = data.CreateParms.u64UserAddress;
1164 pCreateParms->u32Sid = data.CreateParms.u32Sid;
1165
1166 /* Create a kernel mode allocation for render targets,
1167 * because we will need kernel mode handles for Present.
1168 */
1169 if (pCreateParms->s.flags & SVGA3D_SURFACE_HINT_RENDERTARGET)
1170 {
1171 /* First check if the format is supported. */
1172 D3DDDIFORMAT const ddiFormat = svgaToD3DDDIFormat((SVGA3dSurfaceFormat)pCreateParms->s.format);
1173 if (ddiFormat != D3DDDIFMT_UNKNOWN)
1174 {
1175 GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)malloc(sizeof(GAWDDMSURFACEINFO));
1176 if (pSurfaceInfo)
1177 {
1178 memset(pSurfaceInfo, 0, sizeof(GAWDDMSURFACEINFO));
1179
1180 VBOXWDDM_ALLOCINFO wddmAllocInfo;
1181 memset(&wddmAllocInfo, 0, sizeof(wddmAllocInfo));
1182
1183 wddmAllocInfo.enmType = VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC;
1184 wddmAllocInfo.fFlags.RenderTarget = 1;
1185 wddmAllocInfo.hSharedHandle = 0;
1186 wddmAllocInfo.hostID = pCreateParms->u32Sid;
1187 wddmAllocInfo.SurfDesc.slicePitch = 0;
1188 wddmAllocInfo.SurfDesc.depth = pCreateParms->s.size.depth;
1189 wddmAllocInfo.SurfDesc.width = pCreateParms->s.size.width;
1190 wddmAllocInfo.SurfDesc.height = pCreateParms->s.size.height;
1191 wddmAllocInfo.SurfDesc.format = ddiFormat;
1192 wddmAllocInfo.SurfDesc.VidPnSourceId = 0;
1193 wddmAllocInfo.SurfDesc.bpp = vboxWddmCalcBitsPerPixel(wddmAllocInfo.SurfDesc.format);
1194 wddmAllocInfo.SurfDesc.pitch = vboxWddmCalcPitch(wddmAllocInfo.SurfDesc.width,
1195 wddmAllocInfo.SurfDesc.format);
1196 wddmAllocInfo.SurfDesc.cbSize = vboxWddmCalcSize(wddmAllocInfo.SurfDesc.pitch,
1197 wddmAllocInfo.SurfDesc.height,
1198 wddmAllocInfo.SurfDesc.format);
1199 wddmAllocInfo.SurfDesc.d3dWidth = vboxWddmCalcWidthForPitch(wddmAllocInfo.SurfDesc.pitch,
1200 wddmAllocInfo.SurfDesc.format);
1201
1202 D3DDDI_ALLOCATIONINFO AllocationInfo;
1203 memset(&AllocationInfo, 0, sizeof(AllocationInfo));
1204 // AllocationInfo.hAllocation = NULL;
1205 // AllocationInfo.pSystemMem = NULL;
1206 AllocationInfo.pPrivateDriverData = &wddmAllocInfo;
1207 AllocationInfo.PrivateDriverDataSize = sizeof(wddmAllocInfo);
1208
1209 D3DKMT_CREATEALLOCATION CreateAllocation;
1210 memset(&CreateAllocation, 0, sizeof(CreateAllocation));
1211 CreateAllocation.hDevice = pThis->mKmtCallbacks.hDevice;
1212 CreateAllocation.NumAllocations = 1;
1213 CreateAllocation.pAllocationInfo = &AllocationInfo;
1214
1215 Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTCreateAllocation(&CreateAllocation);
1216 if (Status == STATUS_SUCCESS)
1217 {
1218 pSurfaceInfo->Core.Key = pCreateParms->u32Sid;
1219 pSurfaceInfo->hAllocation = AllocationInfo.hAllocation;
1220 if (!RTAvlU32Insert(&pThis->mSurfaceTree, &pSurfaceInfo->Core))
1221 {
1222 Status = STATUS_NOT_SUPPORTED;
1223 }
1224 }
1225
1226 if (Status != STATUS_SUCCESS)
1227 {
1228 free(pSurfaceInfo);
1229 }
1230 }
1231 else
1232 {
1233 Status = STATUS_NOT_SUPPORTED;
1234 }
1235 }
1236 else
1237 {
1238 /* Unsupported render target format. */
1239 Assert(0);
1240 Status = STATUS_NOT_SUPPORTED;
1241 }
1242 }
1243
1244 if (Status != STATUS_SUCCESS)
1245 {
1246 gaEnvSurfaceDestroy(pvEnv, pCreateParms->u32Sid);
1247 }
1248 }
1249
1250 if (Status == STATUS_SUCCESS)
1251 return 0;
1252
1253 Assert(0);
1254 return -1;
1255}
1256
1257GaDrvEnvKmt::GaDrvEnvKmt()
1258 :
1259 mContextTree(0),
1260 mSurfaceTree(0)
1261{
1262 RT_ZERO(mKmtCallbacks);
1263 RT_ZERO(mHWInfo);
1264 RT_ZERO(mEnv);
1265}
1266
1267GaDrvEnvKmt::~GaDrvEnvKmt()
1268{
1269}
1270
1271HRESULT GaDrvEnvKmt::Init(void)
1272{
1273 mKmtCallbacks.d3dkmt = D3DKMTFunctions();
1274
1275 /* Figure out which adapter to use. */
1276 NTSTATUS Status = vboxDispKmtOpenAdapter2(&mKmtCallbacks.hAdapter, &mKmtCallbacks.AdapterLuid);
1277 Assert(Status == STATUS_SUCCESS);
1278 if (Status == STATUS_SUCCESS)
1279 {
1280 VBOXWDDM_QAI adapterInfo;
1281 bool fSuccess = vboxDdiQueryAdapterInfo(&mKmtCallbacks, mKmtCallbacks.hAdapter, &adapterInfo, sizeof(adapterInfo));
1282 Assert(fSuccess);
1283 if (fSuccess)
1284 {
1285 fSuccess = vboxDdiDeviceCreate(&mKmtCallbacks, &mKmtCallbacks.hDevice);
1286 Assert(fSuccess);
1287 if (fSuccess)
1288 {
1289 mHWInfo = adapterInfo.u.vmsvga.HWInfo;
1290
1291 /*
1292 * Success.
1293 */
1294 return S_OK;
1295 }
1296
1297 vboxDdiDeviceDestroy(&mKmtCallbacks, mKmtCallbacks.hDevice);
1298 }
1299
1300 vboxDispKmtCloseAdapter(mKmtCallbacks.hAdapter);
1301 }
1302
1303 return E_FAIL;
1304}
1305
1306const WDDMGalliumDriverEnv *GaDrvEnvKmt::Env()
1307{
1308 if (mEnv.cb == 0)
1309 {
1310 mEnv.cb = sizeof(WDDMGalliumDriverEnv);
1311 mEnv.pHWInfo = &mHWInfo;
1312 mEnv.pvEnv = this;
1313 mEnv.pfnContextCreate = gaEnvContextCreate;
1314 mEnv.pfnContextDestroy = gaEnvContextDestroy;
1315 mEnv.pfnSurfaceDefine = gaEnvSurfaceDefine;
1316 mEnv.pfnSurfaceDestroy = gaEnvSurfaceDestroy;
1317 mEnv.pfnRender = gaEnvRender;
1318 mEnv.pfnFenceUnref = gaEnvFenceUnref;
1319 mEnv.pfnFenceQuery = gaEnvFenceQuery;
1320 mEnv.pfnFenceWait = gaEnvFenceWait;
1321 mEnv.pfnRegionCreate = gaEnvRegionCreate;
1322 mEnv.pfnRegionDestroy = gaEnvRegionDestroy;
1323 /* VGPU10 */
1324 mEnv.pfnGBSurfaceDefine = gaEnvGBSurfaceDefine;
1325 }
1326
1327 return &mEnv;
1328}
1329
1330RT_C_DECLS_BEGIN
1331
1332const WDDMGalliumDriverEnv *GaDrvEnvKmtCreate(void)
1333{
1334 GaDrvEnvKmt *p = new GaDrvEnvKmt();
1335 if (p)
1336 {
1337 HRESULT hr = p->Init();
1338 if (hr != S_OK)
1339 {
1340 delete p;
1341 p = NULL;
1342 }
1343 }
1344 return p ? p->Env() : NULL;
1345}
1346
1347void GaDrvEnvKmtDelete(const WDDMGalliumDriverEnv *pEnv)
1348{
1349 if (pEnv)
1350 {
1351 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1352 delete p;
1353 }
1354}
1355
1356D3DKMT_HANDLE GaDrvEnvKmtContextHandle(const WDDMGalliumDriverEnv *pEnv, uint32_t u32Cid)
1357{
1358 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1359 return p->drvEnvKmtContextHandle(u32Cid);
1360}
1361
1362D3DKMT_HANDLE GaDrvEnvKmtSurfaceHandle(const WDDMGalliumDriverEnv *pEnv, uint32_t u32Sid)
1363{
1364 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1365 return p->drvEnvKmtSurfaceHandle(u32Sid);
1366}
1367
1368void GaDrvEnvKmtAdapterLUID(const WDDMGalliumDriverEnv *pEnv, LUID *pAdapterLuid)
1369{
1370 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1371 *pAdapterLuid = p->mKmtCallbacks.AdapterLuid;
1372}
1373
1374D3DKMT_HANDLE GaDrvEnvKmtAdapterHandle(const WDDMGalliumDriverEnv *pEnv)
1375{
1376 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1377 return p->mKmtCallbacks.hAdapter;
1378}
1379
1380D3DKMT_HANDLE GaDrvEnvKmtDeviceHandle(const WDDMGalliumDriverEnv *pEnv)
1381{
1382 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1383 return p->mKmtCallbacks.hDevice;
1384}
1385
1386void GaDrvEnvKmtRenderCompose(const WDDMGalliumDriverEnv *pEnv,
1387 uint32_t u32Cid,
1388 void *pvCommands,
1389 uint32_t cbCommands,
1390 ULONGLONG PresentHistoryToken)
1391{
1392 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1393 p->drvEnvKmtRenderCompose(u32Cid, pvCommands, cbCommands, PresentHistoryToken);
1394}
1395
1396RT_C_DECLS_END
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use