VirtualBox

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

Last change on this file since 78601 was 78601, checked in by vboxsync, 6 years ago

VMSVGA: Fixed uninitialized pointer mSurfaceTree

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.5 KB
Line 
1/* $Id: GaDrvEnvKMT.cpp 78601 2019-05-20 15:01:25Z 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-2019 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 /*
152 * Internal.
153 */
154 bool doRender(uint32_t u32Cid, void *pvCommands, uint32_t cbCommands,
155 GAFENCEQUERY *pFenceQuery, ULONGLONG PresentHistoryToken, bool fPresentRedirected);
156};
157
158typedef struct GAWDDMCONTEXTINFO
159{
160 AVLU32NODECORE Core;
161 D3DKMT_HANDLE hContext;
162 VOID *pCommandBuffer;
163 UINT CommandBufferSize;
164 D3DDDI_ALLOCATIONLIST *pAllocationList;
165 UINT AllocationListSize;
166 D3DDDI_PATCHLOCATIONLIST *pPatchLocationList;
167 UINT PatchLocationListSize;
168} GAWDDMCONTEXTINFO;
169
170typedef struct GAWDDMSURFACEINFO
171{
172 AVLU32NODECORE Core;
173 D3DKMT_HANDLE hAllocation;
174} GAWDDMSURFACEINFO;
175
176
177/// @todo vboxDdi helpers must return a boof success indicator
178static bool
179vboxDdiQueryAdapterInfo(GaKmtCallbacks *pKmtCallbacks,
180 D3DKMT_HANDLE hAdapter,
181 VBOXWDDM_QAI *pAdapterInfo,
182 uint32_t cbAdapterInfo)
183{
184 D3DKMT_QUERYADAPTERINFO QAI;
185 memset(&QAI, 0, sizeof(QAI));
186 QAI.hAdapter = hAdapter;
187 QAI.Type = KMTQAITYPE_UMDRIVERPRIVATE;
188 QAI.pPrivateDriverData = pAdapterInfo;
189 QAI.PrivateDriverDataSize = cbAdapterInfo;
190
191 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTQueryAdapterInfo(&QAI);
192 return Status == STATUS_SUCCESS;
193}
194
195static void
196vboxDdiDeviceDestroy(GaKmtCallbacks *pKmtCallbacks,
197 D3DKMT_HANDLE hDevice)
198{
199 if (hDevice)
200 {
201 D3DKMT_DESTROYDEVICE DestroyDeviceData;
202 memset(&DestroyDeviceData, 0, sizeof(DestroyDeviceData));
203 DestroyDeviceData.hDevice = hDevice;
204 pKmtCallbacks->d3dkmt->pfnD3DKMTDestroyDevice(&DestroyDeviceData);
205 }
206}
207
208static bool
209vboxDdiDeviceCreate(GaKmtCallbacks *pKmtCallbacks,
210 D3DKMT_HANDLE *phDevice)
211{
212 D3DKMT_CREATEDEVICE CreateDeviceData;
213 memset(&CreateDeviceData, 0, sizeof(CreateDeviceData));
214 CreateDeviceData.hAdapter = pKmtCallbacks->hAdapter;
215 // CreateDeviceData.Flags = 0;
216
217 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTCreateDevice(&CreateDeviceData);
218 if (Status == STATUS_SUCCESS)
219 {
220 *phDevice = CreateDeviceData.hDevice;
221 return true;
222 }
223 return false;
224}
225
226static bool
227vboxDdiContextGetId(GaKmtCallbacks *pKmtCallbacks,
228 D3DKMT_HANDLE hContext,
229 uint32_t *pu32Cid)
230{
231 VBOXDISPIFESCAPE_GAGETCID data;
232 memset(&data, 0, sizeof(data));
233 data.EscapeHdr.escapeCode = VBOXESC_GAGETCID;
234 // data.EscapeHdr.cmdSpecific = 0;
235 // data.u32Cid = 0;
236
237 /* If the user-mode display driver sets hContext to a non-NULL value, the driver must
238 * have also set hDevice to a non-NULL value...
239 */
240 D3DKMT_ESCAPE EscapeData;
241 memset(&EscapeData, 0, sizeof(EscapeData));
242 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
243 EscapeData.hDevice = pKmtCallbacks->hDevice;
244 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
245 // EscapeData.Flags.HardwareAccess = 0;
246 EscapeData.pPrivateDriverData = &data;
247 EscapeData.PrivateDriverDataSize = sizeof(data);
248 EscapeData.hContext = hContext;
249
250 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
251 if (Status == STATUS_SUCCESS)
252 {
253 *pu32Cid = data.u32Cid;
254 return true;
255 }
256 return false;
257}
258
259static void
260vboxDdiContextDestroy(GaKmtCallbacks *pKmtCallbacks,
261 GAWDDMCONTEXTINFO *pContextInfo)
262{
263 if (pContextInfo->hContext)
264 {
265 D3DKMT_DESTROYCONTEXT DestroyContextData;
266 memset(&DestroyContextData, 0, sizeof(DestroyContextData));
267 DestroyContextData.hContext = pContextInfo->hContext;
268 pKmtCallbacks->d3dkmt->pfnD3DKMTDestroyContext(&DestroyContextData);
269 }
270}
271
272static bool
273vboxDdiContextCreate(GaKmtCallbacks *pKmtCallbacks,
274 void *pvPrivateData, uint32_t cbPrivateData,
275 GAWDDMCONTEXTINFO *pContextInfo)
276{
277 D3DKMT_CREATECONTEXT CreateContextData;
278 memset(&CreateContextData, 0, sizeof(CreateContextData));
279 CreateContextData.hDevice = pKmtCallbacks->hDevice;
280 // CreateContextData.NodeOrdinal = 0;
281 // CreateContextData.EngineAffinity = 0;
282 // CreateContextData.Flags.Value = 0;
283 CreateContextData.pPrivateDriverData = pvPrivateData;
284 CreateContextData.PrivateDriverDataSize = cbPrivateData;
285 CreateContextData.ClientHint = D3DKMT_CLIENTHINT_OPENGL;
286
287 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTCreateContext(&CreateContextData);
288 if (Status == STATUS_SUCCESS)
289 {
290 /* Query cid. */
291 uint32_t u32Cid = 0;
292 bool fSuccess = vboxDdiContextGetId(pKmtCallbacks, CreateContextData.hContext, &u32Cid);
293 if (fSuccess)
294 {
295 pContextInfo->Core.Key = u32Cid;
296 pContextInfo->hContext = CreateContextData.hContext;
297 pContextInfo->pCommandBuffer = CreateContextData.pCommandBuffer;
298 pContextInfo->CommandBufferSize = CreateContextData.CommandBufferSize;
299 pContextInfo->pAllocationList = CreateContextData.pAllocationList;
300 pContextInfo->AllocationListSize = CreateContextData.AllocationListSize;
301 pContextInfo->pPatchLocationList = CreateContextData.pPatchLocationList;
302 pContextInfo->PatchLocationListSize = CreateContextData.PatchLocationListSize;
303
304 return true;
305 }
306
307 vboxDdiContextDestroy(pKmtCallbacks, pContextInfo);
308 }
309
310 return false;
311}
312
313/* static */ DECLCALLBACK(void)
314GaDrvEnvKmt::gaEnvContextDestroy(void *pvEnv,
315 uint32_t u32Cid)
316{
317 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
318
319 GAWDDMCONTEXTINFO *pContextInfo = (GAWDDMCONTEXTINFO *)RTAvlU32Remove(&pThis->mContextTree, u32Cid);
320 if (pContextInfo)
321 {
322 vboxDdiContextDestroy(&pThis->mKmtCallbacks, pContextInfo);
323 memset(pContextInfo, 0, sizeof(*pContextInfo));
324 free(pContextInfo);
325 }
326}
327
328D3DKMT_HANDLE GaDrvEnvKmt::drvEnvKmtContextHandle(uint32_t u32Cid)
329{
330 GAWDDMCONTEXTINFO *pContextInfo = (GAWDDMCONTEXTINFO *)RTAvlU32Get(&mContextTree, u32Cid);
331 Assert(pContextInfo);
332 return pContextInfo ? pContextInfo->hContext : 0;
333}
334
335/* static */ DECLCALLBACK(uint32_t)
336GaDrvEnvKmt::gaEnvContextCreate(void *pvEnv,
337 boolean extended,
338 boolean vgpu10)
339{
340 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
341
342 GAWDDMCONTEXTINFO *pContextInfo;
343 pContextInfo = (GAWDDMCONTEXTINFO *)malloc(sizeof(GAWDDMCONTEXTINFO));
344 if (!pContextInfo)
345 return (uint32_t)-1;
346
347 VBOXWDDM_CREATECONTEXT_INFO privateData;
348 memset(&privateData, 0, sizeof(privateData));
349 privateData.u32IfVersion = 9;
350 privateData.enmType = VBOXWDDM_CONTEXT_TYPE_GA_3D;
351 privateData.u.vmsvga.u32Flags = extended? VBOXWDDM_F_GA_CONTEXT_EXTENDED: 0;
352 privateData.u.vmsvga.u32Flags |= vgpu10? VBOXWDDM_F_GA_CONTEXT_VGPU10: 0;
353
354 bool fSuccess = vboxDdiContextCreate(&pThis->mKmtCallbacks,
355 &privateData, sizeof(privateData), pContextInfo);
356 if (fSuccess)
357 {
358 if (RTAvlU32Insert(&pThis->mContextTree, &pContextInfo->Core))
359 {
360 return pContextInfo->Core.Key;
361 }
362
363 vboxDdiContextDestroy(&pThis->mKmtCallbacks,
364 pContextInfo);
365 }
366
367 Assert(0);
368 free(pContextInfo);
369 return (uint32_t)-1;
370}
371
372static D3DDDIFORMAT svgaToD3DDDIFormat(SVGA3dSurfaceFormat format)
373{
374 switch (format)
375 {
376 case SVGA3D_X8R8G8B8: return D3DDDIFMT_X8R8G8B8;
377 case SVGA3D_A8R8G8B8: return D3DDDIFMT_A8R8G8B8;
378 case SVGA3D_ALPHA8: return D3DDDIFMT_A8;
379 case SVGA3D_R8G8B8A8_UNORM: return D3DDDIFMT_A8B8G8R8;
380 case SVGA3D_A4R4G4B4: return D3DDDIFMT_A4R4G4B4;
381 case SVGA3D_LUMINANCE8: return D3DDDIFMT_L8;
382 case SVGA3D_A1R5G5B5: return D3DDDIFMT_A1R5G5B5;
383 case SVGA3D_LUMINANCE8_ALPHA8: return D3DDDIFMT_A8L8;
384 case SVGA3D_R5G6B5: return D3DDDIFMT_R5G6B5;
385 default: break;
386 }
387
388 Assert(0);
389 VBoxDispMpLoggerLogF("WDDM: EnvKMT: unsupported surface format %d\n", format);
390 return D3DDDIFMT_UNKNOWN;
391}
392
393/* static */ DECLCALLBACK(int)
394GaDrvEnvKmt::gaEnvSurfaceDefine(void *pvEnv,
395 GASURFCREATE *pCreateParms,
396 GASURFSIZE *paSizes,
397 uint32_t cSizes,
398 uint32_t *pu32Sid)
399{
400 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
401
402 D3DKMT_ESCAPE EscapeData;
403 VBOXDISPIFESCAPE_GASURFACEDEFINE *pData;
404 uint32_t cbAlloc;
405 uint8_t *pu8Req;
406 uint32_t cbReq;
407
408 /* Size of the SVGA request data */
409 cbReq = sizeof(GASURFCREATE) + cSizes * sizeof(GASURFSIZE);
410 /* How much to allocate for WDDM escape data. */
411 cbAlloc = sizeof(VBOXDISPIFESCAPE_GASURFACEDEFINE)
412 + cbReq;
413
414 pData = (VBOXDISPIFESCAPE_GASURFACEDEFINE *)malloc(cbAlloc);
415 if (!pData)
416 return -1;
417
418 pData->EscapeHdr.escapeCode = VBOXESC_GASURFACEDEFINE;
419 // pData->EscapeHdr.cmdSpecific = 0;
420 // pData->u32Sid = 0;
421 pData->cbReq = cbReq;
422 pData->cSizes = cSizes;
423
424 pu8Req = (uint8_t *)&pData[1];
425 memcpy(pu8Req, pCreateParms, sizeof(GASURFCREATE));
426 memcpy(&pu8Req[sizeof(GASURFCREATE)], paSizes, cSizes * sizeof(GASURFSIZE));
427
428 memset(&EscapeData, 0, sizeof(EscapeData));
429 EscapeData.hAdapter = pThis->mKmtCallbacks.hAdapter;
430 EscapeData.hDevice = pThis->mKmtCallbacks.hDevice;
431 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
432 EscapeData.Flags.HardwareAccess = 1;
433 EscapeData.pPrivateDriverData = pData;
434 EscapeData.PrivateDriverDataSize = cbAlloc;
435 // EscapeData.hContext = 0;
436
437 NTSTATUS Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTEscape(&EscapeData);
438 if (Status == STATUS_SUCCESS)
439 {
440 /* Create a kernel mode allocation for render targets,
441 * because we will need kernel mode handles for Present.
442 */
443 if (pCreateParms->flags & SVGA3D_SURFACE_HINT_RENDERTARGET)
444 {
445 GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)malloc(sizeof(GAWDDMSURFACEINFO));
446 if (pSurfaceInfo)
447 {
448 memset(pSurfaceInfo, 0, sizeof(GAWDDMSURFACEINFO));
449
450 VBOXWDDM_ALLOCINFO wddmAllocInfo;
451 memset(&wddmAllocInfo, 0, sizeof(wddmAllocInfo));
452
453 wddmAllocInfo.enmType = VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC;
454 wddmAllocInfo.fFlags.RenderTarget = 1;
455 wddmAllocInfo.hSharedHandle = 0;
456 wddmAllocInfo.hostID = pData->u32Sid;
457 wddmAllocInfo.SurfDesc.slicePitch = 0;
458 wddmAllocInfo.SurfDesc.depth = paSizes[0].cDepth;
459 wddmAllocInfo.SurfDesc.width = paSizes[0].cWidth;
460 wddmAllocInfo.SurfDesc.height = paSizes[0].cHeight;
461 wddmAllocInfo.SurfDesc.format = svgaToD3DDDIFormat((SVGA3dSurfaceFormat)pCreateParms->format);
462 wddmAllocInfo.SurfDesc.VidPnSourceId = 0;
463 wddmAllocInfo.SurfDesc.bpp = vboxWddmCalcBitsPerPixel(wddmAllocInfo.SurfDesc.format);
464 wddmAllocInfo.SurfDesc.pitch = vboxWddmCalcPitch(wddmAllocInfo.SurfDesc.width,
465 wddmAllocInfo.SurfDesc.format);
466 wddmAllocInfo.SurfDesc.cbSize = vboxWddmCalcSize(wddmAllocInfo.SurfDesc.pitch,
467 wddmAllocInfo.SurfDesc.height,
468 wddmAllocInfo.SurfDesc.format);
469 wddmAllocInfo.SurfDesc.d3dWidth = vboxWddmCalcWidthForPitch(wddmAllocInfo.SurfDesc.pitch,
470 wddmAllocInfo.SurfDesc.format);
471
472 D3DDDI_ALLOCATIONINFO AllocationInfo;
473 memset(&AllocationInfo, 0, sizeof(AllocationInfo));
474 // AllocationInfo.hAllocation = NULL;
475 // AllocationInfo.pSystemMem = NULL;
476 AllocationInfo.pPrivateDriverData = &wddmAllocInfo;
477 AllocationInfo.PrivateDriverDataSize = sizeof(wddmAllocInfo);
478
479 D3DKMT_CREATEALLOCATION CreateAllocation;
480 memset(&CreateAllocation, 0, sizeof(CreateAllocation));
481 CreateAllocation.hDevice = pThis->mKmtCallbacks.hDevice;
482 CreateAllocation.NumAllocations = 1;
483 CreateAllocation.pAllocationInfo = &AllocationInfo;
484
485 Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTCreateAllocation(&CreateAllocation);
486 if (Status == STATUS_SUCCESS)
487 {
488 pSurfaceInfo->Core.Key = pData->u32Sid;
489 pSurfaceInfo->hAllocation = AllocationInfo.hAllocation;
490 if (!RTAvlU32Insert(&pThis->mSurfaceTree, &pSurfaceInfo->Core))
491 {
492 Status = STATUS_NOT_SUPPORTED;
493 }
494 }
495
496 if (Status != STATUS_SUCCESS)
497 {
498 free(pSurfaceInfo);
499 }
500 }
501 else
502 {
503 Status = STATUS_NOT_SUPPORTED;
504 }
505 }
506
507 if (Status != STATUS_SUCCESS)
508 {
509 gaEnvSurfaceDestroy(pvEnv, pData->u32Sid);
510 }
511 }
512
513 if (Status == STATUS_SUCCESS)
514 {
515 *pu32Sid = pData->u32Sid;
516 free(pData);
517 return 0;
518 }
519
520 Assert(0);
521 free(pData);
522 return -1;
523}
524
525/* static */ DECLCALLBACK(void)
526GaDrvEnvKmt::gaEnvSurfaceDestroy(void *pvEnv,
527 uint32_t u32Sid)
528{
529 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
530
531 VBOXDISPIFESCAPE_GASURFACEDESTROY data;
532 memset(&data, 0, sizeof(data));
533 data.EscapeHdr.escapeCode = VBOXESC_GASURFACEDESTROY;
534 // data.EscapeHdr.cmdSpecific = 0;
535 data.u32Sid = u32Sid;
536
537 D3DKMT_ESCAPE EscapeData;
538 memset(&EscapeData, 0, sizeof(EscapeData));
539 EscapeData.hAdapter = pThis->mKmtCallbacks.hAdapter;
540 EscapeData.hDevice = pThis->mKmtCallbacks.hDevice;
541 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
542 EscapeData.Flags.HardwareAccess = 1;
543 EscapeData.pPrivateDriverData = &data;
544 EscapeData.PrivateDriverDataSize = sizeof(data);
545 // EscapeData.hContext = 0;
546
547 NTSTATUS Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTEscape(&EscapeData);
548 Assert(Status == STATUS_SUCCESS);
549
550 /* Try to remove from sid -> hAllocation map. */
551 GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)RTAvlU32Remove(&pThis->mSurfaceTree, u32Sid);
552 if (pSurfaceInfo)
553 {
554 D3DKMT_DESTROYALLOCATION DestroyAllocation;
555 memset(&DestroyAllocation, 0, sizeof(DestroyAllocation));
556 DestroyAllocation.hDevice = pThis->mKmtCallbacks.hDevice;
557 // DestroyAllocation.hResource = 0;
558 DestroyAllocation.phAllocationList = &pSurfaceInfo->hAllocation;
559 DestroyAllocation.AllocationCount = 1;
560
561 Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTDestroyAllocation(&DestroyAllocation);
562 Assert(Status == STATUS_SUCCESS);
563
564 free(pSurfaceInfo);
565 }
566}
567
568D3DKMT_HANDLE GaDrvEnvKmt::drvEnvKmtSurfaceHandle(uint32_t u32Sid)
569{
570 GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)RTAvlU32Get(&mSurfaceTree, u32Sid);
571 return pSurfaceInfo ? pSurfaceInfo->hAllocation : 0;
572}
573
574static bool
575vboxDdiFenceCreate(GaKmtCallbacks *pKmtCallbacks,
576 GAWDDMCONTEXTINFO *pContextInfo,
577 uint32_t *pu32FenceHandle)
578{
579 VBOXDISPIFESCAPE_GAFENCECREATE fenceCreate;
580 memset(&fenceCreate, 0, sizeof(fenceCreate));
581 fenceCreate.EscapeHdr.escapeCode = VBOXESC_GAFENCECREATE;
582 // fenceCreate.EscapeHdr.cmdSpecific = 0;
583
584 /* If the user-mode display driver sets hContext to a non-NULL value, the driver must
585 * have also set hDevice to a non-NULL value...
586 */
587 D3DKMT_ESCAPE EscapeData;
588 memset(&EscapeData, 0, sizeof(EscapeData));
589 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
590 EscapeData.hDevice = pKmtCallbacks->hDevice;
591 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
592 // EscapeData.Flags.HardwareAccess = 0;
593 EscapeData.pPrivateDriverData = &fenceCreate;
594 EscapeData.PrivateDriverDataSize = sizeof(fenceCreate);
595 EscapeData.hContext = pContextInfo->hContext;
596
597 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
598 if (Status == STATUS_SUCCESS)
599 {
600 *pu32FenceHandle = fenceCreate.u32FenceHandle;
601 return true;
602 }
603
604 Assert(0);
605 return false;
606}
607
608static bool
609vboxDdiFenceQuery(GaKmtCallbacks *pKmtCallbacks,
610 uint32_t u32FenceHandle,
611 GAFENCEQUERY *pFenceQuery)
612{
613 VBOXDISPIFESCAPE_GAFENCEQUERY fenceQuery;
614 memset(&fenceQuery, 0, sizeof(fenceQuery));
615 fenceQuery.EscapeHdr.escapeCode = VBOXESC_GAFENCEQUERY;
616 // fenceQuery.EscapeHdr.cmdSpecific = 0;
617 fenceQuery.u32FenceHandle = u32FenceHandle;
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 = &fenceQuery;
626 EscapeData.PrivateDriverDataSize = sizeof(fenceQuery);
627 EscapeData.hContext = 0;
628
629 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
630 if (Status == STATUS_SUCCESS)
631 {
632 pFenceQuery->u32FenceHandle = fenceQuery.u32FenceHandle;
633 pFenceQuery->u32SubmittedSeqNo = fenceQuery.u32SubmittedSeqNo;
634 pFenceQuery->u32ProcessedSeqNo = fenceQuery.u32ProcessedSeqNo;
635 pFenceQuery->u32FenceStatus = fenceQuery.u32FenceStatus;
636 return true;
637 }
638
639 Assert(0);
640 return false;
641}
642
643/* static */ DECLCALLBACK(int)
644GaDrvEnvKmt::gaEnvFenceQuery(void *pvEnv,
645 uint32_t u32FenceHandle,
646 GAFENCEQUERY *pFenceQuery)
647{
648 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
649
650 if (!pThis->mKmtCallbacks.hDevice)
651 {
652 pFenceQuery->u32FenceStatus = GA_FENCE_STATUS_NULL;
653 return 0;
654 }
655
656 bool fSuccess = vboxDdiFenceQuery(&pThis->mKmtCallbacks, u32FenceHandle, pFenceQuery);
657 return fSuccess ? 0: -1;
658}
659
660static bool
661vboxDdiFenceWait(GaKmtCallbacks *pKmtCallbacks,
662 uint32_t u32FenceHandle,
663 uint32_t u32TimeoutUS)
664{
665 VBOXDISPIFESCAPE_GAFENCEWAIT fenceWait;
666 memset(&fenceWait, 0, sizeof(fenceWait));
667 fenceWait.EscapeHdr.escapeCode = VBOXESC_GAFENCEWAIT;
668 // pFenceWait->EscapeHdr.cmdSpecific = 0;
669 fenceWait.u32FenceHandle = u32FenceHandle;
670 fenceWait.u32TimeoutUS = u32TimeoutUS;
671
672 D3DKMT_ESCAPE EscapeData;
673 memset(&EscapeData, 0, sizeof(EscapeData));
674 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
675 EscapeData.hDevice = pKmtCallbacks->hDevice;
676 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
677 // EscapeData.Flags.HardwareAccess = 0;
678 EscapeData.pPrivateDriverData = &fenceWait;
679 EscapeData.PrivateDriverDataSize = sizeof(fenceWait);
680 EscapeData.hContext = 0;
681
682 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
683 Assert(Status == STATUS_SUCCESS);
684 return Status == STATUS_SUCCESS;
685}
686
687/* static */ DECLCALLBACK(int)
688GaDrvEnvKmt::gaEnvFenceWait(void *pvEnv,
689 uint32_t u32FenceHandle,
690 uint32_t u32TimeoutUS)
691{
692 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
693
694 if (!pThis->mKmtCallbacks.hDevice)
695 return 0;
696
697 bool fSuccess = vboxDdiFenceWait(&pThis->mKmtCallbacks, u32FenceHandle, u32TimeoutUS);
698 return fSuccess ? 0 : -1;
699}
700
701static bool
702vboxDdiFenceUnref(GaKmtCallbacks *pKmtCallbacks,
703 uint32_t u32FenceHandle)
704{
705 VBOXDISPIFESCAPE_GAFENCEUNREF fenceUnref;
706 memset(&fenceUnref, 0, sizeof(fenceUnref));
707 fenceUnref.EscapeHdr.escapeCode = VBOXESC_GAFENCEUNREF;
708 // pFenceUnref->EscapeHdr.cmdSpecific = 0;
709 fenceUnref.u32FenceHandle = u32FenceHandle;
710
711 D3DKMT_ESCAPE EscapeData;
712 memset(&EscapeData, 0, sizeof(EscapeData));
713 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
714 EscapeData.hDevice = pKmtCallbacks->hDevice;
715 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
716 // EscapeData.Flags.HardwareAccess = 0;
717 EscapeData.pPrivateDriverData = &fenceUnref;
718 EscapeData.PrivateDriverDataSize = sizeof(fenceUnref);
719 EscapeData.hContext = 0;
720
721 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
722 Assert(Status == STATUS_SUCCESS);
723 return Status == STATUS_SUCCESS;
724}
725
726/* static */ DECLCALLBACK(void)
727GaDrvEnvKmt::gaEnvFenceUnref(void *pvEnv,
728 uint32_t u32FenceHandle)
729{
730 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
731
732 if (!pThis->mKmtCallbacks.hDevice)
733 return;
734
735 vboxDdiFenceUnref(&pThis->mKmtCallbacks, u32FenceHandle);
736}
737
738/** Calculate how many commands will fit in the buffer.
739 *
740 * @param pu8Commands Command buffer.
741 * @param cbCommands Size of command buffer.
742 * @param cbAvail Available buffer size..
743 * @param pu32Length Size of commands which will fit in cbAvail bytes.
744 */
745static bool
746vboxCalcCommandLength(const uint8_t *pu8Commands, uint32_t cbCommands, uint32_t cbAvail, uint32_t *pu32Length)
747{
748 uint32_t u32Length = 0;
749 const uint8_t *pu8Src = pu8Commands;
750 const uint8_t *pu8SrcEnd = pu8Commands + cbCommands;
751
752 while (pu8SrcEnd > pu8Src)
753 {
754 const uint32_t cbSrcLeft = pu8SrcEnd - pu8Src;
755 if (cbSrcLeft < sizeof(uint32_t))
756 {
757 return false;
758 }
759
760 /* Get the command id and command length. */
761 const uint32_t u32CmdId = *(uint32_t *)pu8Src;
762 uint32_t cbCmd = 0;
763
764 if (SVGA_3D_CMD_BASE <= u32CmdId && u32CmdId < SVGA_3D_CMD_MAX)
765 {
766 if (cbSrcLeft < sizeof(SVGA3dCmdHeader))
767 {
768 return false;
769 }
770
771 const SVGA3dCmdHeader *pHeader = (SVGA3dCmdHeader *)pu8Src;
772 cbCmd = sizeof(SVGA3dCmdHeader) + pHeader->size;
773 if (cbCmd % sizeof(uint32_t) != 0)
774 {
775 return false;
776 }
777 if (cbSrcLeft < cbCmd)
778 {
779 return false;
780 }
781 }
782 else
783 {
784 /* It is not expected that any of common SVGA commands will be in the command buffer
785 * because the SVGA gallium driver does not use them.
786 */
787 return false;
788 }
789
790 if (u32Length + cbCmd > cbAvail)
791 {
792 if (u32Length == 0)
793 {
794 /* No commands fit into the buffer. */
795 return false;
796 }
797 break;
798 }
799
800 pu8Src += cbCmd;
801 u32Length += cbCmd;
802 }
803
804 *pu32Length = u32Length;
805 return true;
806}
807
808static bool
809vboxDdiRender(GaKmtCallbacks *pKmtCallbacks,
810 GAWDDMCONTEXTINFO *pContextInfo, uint32_t u32FenceHandle, void *pvCommands, uint32_t cbCommands,
811 ULONGLONG PresentHistoryToken, bool fPresentRedirected)
812{
813 uint32_t cbLeft;
814 const uint8_t *pu8Src;
815
816 cbLeft = cbCommands;
817 pu8Src = (uint8_t *)pvCommands;
818 /* Even when cbCommands is 0, submit the fence. The following code deals with this. */
819 do
820 {
821 /* Actually available space. */
822 const uint32_t cbAvail = pContextInfo->CommandBufferSize;
823 if (cbAvail <= sizeof(u32FenceHandle))
824 {
825 return false;
826 }
827
828 /* How many bytes of command data still to copy. */
829 uint32_t cbCommandChunk = cbLeft;
830
831 /* How many bytes still to copy. */
832 uint32_t cbToCopy = sizeof(u32FenceHandle) + cbCommandChunk;
833
834 /* Copy the buffer identifier. */
835 if (cbToCopy <= cbAvail)
836 {
837 /* Command buffer is big enough. */
838 *(uint32_t *)pContextInfo->pCommandBuffer = u32FenceHandle;
839 }
840 else
841 {
842 /* Split. Write zero as buffer identifier. */
843 *(uint32_t *)pContextInfo->pCommandBuffer = 0;
844
845 /* Get how much commands data will fit in the buffer. */
846 if (!vboxCalcCommandLength(pu8Src, cbCommandChunk, cbAvail - sizeof(u32FenceHandle), &cbCommandChunk))
847 {
848 return false;
849 }
850
851 cbToCopy = sizeof(u32FenceHandle) + cbCommandChunk;
852 }
853
854 if (cbCommandChunk)
855 {
856 /* Copy the command data. */
857 memcpy((uint8_t *)pContextInfo->pCommandBuffer + sizeof(u32FenceHandle), pu8Src, cbCommandChunk);
858 }
859
860 /* Advance the command position. */
861 pu8Src += cbCommandChunk;
862 cbLeft -= cbCommandChunk;
863
864 D3DKMT_RENDER RenderData;
865 memset(&RenderData, 0, sizeof(RenderData));
866 RenderData.hContext = pContextInfo->hContext;
867 // RenderData.CommandOffset = 0;
868 RenderData.CommandLength = cbToCopy;
869 // RenderData.AllocationCount = 0;
870 // RenderData.PatchLocationCount = 0;
871 RenderData.PresentHistoryToken = PresentHistoryToken;
872 RenderData.Flags.PresentRedirected = fPresentRedirected;
873
874 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTRender(&RenderData);
875 Assert(Status == STATUS_SUCCESS);
876 if (Status != STATUS_SUCCESS)
877 {
878 return false;
879 }
880
881 pContextInfo->pCommandBuffer = RenderData.pNewCommandBuffer;
882 pContextInfo->CommandBufferSize = RenderData.NewCommandBufferSize;
883 pContextInfo->pAllocationList = RenderData.pNewAllocationList;
884 pContextInfo->AllocationListSize = RenderData.NewAllocationListSize;
885 pContextInfo->pPatchLocationList = RenderData.pNewPatchLocationList;
886 pContextInfo->PatchLocationListSize = RenderData.NewPatchLocationListSize;
887 } while (cbLeft);
888
889 return true;
890}
891
892bool GaDrvEnvKmt::doRender(uint32_t u32Cid, void *pvCommands, uint32_t cbCommands,
893 GAFENCEQUERY *pFenceQuery, ULONGLONG PresentHistoryToken, bool fPresentRedirected)
894{
895 uint32_t u32FenceHandle;
896 GAWDDMCONTEXTINFO *pContextInfo = (GAWDDMCONTEXTINFO *)RTAvlU32Get(&mContextTree, u32Cid);
897 if (!pContextInfo)
898 return false;
899
900 bool fSuccess = true;
901 u32FenceHandle = 0;
902 if (pFenceQuery)
903 {
904 fSuccess = vboxDdiFenceCreate(&mKmtCallbacks, pContextInfo, &u32FenceHandle);
905 }
906
907 if (fSuccess)
908 {
909 fSuccess = vboxDdiRender(&mKmtCallbacks, pContextInfo, u32FenceHandle,
910 pvCommands, cbCommands, PresentHistoryToken, fPresentRedirected);
911 if (fSuccess)
912 {
913 if (pFenceQuery)
914 {
915 if (!vboxDdiFenceQuery(&mKmtCallbacks, u32FenceHandle, pFenceQuery))
916 {
917 pFenceQuery->u32FenceStatus = GA_FENCE_STATUS_NULL;
918 }
919 }
920 }
921 }
922 return fSuccess;
923}
924
925/* static */ DECLCALLBACK(int)
926GaDrvEnvKmt::gaEnvRender(void *pvEnv,
927 uint32_t u32Cid,
928 void *pvCommands,
929 uint32_t cbCommands,
930 GAFENCEQUERY *pFenceQuery)
931{
932 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
933 return pThis->doRender(u32Cid, pvCommands, cbCommands, pFenceQuery, 0, false) ? 1 : 0;
934}
935
936bool GaDrvEnvKmt::drvEnvKmtRenderCompose(uint32_t u32Cid,
937 void *pvCommands,
938 uint32_t cbCommands,
939 ULONGLONG PresentHistoryToken)
940{
941 return doRender(u32Cid, pvCommands, cbCommands, NULL, PresentHistoryToken, true);
942}
943
944
945static bool
946vboxDdiRegionCreate(GaKmtCallbacks *pKmtCallbacks,
947 uint32_t u32RegionSize,
948 uint32_t *pu32GmrId,
949 void **ppvMap)
950{
951 VBOXDISPIFESCAPE_GAREGION data;
952 memset(&data, 0, sizeof(data));
953 data.EscapeHdr.escapeCode = VBOXESC_GAREGION;
954 // data.EscapeHdr.cmdSpecific = 0;
955 data.u32Command = GA_REGION_CMD_CREATE;
956 data.u32NumPages = (u32RegionSize + PAGE_SIZE - 1) / PAGE_SIZE;
957 // data.u32GmrId = 0;
958 // data.u64UserAddress = 0;
959
960 D3DKMT_ESCAPE EscapeData;
961 memset(&EscapeData, 0, sizeof(EscapeData));
962 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
963 EscapeData.hDevice = pKmtCallbacks->hDevice;
964 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
965 // EscapeData.Flags.HardwareAccess = 0;
966 EscapeData.pPrivateDriverData = &data;
967 EscapeData.PrivateDriverDataSize = sizeof(data);
968 // EscapeData.hContext = 0;
969
970 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
971 if (Status == STATUS_SUCCESS)
972 {
973 *pu32GmrId = data.u32GmrId;
974 *ppvMap = (void *)(uintptr_t)data.u64UserAddress;
975 return true;
976 }
977
978 Assert(0);
979 return false;
980}
981
982/* static */ DECLCALLBACK(int)
983GaDrvEnvKmt::gaEnvRegionCreate(void *pvEnv,
984 uint32_t u32RegionSize,
985 uint32_t *pu32GmrId,
986 void **ppvMap)
987{
988 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
989
990 if (pThis->mKmtCallbacks.hDevice)
991 {
992 /* That is a real device */
993 bool fSuccess = vboxDdiRegionCreate(&pThis->mKmtCallbacks, u32RegionSize, pu32GmrId, ppvMap);
994 return fSuccess ? 0: -1;
995 }
996
997 /* That is a fake device, created when WDDM adapter is initialized. */
998 *ppvMap = malloc(u32RegionSize);
999 if (*ppvMap)
1000 {
1001 *pu32GmrId = 0;
1002 return 0;
1003 }
1004
1005 return -1;
1006}
1007
1008static bool
1009vboxDdiRegionDestroy(GaKmtCallbacks *pKmtCallbacks,
1010 uint32_t u32GmrId)
1011{
1012 VBOXDISPIFESCAPE_GAREGION data;
1013 memset(&data, 0, sizeof(data));
1014 data.EscapeHdr.escapeCode = VBOXESC_GAREGION;
1015 // data.EscapeHdr.cmdSpecific = 0;
1016 data.u32Command = GA_REGION_CMD_DESTROY;
1017 // data.u32NumPages = 0;
1018 data.u32GmrId = u32GmrId;
1019 // data.u64UserAddress = 0;
1020
1021 D3DKMT_ESCAPE EscapeData;
1022 memset(&EscapeData, 0, sizeof(EscapeData));
1023 EscapeData.hAdapter = pKmtCallbacks->hAdapter;
1024 EscapeData.hDevice = pKmtCallbacks->hDevice;
1025 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
1026 // EscapeData.Flags.HardwareAccess = 0;
1027 EscapeData.pPrivateDriverData = &data;
1028 EscapeData.PrivateDriverDataSize = sizeof(data);
1029 // EscapeData.hContext = 0;
1030
1031 NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
1032 Assert(Status == STATUS_SUCCESS);
1033 return Status == STATUS_SUCCESS;
1034}
1035
1036/* static */ DECLCALLBACK(void)
1037GaDrvEnvKmt::gaEnvRegionDestroy(void *pvEnv,
1038 uint32_t u32GmrId,
1039 void *pvMap)
1040{
1041 GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
1042
1043 if (pThis->mKmtCallbacks.hDevice)
1044 {
1045 vboxDdiRegionDestroy(&pThis->mKmtCallbacks, u32GmrId);
1046 }
1047 else
1048 {
1049 free(pvMap);
1050 }
1051}
1052
1053GaDrvEnvKmt::GaDrvEnvKmt()
1054 :
1055 mContextTree(0),
1056 mSurfaceTree(0)
1057{
1058 RT_ZERO(mKmtCallbacks);
1059 RT_ZERO(mHWInfo);
1060 RT_ZERO(mEnv);
1061}
1062
1063GaDrvEnvKmt::~GaDrvEnvKmt()
1064{
1065}
1066
1067HRESULT GaDrvEnvKmt::Init(void)
1068{
1069 mKmtCallbacks.d3dkmt = D3DKMTFunctions();
1070
1071 /* Figure out which adapter to use. */
1072 NTSTATUS Status = vboxDispKmtOpenAdapter2(&mKmtCallbacks.hAdapter, &mKmtCallbacks.AdapterLuid);
1073 Assert(Status == STATUS_SUCCESS);
1074 if (Status == STATUS_SUCCESS)
1075 {
1076 VBOXWDDM_QAI adapterInfo;
1077 bool fSuccess = vboxDdiQueryAdapterInfo(&mKmtCallbacks, mKmtCallbacks.hAdapter, &adapterInfo, sizeof(adapterInfo));
1078 Assert(fSuccess);
1079 if (fSuccess)
1080 {
1081 fSuccess = vboxDdiDeviceCreate(&mKmtCallbacks, &mKmtCallbacks.hDevice);
1082 Assert(fSuccess);
1083 if (fSuccess)
1084 {
1085 mHWInfo = adapterInfo.u.vmsvga.HWInfo;
1086
1087 /*
1088 * Success.
1089 */
1090 return S_OK;
1091 }
1092
1093 vboxDdiDeviceDestroy(&mKmtCallbacks, mKmtCallbacks.hDevice);
1094 }
1095
1096 vboxDispKmtCloseAdapter(mKmtCallbacks.hAdapter);
1097 }
1098
1099 return E_FAIL;
1100}
1101
1102const WDDMGalliumDriverEnv *GaDrvEnvKmt::Env()
1103{
1104 if (mEnv.cb == 0)
1105 {
1106 mEnv.cb = sizeof(WDDMGalliumDriverEnv);
1107 mEnv.pHWInfo = &mHWInfo;
1108 mEnv.pvEnv = this;
1109 mEnv.pfnContextCreate = gaEnvContextCreate;
1110 mEnv.pfnContextDestroy = gaEnvContextDestroy;
1111 mEnv.pfnSurfaceDefine = gaEnvSurfaceDefine;
1112 mEnv.pfnSurfaceDestroy = gaEnvSurfaceDestroy;
1113 mEnv.pfnRender = gaEnvRender;
1114 mEnv.pfnFenceUnref = gaEnvFenceUnref;
1115 mEnv.pfnFenceQuery = gaEnvFenceQuery;
1116 mEnv.pfnFenceWait = gaEnvFenceWait;
1117 mEnv.pfnRegionCreate = gaEnvRegionCreate;
1118 mEnv.pfnRegionDestroy = gaEnvRegionDestroy;
1119 }
1120
1121 return &mEnv;
1122}
1123
1124RT_C_DECLS_BEGIN
1125
1126const WDDMGalliumDriverEnv *GaDrvEnvKmtCreate(void)
1127{
1128 GaDrvEnvKmt *p = new GaDrvEnvKmt();
1129 if (p)
1130 {
1131 HRESULT hr = p->Init();
1132 if (hr != S_OK)
1133 {
1134 delete p;
1135 p = NULL;
1136 }
1137 }
1138 return p ? p->Env() : NULL;
1139}
1140
1141void GaDrvEnvKmtDelete(const WDDMGalliumDriverEnv *pEnv)
1142{
1143 if (pEnv)
1144 {
1145 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1146 delete p;
1147 }
1148}
1149
1150D3DKMT_HANDLE GaDrvEnvKmtContextHandle(const WDDMGalliumDriverEnv *pEnv, uint32_t u32Cid)
1151{
1152 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1153 return p->drvEnvKmtContextHandle(u32Cid);
1154}
1155
1156D3DKMT_HANDLE GaDrvEnvKmtSurfaceHandle(const WDDMGalliumDriverEnv *pEnv, uint32_t u32Sid)
1157{
1158 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1159 return p->drvEnvKmtSurfaceHandle(u32Sid);
1160}
1161
1162void GaDrvEnvKmtAdapterLUID(const WDDMGalliumDriverEnv *pEnv, LUID *pAdapterLuid)
1163{
1164 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1165 *pAdapterLuid = p->mKmtCallbacks.AdapterLuid;
1166}
1167
1168D3DKMT_HANDLE GaDrvEnvKmtAdapterHandle(const WDDMGalliumDriverEnv *pEnv)
1169{
1170 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1171 return p->mKmtCallbacks.hAdapter;
1172}
1173
1174D3DKMT_HANDLE GaDrvEnvKmtDeviceHandle(const WDDMGalliumDriverEnv *pEnv)
1175{
1176 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1177 return p->mKmtCallbacks.hDevice;
1178}
1179
1180void GaDrvEnvKmtRenderCompose(const WDDMGalliumDriverEnv *pEnv,
1181 uint32_t u32Cid,
1182 void *pvCommands,
1183 uint32_t cbCommands,
1184 ULONGLONG PresentHistoryToken)
1185{
1186 GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
1187 p->drvEnvKmtRenderCompose(u32Cid, pvCommands, cbCommands, PresentHistoryToken);
1188}
1189
1190RT_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