summaryrefslogtreecommitdiffstats
path: root/src/VBox/Additions/3D/win
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:49:04 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:49:04 +0000
commit16f504a9dca3fe3b70568f67b7d41241ae485288 (patch)
treec60f36ada0496ba928b7161059ba5ab1ab224f9d /src/VBox/Additions/3D/win
parentInitial commit. (diff)
downloadvirtualbox-upstream.tar.xz
virtualbox-upstream.zip
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Additions/3D/win')
-rw-r--r--src/VBox/Additions/3D/win/Makefile.kmk37
-rw-r--r--src/VBox/Additions/3D/win/VBoxGL/GaDrvEnvKMT.cpp1344
-rw-r--r--src/VBox/Additions/3D/win/VBoxGL/GaDrvEnvKMT.h58
-rw-r--r--src/VBox/Additions/3D/win/VBoxGL/Makefile.kmk87
-rw-r--r--src/VBox/Additions/3D/win/VBoxGL/VBoxGL.c580
-rw-r--r--src/VBox/Additions/3D/win/VBoxGL/VBoxGL.rc66
-rw-r--r--src/VBox/Additions/3D/win/VBoxICD/.scm-settings29
-rw-r--r--src/VBox/Additions/3D/win/VBoxICD/Makefile.kmk85
-rw-r--r--src/VBox/Additions/3D/win/VBoxICD/VBoxICD.c165
-rw-r--r--src/VBox/Additions/3D/win/VBoxICD/VBoxICD.rc66
-rwxr-xr-xsrc/VBox/Additions/3D/win/VBoxICD/icd_forwarders.py105
-rwxr-xr-xsrc/VBox/Additions/3D/win/VBoxICD/icd_pfns.py73
-rw-r--r--src/VBox/Additions/3D/win/VBoxICD/opengl32.def388
-rw-r--r--src/VBox/Additions/3D/win/VBoxICD/opengl32.mingw.def388
-rw-r--r--src/VBox/Additions/3D/win/VBoxNine/Makefile.kmk74
-rw-r--r--src/VBox/Additions/3D/win/VBoxNine/VBoxNine.c181
-rw-r--r--src/VBox/Additions/3D/win/VBoxNine/VBoxNine.def34
-rw-r--r--src/VBox/Additions/3D/win/VBoxNine/VBoxNine.rc66
-rw-r--r--src/VBox/Additions/3D/win/VBoxNine/nine/nine_memory_helper.c176
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/.scm-settings28
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/Makefile.kmk85
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/VBoxSVGA.c146
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/VBoxSVGA.def36
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/VBoxSVGA.rc66
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/wddm_screen.h47
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/winsys/Makefile.kup0
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen.c134
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_ioctl.c979
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_wddm.c177
-rw-r--r--src/VBox/Additions/3D/win/VBoxWddmUmHlp/D3DKMT.cpp260
-rw-r--r--src/VBox/Additions/3D/win/VBoxWddmUmHlp/Makefile.kmk54
-rw-r--r--src/VBox/Additions/3D/win/VBoxWddmUmHlp/UmHlpInternal.h36
-rw-r--r--src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxMpLogger.cpp167
-rw-r--r--src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxWddmUmHlp.h116
-rw-r--r--src/VBox/Additions/3D/win/include/VBoxGaDriver.h115
-rw-r--r--src/VBox/Additions/3D/win/include/VBoxGaHWInfo.h64
-rw-r--r--src/VBox/Additions/3D/win/include/VBoxGaHwSVGA.h66
-rw-r--r--src/VBox/Additions/3D/win/include/VBoxGaNine.h58
-rw-r--r--src/VBox/Additions/3D/win/include/VBoxGaTypes.h114
39 files changed, 6750 insertions, 0 deletions
diff --git a/src/VBox/Additions/3D/win/Makefile.kmk b/src/VBox/Additions/3D/win/Makefile.kmk
new file mode 100644
index 00000000..6e21e0fc
--- /dev/null
+++ b/src/VBox/Additions/3D/win/Makefile.kmk
@@ -0,0 +1,37 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for the Windows guest components using Mesa3D.
+#
+
+#
+# Copyright (C) 2016-2022 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+# Include sub-makefile.
+include $(PATH_SUB_CURRENT)/VBoxGL/Makefile.kmk
+include $(PATH_SUB_CURRENT)/VBoxNine/Makefile.kmk
+include $(PATH_SUB_CURRENT)/VBoxSVGA/Makefile.kmk
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Additions/3D/win/VBoxGL/GaDrvEnvKMT.cpp b/src/VBox/Additions/3D/win/VBoxGL/GaDrvEnvKMT.cpp
new file mode 100644
index 00000000..c44f4d4c
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxGL/GaDrvEnvKMT.cpp
@@ -0,0 +1,1344 @@
+/* $Id: GaDrvEnvKMT.cpp $ */
+/** @file
+ * VirtualBox Windows Guest Mesa3D - Gallium driver interface to the WDDM miniport driver using Kernel Mode Thunks.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "GaDrvEnvKMT.h"
+
+#include <UmHlpInternal.h>
+
+#include "svga3d_reg.h"
+
+#include <common/wddm/VBoxMPIf.h>
+
+#include <iprt/assertcompile.h>
+#include <iprt/param.h> /* For PAGE_SIZE */
+
+AssertCompile(sizeof(HANDLE) >= sizeof(D3DKMT_HANDLE));
+
+
+/*
+ * AVL configuration.
+ */
+#define KAVL_FN(a) RTAvlU32##a
+#define KAVL_MAX_STACK 27 /* Up to 2^24 nodes. */
+#define KAVL_CHECK_FOR_EQUAL_INSERT 1 /* No duplicate keys! */
+#define KAVLNODECORE AVLU32NODECORE
+#define PKAVLNODECORE PAVLU32NODECORE
+#define PPKAVLNODECORE PPAVLU32NODECORE
+#define KAVLKEY AVLU32KEY
+#define PKAVLKEY PAVLU32KEY
+#define KAVLENUMDATA AVLU32ENUMDATA
+#define PKAVLENUMDATA PAVLU32ENUMDATA
+#define PKAVLCALLBACK PAVLU32CALLBACK
+
+
+/*
+ * AVL Compare macros
+ */
+#define KAVL_G(key1, key2) ( (key1) > (key2) )
+#define KAVL_E(key1, key2) ( (key1) == (key2) )
+#define KAVL_NE(key1, key2) ( (key1) != (key2) )
+
+
+#include <iprt/avl.h>
+
+/*
+ * Include the code.
+ */
+#define SSToDS(ptr) ptr
+#define KMAX RT_MAX
+#define kASSERT(_e) do { } while (0)
+#include "avl_Base.cpp.h"
+#include "avl_Get.cpp.h"
+//#include "avl_GetBestFit.cpp.h"
+//#include "avl_RemoveBestFit.cpp.h"
+//#include "avl_DoWithAll.cpp.h"
+#include "avl_Destroy.cpp.h"
+
+
+typedef struct GaKmtCallbacks
+{
+ D3DKMT_HANDLE hAdapter;
+ D3DKMT_HANDLE hDevice;
+ D3DKMTFUNCTIONS const *d3dkmt;
+ LUID AdapterLuid;
+} GaKmtCallbacks;
+
+class GaDrvEnvKmt
+{
+ public:
+ GaDrvEnvKmt();
+ ~GaDrvEnvKmt();
+
+ HRESULT Init(void);
+
+ const WDDMGalliumDriverEnv *Env();
+
+ /*
+ * KMT specific helpers.
+ */
+ bool drvEnvKmtRenderCompose(uint32_t u32Cid,
+ void *pvCommands,
+ uint32_t cbCommands,
+ ULONGLONG PresentHistoryToken);
+ D3DKMT_HANDLE drvEnvKmtContextHandle(uint32_t u32Cid);
+ D3DKMT_HANDLE drvEnvKmtSurfaceHandle(uint32_t u32Sid);
+
+ GaKmtCallbacks mKmtCallbacks;
+
+ private:
+
+ VBOXGAHWINFO mHWInfo;
+
+ /* Map to convert context id (cid) to WDDM context information (GAWDDMCONTEXTINFO).
+ * Key is the 32 bit context id.
+ */
+ AVLU32TREE mContextTree;
+
+ /* Map to convert surface id (sid) to WDDM surface information (GAWDDMSURFACEINFO).
+ * Key is the 32 bit surface id.
+ */
+ AVLU32TREE mSurfaceTree;
+
+ WDDMGalliumDriverEnv mEnv;
+
+ static DECLCALLBACK(uint32_t) gaEnvContextCreate(void *pvEnv,
+ boolean extended,
+ boolean vgpu10);
+ static DECLCALLBACK(void) gaEnvContextDestroy(void *pvEnv,
+ uint32_t u32Cid);
+ static DECLCALLBACK(int) gaEnvSurfaceDefine(void *pvEnv,
+ GASURFCREATE *pCreateParms,
+ GASURFSIZE *paSizes,
+ uint32_t cSizes,
+ uint32_t *pu32Sid);
+ static DECLCALLBACK(void) gaEnvSurfaceDestroy(void *pvEnv,
+ uint32_t u32Sid);
+ static DECLCALLBACK(int) gaEnvRender(void *pvEnv,
+ uint32_t u32Cid,
+ void *pvCommands,
+ uint32_t cbCommands,
+ GAFENCEQUERY *pFenceQuery);
+ static DECLCALLBACK(void) gaEnvFenceUnref(void *pvEnv,
+ uint32_t u32FenceHandle);
+ static DECLCALLBACK(int) gaEnvFenceQuery(void *pvEnv,
+ uint32_t u32FenceHandle,
+ GAFENCEQUERY *pFenceQuery);
+ static DECLCALLBACK(int) gaEnvFenceWait(void *pvEnv,
+ uint32_t u32FenceHandle,
+ uint32_t u32TimeoutUS);
+ static DECLCALLBACK(int) gaEnvRegionCreate(void *pvEnv,
+ uint32_t u32RegionSize,
+ uint32_t *pu32GmrId,
+ void **ppvMap);
+ static DECLCALLBACK(void) gaEnvRegionDestroy(void *pvEnv,
+ uint32_t u32GmrId,
+ void *pvMap);
+
+ /* VGPU10 */
+ static DECLCALLBACK(int) gaEnvGBSurfaceDefine(void *pvEnv,
+ SVGAGBSURFCREATE *pCreateParms);
+
+ /*
+ * Internal.
+ */
+ bool doRender(uint32_t u32Cid, void *pvCommands, uint32_t cbCommands,
+ GAFENCEQUERY *pFenceQuery, ULONGLONG PresentHistoryToken, bool fPresentRedirected);
+};
+
+typedef struct GAWDDMCONTEXTINFO
+{
+ AVLU32NODECORE Core;
+ D3DKMT_HANDLE hContext;
+ VOID *pCommandBuffer;
+ UINT CommandBufferSize;
+ D3DDDI_ALLOCATIONLIST *pAllocationList;
+ UINT AllocationListSize;
+ D3DDDI_PATCHLOCATIONLIST *pPatchLocationList;
+ UINT PatchLocationListSize;
+} GAWDDMCONTEXTINFO;
+
+typedef struct GAWDDMSURFACEINFO
+{
+ AVLU32NODECORE Core;
+ D3DKMT_HANDLE hAllocation;
+} GAWDDMSURFACEINFO;
+
+
+/// @todo vboxDdi helpers must return a boof success indicator
+static bool
+vboxDdiQueryAdapterInfo(GaKmtCallbacks *pKmtCallbacks,
+ D3DKMT_HANDLE hAdapter,
+ VBOXWDDM_QAI *pAdapterInfo,
+ uint32_t cbAdapterInfo)
+{
+ D3DKMT_QUERYADAPTERINFO QAI;
+ memset(&QAI, 0, sizeof(QAI));
+ QAI.hAdapter = hAdapter;
+ QAI.Type = KMTQAITYPE_UMDRIVERPRIVATE;
+ QAI.pPrivateDriverData = pAdapterInfo;
+ QAI.PrivateDriverDataSize = cbAdapterInfo;
+
+ NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTQueryAdapterInfo(&QAI);
+ return Status == STATUS_SUCCESS;
+}
+
+static void
+vboxDdiDeviceDestroy(GaKmtCallbacks *pKmtCallbacks,
+ D3DKMT_HANDLE hDevice)
+{
+ if (hDevice)
+ {
+ D3DKMT_DESTROYDEVICE DestroyDeviceData;
+ memset(&DestroyDeviceData, 0, sizeof(DestroyDeviceData));
+ DestroyDeviceData.hDevice = hDevice;
+ pKmtCallbacks->d3dkmt->pfnD3DKMTDestroyDevice(&DestroyDeviceData);
+ }
+}
+
+static bool
+vboxDdiDeviceCreate(GaKmtCallbacks *pKmtCallbacks,
+ D3DKMT_HANDLE *phDevice)
+{
+ D3DKMT_CREATEDEVICE CreateDeviceData;
+ memset(&CreateDeviceData, 0, sizeof(CreateDeviceData));
+ CreateDeviceData.hAdapter = pKmtCallbacks->hAdapter;
+ // CreateDeviceData.Flags = 0;
+
+ NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTCreateDevice(&CreateDeviceData);
+ if (Status == STATUS_SUCCESS)
+ {
+ *phDevice = CreateDeviceData.hDevice;
+ return true;
+ }
+ return false;
+}
+
+static bool
+vboxDdiContextGetId(GaKmtCallbacks *pKmtCallbacks,
+ D3DKMT_HANDLE hContext,
+ uint32_t *pu32Cid)
+{
+ VBOXDISPIFESCAPE_GAGETCID data;
+ memset(&data, 0, sizeof(data));
+ data.EscapeHdr.escapeCode = VBOXESC_GAGETCID;
+ // data.EscapeHdr.cmdSpecific = 0;
+ // data.u32Cid = 0;
+
+ /* If the user-mode display driver sets hContext to a non-NULL value, the driver must
+ * have also set hDevice to a non-NULL value...
+ */
+ D3DKMT_ESCAPE EscapeData;
+ memset(&EscapeData, 0, sizeof(EscapeData));
+ EscapeData.hAdapter = pKmtCallbacks->hAdapter;
+ EscapeData.hDevice = pKmtCallbacks->hDevice;
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ // EscapeData.Flags.HardwareAccess = 0;
+ EscapeData.pPrivateDriverData = &data;
+ EscapeData.PrivateDriverDataSize = sizeof(data);
+ EscapeData.hContext = hContext;
+
+ NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
+ if (Status == STATUS_SUCCESS)
+ {
+ *pu32Cid = data.u32Cid;
+ return true;
+ }
+ return false;
+}
+
+static void
+vboxDdiContextDestroy(GaKmtCallbacks *pKmtCallbacks,
+ GAWDDMCONTEXTINFO *pContextInfo)
+{
+ if (pContextInfo->hContext)
+ {
+ D3DKMT_DESTROYCONTEXT DestroyContextData;
+ memset(&DestroyContextData, 0, sizeof(DestroyContextData));
+ DestroyContextData.hContext = pContextInfo->hContext;
+ pKmtCallbacks->d3dkmt->pfnD3DKMTDestroyContext(&DestroyContextData);
+ }
+}
+
+static bool
+vboxDdiContextCreate(GaKmtCallbacks *pKmtCallbacks,
+ void *pvPrivateData, uint32_t cbPrivateData,
+ GAWDDMCONTEXTINFO *pContextInfo)
+{
+ D3DKMT_CREATECONTEXT CreateContextData;
+ memset(&CreateContextData, 0, sizeof(CreateContextData));
+ CreateContextData.hDevice = pKmtCallbacks->hDevice;
+ // CreateContextData.NodeOrdinal = 0;
+ // CreateContextData.EngineAffinity = 0;
+ // CreateContextData.Flags.Value = 0;
+ CreateContextData.pPrivateDriverData = pvPrivateData;
+ CreateContextData.PrivateDriverDataSize = cbPrivateData;
+ CreateContextData.ClientHint = D3DKMT_CLIENTHINT_OPENGL;
+
+ NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTCreateContext(&CreateContextData);
+ if (Status == STATUS_SUCCESS)
+ {
+ /* Query cid. */
+ uint32_t u32Cid = 0;
+ bool fSuccess = vboxDdiContextGetId(pKmtCallbacks, CreateContextData.hContext, &u32Cid);
+ if (fSuccess)
+ {
+ pContextInfo->Core.Key = u32Cid;
+ pContextInfo->hContext = CreateContextData.hContext;
+ pContextInfo->pCommandBuffer = CreateContextData.pCommandBuffer;
+ pContextInfo->CommandBufferSize = CreateContextData.CommandBufferSize;
+ pContextInfo->pAllocationList = CreateContextData.pAllocationList;
+ pContextInfo->AllocationListSize = CreateContextData.AllocationListSize;
+ pContextInfo->pPatchLocationList = CreateContextData.pPatchLocationList;
+ pContextInfo->PatchLocationListSize = CreateContextData.PatchLocationListSize;
+
+ return true;
+ }
+
+ vboxDdiContextDestroy(pKmtCallbacks, pContextInfo);
+ }
+
+ return false;
+}
+
+/* static */ DECLCALLBACK(void)
+GaDrvEnvKmt::gaEnvContextDestroy(void *pvEnv,
+ uint32_t u32Cid)
+{
+ GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
+
+ GAWDDMCONTEXTINFO *pContextInfo = (GAWDDMCONTEXTINFO *)RTAvlU32Remove(&pThis->mContextTree, u32Cid);
+ if (pContextInfo)
+ {
+ vboxDdiContextDestroy(&pThis->mKmtCallbacks, pContextInfo);
+ memset(pContextInfo, 0, sizeof(*pContextInfo));
+ free(pContextInfo);
+ }
+}
+
+D3DKMT_HANDLE GaDrvEnvKmt::drvEnvKmtContextHandle(uint32_t u32Cid)
+{
+ GAWDDMCONTEXTINFO *pContextInfo = (GAWDDMCONTEXTINFO *)RTAvlU32Get(&mContextTree, u32Cid);
+ Assert(pContextInfo);
+ return pContextInfo ? pContextInfo->hContext : 0;
+}
+
+/* static */ DECLCALLBACK(uint32_t)
+GaDrvEnvKmt::gaEnvContextCreate(void *pvEnv,
+ boolean extended,
+ boolean vgpu10)
+{
+ GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
+
+ GAWDDMCONTEXTINFO *pContextInfo;
+ pContextInfo = (GAWDDMCONTEXTINFO *)malloc(sizeof(GAWDDMCONTEXTINFO));
+ if (!pContextInfo)
+ return (uint32_t)-1;
+
+ VBOXWDDM_CREATECONTEXT_INFO privateData;
+ memset(&privateData, 0, sizeof(privateData));
+ privateData.u32IfVersion = 9;
+ privateData.enmType = VBOXWDDM_CONTEXT_TYPE_GA_3D;
+ privateData.u.vmsvga.u32Flags = extended? VBOXWDDM_F_GA_CONTEXT_EXTENDED: 0;
+ privateData.u.vmsvga.u32Flags |= vgpu10? VBOXWDDM_F_GA_CONTEXT_VGPU10: 0;
+
+ bool fSuccess = vboxDdiContextCreate(&pThis->mKmtCallbacks,
+ &privateData, sizeof(privateData), pContextInfo);
+ if (fSuccess)
+ {
+ if (RTAvlU32Insert(&pThis->mContextTree, &pContextInfo->Core))
+ {
+ return pContextInfo->Core.Key;
+ }
+
+ vboxDdiContextDestroy(&pThis->mKmtCallbacks,
+ pContextInfo);
+ }
+
+ Assert(0);
+ free(pContextInfo);
+ return (uint32_t)-1;
+}
+
+static D3DDDIFORMAT svgaToD3DDDIFormat(SVGA3dSurfaceFormat format)
+{
+ switch (format)
+ {
+ case SVGA3D_X8R8G8B8: return D3DDDIFMT_X8R8G8B8;
+ case SVGA3D_A8R8G8B8: return D3DDDIFMT_A8R8G8B8;
+ case SVGA3D_ALPHA8: return D3DDDIFMT_A8;
+ case SVGA3D_R8G8B8A8_UNORM: return D3DDDIFMT_A8B8G8R8;
+ case SVGA3D_A4R4G4B4: return D3DDDIFMT_A4R4G4B4;
+ case SVGA3D_LUMINANCE8: return D3DDDIFMT_L8;
+ case SVGA3D_A1R5G5B5: return D3DDDIFMT_A1R5G5B5;
+ case SVGA3D_LUMINANCE8_ALPHA8: return D3DDDIFMT_A8L8;
+ case SVGA3D_R5G6B5: return D3DDDIFMT_R5G6B5;
+ case SVGA3D_ARGB_S10E5: return D3DDDIFMT_A16B16G16R16F;
+ case SVGA3D_ARGB_S23E8: return D3DDDIFMT_A32B32G32R32F;
+ case SVGA3D_B8G8R8A8_UNORM: return D3DDDIFMT_A8R8G8B8;
+ case SVGA3D_B8G8R8X8_UNORM: return D3DDDIFMT_X8R8G8B8;
+ case SVGA3D_R8_UNORM: /* R8->A8 conversion is not correct, but it does not matter here,
+ * because the D3DDDIFMT_ value is used only to compute bpp, pitch, etc. */
+ case SVGA3D_A8_UNORM: return D3DDDIFMT_A8;
+ case SVGA3D_B5G5R5A1_UNORM: return D3DDDIFMT_A1R5G5B5;
+ default: break;
+ }
+
+ VBoxDispMpLoggerLogF("WDDM: EnvKMT: unsupported surface format %d\n", format);
+ Assert(0);
+ return D3DDDIFMT_UNKNOWN;
+}
+
+/* static */ DECLCALLBACK(int)
+GaDrvEnvKmt::gaEnvSurfaceDefine(void *pvEnv,
+ GASURFCREATE *pCreateParms,
+ GASURFSIZE *paSizes,
+ uint32_t cSizes,
+ uint32_t *pu32Sid)
+{
+ GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
+
+ D3DKMT_ESCAPE EscapeData;
+ VBOXDISPIFESCAPE_GASURFACEDEFINE *pData;
+ uint32_t cbAlloc;
+ uint8_t *pu8Req;
+ uint32_t cbReq;
+
+ /* Size of the SVGA request data */
+ cbReq = sizeof(GASURFCREATE) + cSizes * sizeof(GASURFSIZE);
+ /* How much to allocate for WDDM escape data. */
+ cbAlloc = sizeof(VBOXDISPIFESCAPE_GASURFACEDEFINE)
+ + cbReq;
+
+ pData = (VBOXDISPIFESCAPE_GASURFACEDEFINE *)malloc(cbAlloc);
+ if (!pData)
+ return -1;
+
+ pData->EscapeHdr.escapeCode = VBOXESC_GASURFACEDEFINE;
+ // pData->EscapeHdr.cmdSpecific = 0;
+ // pData->u32Sid = 0;
+ pData->cbReq = cbReq;
+ pData->cSizes = cSizes;
+
+ pu8Req = (uint8_t *)&pData[1];
+ memcpy(pu8Req, pCreateParms, sizeof(GASURFCREATE));
+ memcpy(&pu8Req[sizeof(GASURFCREATE)], paSizes, cSizes * sizeof(GASURFSIZE));
+
+ memset(&EscapeData, 0, sizeof(EscapeData));
+ EscapeData.hAdapter = pThis->mKmtCallbacks.hAdapter;
+ EscapeData.hDevice = pThis->mKmtCallbacks.hDevice;
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ EscapeData.Flags.HardwareAccess = 1;
+ EscapeData.pPrivateDriverData = pData;
+ EscapeData.PrivateDriverDataSize = cbAlloc;
+ // EscapeData.hContext = 0;
+
+ NTSTATUS Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTEscape(&EscapeData);
+ if (Status == STATUS_SUCCESS)
+ {
+ /* Create a kernel mode allocation for render targets,
+ * because we will need kernel mode handles for Present.
+ */
+ if (pCreateParms->flags & SVGA3D_SURFACE_HINT_RENDERTARGET)
+ {
+ /* First check if the format is supported. */
+ D3DDDIFORMAT const ddiFormat = svgaToD3DDDIFormat((SVGA3dSurfaceFormat)pCreateParms->format);
+ if (ddiFormat != D3DDDIFMT_UNKNOWN)
+ {
+ GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)malloc(sizeof(GAWDDMSURFACEINFO));
+ if (pSurfaceInfo)
+ {
+ memset(pSurfaceInfo, 0, sizeof(GAWDDMSURFACEINFO));
+
+ VBOXWDDM_ALLOCINFO wddmAllocInfo;
+ memset(&wddmAllocInfo, 0, sizeof(wddmAllocInfo));
+
+ wddmAllocInfo.enmType = VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC;
+ wddmAllocInfo.fFlags.RenderTarget = 1;
+ wddmAllocInfo.hSharedHandle = 0;
+ wddmAllocInfo.hostID = pData->u32Sid;
+ wddmAllocInfo.SurfDesc.slicePitch = 0;
+ wddmAllocInfo.SurfDesc.depth = paSizes[0].cDepth;
+ wddmAllocInfo.SurfDesc.width = paSizes[0].cWidth;
+ wddmAllocInfo.SurfDesc.height = paSizes[0].cHeight;
+ wddmAllocInfo.SurfDesc.format = ddiFormat;
+ wddmAllocInfo.SurfDesc.VidPnSourceId = 0;
+ wddmAllocInfo.SurfDesc.bpp = vboxWddmCalcBitsPerPixel(wddmAllocInfo.SurfDesc.format);
+ wddmAllocInfo.SurfDesc.pitch = vboxWddmCalcPitch(wddmAllocInfo.SurfDesc.width,
+ wddmAllocInfo.SurfDesc.format);
+ wddmAllocInfo.SurfDesc.cbSize = vboxWddmCalcSize(wddmAllocInfo.SurfDesc.pitch,
+ wddmAllocInfo.SurfDesc.height,
+ wddmAllocInfo.SurfDesc.format);
+ wddmAllocInfo.SurfDesc.d3dWidth = vboxWddmCalcWidthForPitch(wddmAllocInfo.SurfDesc.pitch,
+ wddmAllocInfo.SurfDesc.format);
+
+ D3DDDI_ALLOCATIONINFO AllocationInfo;
+ memset(&AllocationInfo, 0, sizeof(AllocationInfo));
+ // AllocationInfo.hAllocation = NULL;
+ // AllocationInfo.pSystemMem = NULL;
+ AllocationInfo.pPrivateDriverData = &wddmAllocInfo;
+ AllocationInfo.PrivateDriverDataSize = sizeof(wddmAllocInfo);
+
+ D3DKMT_CREATEALLOCATION CreateAllocation;
+ memset(&CreateAllocation, 0, sizeof(CreateAllocation));
+ CreateAllocation.hDevice = pThis->mKmtCallbacks.hDevice;
+ CreateAllocation.NumAllocations = 1;
+ CreateAllocation.pAllocationInfo = &AllocationInfo;
+
+ Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTCreateAllocation(&CreateAllocation);
+ if (Status == STATUS_SUCCESS)
+ {
+ pSurfaceInfo->Core.Key = pData->u32Sid;
+ pSurfaceInfo->hAllocation = AllocationInfo.hAllocation;
+ if (!RTAvlU32Insert(&pThis->mSurfaceTree, &pSurfaceInfo->Core))
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ }
+ }
+
+ if (Status != STATUS_SUCCESS)
+ {
+ free(pSurfaceInfo);
+ }
+ }
+ else
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ }
+ }
+ else
+ {
+ /* Unsupported render target format. */
+ Status = STATUS_NOT_SUPPORTED;
+ }
+ }
+
+ if (Status != STATUS_SUCCESS)
+ {
+ gaEnvSurfaceDestroy(pvEnv, pData->u32Sid);
+ }
+ }
+
+ if (Status == STATUS_SUCCESS)
+ {
+ *pu32Sid = pData->u32Sid;
+ free(pData);
+ return 0;
+ }
+
+ Assert(0);
+ free(pData);
+ return -1;
+}
+
+/* static */ DECLCALLBACK(void)
+GaDrvEnvKmt::gaEnvSurfaceDestroy(void *pvEnv,
+ uint32_t u32Sid)
+{
+ GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
+
+ VBOXDISPIFESCAPE_GASURFACEDESTROY data;
+ memset(&data, 0, sizeof(data));
+ data.EscapeHdr.escapeCode = VBOXESC_GASURFACEDESTROY;
+ // data.EscapeHdr.cmdSpecific = 0;
+ data.u32Sid = u32Sid;
+
+ D3DKMT_ESCAPE EscapeData;
+ memset(&EscapeData, 0, sizeof(EscapeData));
+ EscapeData.hAdapter = pThis->mKmtCallbacks.hAdapter;
+ EscapeData.hDevice = pThis->mKmtCallbacks.hDevice;
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ EscapeData.Flags.HardwareAccess = 1;
+ EscapeData.pPrivateDriverData = &data;
+ EscapeData.PrivateDriverDataSize = sizeof(data);
+ // EscapeData.hContext = 0;
+
+ NTSTATUS Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTEscape(&EscapeData);
+ Assert(Status == STATUS_SUCCESS);
+
+ /* Try to remove from sid -> hAllocation map. */
+ GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)RTAvlU32Remove(&pThis->mSurfaceTree, u32Sid);
+ if (pSurfaceInfo)
+ {
+ D3DKMT_DESTROYALLOCATION DestroyAllocation;
+ memset(&DestroyAllocation, 0, sizeof(DestroyAllocation));
+ DestroyAllocation.hDevice = pThis->mKmtCallbacks.hDevice;
+ // DestroyAllocation.hResource = 0;
+ DestroyAllocation.phAllocationList = &pSurfaceInfo->hAllocation;
+ DestroyAllocation.AllocationCount = 1;
+
+ Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTDestroyAllocation(&DestroyAllocation);
+ Assert(Status == STATUS_SUCCESS);
+
+ free(pSurfaceInfo);
+ }
+}
+
+D3DKMT_HANDLE GaDrvEnvKmt::drvEnvKmtSurfaceHandle(uint32_t u32Sid)
+{
+ GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)RTAvlU32Get(&mSurfaceTree, u32Sid);
+ return pSurfaceInfo ? pSurfaceInfo->hAllocation : 0;
+}
+
+static bool
+vboxDdiFenceCreate(GaKmtCallbacks *pKmtCallbacks,
+ GAWDDMCONTEXTINFO *pContextInfo,
+ uint32_t *pu32FenceHandle)
+{
+ VBOXDISPIFESCAPE_GAFENCECREATE fenceCreate;
+ memset(&fenceCreate, 0, sizeof(fenceCreate));
+ fenceCreate.EscapeHdr.escapeCode = VBOXESC_GAFENCECREATE;
+ // fenceCreate.EscapeHdr.cmdSpecific = 0;
+
+ /* If the user-mode display driver sets hContext to a non-NULL value, the driver must
+ * have also set hDevice to a non-NULL value...
+ */
+ D3DKMT_ESCAPE EscapeData;
+ memset(&EscapeData, 0, sizeof(EscapeData));
+ EscapeData.hAdapter = pKmtCallbacks->hAdapter;
+ EscapeData.hDevice = pKmtCallbacks->hDevice;
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ // EscapeData.Flags.HardwareAccess = 0;
+ EscapeData.pPrivateDriverData = &fenceCreate;
+ EscapeData.PrivateDriverDataSize = sizeof(fenceCreate);
+ EscapeData.hContext = pContextInfo->hContext;
+
+ NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
+ if (Status == STATUS_SUCCESS)
+ {
+ *pu32FenceHandle = fenceCreate.u32FenceHandle;
+ return true;
+ }
+
+ Assert(0);
+ return false;
+}
+
+static bool
+vboxDdiFenceQuery(GaKmtCallbacks *pKmtCallbacks,
+ uint32_t u32FenceHandle,
+ GAFENCEQUERY *pFenceQuery)
+{
+ VBOXDISPIFESCAPE_GAFENCEQUERY fenceQuery;
+ memset(&fenceQuery, 0, sizeof(fenceQuery));
+ fenceQuery.EscapeHdr.escapeCode = VBOXESC_GAFENCEQUERY;
+ // fenceQuery.EscapeHdr.cmdSpecific = 0;
+ fenceQuery.u32FenceHandle = u32FenceHandle;
+
+ D3DKMT_ESCAPE EscapeData;
+ memset(&EscapeData, 0, sizeof(EscapeData));
+ EscapeData.hAdapter = pKmtCallbacks->hAdapter;
+ EscapeData.hDevice = pKmtCallbacks->hDevice;
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ // EscapeData.Flags.HardwareAccess = 0;
+ EscapeData.pPrivateDriverData = &fenceQuery;
+ EscapeData.PrivateDriverDataSize = sizeof(fenceQuery);
+ EscapeData.hContext = 0;
+
+ NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
+ if (Status == STATUS_SUCCESS)
+ {
+ pFenceQuery->u32FenceHandle = fenceQuery.u32FenceHandle;
+ pFenceQuery->u32SubmittedSeqNo = fenceQuery.u32SubmittedSeqNo;
+ pFenceQuery->u32ProcessedSeqNo = fenceQuery.u32ProcessedSeqNo;
+ pFenceQuery->u32FenceStatus = fenceQuery.u32FenceStatus;
+ return true;
+ }
+
+ Assert(0);
+ return false;
+}
+
+/* static */ DECLCALLBACK(int)
+GaDrvEnvKmt::gaEnvFenceQuery(void *pvEnv,
+ uint32_t u32FenceHandle,
+ GAFENCEQUERY *pFenceQuery)
+{
+ GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
+
+ if (!pThis->mKmtCallbacks.hDevice)
+ {
+ pFenceQuery->u32FenceStatus = GA_FENCE_STATUS_NULL;
+ return 0;
+ }
+
+ bool fSuccess = vboxDdiFenceQuery(&pThis->mKmtCallbacks, u32FenceHandle, pFenceQuery);
+ return fSuccess ? 0: -1;
+}
+
+static bool
+vboxDdiFenceWait(GaKmtCallbacks *pKmtCallbacks,
+ uint32_t u32FenceHandle,
+ uint32_t u32TimeoutUS)
+{
+ VBOXDISPIFESCAPE_GAFENCEWAIT fenceWait;
+ memset(&fenceWait, 0, sizeof(fenceWait));
+ fenceWait.EscapeHdr.escapeCode = VBOXESC_GAFENCEWAIT;
+ // pFenceWait->EscapeHdr.cmdSpecific = 0;
+ fenceWait.u32FenceHandle = u32FenceHandle;
+ fenceWait.u32TimeoutUS = u32TimeoutUS;
+
+ D3DKMT_ESCAPE EscapeData;
+ memset(&EscapeData, 0, sizeof(EscapeData));
+ EscapeData.hAdapter = pKmtCallbacks->hAdapter;
+ EscapeData.hDevice = pKmtCallbacks->hDevice;
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ // EscapeData.Flags.HardwareAccess = 0;
+ EscapeData.pPrivateDriverData = &fenceWait;
+ EscapeData.PrivateDriverDataSize = sizeof(fenceWait);
+ EscapeData.hContext = 0;
+
+ NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
+ Assert(Status == STATUS_SUCCESS);
+ return Status == STATUS_SUCCESS;
+}
+
+/* static */ DECLCALLBACK(int)
+GaDrvEnvKmt::gaEnvFenceWait(void *pvEnv,
+ uint32_t u32FenceHandle,
+ uint32_t u32TimeoutUS)
+{
+ GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
+
+ if (!pThis->mKmtCallbacks.hDevice)
+ return 0;
+
+ bool fSuccess = vboxDdiFenceWait(&pThis->mKmtCallbacks, u32FenceHandle, u32TimeoutUS);
+ return fSuccess ? 0 : -1;
+}
+
+static bool
+vboxDdiFenceUnref(GaKmtCallbacks *pKmtCallbacks,
+ uint32_t u32FenceHandle)
+{
+ VBOXDISPIFESCAPE_GAFENCEUNREF fenceUnref;
+ memset(&fenceUnref, 0, sizeof(fenceUnref));
+ fenceUnref.EscapeHdr.escapeCode = VBOXESC_GAFENCEUNREF;
+ // pFenceUnref->EscapeHdr.cmdSpecific = 0;
+ fenceUnref.u32FenceHandle = u32FenceHandle;
+
+ D3DKMT_ESCAPE EscapeData;
+ memset(&EscapeData, 0, sizeof(EscapeData));
+ EscapeData.hAdapter = pKmtCallbacks->hAdapter;
+ EscapeData.hDevice = pKmtCallbacks->hDevice;
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ // EscapeData.Flags.HardwareAccess = 0;
+ EscapeData.pPrivateDriverData = &fenceUnref;
+ EscapeData.PrivateDriverDataSize = sizeof(fenceUnref);
+ EscapeData.hContext = 0;
+
+ NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
+ Assert(Status == STATUS_SUCCESS);
+ return Status == STATUS_SUCCESS;
+}
+
+/* static */ DECLCALLBACK(void)
+GaDrvEnvKmt::gaEnvFenceUnref(void *pvEnv,
+ uint32_t u32FenceHandle)
+{
+ GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
+
+ if (!pThis->mKmtCallbacks.hDevice)
+ return;
+
+ vboxDdiFenceUnref(&pThis->mKmtCallbacks, u32FenceHandle);
+}
+
+/** Calculate how many commands will fit in the buffer.
+ *
+ * @param pu8Commands Command buffer.
+ * @param cbCommands Size of command buffer.
+ * @param cbAvail Available buffer size..
+ * @param pu32Length Size of commands which will fit in cbAvail bytes.
+ */
+static bool
+vboxCalcCommandLength(const uint8_t *pu8Commands, uint32_t cbCommands, uint32_t cbAvail, uint32_t *pu32Length)
+{
+ uint32_t u32Length = 0;
+ const uint8_t *pu8Src = pu8Commands;
+ const uint8_t *pu8SrcEnd = pu8Commands + cbCommands;
+
+ while (pu8SrcEnd > pu8Src)
+ {
+ const uint32_t cbSrcLeft = pu8SrcEnd - pu8Src;
+ if (cbSrcLeft < sizeof(uint32_t))
+ {
+ return false;
+ }
+
+ /* Get the command id and command length. */
+ const uint32_t u32CmdId = *(uint32_t *)pu8Src;
+ uint32_t cbCmd = 0;
+
+ if (SVGA_3D_CMD_BASE <= u32CmdId && u32CmdId < SVGA_3D_CMD_MAX)
+ {
+ if (cbSrcLeft < sizeof(SVGA3dCmdHeader))
+ {
+ return false;
+ }
+
+ const SVGA3dCmdHeader *pHeader = (SVGA3dCmdHeader *)pu8Src;
+ cbCmd = sizeof(SVGA3dCmdHeader) + pHeader->size;
+ if (cbCmd % sizeof(uint32_t) != 0)
+ {
+ return false;
+ }
+ if (cbSrcLeft < cbCmd)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ /* It is not expected that any of common SVGA commands will be in the command buffer
+ * because the SVGA gallium driver does not use them.
+ */
+ return false;
+ }
+
+ if (u32Length + cbCmd > cbAvail)
+ {
+ if (u32Length == 0)
+ {
+ /* No commands fit into the buffer. */
+ return false;
+ }
+ break;
+ }
+
+ pu8Src += cbCmd;
+ u32Length += cbCmd;
+ }
+
+ *pu32Length = u32Length;
+ return true;
+}
+
+static bool
+vboxDdiRender(GaKmtCallbacks *pKmtCallbacks,
+ GAWDDMCONTEXTINFO *pContextInfo, uint32_t u32FenceHandle, void *pvCommands, uint32_t cbCommands,
+ ULONGLONG PresentHistoryToken, bool fPresentRedirected)
+{
+ uint32_t cbLeft;
+ const uint8_t *pu8Src;
+
+ cbLeft = cbCommands;
+ pu8Src = (uint8_t *)pvCommands;
+ /* Even when cbCommands is 0, submit the fence. The following code deals with this. */
+ do
+ {
+ /* Actually available space. */
+ const uint32_t cbAvail = pContextInfo->CommandBufferSize;
+ if (cbAvail <= sizeof(u32FenceHandle))
+ {
+ return false;
+ }
+
+ /* How many bytes of command data still to copy. */
+ uint32_t cbCommandChunk = cbLeft;
+
+ /* How many bytes still to copy. */
+ uint32_t cbToCopy = sizeof(u32FenceHandle) + cbCommandChunk;
+
+ /* Copy the buffer identifier. */
+ if (cbToCopy <= cbAvail)
+ {
+ /* Command buffer is big enough. */
+ *(uint32_t *)pContextInfo->pCommandBuffer = u32FenceHandle;
+ }
+ else
+ {
+ /* Split. Write zero as buffer identifier. */
+ *(uint32_t *)pContextInfo->pCommandBuffer = 0;
+
+ /* Get how much commands data will fit in the buffer. */
+ if (!vboxCalcCommandLength(pu8Src, cbCommandChunk, cbAvail - sizeof(u32FenceHandle), &cbCommandChunk))
+ {
+ return false;
+ }
+
+ cbToCopy = sizeof(u32FenceHandle) + cbCommandChunk;
+ }
+
+ if (cbCommandChunk)
+ {
+ /* Copy the command data. */
+ memcpy((uint8_t *)pContextInfo->pCommandBuffer + sizeof(u32FenceHandle), pu8Src, cbCommandChunk);
+ }
+
+ /* Advance the command position. */
+ pu8Src += cbCommandChunk;
+ cbLeft -= cbCommandChunk;
+
+ D3DKMT_RENDER RenderData;
+ memset(&RenderData, 0, sizeof(RenderData));
+ RenderData.hContext = pContextInfo->hContext;
+ // RenderData.CommandOffset = 0;
+ RenderData.CommandLength = cbToCopy;
+ // RenderData.AllocationCount = 0;
+ // RenderData.PatchLocationCount = 0;
+ RenderData.PresentHistoryToken = PresentHistoryToken;
+ RenderData.Flags.PresentRedirected = fPresentRedirected;
+
+ NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTRender(&RenderData);
+ Assert(Status == STATUS_SUCCESS);
+ if (Status != STATUS_SUCCESS)
+ {
+ return false;
+ }
+
+ pContextInfo->pCommandBuffer = RenderData.pNewCommandBuffer;
+ pContextInfo->CommandBufferSize = RenderData.NewCommandBufferSize;
+ pContextInfo->pAllocationList = RenderData.pNewAllocationList;
+ pContextInfo->AllocationListSize = RenderData.NewAllocationListSize;
+ pContextInfo->pPatchLocationList = RenderData.pNewPatchLocationList;
+ pContextInfo->PatchLocationListSize = RenderData.NewPatchLocationListSize;
+ } while (cbLeft);
+
+ return true;
+}
+
+bool GaDrvEnvKmt::doRender(uint32_t u32Cid, void *pvCommands, uint32_t cbCommands,
+ GAFENCEQUERY *pFenceQuery, ULONGLONG PresentHistoryToken, bool fPresentRedirected)
+{
+ uint32_t u32FenceHandle;
+ GAWDDMCONTEXTINFO *pContextInfo = (GAWDDMCONTEXTINFO *)RTAvlU32Get(&mContextTree, u32Cid);
+ if (!pContextInfo)
+ return false;
+
+ bool fSuccess = true;
+ u32FenceHandle = 0;
+ if (pFenceQuery)
+ {
+ fSuccess = vboxDdiFenceCreate(&mKmtCallbacks, pContextInfo, &u32FenceHandle);
+ }
+
+ if (fSuccess)
+ {
+ fSuccess = vboxDdiRender(&mKmtCallbacks, pContextInfo, u32FenceHandle,
+ pvCommands, cbCommands, PresentHistoryToken, fPresentRedirected);
+ if (fSuccess)
+ {
+ if (pFenceQuery)
+ {
+ if (!vboxDdiFenceQuery(&mKmtCallbacks, u32FenceHandle, pFenceQuery))
+ {
+ pFenceQuery->u32FenceStatus = GA_FENCE_STATUS_NULL;
+ }
+ }
+ }
+ }
+ return fSuccess;
+}
+
+/* static */ DECLCALLBACK(int)
+GaDrvEnvKmt::gaEnvRender(void *pvEnv,
+ uint32_t u32Cid,
+ void *pvCommands,
+ uint32_t cbCommands,
+ GAFENCEQUERY *pFenceQuery)
+{
+ GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
+ return pThis->doRender(u32Cid, pvCommands, cbCommands, pFenceQuery, 0, false) ? 1 : 0;
+}
+
+bool GaDrvEnvKmt::drvEnvKmtRenderCompose(uint32_t u32Cid,
+ void *pvCommands,
+ uint32_t cbCommands,
+ ULONGLONG PresentHistoryToken)
+{
+ return doRender(u32Cid, pvCommands, cbCommands, NULL, PresentHistoryToken, true);
+}
+
+
+static bool
+vboxDdiRegionCreate(GaKmtCallbacks *pKmtCallbacks,
+ uint32_t u32RegionSize,
+ uint32_t *pu32GmrId,
+ void **ppvMap)
+{
+ VBOXDISPIFESCAPE_GAREGION data;
+ memset(&data, 0, sizeof(data));
+ data.EscapeHdr.escapeCode = VBOXESC_GAREGION;
+ // data.EscapeHdr.cmdSpecific = 0;
+ data.u32Command = GA_REGION_CMD_CREATE;
+ data.u32NumPages = (u32RegionSize + PAGE_SIZE - 1) / PAGE_SIZE;
+ // data.u32GmrId = 0;
+ // data.u64UserAddress = 0;
+
+ D3DKMT_ESCAPE EscapeData;
+ memset(&EscapeData, 0, sizeof(EscapeData));
+ EscapeData.hAdapter = pKmtCallbacks->hAdapter;
+ EscapeData.hDevice = pKmtCallbacks->hDevice;
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ // EscapeData.Flags.HardwareAccess = 0;
+ EscapeData.pPrivateDriverData = &data;
+ EscapeData.PrivateDriverDataSize = sizeof(data);
+ // EscapeData.hContext = 0;
+
+ NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
+ if (Status == STATUS_SUCCESS)
+ {
+ *pu32GmrId = data.u32GmrId;
+ *ppvMap = (void *)(uintptr_t)data.u64UserAddress;
+ return true;
+ }
+
+ Assert(0);
+ return false;
+}
+
+/* static */ DECLCALLBACK(int)
+GaDrvEnvKmt::gaEnvRegionCreate(void *pvEnv,
+ uint32_t u32RegionSize,
+ uint32_t *pu32GmrId,
+ void **ppvMap)
+{
+ GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
+
+ if (pThis->mKmtCallbacks.hDevice)
+ {
+ /* That is a real device */
+ bool fSuccess = vboxDdiRegionCreate(&pThis->mKmtCallbacks, u32RegionSize, pu32GmrId, ppvMap);
+ return fSuccess ? 0: -1;
+ }
+
+ /* That is a fake device, created when WDDM adapter is initialized. */
+ *ppvMap = malloc(u32RegionSize);
+ if (*ppvMap)
+ {
+ *pu32GmrId = 0;
+ return 0;
+ }
+
+ return -1;
+}
+
+static bool
+vboxDdiRegionDestroy(GaKmtCallbacks *pKmtCallbacks,
+ uint32_t u32GmrId)
+{
+ VBOXDISPIFESCAPE_GAREGION data;
+ memset(&data, 0, sizeof(data));
+ data.EscapeHdr.escapeCode = VBOXESC_GAREGION;
+ // data.EscapeHdr.cmdSpecific = 0;
+ data.u32Command = GA_REGION_CMD_DESTROY;
+ // data.u32NumPages = 0;
+ data.u32GmrId = u32GmrId;
+ // data.u64UserAddress = 0;
+
+ D3DKMT_ESCAPE EscapeData;
+ memset(&EscapeData, 0, sizeof(EscapeData));
+ EscapeData.hAdapter = pKmtCallbacks->hAdapter;
+ EscapeData.hDevice = pKmtCallbacks->hDevice;
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ // EscapeData.Flags.HardwareAccess = 0;
+ EscapeData.pPrivateDriverData = &data;
+ EscapeData.PrivateDriverDataSize = sizeof(data);
+ // EscapeData.hContext = 0;
+
+ NTSTATUS Status = pKmtCallbacks->d3dkmt->pfnD3DKMTEscape(&EscapeData);
+ Assert(Status == STATUS_SUCCESS);
+ return Status == STATUS_SUCCESS;
+}
+
+/* static */ DECLCALLBACK(void)
+GaDrvEnvKmt::gaEnvRegionDestroy(void *pvEnv,
+ uint32_t u32GmrId,
+ void *pvMap)
+{
+ GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
+
+ if (pThis->mKmtCallbacks.hDevice)
+ {
+ vboxDdiRegionDestroy(&pThis->mKmtCallbacks, u32GmrId);
+ }
+ else
+ {
+ free(pvMap);
+ }
+}
+
+/* static */ DECLCALLBACK(int)
+GaDrvEnvKmt::gaEnvGBSurfaceDefine(void *pvEnv,
+ SVGAGBSURFCREATE *pCreateParms)
+{
+ GaDrvEnvKmt *pThis = (GaDrvEnvKmt *)pvEnv;
+
+ VBOXDISPIFESCAPE_SVGAGBSURFACEDEFINE data;
+ data.EscapeHdr.escapeCode = VBOXESC_SVGAGBSURFACEDEFINE;
+ data.EscapeHdr.u32CmdSpecific = 0;
+ data.CreateParms = *pCreateParms;
+
+ D3DKMT_ESCAPE EscapeData;
+ memset(&EscapeData, 0, sizeof(EscapeData));
+ EscapeData.hAdapter = pThis->mKmtCallbacks.hAdapter;
+ EscapeData.hDevice = pThis->mKmtCallbacks.hDevice;
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ EscapeData.Flags.HardwareAccess = 1;
+ EscapeData.pPrivateDriverData = &data;
+ EscapeData.PrivateDriverDataSize = sizeof(data);
+ // EscapeData.hContext = 0;
+
+ NTSTATUS Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTEscape(&EscapeData);
+ if (Status == STATUS_SUCCESS)
+ {
+ pCreateParms->gmrid = data.CreateParms.gmrid;
+ pCreateParms->cbGB = data.CreateParms.cbGB;
+ pCreateParms->u64UserAddress = data.CreateParms.u64UserAddress;
+ pCreateParms->u32Sid = data.CreateParms.u32Sid;
+
+ /* Create a kernel mode allocation for render targets,
+ * because we will need kernel mode handles for Present.
+ */
+ if (pCreateParms->s.flags & SVGA3D_SURFACE_HINT_RENDERTARGET)
+ {
+ /* First check if the format is supported. */
+ D3DDDIFORMAT const ddiFormat = svgaToD3DDDIFormat((SVGA3dSurfaceFormat)pCreateParms->s.format);
+ if (ddiFormat != D3DDDIFMT_UNKNOWN)
+ {
+ GAWDDMSURFACEINFO *pSurfaceInfo = (GAWDDMSURFACEINFO *)malloc(sizeof(GAWDDMSURFACEINFO));
+ if (pSurfaceInfo)
+ {
+ memset(pSurfaceInfo, 0, sizeof(GAWDDMSURFACEINFO));
+
+ VBOXWDDM_ALLOCINFO wddmAllocInfo;
+ memset(&wddmAllocInfo, 0, sizeof(wddmAllocInfo));
+
+ wddmAllocInfo.enmType = VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC;
+ wddmAllocInfo.fFlags.RenderTarget = 1;
+ wddmAllocInfo.hSharedHandle = 0;
+ wddmAllocInfo.hostID = pCreateParms->u32Sid;
+ wddmAllocInfo.SurfDesc.slicePitch = 0;
+ wddmAllocInfo.SurfDesc.depth = pCreateParms->s.size.depth;
+ wddmAllocInfo.SurfDesc.width = pCreateParms->s.size.width;
+ wddmAllocInfo.SurfDesc.height = pCreateParms->s.size.height;
+ wddmAllocInfo.SurfDesc.format = ddiFormat;
+ wddmAllocInfo.SurfDesc.VidPnSourceId = 0;
+ wddmAllocInfo.SurfDesc.bpp = vboxWddmCalcBitsPerPixel(wddmAllocInfo.SurfDesc.format);
+ wddmAllocInfo.SurfDesc.pitch = vboxWddmCalcPitch(wddmAllocInfo.SurfDesc.width,
+ wddmAllocInfo.SurfDesc.format);
+ wddmAllocInfo.SurfDesc.cbSize = vboxWddmCalcSize(wddmAllocInfo.SurfDesc.pitch,
+ wddmAllocInfo.SurfDesc.height,
+ wddmAllocInfo.SurfDesc.format);
+ wddmAllocInfo.SurfDesc.d3dWidth = vboxWddmCalcWidthForPitch(wddmAllocInfo.SurfDesc.pitch,
+ wddmAllocInfo.SurfDesc.format);
+
+ D3DDDI_ALLOCATIONINFO AllocationInfo;
+ memset(&AllocationInfo, 0, sizeof(AllocationInfo));
+ // AllocationInfo.hAllocation = NULL;
+ // AllocationInfo.pSystemMem = NULL;
+ AllocationInfo.pPrivateDriverData = &wddmAllocInfo;
+ AllocationInfo.PrivateDriverDataSize = sizeof(wddmAllocInfo);
+
+ D3DKMT_CREATEALLOCATION CreateAllocation;
+ memset(&CreateAllocation, 0, sizeof(CreateAllocation));
+ CreateAllocation.hDevice = pThis->mKmtCallbacks.hDevice;
+ CreateAllocation.NumAllocations = 1;
+ CreateAllocation.pAllocationInfo = &AllocationInfo;
+
+ Status = pThis->mKmtCallbacks.d3dkmt->pfnD3DKMTCreateAllocation(&CreateAllocation);
+ if (Status == STATUS_SUCCESS)
+ {
+ pSurfaceInfo->Core.Key = pCreateParms->u32Sid;
+ pSurfaceInfo->hAllocation = AllocationInfo.hAllocation;
+ if (!RTAvlU32Insert(&pThis->mSurfaceTree, &pSurfaceInfo->Core))
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ }
+ }
+
+ if (Status != STATUS_SUCCESS)
+ {
+ free(pSurfaceInfo);
+ }
+ }
+ else
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ }
+ }
+ else
+ {
+ /* Unsupported render target format. */
+ Assert(0);
+ Status = STATUS_NOT_SUPPORTED;
+ }
+ }
+
+ if (Status != STATUS_SUCCESS)
+ {
+ gaEnvSurfaceDestroy(pvEnv, pCreateParms->u32Sid);
+ }
+ }
+
+ if (Status == STATUS_SUCCESS)
+ return 0;
+
+ Assert(0);
+ return -1;
+}
+
+GaDrvEnvKmt::GaDrvEnvKmt()
+ :
+ mContextTree(0),
+ mSurfaceTree(0)
+{
+ RT_ZERO(mKmtCallbacks);
+ RT_ZERO(mHWInfo);
+ RT_ZERO(mEnv);
+}
+
+GaDrvEnvKmt::~GaDrvEnvKmt()
+{
+}
+
+HRESULT GaDrvEnvKmt::Init(void)
+{
+ mKmtCallbacks.d3dkmt = D3DKMTFunctions();
+
+ /* Figure out which adapter to use. */
+ NTSTATUS Status = vboxDispKmtOpenAdapter2(&mKmtCallbacks.hAdapter, &mKmtCallbacks.AdapterLuid);
+ Assert(Status == STATUS_SUCCESS);
+ if (Status == STATUS_SUCCESS)
+ {
+ VBOXWDDM_QAI adapterInfo;
+ bool fSuccess = vboxDdiQueryAdapterInfo(&mKmtCallbacks, mKmtCallbacks.hAdapter, &adapterInfo, sizeof(adapterInfo));
+ Assert(fSuccess);
+ if (fSuccess)
+ {
+ fSuccess = vboxDdiDeviceCreate(&mKmtCallbacks, &mKmtCallbacks.hDevice);
+ Assert(fSuccess);
+ if (fSuccess)
+ {
+ mHWInfo = adapterInfo.u.vmsvga.HWInfo;
+
+ /*
+ * Success.
+ */
+ return S_OK;
+ }
+
+ vboxDdiDeviceDestroy(&mKmtCallbacks, mKmtCallbacks.hDevice);
+ }
+
+ vboxDispKmtCloseAdapter(mKmtCallbacks.hAdapter);
+ }
+
+ return E_FAIL;
+}
+
+const WDDMGalliumDriverEnv *GaDrvEnvKmt::Env()
+{
+ if (mEnv.cb == 0)
+ {
+ mEnv.cb = sizeof(WDDMGalliumDriverEnv);
+ mEnv.pHWInfo = &mHWInfo;
+ mEnv.pvEnv = this;
+ mEnv.pfnContextCreate = gaEnvContextCreate;
+ mEnv.pfnContextDestroy = gaEnvContextDestroy;
+ mEnv.pfnSurfaceDefine = gaEnvSurfaceDefine;
+ mEnv.pfnSurfaceDestroy = gaEnvSurfaceDestroy;
+ mEnv.pfnRender = gaEnvRender;
+ mEnv.pfnFenceUnref = gaEnvFenceUnref;
+ mEnv.pfnFenceQuery = gaEnvFenceQuery;
+ mEnv.pfnFenceWait = gaEnvFenceWait;
+ mEnv.pfnRegionCreate = gaEnvRegionCreate;
+ mEnv.pfnRegionDestroy = gaEnvRegionDestroy;
+ /* VGPU10 */
+ mEnv.pfnGBSurfaceDefine = gaEnvGBSurfaceDefine;
+ }
+
+ return &mEnv;
+}
+
+RT_C_DECLS_BEGIN
+
+const WDDMGalliumDriverEnv *GaDrvEnvKmtCreate(void)
+{
+ GaDrvEnvKmt *p = new GaDrvEnvKmt();
+ if (p)
+ {
+ HRESULT hr = p->Init();
+ if (hr != S_OK)
+ {
+ delete p;
+ p = NULL;
+ }
+ }
+ return p ? p->Env() : NULL;
+}
+
+void GaDrvEnvKmtDelete(const WDDMGalliumDriverEnv *pEnv)
+{
+ if (pEnv)
+ {
+ GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
+ delete p;
+ }
+}
+
+D3DKMT_HANDLE GaDrvEnvKmtContextHandle(const WDDMGalliumDriverEnv *pEnv, uint32_t u32Cid)
+{
+ GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
+ return p->drvEnvKmtContextHandle(u32Cid);
+}
+
+D3DKMT_HANDLE GaDrvEnvKmtSurfaceHandle(const WDDMGalliumDriverEnv *pEnv, uint32_t u32Sid)
+{
+ GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
+ return p->drvEnvKmtSurfaceHandle(u32Sid);
+}
+
+void GaDrvEnvKmtAdapterLUID(const WDDMGalliumDriverEnv *pEnv, LUID *pAdapterLuid)
+{
+ GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
+ *pAdapterLuid = p->mKmtCallbacks.AdapterLuid;
+}
+
+D3DKMT_HANDLE GaDrvEnvKmtAdapterHandle(const WDDMGalliumDriverEnv *pEnv)
+{
+ GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
+ return p->mKmtCallbacks.hAdapter;
+}
+
+D3DKMT_HANDLE GaDrvEnvKmtDeviceHandle(const WDDMGalliumDriverEnv *pEnv)
+{
+ GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
+ return p->mKmtCallbacks.hDevice;
+}
+
+void GaDrvEnvKmtRenderCompose(const WDDMGalliumDriverEnv *pEnv,
+ uint32_t u32Cid,
+ void *pvCommands,
+ uint32_t cbCommands,
+ ULONGLONG PresentHistoryToken)
+{
+ GaDrvEnvKmt *p = (GaDrvEnvKmt *)pEnv->pvEnv;
+ p->drvEnvKmtRenderCompose(u32Cid, pvCommands, cbCommands, PresentHistoryToken);
+}
+
+RT_C_DECLS_END
diff --git a/src/VBox/Additions/3D/win/VBoxGL/GaDrvEnvKMT.h b/src/VBox/Additions/3D/win/VBoxGL/GaDrvEnvKMT.h
new file mode 100644
index 00000000..c869ed2c
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxGL/GaDrvEnvKMT.h
@@ -0,0 +1,58 @@
+/* $Id: GaDrvEnvKMT.h $ */
+/** @file
+ * VirtualBox Windows Guest Mesa3D - Gallium driver interface to the WDDM miniport driver.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef GA_INCLUDED_SRC_3D_win_VBoxGL_GaDrvEnvKMT_h
+#define GA_INCLUDED_SRC_3D_win_VBoxGL_GaDrvEnvKMT_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBoxGaDriver.h>
+#include <VBoxWddmUmHlp.h>
+
+RT_C_DECLS_BEGIN
+
+const WDDMGalliumDriverEnv *GaDrvEnvKmtCreate(void);
+void GaDrvEnvKmtDelete(const WDDMGalliumDriverEnv *pEnv);
+
+D3DKMT_HANDLE GaDrvEnvKmtContextHandle(const WDDMGalliumDriverEnv *pEnv,
+ uint32_t u32Cid);
+D3DKMT_HANDLE GaDrvEnvKmtSurfaceHandle(const WDDMGalliumDriverEnv *pEnv,
+ uint32_t u32Sid);
+void GaDrvEnvKmtAdapterLUID(const WDDMGalliumDriverEnv *pEnv,
+ LUID *pAdapterLuid);
+D3DKMT_HANDLE GaDrvEnvKmtAdapterHandle(const WDDMGalliumDriverEnv *pEnv);
+D3DKMT_HANDLE GaDrvEnvKmtDeviceHandle(const WDDMGalliumDriverEnv *pEnv);
+void GaDrvEnvKmtRenderCompose(const WDDMGalliumDriverEnv *pEnv,
+ uint32_t u32Cid,
+ void *pvCommands,
+ uint32_t cbCommands,
+ ULONGLONG PresentHistoryToken);
+
+RT_C_DECLS_END
+
+#endif /* !GA_INCLUDED_SRC_3D_win_VBoxGL_GaDrvEnvKMT_h */
diff --git a/src/VBox/Additions/3D/win/VBoxGL/Makefile.kmk b/src/VBox/Additions/3D/win/VBoxGL/Makefile.kmk
new file mode 100644
index 00000000..bf3f5133
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxGL/Makefile.kmk
@@ -0,0 +1,87 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for VBoxGL OpenGL state tracker.
+#
+
+#
+# Copyright (C) 2018-2022 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+DLLS += VBoxGL
+DLLS.amd64 += VBoxGL-x86
+
+VBoxGL_TEMPLATE = VBoxMesa3DGuestR3DllMinVista
+VBoxGL_DEFS = VBOXGL
+# -wd4005: '__useHeader' : redefinition
+VBOXGL_DISABLED_WARNINGS := -wd4005
+# -wd4204: nonstandard extension used: non-constant aggregate initializer
+# -wd4267: 'initializing': conversion from 'size_t' to 'unsigned int', possible loss of data
+# -wd4459: stw_device.h(102): warning C4459: declaration of 'stw_dev' hides global declaration
+# -wd4668: c99_compat.h(99): warning C4668: '__STDC_VERSION__' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
+VBOXGL_DISABLED_WARNINGS += -wd4204 -wd4267 -wd4459 -wd4668
+VBoxGL_CFLAGS = $(VBOXGL_DISABLED_WARNINGS)
+VBoxGL_CXXFLAGS = $(VBOXGL_DISABLED_WARNINGS)
+VBoxGL_INCS = \
+ $(VBOX_PATH_3D)/win/include \
+ $(VBOX_PATH_MESA)/include/GL \
+ $(VBOX_PATH_MESA)/src/gallium/frontends/wgl \
+ $(VBOX_PATH_MESA)/src/gallium/winsys/sw \
+ $(VBOX_PATH_MESA)/src/gallium/drivers \
+ $(PATH_ROOT)/src/VBox/Additions/WINNT/Graphics/Video \
+ $(PATH_ROOT)/src/VBox/Runtime/common/table \
+ $(VBOX_PATH_VMSVGA_INC) \
+ $(VBOX_GRAPHICS_INCS)
+VBoxGL_SOURCES = \
+ $(VBOX_PATH_MESA)/src/gallium/targets/libgl-gdi/opengl32.def \
+ VBoxGL.rc
+VBoxGL_SOURCES += \
+ GaDrvEnvKMT.cpp \
+ VBoxGL.c
+VBoxGL_LIBS = \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxWddmUmHlp$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaGalliumAuxLib$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaWglLib$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaUtilLib$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaLib$(VBOX_SUFF_LIB)
+
+if defined(VBOX_SIGNING_MODE) && defined(VBOX_SIGN_ADDITIONS)
+ VBoxGL_INSTTYPE = none
+ VBoxGL_DEBUG_INSTTYPE = both
+endif
+
+#
+# VBoxGL-x86 - x86 version of VBoxGL built for amd64 build
+#
+VBoxGL-x86_EXTENDS = VBoxGL
+VBoxGL-x86_BLD_TRG_ARCH = x86
+VBoxGL-x86_LIBS = \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxWddmUmHlp-x86$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaGalliumAuxLib-x86$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaWglLib-x86$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaUtilLib-x86$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaLib-x86$(VBOX_SUFF_LIB)
+VBoxGL-x86_DEFS = $(VBoxGL_DEFS) VBOX_WOW64
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Additions/3D/win/VBoxGL/VBoxGL.c b/src/VBox/Additions/3D/win/VBoxGL/VBoxGL.c
new file mode 100644
index 00000000..9871bd6b
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxGL/VBoxGL.c
@@ -0,0 +1,580 @@
+/* $Id: VBoxGL.c $ */
+/** @file
+ * VirtualBox Windows Guest Mesa3D - OpenGL driver.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "GaDrvEnvKMT.h"
+
+#include "stw_winsys.h"
+#include "stw_device.h"
+#include "stw_context.h"
+
+#include "pipe/p_state.h"
+#include "svga3d_reg.h"
+
+#include <iprt/asm.h>
+
+#include <common/wddm/VBoxMPIf.h>
+
+#include <Psapi.h>
+
+static const char *g_pszSvgaDll =
+#ifdef VBOX_WOW64
+ "VBoxSVGA-x86.dll"
+#else
+ "VBoxSVGA.dll"
+#endif
+;
+
+static struct GaDrvFunctions
+{
+ PFNGaDrvScreenCreate pfnGaDrvScreenCreate;
+ PFNGaDrvScreenDestroy pfnGaDrvScreenDestroy;
+ PFNGaDrvGetWDDMEnv pfnGaDrvGetWDDMEnv;
+ PFNGaDrvGetContextId pfnGaDrvGetContextId;
+ PFNGaDrvGetSurfaceId pfnGaDrvGetSurfaceId;
+ PFNGaDrvContextFlush pfnGaDrvContextFlush;
+} g_drvfuncs;
+
+
+static HMODULE gaDrvLoadSVGA(struct GaDrvFunctions *pDrvFuncs)
+{
+ struct VBOXWDDMDLLPROC aDrvProcs[] =
+ {
+ { "GaDrvScreenCreate", (FARPROC *)&pDrvFuncs->pfnGaDrvScreenCreate },
+ { "GaDrvScreenDestroy", (FARPROC *)&pDrvFuncs->pfnGaDrvScreenDestroy },
+ { "GaDrvGetWDDMEnv", (FARPROC *)&pDrvFuncs->pfnGaDrvGetWDDMEnv },
+ { "GaDrvGetContextId", (FARPROC *)&pDrvFuncs->pfnGaDrvGetContextId },
+ { "GaDrvGetSurfaceId", (FARPROC *)&pDrvFuncs->pfnGaDrvGetSurfaceId },
+ { "GaDrvContextFlush", (FARPROC *)&pDrvFuncs->pfnGaDrvContextFlush },
+ { NULL, NULL }
+ };
+
+ HMODULE hmod = VBoxWddmLoadSystemDll(g_pszSvgaDll);
+ if (hmod)
+ {
+ VBoxWddmLoadAdresses(hmod, aDrvProcs);
+ }
+ return hmod;
+}
+
+struct stw_shared_surface
+{
+ D3DKMT_HANDLE hResource;
+ D3DKMT_HANDLE hSurface;
+ uint32_t u32Sid;
+};
+
+static NTSTATUS vboxKmtPresent(D3DKMT_HANDLE hContext, HWND hwnd, D3DKMT_HANDLE hSource, LONG lWidth, LONG lHeight)
+{
+ RECT r;
+ r.left = 0;
+ r.top = 0;
+ r.right = lWidth;
+ r.bottom = lHeight;
+
+ D3DKMT_PRESENT PresentData;
+ memset(&PresentData, 0, sizeof(PresentData));
+ PresentData.hContext = hContext;
+ PresentData.hWindow = hwnd;
+ PresentData.hSource = hSource;
+ PresentData.hDestination = 0;
+ PresentData.Flags.Blt = 1;
+ PresentData.Flags.SrcRectValid = 1;
+ PresentData.Flags.DstRectValid = 1;
+ PresentData.SrcRect = r;
+ PresentData.SubRectCnt = 1;
+ PresentData.pSrcSubRects = &r;
+ PresentData.DstRect = r;
+
+ D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
+ NTSTATUS Status = d3dkmt->pfnD3DKMTPresent(&PresentData);
+ return Status;
+}
+
+NTSTATUS vboxKmtOpenSharedSurface(D3DKMT_HANDLE hAdapter, D3DKMT_HANDLE hDevice, D3DKMT_HANDLE hSharedSurface, struct stw_shared_surface *pSurf)
+{
+ D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
+
+ D3DKMT_QUERYRESOURCEINFO QueryResourceInfoData;
+ memset(&QueryResourceInfoData, 0, sizeof(QueryResourceInfoData));
+ QueryResourceInfoData.hDevice = hDevice;
+ QueryResourceInfoData.hGlobalShare = hSharedSurface;
+
+ NTSTATUS Status = d3dkmt->pfnD3DKMTQueryResourceInfo(&QueryResourceInfoData);
+ if (Status == STATUS_SUCCESS)
+ {
+ D3DDDI_OPENALLOCATIONINFO OpenAllocationInfoData;
+ memset(&OpenAllocationInfoData, 0, sizeof(OpenAllocationInfoData));
+
+ D3DKMT_OPENRESOURCE OpenResourceData;
+ memset(&OpenResourceData, 0, sizeof(OpenResourceData));
+ OpenResourceData.hDevice = hDevice;
+ OpenResourceData.hGlobalShare = hSharedSurface;
+ OpenResourceData.NumAllocations = 1;
+ OpenResourceData.pOpenAllocationInfo = &OpenAllocationInfoData;
+ if (QueryResourceInfoData.PrivateRuntimeDataSize)
+ {
+ OpenResourceData.pPrivateRuntimeData = malloc(QueryResourceInfoData.PrivateRuntimeDataSize);
+ if (OpenResourceData.pPrivateRuntimeData == NULL)
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ }
+ OpenResourceData.PrivateRuntimeDataSize = QueryResourceInfoData.PrivateRuntimeDataSize;
+ }
+ if (QueryResourceInfoData.ResourcePrivateDriverDataSize)
+ {
+ OpenResourceData.pResourcePrivateDriverData = malloc(QueryResourceInfoData.ResourcePrivateDriverDataSize);
+ if (OpenResourceData.pResourcePrivateDriverData == NULL)
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ }
+ OpenResourceData.ResourcePrivateDriverDataSize = QueryResourceInfoData.ResourcePrivateDriverDataSize;
+ }
+ if (QueryResourceInfoData.TotalPrivateDriverDataSize)
+ {
+ OpenResourceData.pTotalPrivateDriverDataBuffer = malloc(QueryResourceInfoData.TotalPrivateDriverDataSize);
+ if (OpenResourceData.pTotalPrivateDriverDataBuffer == NULL)
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ }
+ OpenResourceData.TotalPrivateDriverDataBufferSize = QueryResourceInfoData.TotalPrivateDriverDataSize;
+ }
+
+ if (Status == STATUS_SUCCESS)
+ {
+ Status = d3dkmt->pfnD3DKMTOpenResource(&OpenResourceData);
+ if (Status == STATUS_SUCCESS)
+ {
+ if (OpenAllocationInfoData.PrivateDriverDataSize == sizeof(VBOXWDDM_ALLOCINFO))
+ {
+ VBOXWDDM_ALLOCINFO *pVBoxAllocInfo = (VBOXWDDM_ALLOCINFO *)OpenAllocationInfoData.pPrivateDriverData;
+ pSurf->hResource = OpenResourceData.hResource;
+ pSurf->hSurface = OpenAllocationInfoData.hAllocation;
+ pSurf->u32Sid = pVBoxAllocInfo->hostID;
+ }
+ else if (OpenAllocationInfoData.PrivateDriverDataSize == sizeof(VBOXDXALLOCATIONDESC))
+ {
+ //VBOXDXALLOCATIONDESC *pAllocDesc = (VBOXDXALLOCATIONDESC *)OpenAllocationInfoData.PrivateDriverDataSize;
+ pSurf->hResource = OpenResourceData.hResource;
+ pSurf->hSurface = OpenAllocationInfoData.hAllocation;
+
+ VBOXDISPIFESCAPE_SVGAGETSID data;
+ memset(&data, 0, sizeof(data));
+ data.EscapeHdr.escapeCode = VBOXESC_SVGAGETSID;
+ data.hAllocation = OpenAllocationInfoData.hAllocation;
+ // data.u32Sid = 0;
+
+ D3DKMT_ESCAPE EscapeData;
+ memset(&EscapeData, 0, sizeof(EscapeData));
+ EscapeData.hAdapter = hAdapter;
+ EscapeData.hDevice = hDevice;
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ // EscapeData.Flags.HardwareAccess = 0;
+ EscapeData.pPrivateDriverData = &data;
+ EscapeData.PrivateDriverDataSize = sizeof(data);
+ // EscapeData.hContext = 0;
+ Status = d3dkmt->pfnD3DKMTEscape(&EscapeData);
+ if (Status == STATUS_SUCCESS)
+ pSurf->u32Sid = data.u32Sid;
+ else
+ Assert(0);
+ }
+ else
+ Assert(0);
+ }
+ }
+
+ if (OpenResourceData.pPrivateRuntimeData != NULL)
+ {
+ free(OpenResourceData.pPrivateRuntimeData);
+ }
+ if (OpenResourceData.pResourcePrivateDriverData != NULL)
+ {
+ free(OpenResourceData.pResourcePrivateDriverData);
+ }
+ if (OpenResourceData.pTotalPrivateDriverDataBuffer != NULL)
+ {
+ free(OpenResourceData.pTotalPrivateDriverDataBuffer);
+ }
+ }
+
+ return Status;
+}
+
+NTSTATUS vboxKmtCloseSharedSurface(D3DKMT_HANDLE hDevice, struct stw_shared_surface *pSurf)
+{
+ D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
+
+ D3DKMT_DESTROYALLOCATION DestroyAllocationData;
+ memset(&DestroyAllocationData, 0, sizeof(DestroyAllocationData));
+ DestroyAllocationData.hDevice = hDevice;
+ DestroyAllocationData.hResource = pSurf->hResource;
+ /* "If the OpenGL ICD sets the handle in the hResource member to a non-NULL value,
+ * the ICD must set phAllocationList to NULL." and
+ * "the AllocationCount member is ignored by the OpenGL runtime."
+ */
+ // DestroyAllocationData.phAllocationList = NULL;
+ // DestroyAllocationData.AllocationCount = 0;
+
+ NTSTATUS Status = d3dkmt->pfnD3DKMTDestroyAllocation(&DestroyAllocationData);
+ Assert(Status == STATUS_SUCCESS);
+ return Status;
+}
+
+
+static struct pipe_screen *
+wddm_screen_create(HDC hDC)
+{
+ RT_NOREF(hDC); /** @todo Use it? */
+ struct pipe_screen *screen = NULL;
+
+ if (gaDrvLoadSVGA(&g_drvfuncs))
+ {
+ WDDMGalliumDriverEnv const *pEnv = GaDrvEnvKmtCreate();
+ if (pEnv)
+ {
+ /// @todo pEnv to include destructor callback, to be called from winsys screen destructor?
+ screen = g_drvfuncs.pfnGaDrvScreenCreate(pEnv);
+ }
+ }
+
+ return screen;
+}
+
+static void
+wddm_present(struct pipe_screen *screen,
+ struct pipe_context *context,
+ struct pipe_resource *res,
+ HDC hDC)
+{
+ RT_NOREF(context);
+ struct stw_context *ctx = stw_current_context();
+ struct pipe_context *pipe = ctx->st->pipe;
+
+ const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
+ if (pEnv)
+ {
+ /* Get context and kernel-mode handle of the resource. */
+ uint32_t u32Cid = g_drvfuncs.pfnGaDrvGetContextId(pipe);
+ D3DKMT_HANDLE hContext = GaDrvEnvKmtContextHandle(pEnv, u32Cid);
+
+ uint32_t u32SourceSid = g_drvfuncs.pfnGaDrvGetSurfaceId(screen, res);
+ D3DKMT_HANDLE hSource = GaDrvEnvKmtSurfaceHandle(pEnv, u32SourceSid);
+
+ HWND hwnd = WindowFromDC(hDC);
+
+ vboxKmtPresent(hContext, hwnd, hSource, res->width0, res->height0);
+ }
+}
+
+static boolean
+wddm_get_adapter_luid(struct pipe_screen *screen,
+ HDC hDC,
+ LUID *pAdapterLuid)
+{
+ RT_NOREF(hDC); /** @todo Use it? */
+ const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
+ if (pEnv)
+ {
+ GaDrvEnvKmtAdapterLUID(pEnv, pAdapterLuid);
+ return true;
+ }
+
+ return false;
+}
+
+static struct stw_shared_surface *
+wddm_shared_surface_open(struct pipe_screen *screen,
+ HANDLE hSharedSurface)
+{
+ struct stw_shared_surface *surface = NULL;
+
+ const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
+ if (pEnv)
+ {
+ surface = (struct stw_shared_surface *)malloc(sizeof(struct stw_shared_surface));
+ if (surface)
+ {
+ D3DKMT_HANDLE hAdapter = GaDrvEnvKmtAdapterHandle(pEnv);
+ D3DKMT_HANDLE hDevice = GaDrvEnvKmtDeviceHandle(pEnv);
+ NTSTATUS Status = vboxKmtOpenSharedSurface(hAdapter, hDevice, (D3DKMT_HANDLE)(uintptr_t)hSharedSurface, surface);
+ if (Status != STATUS_SUCCESS)
+ {
+ free(surface);
+ surface = NULL;
+ }
+ }
+ }
+ return surface;
+}
+
+static void
+wddm_shared_surface_close(struct pipe_screen *screen,
+ struct stw_shared_surface *surface)
+{
+ const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
+ if (pEnv)
+ {
+ D3DKMT_HANDLE hDevice = GaDrvEnvKmtDeviceHandle(pEnv);
+ vboxKmtCloseSharedSurface(hDevice, surface);
+ }
+ free(surface);
+}
+
+static void
+wddm_compose(struct pipe_screen *screen,
+ struct pipe_resource *res,
+ struct stw_shared_surface *dest,
+ LPCRECT pRect,
+ ULONGLONG PresentHistoryToken)
+{
+ struct stw_context *ctx = stw_current_context();
+ struct pipe_context *pipe = ctx->st->pipe;
+
+ /* The ICD asked to present something, make sure that any outstanding commends are submitted. */
+ g_drvfuncs.pfnGaDrvContextFlush(pipe);
+
+ uint32_t u32SourceSid = g_drvfuncs.pfnGaDrvGetSurfaceId(screen, res);
+
+ /* Generate SVGA_3D_CMD_SURFACE_COPY command for these resources. */
+ struct
+ {
+ SVGA3dCmdHeader header;
+ SVGA3dCmdSurfaceCopy surfaceCopy;
+ SVGA3dCopyBox box;
+ } command;
+
+ command.header.id = SVGA_3D_CMD_SURFACE_COPY;
+ command.header.size = sizeof(command) - sizeof(SVGA3dCmdHeader);
+
+ command.surfaceCopy.src.sid = u32SourceSid;
+ command.surfaceCopy.src.face = 0;
+ command.surfaceCopy.src.mipmap = 0;
+ command.surfaceCopy.dest.sid = dest->u32Sid;
+ command.surfaceCopy.dest.face = 0;
+ command.surfaceCopy.dest.mipmap = 0;
+
+ command.box.x = pRect->left;
+ command.box.y = pRect->top;
+ command.box.z = 0;
+ command.box.w = pRect->right - pRect->left;
+ command.box.h = pRect->bottom - pRect->top;
+ command.box.d = 1;
+ command.box.srcx = 0;
+ command.box.srcy = 0;
+ command.box.srcz = 0;
+
+ const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
+ if (pEnv)
+ {
+ uint32_t u32Cid = g_drvfuncs.pfnGaDrvGetContextId(pipe);
+ GaDrvEnvKmtRenderCompose(pEnv, u32Cid, &command, sizeof(command), PresentHistoryToken);
+ }
+}
+
+static unsigned
+wddm_get_pfd_flags(struct pipe_screen *screen)
+{
+ (void)screen;
+ return stw_pfd_gdi_support | stw_pfd_double_buffer;
+}
+
+static const char *
+wddm_get_name(void)
+{
+ return "VBoxGL";
+}
+
+static const struct stw_winsys stw_winsys = {
+ wddm_screen_create,
+ wddm_present,
+ wddm_get_adapter_luid,
+ wddm_shared_surface_open,
+ wddm_shared_surface_close,
+ wddm_compose,
+ wddm_get_pfd_flags,
+ NULL, /* create_framebuffer */
+ wddm_get_name,
+};
+
+#ifdef DEBUG
+typedef BOOL WINAPI FNGetModuleInformation(HANDLE hProcess, HMODULE hModule, LPMODULEINFO lpmodinfo, DWORD cb);
+typedef FNGetModuleInformation *PFNGetModuleInformation;
+
+static PFNGetModuleInformation g_pfnGetModuleInformation = NULL;
+static HMODULE g_hModPsapi = NULL;
+static PVOID g_VBoxWDbgVEHandler = NULL;
+
+static bool vboxVDbgIsAddressInModule(PVOID pv, const char *pszModuleName)
+{
+ HMODULE hMod = GetModuleHandleA(pszModuleName);
+ if (!hMod)
+ return false;
+
+ if (!g_pfnGetModuleInformation)
+ return false;
+
+ HANDLE hProcess = GetCurrentProcess();
+ MODULEINFO ModuleInfo = {0};
+ if (!g_pfnGetModuleInformation(hProcess, hMod, &ModuleInfo, sizeof(ModuleInfo)))
+ return false;
+
+ return (uintptr_t)ModuleInfo.lpBaseOfDll <= (uintptr_t)pv
+ && (uintptr_t)pv < (uintptr_t)ModuleInfo.lpBaseOfDll + ModuleInfo.SizeOfImage;
+}
+
+static bool vboxVDbgIsExceptionIgnored(PEXCEPTION_RECORD pExceptionRecord)
+{
+ /* Module (dll) names for GetModuleHandle.
+ * Exceptions originated from these modules will be ignored.
+ */
+ static const char *apszIgnoredModuleNames[] =
+ {
+ NULL
+ };
+
+ int i = 0;
+ while (apszIgnoredModuleNames[i])
+ {
+ if (vboxVDbgIsAddressInModule(pExceptionRecord->ExceptionAddress, apszIgnoredModuleNames[i]))
+ return true;
+
+ ++i;
+ }
+
+ return false;
+}
+
+static LONG WINAPI vboxVDbgVectoredHandler(struct _EXCEPTION_POINTERS *pExceptionInfo) RT_NOTHROW_DEF
+{
+ static volatile bool g_fAllowIgnore = true; /* Might be changed in kernel debugger. */
+
+ PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
+ /* PCONTEXT pContextRecord = pExceptionInfo->ContextRecord; */
+
+ switch (pExceptionRecord->ExceptionCode)
+ {
+ default:
+ break;
+ case EXCEPTION_BREAKPOINT:
+ case EXCEPTION_ACCESS_VIOLATION:
+ case EXCEPTION_STACK_OVERFLOW:
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ case EXCEPTION_ILLEGAL_INSTRUCTION:
+ if (g_fAllowIgnore && vboxVDbgIsExceptionIgnored(pExceptionRecord))
+ break;
+ ASMBreakpoint();
+ break;
+ case 0x40010006: /* OutputDebugStringA? */
+ case 0x4001000a: /* OutputDebugStringW? */
+ break;
+ }
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+static void vboxVDbgVEHandlerRegister(void)
+{
+ Assert(!g_VBoxWDbgVEHandler);
+ g_VBoxWDbgVEHandler = AddVectoredExceptionHandler(1, vboxVDbgVectoredHandler);
+ Assert(g_VBoxWDbgVEHandler);
+
+ g_hModPsapi = GetModuleHandleA("Psapi.dll"); /* Usually already loaded. */
+ if (g_hModPsapi)
+ g_pfnGetModuleInformation = (PFNGetModuleInformation)GetProcAddress(g_hModPsapi, "GetModuleInformation");
+}
+
+static void vboxVDbgVEHandlerUnregister(void)
+{
+ Assert(g_VBoxWDbgVEHandler);
+ ULONG uResult = RemoveVectoredExceptionHandler(g_VBoxWDbgVEHandler);
+ Assert(uResult); RT_NOREF(uResult);
+ g_VBoxWDbgVEHandler = NULL;
+
+ g_hModPsapi = NULL;
+ g_pfnGetModuleInformation = NULL;
+}
+#endif /* DEBUG */
+
+BOOL WINAPI DllMain(HINSTANCE hDLLInst,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+ RT_NOREF2(hDLLInst, lpvReserved);
+
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+#ifdef DEBUG
+ vboxVDbgVEHandlerRegister();
+#endif
+ D3DKMTLoad();
+ stw_init(&stw_winsys);
+ stw_init_thread();
+ break;
+
+ case DLL_PROCESS_DETACH:
+#ifdef DEBUG
+ vboxVDbgVEHandlerUnregister();
+#endif
+ break;
+
+ case DLL_THREAD_ATTACH:
+ stw_init_thread();
+ break;
+
+ case DLL_THREAD_DETACH:
+ stw_cleanup_thread();
+ break;
+
+ default:
+ if (lpvReserved == NULL)
+ {
+ // We're being unloaded from the process.
+ stw_cleanup_thread();
+ stw_cleanup();
+ }
+ else
+ {
+ // Process itself is terminating, and all threads and modules are
+ // being detached.
+ //
+ // The order threads (including llvmpipe rasterizer threads) are
+ // destroyed can not be relied up, so it's not safe to cleanup.
+ //
+ // However global destructors (e.g., LLVM's) will still be called, and
+ // if Microsoft OPENGL32.DLL's DllMain is called after us, it will
+ // still try to invoke DrvDeleteContext to destroys all outstanding,
+ // so set stw_dev to NULL to return immediately if that happens.
+ stw_dev = NULL;
+ }
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/src/VBox/Additions/3D/win/VBoxGL/VBoxGL.rc b/src/VBox/Additions/3D/win/VBoxGL/VBoxGL.rc
new file mode 100644
index 00000000..23267650
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxGL/VBoxGL.rc
@@ -0,0 +1,66 @@
+/* $Id: VBoxGL.rc $ */
+/** @file
+ * VBoxGL - Resource file containing version info and icon.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include <windows.h>
+#include <VBox/version.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VBOX_RC_FILE_VERSION
+ PRODUCTVERSION VBOX_RC_FILE_VERSION
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS VBOX_RC_FILE_FLAGS
+ FILEOS VBOX_RC_FILE_OS
+ FILETYPE VBOX_RC_TYPE_DLL
+ FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "VirtualBox OpenGL Mesa State Tracker\0"
+ VALUE "InternalName", "VBoxGL\0"
+#ifdef VBOX_WOW64
+ VALUE "OriginalFilename", "VBoxGL-x86.DLL\0"
+#else
+ VALUE "OriginalFilename", "VBoxGL.DLL\0"
+#endif
+ VALUE "CompanyName", VBOX_RC_COMPANY_NAME
+ VALUE "FileVersion", VBOX_RC_FILE_VERSION_STR
+ VALUE "LegalCopyright", VBOX_RC_LEGAL_COPYRIGHT
+ VALUE "ProductName", VBOX_RC_PRODUCT_NAME_GA_STR
+ VALUE "ProductVersion", VBOX_RC_PRODUCT_VERSION_STR
+ VBOX_RC_MORE_STRINGS
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/src/VBox/Additions/3D/win/VBoxICD/.scm-settings b/src/VBox/Additions/3D/win/VBoxICD/.scm-settings
new file mode 100644
index 00000000..097184e6
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxICD/.scm-settings
@@ -0,0 +1,29 @@
+# $Id: .scm-settings $
+## @file
+# Source code massager settings for VBoxGL.
+#
+
+#
+# Copyright (C) 2010-2022 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+
+--filter-out-files "opengl32*def"
diff --git a/src/VBox/Additions/3D/win/VBoxICD/Makefile.kmk b/src/VBox/Additions/3D/win/VBoxICD/Makefile.kmk
new file mode 100644
index 00000000..6d1b8c67
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxICD/Makefile.kmk
@@ -0,0 +1,85 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for OpenGL ICD loader.
+#
+
+#
+# Copyright (C) 2018-2022 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+VBOX_GL_ICD_DEF_FILE = $(PATH_ROOT)/src/VBox/Additions/3D/win/VBoxICD/opengl32.mingw.def
+
+DLLS += VBoxICD
+DLLS.amd64 += VBoxICD-x86
+
+VBoxICD_TEMPLATE = VBoxMesa3DGuestR3DllMinVista
+# -wd4005: '__useHeader' : redefinition
+VBoxICD_CFLAGS := -wd4005
+if "$(VBOX_NEWER_VCC_TOOL_STEM)" >= "VCC141"
+# -wd4255: 'PFND3DKMT_CHECKEXCLUSIVEOWNERSHIP': no function prototype given: converting '()' to '(void)'
+VBoxICD_CFLAGS += -wd4255
+endif
+
+VBoxICD_INCS = \
+ $(VBOX_PATH_3D)/win/include \
+ $(PATH_ROOT)/src/VBox/Additions/WINNT/Graphics/Video \
+ $(PATH_ROOT)/src/VBox/Devices/Graphics/vmsvga_include \
+ $(VBOX_GRAPHICS_INCS)
+VBoxICD_SOURCES = \
+ opengl32.def \
+ $(VBoxICD_0_OUTDIR)/forwarders.asm \
+ $(VBoxICD_0_OUTDIR)/pfns.c \
+ VBoxICD.c \
+ VBoxICD.rc
+VBoxICD_CLEAN = \
+ $(VBoxICD_0_OUTDIR)/forwarders.asm \
+ $(VBoxICD_0_OUTDIR)/pfns.c
+VBoxICD_LIBS = \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxWddmUmHlp$(VBOX_SUFF_LIB)
+
+$$(VBoxICD_0_OUTDIR)/forwarders.asm: \
+ $(PATH_SUB_CURRENT)/icd_forwarders.py $(VBOX_GL_ICD_DEF_FILE) | $$(dir $$@)
+ $(call MSG_GENERATE,python,$@,$(VBOX_GL_ICD_DEF_FILE))
+ $(QUIET)$(VBOX_BLD_PYTHON) $< $(VBOX_GL_ICD_DEF_FILE) $@
+$$(VBoxICD_0_OUTDIR)/pfns.c: \
+ $(PATH_SUB_CURRENT)/icd_pfns.py $(VBOX_GL_ICD_DEF_FILE) | $$(dir $$@)
+ $(call MSG_GENERATE,python,$@,$(VBOX_GL_ICD_DEF_FILE))
+ $(QUIET)$(VBOX_BLD_PYTHON) $< $(VBOX_GL_ICD_DEF_FILE) $@
+
+if defined(VBOX_SIGNING_MODE) && defined(VBOX_SIGN_ADDITIONS)
+VBoxICD_INSTTYPE = none
+VBoxICD_DEBUG_INSTTYPE = both
+endif
+
+#
+# x86 version built for amd64 build
+#
+VBoxICD-x86_EXTENDS = VBoxICD
+VBoxICD-x86_BLD_TRG_ARCH = x86
+VBoxICD-x86_LIBS = \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxWddmUmHlp-x86$(VBOX_SUFF_LIB)
+VBoxICD-x86_DEFS = $(VBoxICD_DEFS) VBOX_WOW64
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Additions/3D/win/VBoxICD/VBoxICD.c b/src/VBox/Additions/3D/win/VBoxICD/VBoxICD.c
new file mode 100644
index 00000000..4857801f
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxICD/VBoxICD.c
@@ -0,0 +1,165 @@
+/* $Id: VBoxICD.c $ */
+/** @file
+ * VirtualBox Windows Guest Mesa3D - OpenGL driver loader.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include <VBoxWddmUmHlp.h>
+
+#include <common/wddm/VBoxMPIf.h>
+
+static const char *g_pszGalliumDll =
+#ifdef VBOX_WOW64
+ "VBoxGL-x86.dll"
+#else
+ "VBoxGL.dll"
+#endif
+;
+
+static const char *g_pszChromiumDll =
+#ifdef VBOX_WOW64
+ "VBoxOGL-x86.dll"
+#else
+ "VBoxOGL.dll"
+#endif
+;
+
+extern struct VBOXWDDMDLLPROC aIcdProcs[];
+
+HMODULE volatile g_hmodICD = NULL;
+
+static NTSTATUS
+vboxDdiQueryAdapterInfo(D3DKMT_HANDLE hAdapter,
+ VBOXWDDM_QAI *pAdapterInfo,
+ uint32_t cbAdapterInfo)
+{
+ NTSTATUS Status;
+ D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
+
+ if (d3dkmt->pfnD3DKMTQueryAdapterInfo)
+ {
+ D3DKMT_QUERYADAPTERINFO QAI;
+ memset(&QAI, 0, sizeof(QAI));
+ QAI.hAdapter = hAdapter;
+ QAI.Type = KMTQAITYPE_UMDRIVERPRIVATE;
+ QAI.pPrivateDriverData = pAdapterInfo;
+ QAI.PrivateDriverDataSize = cbAdapterInfo;
+
+ Status = d3dkmt->pfnD3DKMTQueryAdapterInfo(&QAI);
+ }
+ else
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ }
+
+ return Status;
+}
+
+void VBoxLoadICD(void)
+{
+ NTSTATUS Status;
+ D3DKMT_HANDLE hAdapter = 0;
+
+ D3DKMTLoad();
+
+ Status = vboxDispKmtOpenAdapter(&hAdapter);
+ if (Status == STATUS_SUCCESS)
+ {
+ VBOXWDDM_QAI adapterInfo;
+ Status = vboxDdiQueryAdapterInfo(hAdapter, &adapterInfo, sizeof(adapterInfo));
+ if (Status == STATUS_SUCCESS)
+ {
+ const char *pszDll = NULL;
+ switch (adapterInfo.enmHwType)
+ {
+ case VBOXVIDEO_HWTYPE_VBOX: pszDll = g_pszChromiumDll; break;
+ default:
+ case VBOXVIDEO_HWTYPE_VMSVGA: pszDll = g_pszGalliumDll; break;
+ }
+
+ if (pszDll)
+ {
+ g_hmodICD = VBoxWddmLoadSystemDll(pszDll);
+ if (g_hmodICD)
+ {
+ VBoxWddmLoadAdresses(g_hmodICD, aIcdProcs);
+ }
+ }
+ }
+
+ vboxDispKmtCloseAdapter(hAdapter);
+ }
+}
+
+/*
+ * MSDN says:
+ * "You should never perform the following tasks from within DllMain:
+ * Call LoadLibrary or LoadLibraryEx (either directly or indirectly)."
+ *
+ * However it turned out that loading the real ICD from DLL_PROCESS_ATTACH works,
+ * and loading it in a lazy way fails for unknown reason on 64 bit Windows.
+ *
+ * So just call VBoxLoadICD from DLL_PROCESS_ATTACH.
+ */
+BOOL WINAPI DllMain(HINSTANCE hDLLInst,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+ RT_NOREF(hDLLInst);
+
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ VBoxLoadICD();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ if (lpvReserved == NULL)
+ {
+ /* "The DLL is being unloaded because of a call to FreeLibrary." */
+ if (g_hmodICD)
+ {
+ FreeLibrary(g_hmodICD);
+ g_hmodICD = NULL;
+ }
+ }
+ else
+ {
+ /* "The DLL is being unloaded due to process termination." */
+ /* Do not bother. */
+ }
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+
+ default:
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/src/VBox/Additions/3D/win/VBoxICD/VBoxICD.rc b/src/VBox/Additions/3D/win/VBoxICD/VBoxICD.rc
new file mode 100644
index 00000000..2e17b82f
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxICD/VBoxICD.rc
@@ -0,0 +1,66 @@
+/* $Id: VBoxICD.rc $ */
+/** @file
+ * VBoxGL - Resource file containing version info and icon.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include <windows.h>
+#include <VBox/version.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VBOX_RC_FILE_VERSION
+ PRODUCTVERSION VBOX_RC_FILE_VERSION
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS VBOX_RC_FILE_FLAGS
+ FILEOS VBOX_RC_FILE_OS
+ FILETYPE VBOX_RC_TYPE_DLL
+ FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "VirtualBox OpenGL ICD Loader\0"
+ VALUE "InternalName", "VBoxICD\0"
+#ifdef VBOX_WOW64
+ VALUE "OriginalFilename", "VBoxICD-x86.dll\0"
+#else
+ VALUE "OriginalFilename", "VBoxICD.dll\0"
+#endif
+ VALUE "CompanyName", VBOX_RC_COMPANY_NAME
+ VALUE "FileVersion", VBOX_RC_FILE_VERSION_STR
+ VALUE "LegalCopyright", VBOX_RC_LEGAL_COPYRIGHT
+ VALUE "ProductName", VBOX_RC_PRODUCT_NAME_GA_STR
+ VALUE "ProductVersion", VBOX_RC_PRODUCT_VERSION_STR
+ VBOX_RC_MORE_STRINGS
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/src/VBox/Additions/3D/win/VBoxICD/icd_forwarders.py b/src/VBox/Additions/3D/win/VBoxICD/icd_forwarders.py
new file mode 100755
index 00000000..b2fe44f3
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxICD/icd_forwarders.py
@@ -0,0 +1,105 @@
+"""
+Copyright (C) 2018-2022 Oracle and/or its affiliates.
+
+This file is part of VirtualBox base platform packages, as
+available from https://www.virtualbox.org.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation, in version 3 of the
+License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, see <https://www.gnu.org/licenses>.
+
+SPDX-License-Identifier: GPL-3.0-only
+"""
+
+import sys
+
+def GenerateForwarders():
+
+ # Get list of functions.
+ exports_file = open(sys.argv[1], "r")
+ if not exports_file:
+ print("Error: couldn't open %s file!" % filename)
+ sys.exit()
+
+ names = []
+ cbArgs = []
+ for line in exports_file.readlines():
+ line = line.strip()
+ if len(line) > 0 and line[0] != ';' and line != 'EXPORTS':
+ # Parse 'glAccum = glAccum@8'
+ words = line.split('=', 1)
+
+ # Function name
+ names.append(words[0].strip())
+
+ # Size of arguments in bytes
+ words = words[1].split('@')
+ cbArgs.append(words[1].strip())
+
+ exports_file.close()
+
+
+ #
+ # Assembler forwarders
+ #
+ asm_file = open(sys.argv[2], "w")
+ if not asm_file:
+ print("Error: couldn't open %s file!" % filename)
+ sys.exit()
+
+ asm_file.write('%include "iprt/asmdefs.mac"\n')
+ asm_file.write('\n')
+ asm_file.write(';;;; Enable ICD_LAZY_LOAD to lazy load the ICD DLL (does not work on Win64)\n')
+ asm_file.write('; %define ICD_LAZY_LOAD 1\n')
+ asm_file.write('\n')
+ asm_file.write('%ifdef RT_ARCH_AMD64\n')
+ asm_file.write('%define PTR_SIZE_PREFIX qword\n')
+ asm_file.write('%else ; X86\n')
+ asm_file.write('%define PTR_SIZE_PREFIX dword\n')
+ asm_file.write('%endif\n')
+ asm_file.write('\n')
+ asm_file.write('%ifdef ICD_LAZY_LOAD\n')
+ asm_file.write('extern NAME(VBoxLoadICD)\n')
+ asm_file.write('%endif\n')
+ asm_file.write('extern NAME(g_hmodICD)\n')
+
+ for index in range(len(names)):
+ fn = names[index]
+ cbRet = cbArgs[index]
+ asm_file.write('\n')
+ asm_file.write('BEGINPROC_EXPORTED %s\n' % fn)
+ asm_file.write(' extern NAME(pfn_%s)\n' % fn)
+ asm_file.write('; int3\n')
+ asm_file.write('%ifdef ICD_LAZY_LOAD\n')
+ asm_file.write(' mov xAX, PTR_SIZE_PREFIX NAME(g_hmodICD)\n')
+ asm_file.write(' mov xAX, [xAX]\n')
+ asm_file.write(' or xAX, xAX\n')
+ asm_file.write(' jnz l_icd_loaded_%s\n' % fn)
+ asm_file.write(' call NAME(VBoxLoadICD)\n')
+ asm_file.write('l_icd_loaded_%s:\n' % fn)
+ asm_file.write('%endif\n')
+ asm_file.write(' mov xAX, PTR_SIZE_PREFIX NAME(pfn_%s)\n' % fn)
+ asm_file.write(' mov xAX, [xAX]\n')
+ asm_file.write(' or xAX, xAX\n')
+ asm_file.write(' jnz l_jmp_to_%s\n' % fn)
+ asm_file.write('%ifdef RT_ARCH_AMD64\n')
+ asm_file.write(' ret\n')
+ asm_file.write('%else ; X86\n')
+ asm_file.write(' ret %s\n' % cbRet)
+ asm_file.write('%endif\n')
+ asm_file.write('l_jmp_to_%s:\n' % fn)
+ asm_file.write(' jmp xAX\n')
+ asm_file.write('ENDPROC %s\n' % fn)
+
+ asm_file.close()
+
+GenerateForwarders()
diff --git a/src/VBox/Additions/3D/win/VBoxICD/icd_pfns.py b/src/VBox/Additions/3D/win/VBoxICD/icd_pfns.py
new file mode 100755
index 00000000..47f7df7c
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxICD/icd_pfns.py
@@ -0,0 +1,73 @@
+"""
+Copyright (C) 2018-2022 Oracle and/or its affiliates.
+
+This file is part of VirtualBox base platform packages, as
+available from https://www.virtualbox.org.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation, in version 3 of the
+License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, see <https://www.gnu.org/licenses>.
+
+SPDX-License-Identifier: GPL-3.0-only
+"""
+
+import sys
+
+def GeneratePfns():
+
+ # Get list of functions.
+ exports_file = open(sys.argv[1], "r")
+ if not exports_file:
+ print("Error: couldn't open %s file!" % filename)
+ sys.exit()
+
+ names = []
+ for line in exports_file.readlines():
+ line = line.strip()
+ if len(line) > 0 and line[0] != ';' and line != 'EXPORTS':
+ # Parse 'glAccum = glAccum@8'
+ words = line.split('=')
+
+ # Function name
+ names.append(words[0].strip())
+
+ exports_file.close()
+
+
+ #
+ # C loader data
+ #
+ c_file = open(sys.argv[2], "w")
+ if not c_file:
+ print("Error: couldn't open %s file!" % filename)
+ sys.exit()
+
+ c_file.write('#include <iprt/win/windows.h>\n')
+ c_file.write('#include <VBoxWddmUmHlp.h>\n')
+ c_file.write('\n')
+
+ for index in range(len(names)):
+ fn = names[index]
+ c_file.write('FARPROC pfn_%s;\n' % fn)
+ c_file.write('\n')
+
+ c_file.write("struct VBOXWDDMDLLPROC aIcdProcs[] =\n")
+ c_file.write('{\n')
+ for index in range(len(names)):
+ fn = names[index]
+ c_file.write(' { "%s", &pfn_%s },\n' % (fn, fn) )
+ c_file.write(' { NULL, NULL }\n')
+ c_file.write('};\n')
+
+ c_file.close()
+
+GeneratePfns()
diff --git a/src/VBox/Additions/3D/win/VBoxICD/opengl32.def b/src/VBox/Additions/3D/win/VBoxICD/opengl32.def
new file mode 100644
index 00000000..c35c23b5
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxICD/opengl32.def
@@ -0,0 +1,388 @@
+EXPORTS
+; GlmfBeginGlsBlock
+; GlmfCloseMetaFile
+; GlmfEndGlsBlock
+; GlmfEndPlayback
+; GlmfInitPlayback
+; GlmfPlayGlsRecord
+ glAccum
+ glAlphaFunc
+ glAreTexturesResident
+ glArrayElement
+ glBegin
+ glBindTexture
+ glBitmap
+ glBlendFunc
+ glCallList
+ glCallLists
+ glClear
+ glClearAccum
+ glClearColor
+ glClearDepth
+ glClearIndex
+ glClearStencil
+ glClipPlane
+ glColor3b
+ glColor3bv
+ glColor3d
+ glColor3dv
+ glColor3f
+ glColor3fv
+ glColor3i
+ glColor3iv
+ glColor3s
+ glColor3sv
+ glColor3ub
+ glColor3ubv
+ glColor3ui
+ glColor3uiv
+ glColor3us
+ glColor3usv
+ glColor4b
+ glColor4bv
+ glColor4d
+ glColor4dv
+ glColor4f
+ glColor4fv
+ glColor4i
+ glColor4iv
+ glColor4s
+ glColor4sv
+ glColor4ub
+ glColor4ubv
+ glColor4ui
+ glColor4uiv
+ glColor4us
+ glColor4usv
+ glColorMask
+ glColorMaterial
+ glColorPointer
+ glCopyPixels
+ glCopyTexImage1D
+ glCopyTexImage2D
+ glCopyTexSubImage1D
+ glCopyTexSubImage2D
+ glCullFace
+; glDebugEntry
+ glDeleteLists
+ glDeleteTextures
+ glDepthFunc
+ glDepthMask
+ glDepthRange
+ glDisable
+ glDisableClientState
+ glDrawArrays
+ glDrawBuffer
+ glDrawElements
+ glDrawPixels
+ glEdgeFlag
+ glEdgeFlagPointer
+ glEdgeFlagv
+ glEnable
+ glEnableClientState
+ glEnd
+ glEndList
+ glEvalCoord1d
+ glEvalCoord1dv
+ glEvalCoord1f
+ glEvalCoord1fv
+ glEvalCoord2d
+ glEvalCoord2dv
+ glEvalCoord2f
+ glEvalCoord2fv
+ glEvalMesh1
+ glEvalMesh2
+ glEvalPoint1
+ glEvalPoint2
+ glFeedbackBuffer
+ glFinish
+ glFlush
+ glFogf
+ glFogfv
+ glFogi
+ glFogiv
+ glFrontFace
+ glFrustum
+ glGenLists
+ glGenTextures
+ glGetBooleanv
+ glGetClipPlane
+ glGetDoublev
+ glGetError
+ glGetFloatv
+ glGetIntegerv
+ glGetLightfv
+ glGetLightiv
+ glGetMapdv
+ glGetMapfv
+ glGetMapiv
+ glGetMaterialfv
+ glGetMaterialiv
+ glGetPixelMapfv
+ glGetPixelMapuiv
+ glGetPixelMapusv
+ glGetPointerv
+ glGetPolygonStipple
+ glGetString
+ glGetTexEnvfv
+ glGetTexEnviv
+ glGetTexGendv
+ glGetTexGenfv
+ glGetTexGeniv
+ glGetTexImage
+ glGetTexLevelParameterfv
+ glGetTexLevelParameteriv
+ glGetTexParameterfv
+ glGetTexParameteriv
+ glHint
+ glIndexMask
+ glIndexPointer
+ glIndexd
+ glIndexdv
+ glIndexf
+ glIndexfv
+ glIndexi
+ glIndexiv
+ glIndexs
+ glIndexsv
+ glIndexub
+ glIndexubv
+ glInitNames
+ glInterleavedArrays
+ glIsEnabled
+ glIsList
+ glIsTexture
+ glLightModelf
+ glLightModelfv
+ glLightModeli
+ glLightModeliv
+ glLightf
+ glLightfv
+ glLighti
+ glLightiv
+ glLineStipple
+ glLineWidth
+ glListBase
+ glLoadIdentity
+ glLoadMatrixd
+ glLoadMatrixf
+ glLoadName
+ glLogicOp
+ glMap1d
+ glMap1f
+ glMap2d
+ glMap2f
+ glMapGrid1d
+ glMapGrid1f
+ glMapGrid2d
+ glMapGrid2f
+ glMaterialf
+ glMaterialfv
+ glMateriali
+ glMaterialiv
+ glMatrixMode
+ glMultMatrixd
+ glMultMatrixf
+ glNewList
+ glNormal3b
+ glNormal3bv
+ glNormal3d
+ glNormal3dv
+ glNormal3f
+ glNormal3fv
+ glNormal3i
+ glNormal3iv
+ glNormal3s
+ glNormal3sv
+ glNormalPointer
+ glOrtho
+ glPassThrough
+ glPixelMapfv
+ glPixelMapuiv
+ glPixelMapusv
+ glPixelStoref
+ glPixelStorei
+ glPixelTransferf
+ glPixelTransferi
+ glPixelZoom
+ glPointSize
+ glPolygonMode
+ glPolygonOffset
+ glPolygonStipple
+ glPopAttrib
+ glPopClientAttrib
+ glPopMatrix
+ glPopName
+ glPrioritizeTextures
+ glPushAttrib
+ glPushClientAttrib
+ glPushMatrix
+ glPushName
+ glRasterPos2d
+ glRasterPos2dv
+ glRasterPos2f
+ glRasterPos2fv
+ glRasterPos2i
+ glRasterPos2iv
+ glRasterPos2s
+ glRasterPos2sv
+ glRasterPos3d
+ glRasterPos3dv
+ glRasterPos3f
+ glRasterPos3fv
+ glRasterPos3i
+ glRasterPos3iv
+ glRasterPos3s
+ glRasterPos3sv
+ glRasterPos4d
+ glRasterPos4dv
+ glRasterPos4f
+ glRasterPos4fv
+ glRasterPos4i
+ glRasterPos4iv
+ glRasterPos4s
+ glRasterPos4sv
+ glReadBuffer
+ glReadPixels
+ glRectd
+ glRectdv
+ glRectf
+ glRectfv
+ glRecti
+ glRectiv
+ glRects
+ glRectsv
+ glRenderMode
+ glRotated
+ glRotatef
+ glScaled
+ glScalef
+ glScissor
+ glSelectBuffer
+ glShadeModel
+ glStencilFunc
+ glStencilMask
+ glStencilOp
+ glTexCoord1d
+ glTexCoord1dv
+ glTexCoord1f
+ glTexCoord1fv
+ glTexCoord1i
+ glTexCoord1iv
+ glTexCoord1s
+ glTexCoord1sv
+ glTexCoord2d
+ glTexCoord2dv
+ glTexCoord2f
+ glTexCoord2fv
+ glTexCoord2i
+ glTexCoord2iv
+ glTexCoord2s
+ glTexCoord2sv
+ glTexCoord3d
+ glTexCoord3dv
+ glTexCoord3f
+ glTexCoord3fv
+ glTexCoord3i
+ glTexCoord3iv
+ glTexCoord3s
+ glTexCoord3sv
+ glTexCoord4d
+ glTexCoord4dv
+ glTexCoord4f
+ glTexCoord4fv
+ glTexCoord4i
+ glTexCoord4iv
+ glTexCoord4s
+ glTexCoord4sv
+ glTexCoordPointer
+ glTexEnvf
+ glTexEnvfv
+ glTexEnvi
+ glTexEnviv
+ glTexGend
+ glTexGendv
+ glTexGenf
+ glTexGenfv
+ glTexGeni
+ glTexGeniv
+ glTexImage1D
+ glTexImage2D
+ glTexParameterf
+ glTexParameterfv
+ glTexParameteri
+ glTexParameteriv
+ glTexSubImage1D
+ glTexSubImage2D
+ glTranslated
+ glTranslatef
+ glVertex2d
+ glVertex2dv
+ glVertex2f
+ glVertex2fv
+ glVertex2i
+ glVertex2iv
+ glVertex2s
+ glVertex2sv
+ glVertex3d
+ glVertex3dv
+ glVertex3f
+ glVertex3fv
+ glVertex3i
+ glVertex3iv
+ glVertex3s
+ glVertex3sv
+ glVertex4d
+ glVertex4dv
+ glVertex4f
+ glVertex4fv
+ glVertex4i
+ glVertex4iv
+ glVertex4s
+ glVertex4sv
+ glVertexPointer
+ glViewport
+ wglChoosePixelFormat
+ wglCopyContext
+ wglCreateContext
+ wglCreateLayerContext
+ wglDeleteContext
+ wglDescribeLayerPlane
+ wglDescribePixelFormat
+ wglGetCurrentContext
+ wglGetCurrentDC
+; wglGetDefaultProcAddress
+ wglGetLayerPaletteEntries
+ wglGetPixelFormat
+ wglGetProcAddress
+ wglMakeCurrent
+ wglRealizeLayerPalette
+ wglSetLayerPaletteEntries
+ wglSetPixelFormat
+ wglShareLists
+ wglSwapBuffers
+ wglSwapLayerBuffers
+ wglSwapMultipleBuffers
+ wglUseFontBitmapsA
+ wglUseFontBitmapsW
+ wglUseFontOutlinesA
+ wglUseFontOutlinesW
+ DrvCopyContext
+ DrvCreateContext
+ DrvCreateLayerContext
+ DrvDeleteContext
+ DrvDescribeLayerPlane
+ DrvDescribePixelFormat
+ DrvGetLayerPaletteEntries
+ DrvGetProcAddress
+ DrvPresentBuffers
+ DrvRealizeLayerPalette
+ DrvReleaseContext
+ DrvSetCallbackProcs
+ DrvSetContext
+ DrvSetLayerPaletteEntries
+ DrvSetPixelFormat
+ DrvShareLists
+ DrvSwapBuffers
+ DrvSwapLayerBuffers
+ DrvValidateVersion
diff --git a/src/VBox/Additions/3D/win/VBoxICD/opengl32.mingw.def b/src/VBox/Additions/3D/win/VBoxICD/opengl32.mingw.def
new file mode 100644
index 00000000..0bceee06
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxICD/opengl32.mingw.def
@@ -0,0 +1,388 @@
+EXPORTS
+; GlmfBeginGlsBlock = GlmfBeginGlsBlock@4
+; GlmfCloseMetaFile = GlmfCloseMetaFile@4
+; GlmfEndGlsBlock = GlmfEndGlsBlock@4
+; GlmfEndPlayback = GlmfEndPlayback@4
+; GlmfInitPlayback = GlmfInitPlayback@12
+; GlmfPlayGlsRecord = GlmfPlayGlsRecord@16
+ glAccum = glAccum@8
+ glAlphaFunc = glAlphaFunc@8
+ glAreTexturesResident = glAreTexturesResident@12
+ glArrayElement = glArrayElement@4
+ glBegin = glBegin@4
+ glBindTexture = glBindTexture@8
+ glBitmap = glBitmap@28
+ glBlendFunc = glBlendFunc@8
+ glCallList = glCallList@4
+ glCallLists = glCallLists@12
+ glClear = glClear@4
+ glClearAccum = glClearAccum@16
+ glClearColor = glClearColor@16
+ glClearDepth = glClearDepth@8
+ glClearIndex = glClearIndex@4
+ glClearStencil = glClearStencil@4
+ glClipPlane = glClipPlane@8
+ glColor3b = glColor3b@12
+ glColor3bv = glColor3bv@4
+ glColor3d = glColor3d@24
+ glColor3dv = glColor3dv@4
+ glColor3f = glColor3f@12
+ glColor3fv = glColor3fv@4
+ glColor3i = glColor3i@12
+ glColor3iv = glColor3iv@4
+ glColor3s = glColor3s@12
+ glColor3sv = glColor3sv@4
+ glColor3ub = glColor3ub@12
+ glColor3ubv = glColor3ubv@4
+ glColor3ui = glColor3ui@12
+ glColor3uiv = glColor3uiv@4
+ glColor3us = glColor3us@12
+ glColor3usv = glColor3usv@4
+ glColor4b = glColor4b@16
+ glColor4bv = glColor4bv@4
+ glColor4d = glColor4d@32
+ glColor4dv = glColor4dv@4
+ glColor4f = glColor4f@16
+ glColor4fv = glColor4fv@4
+ glColor4i = glColor4i@16
+ glColor4iv = glColor4iv@4
+ glColor4s = glColor4s@16
+ glColor4sv = glColor4sv@4
+ glColor4ub = glColor4ub@16
+ glColor4ubv = glColor4ubv@4
+ glColor4ui = glColor4ui@16
+ glColor4uiv = glColor4uiv@4
+ glColor4us = glColor4us@16
+ glColor4usv = glColor4usv@4
+ glColorMask = glColorMask@16
+ glColorMaterial = glColorMaterial@8
+ glColorPointer = glColorPointer@16
+ glCopyPixels = glCopyPixels@20
+ glCopyTexImage1D = glCopyTexImage1D@28
+ glCopyTexImage2D = glCopyTexImage2D@32
+ glCopyTexSubImage1D = glCopyTexSubImage1D@24
+ glCopyTexSubImage2D = glCopyTexSubImage2D@32
+ glCullFace = glCullFace@4
+; glDebugEntry = glDebugEntry@8
+ glDeleteLists = glDeleteLists@8
+ glDeleteTextures = glDeleteTextures@8
+ glDepthFunc = glDepthFunc@4
+ glDepthMask = glDepthMask@4
+ glDepthRange = glDepthRange@16
+ glDisable = glDisable@4
+ glDisableClientState = glDisableClientState@4
+ glDrawArrays = glDrawArrays@12
+ glDrawBuffer = glDrawBuffer@4
+ glDrawElements = glDrawElements@16
+ glDrawPixels = glDrawPixels@20
+ glEdgeFlag = glEdgeFlag@4
+ glEdgeFlagPointer = glEdgeFlagPointer@8
+ glEdgeFlagv = glEdgeFlagv@4
+ glEnable = glEnable@4
+ glEnableClientState = glEnableClientState@4
+ glEnd = glEnd@0
+ glEndList = glEndList@0
+ glEvalCoord1d = glEvalCoord1d@8
+ glEvalCoord1dv = glEvalCoord1dv@4
+ glEvalCoord1f = glEvalCoord1f@4
+ glEvalCoord1fv = glEvalCoord1fv@4
+ glEvalCoord2d = glEvalCoord2d@16
+ glEvalCoord2dv = glEvalCoord2dv@4
+ glEvalCoord2f = glEvalCoord2f@8
+ glEvalCoord2fv = glEvalCoord2fv@4
+ glEvalMesh1 = glEvalMesh1@12
+ glEvalMesh2 = glEvalMesh2@20
+ glEvalPoint1 = glEvalPoint1@4
+ glEvalPoint2 = glEvalPoint2@8
+ glFeedbackBuffer = glFeedbackBuffer@12
+ glFinish = glFinish@0
+ glFlush = glFlush@0
+ glFogf = glFogf@8
+ glFogfv = glFogfv@8
+ glFogi = glFogi@8
+ glFogiv = glFogiv@8
+ glFrontFace = glFrontFace@4
+ glFrustum = glFrustum@48
+ glGenLists = glGenLists@4
+ glGenTextures = glGenTextures@8
+ glGetBooleanv = glGetBooleanv@8
+ glGetClipPlane = glGetClipPlane@8
+ glGetDoublev = glGetDoublev@8
+ glGetError = glGetError@0
+ glGetFloatv = glGetFloatv@8
+ glGetIntegerv = glGetIntegerv@8
+ glGetLightfv = glGetLightfv@12
+ glGetLightiv = glGetLightiv@12
+ glGetMapdv = glGetMapdv@12
+ glGetMapfv = glGetMapfv@12
+ glGetMapiv = glGetMapiv@12
+ glGetMaterialfv = glGetMaterialfv@12
+ glGetMaterialiv = glGetMaterialiv@12
+ glGetPixelMapfv = glGetPixelMapfv@8
+ glGetPixelMapuiv = glGetPixelMapuiv@8
+ glGetPixelMapusv = glGetPixelMapusv@8
+ glGetPointerv = glGetPointerv@8
+ glGetPolygonStipple = glGetPolygonStipple@4
+ glGetString = glGetString@4
+ glGetTexEnvfv = glGetTexEnvfv@12
+ glGetTexEnviv = glGetTexEnviv@12
+ glGetTexGendv = glGetTexGendv@12
+ glGetTexGenfv = glGetTexGenfv@12
+ glGetTexGeniv = glGetTexGeniv@12
+ glGetTexImage = glGetTexImage@20
+ glGetTexLevelParameterfv = glGetTexLevelParameterfv@16
+ glGetTexLevelParameteriv = glGetTexLevelParameteriv@16
+ glGetTexParameterfv = glGetTexParameterfv@12
+ glGetTexParameteriv = glGetTexParameteriv@12
+ glHint = glHint@8
+ glIndexMask = glIndexMask@4
+ glIndexPointer = glIndexPointer@12
+ glIndexd = glIndexd@8
+ glIndexdv = glIndexdv@4
+ glIndexf = glIndexf@4
+ glIndexfv = glIndexfv@4
+ glIndexi = glIndexi@4
+ glIndexiv = glIndexiv@4
+ glIndexs = glIndexs@4
+ glIndexsv = glIndexsv@4
+ glIndexub = glIndexub@4
+ glIndexubv = glIndexubv@4
+ glInitNames = glInitNames@0
+ glInterleavedArrays = glInterleavedArrays@12
+ glIsEnabled = glIsEnabled@4
+ glIsList = glIsList@4
+ glIsTexture = glIsTexture@4
+ glLightModelf = glLightModelf@8
+ glLightModelfv = glLightModelfv@8
+ glLightModeli = glLightModeli@8
+ glLightModeliv = glLightModeliv@8
+ glLightf = glLightf@12
+ glLightfv = glLightfv@12
+ glLighti = glLighti@12
+ glLightiv = glLightiv@12
+ glLineStipple = glLineStipple@8
+ glLineWidth = glLineWidth@4
+ glListBase = glListBase@4
+ glLoadIdentity = glLoadIdentity@0
+ glLoadMatrixd = glLoadMatrixd@4
+ glLoadMatrixf = glLoadMatrixf@4
+ glLoadName = glLoadName@4
+ glLogicOp = glLogicOp@4
+ glMap1d = glMap1d@32
+ glMap1f = glMap1f@24
+ glMap2d = glMap2d@56
+ glMap2f = glMap2f@40
+ glMapGrid1d = glMapGrid1d@20
+ glMapGrid1f = glMapGrid1f@12
+ glMapGrid2d = glMapGrid2d@40
+ glMapGrid2f = glMapGrid2f@24
+ glMaterialf = glMaterialf@12
+ glMaterialfv = glMaterialfv@12
+ glMateriali = glMateriali@12
+ glMaterialiv = glMaterialiv@12
+ glMatrixMode = glMatrixMode@4
+ glMultMatrixd = glMultMatrixd@4
+ glMultMatrixf = glMultMatrixf@4
+ glNewList = glNewList@8
+ glNormal3b = glNormal3b@12
+ glNormal3bv = glNormal3bv@4
+ glNormal3d = glNormal3d@24
+ glNormal3dv = glNormal3dv@4
+ glNormal3f = glNormal3f@12
+ glNormal3fv = glNormal3fv@4
+ glNormal3i = glNormal3i@12
+ glNormal3iv = glNormal3iv@4
+ glNormal3s = glNormal3s@12
+ glNormal3sv = glNormal3sv@4
+ glNormalPointer = glNormalPointer@12
+ glOrtho = glOrtho@48
+ glPassThrough = glPassThrough@4
+ glPixelMapfv = glPixelMapfv@12
+ glPixelMapuiv = glPixelMapuiv@12
+ glPixelMapusv = glPixelMapusv@12
+ glPixelStoref = glPixelStoref@8
+ glPixelStorei = glPixelStorei@8
+ glPixelTransferf = glPixelTransferf@8
+ glPixelTransferi = glPixelTransferi@8
+ glPixelZoom = glPixelZoom@8
+ glPointSize = glPointSize@4
+ glPolygonMode = glPolygonMode@8
+ glPolygonOffset = glPolygonOffset@8
+ glPolygonStipple = glPolygonStipple@4
+ glPopAttrib = glPopAttrib@0
+ glPopClientAttrib = glPopClientAttrib@0
+ glPopMatrix = glPopMatrix@0
+ glPopName = glPopName@0
+ glPrioritizeTextures = glPrioritizeTextures@12
+ glPushAttrib = glPushAttrib@4
+ glPushClientAttrib = glPushClientAttrib@4
+ glPushMatrix = glPushMatrix@0
+ glPushName = glPushName@4
+ glRasterPos2d = glRasterPos2d@16
+ glRasterPos2dv = glRasterPos2dv@4
+ glRasterPos2f = glRasterPos2f@8
+ glRasterPos2fv = glRasterPos2fv@4
+ glRasterPos2i = glRasterPos2i@8
+ glRasterPos2iv = glRasterPos2iv@4
+ glRasterPos2s = glRasterPos2s@8
+ glRasterPos2sv = glRasterPos2sv@4
+ glRasterPos3d = glRasterPos3d@24
+ glRasterPos3dv = glRasterPos3dv@4
+ glRasterPos3f = glRasterPos3f@12
+ glRasterPos3fv = glRasterPos3fv@4
+ glRasterPos3i = glRasterPos3i@12
+ glRasterPos3iv = glRasterPos3iv@4
+ glRasterPos3s = glRasterPos3s@12
+ glRasterPos3sv = glRasterPos3sv@4
+ glRasterPos4d = glRasterPos4d@32
+ glRasterPos4dv = glRasterPos4dv@4
+ glRasterPos4f = glRasterPos4f@16
+ glRasterPos4fv = glRasterPos4fv@4
+ glRasterPos4i = glRasterPos4i@16
+ glRasterPos4iv = glRasterPos4iv@4
+ glRasterPos4s = glRasterPos4s@16
+ glRasterPos4sv = glRasterPos4sv@4
+ glReadBuffer = glReadBuffer@4
+ glReadPixels = glReadPixels@28
+ glRectd = glRectd@32
+ glRectdv = glRectdv@8
+ glRectf = glRectf@16
+ glRectfv = glRectfv@8
+ glRecti = glRecti@16
+ glRectiv = glRectiv@8
+ glRects = glRects@16
+ glRectsv = glRectsv@8
+ glRenderMode = glRenderMode@4
+ glRotated = glRotated@32
+ glRotatef = glRotatef@16
+ glScaled = glScaled@24
+ glScalef = glScalef@12
+ glScissor = glScissor@16
+ glSelectBuffer = glSelectBuffer@8
+ glShadeModel = glShadeModel@4
+ glStencilFunc = glStencilFunc@12
+ glStencilMask = glStencilMask@4
+ glStencilOp = glStencilOp@12
+ glTexCoord1d = glTexCoord1d@8
+ glTexCoord1dv = glTexCoord1dv@4
+ glTexCoord1f = glTexCoord1f@4
+ glTexCoord1fv = glTexCoord1fv@4
+ glTexCoord1i = glTexCoord1i@4
+ glTexCoord1iv = glTexCoord1iv@4
+ glTexCoord1s = glTexCoord1s@4
+ glTexCoord1sv = glTexCoord1sv@4
+ glTexCoord2d = glTexCoord2d@16
+ glTexCoord2dv = glTexCoord2dv@4
+ glTexCoord2f = glTexCoord2f@8
+ glTexCoord2fv = glTexCoord2fv@4
+ glTexCoord2i = glTexCoord2i@8
+ glTexCoord2iv = glTexCoord2iv@4
+ glTexCoord2s = glTexCoord2s@8
+ glTexCoord2sv = glTexCoord2sv@4
+ glTexCoord3d = glTexCoord3d@24
+ glTexCoord3dv = glTexCoord3dv@4
+ glTexCoord3f = glTexCoord3f@12
+ glTexCoord3fv = glTexCoord3fv@4
+ glTexCoord3i = glTexCoord3i@12
+ glTexCoord3iv = glTexCoord3iv@4
+ glTexCoord3s = glTexCoord3s@12
+ glTexCoord3sv = glTexCoord3sv@4
+ glTexCoord4d = glTexCoord4d@32
+ glTexCoord4dv = glTexCoord4dv@4
+ glTexCoord4f = glTexCoord4f@16
+ glTexCoord4fv = glTexCoord4fv@4
+ glTexCoord4i = glTexCoord4i@16
+ glTexCoord4iv = glTexCoord4iv@4
+ glTexCoord4s = glTexCoord4s@16
+ glTexCoord4sv = glTexCoord4sv@4
+ glTexCoordPointer = glTexCoordPointer@16
+ glTexEnvf = glTexEnvf@12
+ glTexEnvfv = glTexEnvfv@12
+ glTexEnvi = glTexEnvi@12
+ glTexEnviv = glTexEnviv@12
+ glTexGend = glTexGend@16
+ glTexGendv = glTexGendv@12
+ glTexGenf = glTexGenf@12
+ glTexGenfv = glTexGenfv@12
+ glTexGeni = glTexGeni@12
+ glTexGeniv = glTexGeniv@12
+ glTexImage1D = glTexImage1D@32
+ glTexImage2D = glTexImage2D@36
+ glTexParameterf = glTexParameterf@12
+ glTexParameterfv = glTexParameterfv@12
+ glTexParameteri = glTexParameteri@12
+ glTexParameteriv = glTexParameteriv@12
+ glTexSubImage1D = glTexSubImage1D@28
+ glTexSubImage2D = glTexSubImage2D@36
+ glTranslated = glTranslated@24
+ glTranslatef = glTranslatef@12
+ glVertex2d = glVertex2d@16
+ glVertex2dv = glVertex2dv@4
+ glVertex2f = glVertex2f@8
+ glVertex2fv = glVertex2fv@4
+ glVertex2i = glVertex2i@8
+ glVertex2iv = glVertex2iv@4
+ glVertex2s = glVertex2s@8
+ glVertex2sv = glVertex2sv@4
+ glVertex3d = glVertex3d@24
+ glVertex3dv = glVertex3dv@4
+ glVertex3f = glVertex3f@12
+ glVertex3fv = glVertex3fv@4
+ glVertex3i = glVertex3i@12
+ glVertex3iv = glVertex3iv@4
+ glVertex3s = glVertex3s@12
+ glVertex3sv = glVertex3sv@4
+ glVertex4d = glVertex4d@32
+ glVertex4dv = glVertex4dv@4
+ glVertex4f = glVertex4f@16
+ glVertex4fv = glVertex4fv@4
+ glVertex4i = glVertex4i@16
+ glVertex4iv = glVertex4iv@4
+ glVertex4s = glVertex4s@16
+ glVertex4sv = glVertex4sv@4
+ glVertexPointer = glVertexPointer@16
+ glViewport = glViewport@16
+ wglChoosePixelFormat = wglChoosePixelFormat@8
+ wglCopyContext = wglCopyContext@12
+ wglCreateContext = wglCreateContext@4
+ wglCreateLayerContext = wglCreateLayerContext@8
+ wglDeleteContext = wglDeleteContext@4
+ wglDescribeLayerPlane = wglDescribeLayerPlane@20
+ wglDescribePixelFormat = wglDescribePixelFormat@16
+ wglGetCurrentContext = wglGetCurrentContext@0
+ wglGetCurrentDC = wglGetCurrentDC@0
+; wglGetDefaultProcAddress = wglGetDefaultProcAddress@4
+ wglGetLayerPaletteEntries = wglGetLayerPaletteEntries@20
+ wglGetPixelFormat = wglGetPixelFormat@4
+ wglGetProcAddress = wglGetProcAddress@4
+ wglMakeCurrent = wglMakeCurrent@8
+ wglRealizeLayerPalette = wglRealizeLayerPalette@12
+ wglSetLayerPaletteEntries = wglSetLayerPaletteEntries@20
+ wglSetPixelFormat = wglSetPixelFormat@12
+ wglShareLists = wglShareLists@8
+ wglSwapBuffers = wglSwapBuffers@4
+ wglSwapLayerBuffers = wglSwapLayerBuffers@8
+ wglSwapMultipleBuffers = wglSwapMultipleBuffers@8
+ wglUseFontBitmapsA = wglUseFontBitmapsA@16
+ wglUseFontBitmapsW = wglUseFontBitmapsW@16
+ wglUseFontOutlinesA = wglUseFontOutlinesA@32
+ wglUseFontOutlinesW = wglUseFontOutlinesW@32
+ DrvCopyContext = DrvCopyContext@12
+ DrvCreateContext = DrvCreateContext@4
+ DrvCreateLayerContext = DrvCreateLayerContext@8
+ DrvDeleteContext = DrvDeleteContext@4
+ DrvDescribeLayerPlane = DrvDescribeLayerPlane@20
+ DrvDescribePixelFormat = DrvDescribePixelFormat@16
+ DrvGetLayerPaletteEntries = DrvGetLayerPaletteEntries@20
+ DrvGetProcAddress = DrvGetProcAddress@4
+ DrvPresentBuffers = DrvPresentBuffers@8
+ DrvRealizeLayerPalette = DrvRealizeLayerPalette@12
+ DrvReleaseContext = DrvReleaseContext@4
+ DrvSetCallbackProcs = DrvSetCallbackProcs@8
+ DrvSetContext = DrvSetContext@12
+ DrvSetLayerPaletteEntries = DrvSetLayerPaletteEntries@20
+ DrvSetPixelFormat = DrvSetPixelFormat@8
+ DrvShareLists = DrvShareLists@8
+ DrvSwapBuffers = DrvSwapBuffers@4
+ DrvSwapLayerBuffers = DrvSwapLayerBuffers@8
+ DrvValidateVersion = DrvValidateVersion@4
diff --git a/src/VBox/Additions/3D/win/VBoxNine/Makefile.kmk b/src/VBox/Additions/3D/win/VBoxNine/Makefile.kmk
new file mode 100644
index 00000000..51ddf06f
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxNine/Makefile.kmk
@@ -0,0 +1,74 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for VBoxNine D3D9 state tracker.
+#
+
+#
+# Copyright (C) 2016-2022 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+DLLS += VBoxNine
+DLLS.amd64 += VBoxNine-x86
+
+VBoxNine_TEMPLATE = VBoxMesa3DGuestR3DllMinVista
+# -wd4100: unreferenced formal parameter
+# -wd4200: nonstandard extension used : zero-sized array in struct/union
+# -wd4245: 'return' : conversion from 'int' to 'unsigned int', signed/unsigned mismatch
+# -wd4255: no function prototype given
+# -wd4668: 'something' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
+VBoxNine_CFLAGS = -wd4100 -wd4200 -wd4245 -wd4255 -wd4668
+VBoxNine_INCS = \
+ $(VBOX_PATH_MESA)/src/gallium/frontends/nine
+VBoxNine_SOURCES = \
+ nine/nine_memory_helper.c \
+ VBoxNine.c \
+ VBoxNine.rc \
+ VBoxNine.def
+VBoxNine_LIBS = \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxWddmUmHlp$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaGalliumAuxLib$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaLib$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaUtilLib$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaNineLib$(VBOX_SUFF_LIB)
+
+if defined(VBOX_SIGNING_MODE) && defined(VBOX_SIGN_ADDITIONS)
+ VBoxNine_INSTTYPE = none
+ VBoxNine_DEBUG_INSTTYPE = both
+endif
+
+#
+# VBoxNine-x86 - x86 version of VBoxNine built for amd64 build
+#
+VBoxNine-x86_EXTENDS = VBoxNine
+VBoxNine-x86_BLD_TRG_ARCH = x86
+VBoxNine-x86_LIBS = \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxWddmUmHlp-x86$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaGalliumAuxLib-x86$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaLib-x86$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaUtilLib-x86$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaNineLib-x86$(VBOX_SUFF_LIB)
+VBoxNine-x86_DEFS = $(VBoxNine_DEFS) VBOX_WOW64
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Additions/3D/win/VBoxNine/VBoxNine.c b/src/VBox/Additions/3D/win/VBoxNine/VBoxNine.c
new file mode 100644
index 00000000..5dda66b2
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxNine/VBoxNine.c
@@ -0,0 +1,181 @@
+/* $Id: VBoxNine.c $ */
+/** @file
+ * VirtualBox Windows Guest Mesa3D - Direct3D9 state tracker.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include <iprt/win/windows.h>
+#include <iprt/win/d3d9.h>
+//#include <d3dumddi.h>
+
+#include <VBoxWddmUmHlp.h>
+
+//#include <windef.h>
+//#include <winbase.h>
+//#include <winsvc.h>
+//#include <winnetwk.h>
+//#include <npapi.h>
+//#include <devioctl.h>
+//#include <stdio.h>
+
+//#include <iprt/alloc.h>
+//#include <iprt/initterm.h>
+//#include <iprt/string.h>
+//#include <iprt/log.h>
+//#include <VBox/version.h>
+//#include <VBox/VMMDev.h>
+//#include <VBox/Log.h>
+
+#include "adapter9.h"
+#include "surface9.h"
+#include "pipe/p_screen.h"
+
+#include <iprt/types.h>
+// #include <iprt/asm.h>
+
+// #include "VBoxNine.h"
+
+struct d3dadapter9_context_wddm
+{
+ struct d3dadapter9_context base;
+ void *reserved;
+};
+
+static void
+wddm_destroy(struct d3dadapter9_context *ctx)
+{
+ /* struct d3dadapter9_context_wddm *ctx_wddm = (struct d3dadapter9_context_wddm *)ctx; */
+
+/// @todo screen (hal) is deleted by the upper level. Do not delete here.
+// if (ctx->ref)
+// ctx->ref->destroy(ctx->ref);
+// /* because ref is a wrapper around hal, freeing ref frees hal too. */
+// else if (ctx->hal)
+// ctx->hal->destroy(ctx->hal);
+
+ FREE(ctx);
+}
+
+static HRESULT
+d3dadapter9_context_wddm_create(struct d3dadapter9_context_wddm **ppCtx, struct pipe_screen *s)
+{
+ struct d3dadapter9_context_wddm *ctx = CALLOC_STRUCT(d3dadapter9_context_wddm);
+
+ if (!ctx) { return E_OUTOFMEMORY; }
+
+ ctx->base.hal = s;
+ /** @todo Need software device here. Currently assigned to hw device to prevent NineDevice9_ctor crash. */
+ ctx->base.ref = ctx->base.hal;
+ // D3DADAPTER_IDENTIFIER9 identifier;
+ ctx->base.linear_framebuffer = TRUE;
+ ctx->base.throttling = FALSE;
+ ctx->base.throttling_value = 0;
+ ctx->base.vblank_mode = 1;
+ ctx->base.thread_submit = FALSE;
+ ctx->base.discard_delayed_release = FALSE;
+ ctx->base.tearfree_discard = FALSE;
+ ctx->base.csmt_force = FALSE;
+ ctx->base.dynamic_texture_workaround = FALSE;
+ ctx->base.shader_inline_constants = FALSE;
+ ctx->base.memfd_virtualsizelimit = -1;
+ ctx->base.override_vram_size = -1;
+ ctx->base.destroy = wddm_destroy;
+
+
+ /* read out PCI info */
+ /// @todo read_descriptor(&ctx->base, fd);
+
+ *ppCtx = ctx;
+ return D3D_OK;
+}
+
+HRESULT WINAPI
+GaNineD3DAdapter9Create(struct pipe_screen *s, ID3DAdapter9 **ppOut)
+{
+ HRESULT hr;
+ struct d3dadapter9_context_wddm *pCtx = NULL;
+ hr = d3dadapter9_context_wddm_create(&pCtx, s);
+ if (SUCCEEDED(hr))
+ {
+ hr = NineAdapter9_new(&pCtx->base, (struct NineAdapter9 **)ppOut);
+ if (FAILED(hr))
+ {
+ /// @todo NineAdapter9_new calls this as ctx->base.destroy,
+ // and will not call if memory allocation fails.
+ // wddm_destroy(&pCtx->base);
+ }
+ }
+ return hr;
+}
+
+struct pipe_resource * WINAPI
+GaNinePipeResourceFromSurface(IUnknown *pSurface)
+{
+ /// @todo QueryInterface?
+ struct NineResource9 *pResource = (struct NineResource9 *)pSurface;
+ return pResource->resource;
+}
+
+extern struct pipe_context *
+NineDevice9_GetPipe( struct NineDevice9 *This );
+
+struct pipe_context * WINAPI
+GaNinePipeContextFromDevice(IDirect3DDevice9 *pDevice)
+{
+ /// @todo Verify that this is a NineDevice?
+ struct pipe_context *pPipeContext = NineDevice9_GetPipe((struct NineDevice9 *)pDevice);
+ return pPipeContext;
+}
+
+BOOL WINAPI DllMain(HINSTANCE hDLLInst,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+ BOOL fReturn = TRUE;
+
+ RT_NOREF2(hDLLInst, lpvReserved);
+
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ //RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
+ D3DKMTLoad();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ /// @todo RTR3Term();
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+
+ default:
+ break;
+ }
+
+ return fReturn;
+}
diff --git a/src/VBox/Additions/3D/win/VBoxNine/VBoxNine.def b/src/VBox/Additions/3D/win/VBoxNine/VBoxNine.def
new file mode 100644
index 00000000..b300b3a6
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxNine/VBoxNine.def
@@ -0,0 +1,34 @@
+; $Id: VBoxNine.def $;
+;; @file
+; Export definition file for the VBoxNine D3D9 state tracker.
+;
+
+;
+; Copyright (C) 2016-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+LIBRARY VBOXNINE
+
+EXPORTS
+ GaNineD3DAdapter9Create @1
+ GaNinePipeResourceFromSurface @2
+ GaNinePipeContextFromDevice @3
+
diff --git a/src/VBox/Additions/3D/win/VBoxNine/VBoxNine.rc b/src/VBox/Additions/3D/win/VBoxNine/VBoxNine.rc
new file mode 100644
index 00000000..10493118
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxNine/VBoxNine.rc
@@ -0,0 +1,66 @@
+/* $Id: VBoxNine.rc $ */
+/** @file
+ * VBoxNine - Resource file containing version info and icon.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include <windows.h>
+#include <VBox/version.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VBOX_RC_FILE_VERSION
+ PRODUCTVERSION VBOX_RC_FILE_VERSION
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS VBOX_RC_FILE_FLAGS
+ FILEOS VBOX_RC_FILE_OS
+ FILETYPE VBOX_RC_TYPE_DLL
+ FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "VirtualBox D3D9 Mesa State Tracker\0"
+ VALUE "InternalName", "VBoxNine\0"
+#ifdef VBOX_WOW64
+ VALUE "OriginalFilename", "VBoxNine-x86.DLL\0"
+#else
+ VALUE "OriginalFilename", "VBoxNine.DLL\0"
+#endif
+ VALUE "CompanyName", VBOX_RC_COMPANY_NAME
+ VALUE "FileVersion", VBOX_RC_FILE_VERSION_STR
+ VALUE "LegalCopyright", VBOX_RC_LEGAL_COPYRIGHT
+ VALUE "ProductName", VBOX_RC_PRODUCT_NAME_GA_STR
+ VALUE "ProductVersion", VBOX_RC_PRODUCT_VERSION_STR
+ VBOX_RC_MORE_STRINGS
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/src/VBox/Additions/3D/win/VBoxNine/nine/nine_memory_helper.c b/src/VBox/Additions/3D/win/VBoxNine/nine/nine_memory_helper.c
new file mode 100644
index 00000000..532a8b92
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxNine/nine/nine_memory_helper.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+/*
+ * Copyright 2020 Axel Davy <davyaxel0@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "util/list.h"
+#include "util/u_memory.h"
+#include "util/slab.h"
+
+#include "nine_debug.h"
+#include "nine_memory_helper.h"
+#include "nine_state.h"
+
+#include <iprt/win/windows.h>
+
+#define DIVUP(a,b) (((a)+(b)-1)/(b))
+
+/* Required alignment for allocations */
+#define NINE_ALLOCATION_ALIGNMENT 32
+
+#define DBG_CHANNEL (DBG_BASETEXTURE|DBG_SURFACE|DBG_VOLUME|DBG_TEXTURE|DBG_CUBETEXTURE)
+
+struct nine_allocation {
+ unsigned is_external;
+ void *external;
+};
+
+struct nine_allocator {
+ struct slab_mempool external_allocation_pool;
+ CRITICAL_SECTION mutex_slab;
+};
+
+struct nine_allocation *
+nine_allocate(struct nine_allocator *allocator, unsigned size)
+{
+ struct nine_allocation *allocation;
+ (void)allocator;
+ assert(sizeof(struct nine_allocation) <= NINE_ALLOCATION_ALIGNMENT);
+ allocation = align_calloc(size + NINE_ALLOCATION_ALIGNMENT, NINE_ALLOCATION_ALIGNMENT);
+ allocation->is_external = false;
+ return allocation;
+}
+
+
+void nine_free(struct nine_allocator *allocator, struct nine_allocation *allocation)
+{
+ if (allocation->is_external) {
+ EnterCriticalSection(&allocator->mutex_slab);
+ slab_free_st(&allocator->external_allocation_pool, allocation);
+ LeaveCriticalSection(&allocator->mutex_slab);
+ } else
+ align_free(allocation);
+}
+
+void nine_free_worker(struct nine_allocator *allocator, struct nine_allocation *allocation)
+{
+ nine_free(allocator, allocation);
+}
+
+void *nine_get_pointer(struct nine_allocator *allocator, struct nine_allocation *allocation)
+{
+ (void)allocator;
+ if (allocation->is_external)
+ return allocation->external;
+ return (uint8_t *)allocation + NINE_ALLOCATION_ALIGNMENT;
+}
+
+void nine_pointer_weakrelease(struct nine_allocator *allocator, struct nine_allocation *allocation)
+{
+ (void)allocator;
+ (void)allocation;
+}
+
+void nine_pointer_strongrelease(struct nine_allocator *allocator, struct nine_allocation *allocation)
+{
+ (void)allocator;
+ (void)allocation;
+}
+
+void nine_pointer_delayedstrongrelease(struct nine_allocator *allocator,
+ struct nine_allocation *allocation,
+ unsigned *counter)
+{
+ (void)allocator;
+ (void)allocation;
+ (void)counter;
+}
+
+struct nine_allocation *
+nine_suballocate(struct nine_allocator* allocator, struct nine_allocation *allocation, int offset)
+{
+ struct nine_allocation *new_allocation;
+ EnterCriticalSection(&allocator->mutex_slab);
+ new_allocation = slab_alloc_st(&allocator->external_allocation_pool);
+ LeaveCriticalSection(&allocator->mutex_slab);
+ new_allocation->is_external = true;
+ if (allocation->is_external)
+ new_allocation->external = (uint8_t *)allocation->external + offset;
+ else
+ new_allocation->external = (uint8_t *)allocation + NINE_ALLOCATION_ALIGNMENT + offset;
+ return new_allocation;
+}
+
+struct nine_allocation *
+nine_wrap_external_pointer(struct nine_allocator* allocator, void* data)
+{
+ struct nine_allocation *new_allocation;
+ EnterCriticalSection(&allocator->mutex_slab);
+ new_allocation = slab_alloc_st(&allocator->external_allocation_pool);
+ LeaveCriticalSection(&allocator->mutex_slab);
+ new_allocation->is_external = true;
+ new_allocation->external = data;
+ return new_allocation;
+}
+
+struct nine_allocator *
+nine_allocator_create(struct NineDevice9 *device, int memfd_virtualsizelimit)
+{
+ struct nine_allocator* allocator = MALLOC(sizeof(struct nine_allocator));
+ (void)device;
+ (void)memfd_virtualsizelimit;
+
+ if (!allocator)
+ return NULL;
+
+ slab_create(&allocator->external_allocation_pool, sizeof(struct nine_allocation), 4096);
+ InitializeCriticalSection(&allocator->mutex_slab);
+
+ return allocator;
+}
+
+void
+nine_allocator_destroy(struct nine_allocator *allocator)
+{
+ slab_destroy(&allocator->external_allocation_pool);
+ DeleteCriticalSection(&allocator->mutex_slab);
+}
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/.scm-settings b/src/VBox/Additions/3D/win/VBoxSVGA/.scm-settings
new file mode 100644
index 00000000..5716d6eb
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/.scm-settings
@@ -0,0 +1,28 @@
+# $Id: .scm-settings $
+## @file
+# Source code massager settings for VBoxSVGA.
+#
+
+#
+# Copyright (C) 2010-2022 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+/winsys/*.c: --no-convert-tabs --no-strip-trailing-blanks
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/Makefile.kmk b/src/VBox/Additions/3D/win/VBoxSVGA/Makefile.kmk
new file mode 100644
index 00000000..17d2723f
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/Makefile.kmk
@@ -0,0 +1,85 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for VBoxSVGA hardware driver.
+#
+
+#
+# Copyright (C) 2016-2022 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+DLLS += VBoxSVGA
+DLLS.amd64 += VBoxSVGA-x86
+
+VBoxSVGA_TEMPLATE = VBoxMesa3DGuestR3DllMinVista
+# -wd4005: vcc120: '__useHeader' : macro redefinition
+# -wd4100: unreferenced formal parameter
+# -wd4200: nonstandard extension used : zero-sized array in struct/union
+# -wd4204: vmw_screen_ioctl.c(392): warning C4204: nonstandard extension used: non-constant aggregate initializer
+# -wd4211: nonstandard extension used : redefined extern to static
+# -wd4245: 'return' : conversion from 'int' to 'unsigned int', signed/unsigned mismatch
+# -wd4255: no function prototype given
+# -wd4668: 'something' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
+VBoxSVGA_CFLAGS = -wd4005 -wd4100 -wd4200 -wd4204 -wd4211 -wd4245 -wd4255 -wd4668
+VBoxSVGA_INCS = \
+ $(VBoxSVGA_0_OUTDIR)/../VBoxMesaUtilLib/$(VBOX_MESA)/src \
+ $(VBOX_PATH_3D)/win/include \
+ $(VBOX_PATH_MESA)/src/gallium/drivers/svga \
+ $(VBOX_PATH_MESA)/src/gallium/drivers/svga/include \
+ $(VBOX_PATH_MESA)/src/gallium/winsys/svga/drm
+VBoxSVGA_SOURCES = \
+ winsys/vmw_screen.c \
+ winsys/vmw_screen_wddm.c \
+ winsys/vmw_screen_ioctl.c \
+ VBoxSVGA.c \
+ VBoxSVGA.rc \
+ VBoxSVGA.def
+VBoxSVGA_LIBS = \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxWddmUmHlp$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaGalliumAuxLib$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaUtilLib$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaLib$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaSVGAWinsysLib$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaSVGALib$(VBOX_SUFF_LIB)
+
+if defined(VBOX_SIGNING_MODE) && defined(VBOX_SIGN_ADDITIONS)
+ VBoxSVGA_INSTTYPE = none
+ VBoxSVGA_DEBUG_INSTTYPE = both
+endif
+
+#
+# VBoxSVGA-x86 - x86 version of VBoxSVGA built for amd64 build
+#
+VBoxSVGA-x86_EXTENDS = VBoxSVGA
+VBoxSVGA-x86_BLD_TRG_ARCH = x86
+VBoxSVGA-x86_LIBS = \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxWddmUmHlp-x86$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaGalliumAuxLib-x86$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaUtilLib-x86$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaLib-x86$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaSVGAWinsysLib-x86$(VBOX_SUFF_LIB) \
+ $(VBOX_PATH_ADDITIONS_LIB)/VBoxMesaSVGALib-x86$(VBOX_SUFF_LIB)
+VBoxSVGA-x86_DEFS = $(VBoxSVGA_DEFS) VBOX_WOW64
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/VBoxSVGA.c b/src/VBox/Additions/3D/win/VBoxSVGA/VBoxSVGA.c
new file mode 100644
index 00000000..81eefa11
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/VBoxSVGA.c
@@ -0,0 +1,146 @@
+/* $Id: VBoxSVGA.c $ */
+/** @file
+ * VirtualBox Windows Guest Mesa3D - VMSVGA hardware driver.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include <VBoxWddmUmHlp.h>
+
+#include "svga_public.h"
+#include "svga_screen.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "frontend/drm_driver.h"
+
+#include "wddm_screen.h"
+
+struct svga_winsys_screen *
+svga_wddm_winsys_screen_create(const WDDMGalliumDriverEnv *pEnv);
+
+struct pipe_screen * WINAPI
+GaDrvScreenCreate(const WDDMGalliumDriverEnv *pEnv)
+{
+ struct svga_winsys_screen *sws = svga_wddm_winsys_screen_create(pEnv);
+ if (sws)
+ return svga_screen_create(sws);
+ return NULL;
+}
+
+void WINAPI
+GaDrvScreenDestroy(struct pipe_screen *s)
+{
+ if (s)
+ s->destroy(s);
+}
+
+uint32_t WINAPI
+GaDrvGetSurfaceId(struct pipe_screen *pScreen, struct pipe_resource *pResource)
+{
+ uint32_t u32Sid = 0;
+
+ if ( pScreen
+ && pResource)
+ {
+ /* Get the sid (surface id). */
+ struct winsys_handle whandle;
+ memset(&whandle, 0, sizeof(whandle));
+ whandle.type = WINSYS_HANDLE_TYPE_SHARED;
+
+ if (pScreen->resource_get_handle(pScreen, NULL, pResource, &whandle, 0))
+ {
+ u32Sid = (uint32_t)whandle.handle;
+ }
+ }
+
+ return u32Sid;
+}
+
+const WDDMGalliumDriverEnv *WINAPI
+GaDrvGetWDDMEnv(struct pipe_screen *pScreen)
+{
+ HANDLE hAdapter = NULL;
+
+ if (pScreen)
+ {
+ struct svga_screen *pSvgaScreen = svga_screen(pScreen);
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)pSvgaScreen->sws;
+
+ return vws_wddm->pEnv;
+ }
+
+ return hAdapter;
+}
+
+uint32_t WINAPI
+GaDrvGetContextId(struct pipe_context *pPipeContext)
+{
+ uint32 u32Cid = ~0;
+
+ if (pPipeContext)
+ {
+ struct svga_winsys_context *pSWC = svga_winsys_context(pPipeContext);
+ u32Cid = pSWC->cid;
+ }
+
+ return u32Cid;
+}
+
+void WINAPI
+GaDrvContextFlush(struct pipe_context *pPipeContext)
+{
+ if (pPipeContext)
+ pPipeContext->flush(pPipeContext, NULL, PIPE_FLUSH_END_OF_FRAME);
+}
+
+BOOL WINAPI DllMain(HINSTANCE hDLLInst,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+ BOOL fReturn = TRUE;
+
+ RT_NOREF2(hDLLInst, lpvReserved);
+
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ //RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
+ D3DKMTLoad();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ /// @todo RTR3Term();
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+
+ default:
+ break;
+ }
+
+ return fReturn;
+}
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/VBoxSVGA.def b/src/VBox/Additions/3D/win/VBoxSVGA/VBoxSVGA.def
new file mode 100644
index 00000000..5a95d608
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/VBoxSVGA.def
@@ -0,0 +1,36 @@
+; $Id: VBoxSVGA.def $
+;; @file
+; Linker defintion file for the VBoxSVGA hardware driver.
+;
+
+;
+; Copyright (C) 2016-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+LIBRARY VBOXSVGA
+
+EXPORTS
+ GaDrvScreenCreate @1
+ GaDrvScreenDestroy @2
+ GaDrvGetWDDMEnv @3
+ GaDrvGetContextId @4
+ GaDrvGetSurfaceId @5
+ GaDrvContextFlush @6
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/VBoxSVGA.rc b/src/VBox/Additions/3D/win/VBoxSVGA/VBoxSVGA.rc
new file mode 100644
index 00000000..2349cbd9
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/VBoxSVGA.rc
@@ -0,0 +1,66 @@
+/* $Id: VBoxSVGA.rc $ */
+/** @file
+ * VBoxSVGA - Resource file containing version info and icon.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include <windows.h>
+#include <VBox/version.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VBOX_RC_FILE_VERSION
+ PRODUCTVERSION VBOX_RC_FILE_VERSION
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS VBOX_RC_FILE_FLAGS
+ FILEOS VBOX_RC_FILE_OS
+ FILETYPE VBOX_RC_TYPE_DLL
+ FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "VirtualBox D3D9 Mesa VMSVGA Hardware Driver\0"
+ VALUE "InternalName", "VBoxSVGA\0"
+#ifdef VBOX_WOW64
+ VALUE "OriginalFilename", "VBoxSVGA-x86.DLL\0"
+#else
+ VALUE "OriginalFilename", "VBoxSVGA.DLL\0"
+#endif
+ VALUE "CompanyName", VBOX_RC_COMPANY_NAME
+ VALUE "FileVersion", VBOX_RC_FILE_VERSION_STR
+ VALUE "LegalCopyright", VBOX_RC_LEGAL_COPYRIGHT
+ VALUE "ProductName", VBOX_RC_PRODUCT_NAME_GA_STR
+ VALUE "ProductVersion", VBOX_RC_PRODUCT_VERSION_STR
+ VBOX_RC_MORE_STRINGS
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/wddm_screen.h b/src/VBox/Additions/3D/win/VBoxSVGA/wddm_screen.h
new file mode 100644
index 00000000..d06c4b88
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/wddm_screen.h
@@ -0,0 +1,47 @@
+/* $Id: wddm_screen.h $ */
+/** @file
+ * VirtualBox Windows Guest Mesa3D - VMSVGA hardware driver.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef GA_INCLUDED_SRC_3D_win_VBoxSVGA_wddm_screen_h
+#define GA_INCLUDED_SRC_3D_win_VBoxSVGA_wddm_screen_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBoxGaDriver.h>
+
+#include "vmw_screen.h"
+
+struct vmw_winsys_screen_wddm
+{
+ struct vmw_winsys_screen base;
+
+ const WDDMGalliumDriverEnv *pEnv;
+ VBOXGAHWINFOSVGA HwInfo;
+};
+
+#endif /* !GA_INCLUDED_SRC_3D_win_VBoxSVGA_wddm_screen_h */
+
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/winsys/Makefile.kup b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/Makefile.kup
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen.c b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen.c
new file mode 100644
index 00000000..a86e7375
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+/**********************************************************
+ * Copyright 2009-2015 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **********************************************************/
+
+
+#include "../wddm_screen.h"
+#include "vmw_fence.h"
+#include "vmw_context.h"
+#include "vmwgfx_drm.h"
+
+#include "util/os_file.h"
+#include "util/u_memory.h"
+#include "pipe/p_compiler.h"
+#include "util/u_hash_table.h"
+
+/* Called from vmw_drm_create_screen(), creates and initializes the
+ * vmw_winsys_screen structure, which is the main entity in this
+ * module.
+ * First, check whether a vmw_winsys_screen object already exists for
+ * this device, and in that case return that one, making sure that we
+ * have our own file descriptor open to DRM.
+ */
+
+struct vmw_winsys_screen_wddm *
+vmw_winsys_create_wddm(const WDDMGalliumDriverEnv *pEnv)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm;
+ struct vmw_winsys_screen *vws;
+
+ if ( pEnv->pHWInfo == NULL
+ || pEnv->pHWInfo->u32HwType != VBOX_GA_HW_TYPE_VMSVGA)
+ return NULL;
+
+ vws_wddm = CALLOC_STRUCT(vmw_winsys_screen_wddm);
+ vws = &vws_wddm->base;
+ if (!vws)
+ goto out_no_vws;
+
+ vws_wddm->pEnv = pEnv;
+ vws_wddm->HwInfo = pEnv->pHWInfo->u.svga;
+
+ vws->device = 0; /* not used */
+ vws->open_count = 1;
+ vws->ioctl.drm_fd = -1; /* not used */
+ vws->force_coherent = FALSE;
+ if (!vmw_ioctl_init(vws))
+ goto out_no_ioctl;
+
+ vws->base.have_gb_dma = !vws->force_coherent;
+ vws->base.need_to_rebind_resources = FALSE;
+ vws->base.have_transfer_from_buffer_cmd = vws->base.have_vgpu10;
+ vws->base.have_constant_buffer_offset_cmd = FALSE;
+ vws->cache_maps = FALSE;
+ vws->fence_ops = vmw_fence_ops_create(vws);
+ if (!vws->fence_ops)
+ goto out_no_fence_ops;
+
+ if(!vmw_pools_init(vws))
+ goto out_no_pools;
+
+ if (!vmw_winsys_screen_init_svga(vws))
+ goto out_no_svga;
+
+ cnd_init(&vws->cs_cond);
+ mtx_init(&vws->cs_mutex, mtx_plain);
+
+ return vws_wddm;
+out_no_svga:
+ vmw_pools_cleanup(vws);
+out_no_pools:
+ vws->fence_ops->destroy(vws->fence_ops);
+out_no_fence_ops:
+ vmw_ioctl_cleanup(vws);
+out_no_ioctl:
+ FREE(vws);
+out_no_vws:
+ return NULL;
+}
+
+void
+vmw_winsys_destroy(struct vmw_winsys_screen *vws)
+{
+ if (--vws->open_count == 0) {
+ vmw_pools_cleanup(vws);
+ vws->fence_ops->destroy(vws->fence_ops);
+ vmw_ioctl_cleanup(vws);
+ mtx_destroy(&vws->cs_mutex);
+ cnd_destroy(&vws->cs_cond);
+ FREE(vws);
+ }
+}
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_ioctl.c b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_ioctl.c
new file mode 100644
index 00000000..4dccc92d
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_ioctl.c
@@ -0,0 +1,979 @@
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+/**********************************************************
+ * Copyright 2009-2015 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **********************************************************/
+
+/**
+ * @file
+ *
+ * Wrappers for DRM ioctl functionlaity used by the rest of the vmw
+ * drm winsys.
+ *
+ * Based on svgaicd_escape.c
+ */
+
+
+#include "svga_cmd.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "svgadump/svga_dump.h"
+#include "frontend/drm_driver.h"
+#include "vmw_screen.h"
+#include "vmw_context.h"
+#include "vmw_fence.h"
+#include "vmwgfx_drm.h"
+#include "svga3d_caps.h"
+#include "svga3d_reg.h"
+#include "svga3d_surfacedefs.h"
+
+#include "../wddm_screen.h"
+#include <iprt/asm.h>
+
+#define VMW_MAX_DEFAULT_TEXTURE_SIZE (128 * 1024 * 1024)
+#define VMW_FENCE_TIMEOUT_SECONDS 3600UL
+
+#define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32)
+#define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32)
+#define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \
+ (svga3d_flags & ((uint64_t)UINT32_MAX))
+
+struct vmw_region
+{
+ uint32_t handle;
+ uint64_t map_handle;
+ void *data;
+ uint32_t map_count;
+ struct vmw_winsys_screen_wddm *vws_wddm;
+ uint32_t size;
+};
+
+uint32_t
+vmw_region_size(struct vmw_region *region)
+{
+ return region->size;
+}
+
+#if defined(__DragonFly__) || defined(__FreeBSD__) || \
+ defined(__NetBSD__) || defined(__OpenBSD__)
+#define ERESTART EINTR
+#endif
+
+uint32
+vmw_ioctl_context_create(struct vmw_winsys_screen *vws)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ return vws_wddm->pEnv->pfnContextCreate(vws_wddm->pEnv->pvEnv, false, false);
+}
+
+uint32
+vmw_ioctl_extended_context_create(struct vmw_winsys_screen *vws,
+ boolean vgpu10)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ return vws_wddm->pEnv->pfnContextCreate(vws_wddm->pEnv->pvEnv, true, vgpu10);
+}
+
+void
+vmw_ioctl_context_destroy(struct vmw_winsys_screen *vws, uint32 cid)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ vws_wddm->pEnv->pfnContextDestroy(vws_wddm->pEnv->pvEnv, cid);
+}
+
+uint32
+vmw_ioctl_surface_create(struct vmw_winsys_screen *vws,
+ SVGA3dSurface1Flags flags,
+ SVGA3dSurfaceFormat format,
+ unsigned usage,
+ SVGA3dSize size,
+ uint32_t numFaces, uint32_t numMipLevels,
+ unsigned sampleCount)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+
+ GASURFCREATE createParms;
+ GASURFSIZE sizes[DRM_VMW_MAX_SURFACE_FACES*
+ DRM_VMW_MAX_MIP_LEVELS];
+ GASURFSIZE *cur_size;
+ uint32_t iFace;
+ uint32_t iMipLevel;
+ uint32_t u32Sid;
+ int ret;
+
+ RT_NOREF(sampleCount);
+
+ memset(&createParms, 0, sizeof(createParms));
+ createParms.flags = (uint32_t) flags;
+ createParms.format = (uint32_t) format;
+ createParms.usage = (uint32_t) usage;
+
+ if (numFaces * numMipLevels >= GA_MAX_SURFACE_FACES*GA_MAX_MIP_LEVELS) {
+ return (uint32_t)-1;
+ }
+ cur_size = sizes;
+ for (iFace = 0; iFace < numFaces; ++iFace) {
+ SVGA3dSize mipSize = size;
+
+ createParms.mip_levels[iFace] = numMipLevels;
+ for (iMipLevel = 0; iMipLevel < numMipLevels; ++iMipLevel) {
+ cur_size->cWidth = mipSize.width;
+ cur_size->cHeight = mipSize.height;
+ cur_size->cDepth = mipSize.depth;
+ cur_size->u32Reserved = 0;
+ mipSize.width = MAX2(mipSize.width >> 1, 1);
+ mipSize.height = MAX2(mipSize.height >> 1, 1);
+ mipSize.depth = MAX2(mipSize.depth >> 1, 1);
+ cur_size++;
+ }
+ }
+ for (iFace = numFaces; iFace < SVGA3D_MAX_SURFACE_FACES; ++iFace) {
+ createParms.mip_levels[iFace] = 0;
+ }
+
+ ret = vws_wddm->pEnv->pfnSurfaceDefine(vws_wddm->pEnv->pvEnv, &createParms, &sizes[0], numFaces * numMipLevels, &u32Sid);
+ if (ret) {
+ return (uint32_t)-1;
+ }
+
+ return u32Sid;
+}
+
+
+uint32
+vmw_ioctl_gb_surface_create(struct vmw_winsys_screen *vws,
+ SVGA3dSurfaceAllFlags flags,
+ SVGA3dSurfaceFormat format,
+ unsigned usage,
+ SVGA3dSize size,
+ uint32_t numFaces,
+ uint32_t numMipLevels,
+ unsigned sampleCount,
+ uint32_t buffer_handle,
+ SVGA3dMSPattern multisamplePattern,
+ SVGA3dMSQualityLevel qualityLevel,
+ struct vmw_region **p_region)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+
+ struct vmw_region *region = NULL;
+ if (p_region)
+ {
+ region = CALLOC_STRUCT(vmw_region);
+ if (!region)
+ return SVGA3D_INVALID_ID;
+ }
+
+ SVGAGBSURFCREATE createParms;
+ createParms.s.flags = flags;
+ createParms.s.format = format;
+ createParms.s.usage = usage;
+ createParms.s.size = size;
+ createParms.s.numFaces = numFaces;
+ createParms.s.numMipLevels = numMipLevels;
+ createParms.s.sampleCount = sampleCount;
+ createParms.s.multisamplePattern = multisamplePattern;
+ createParms.s.qualityLevel = qualityLevel;
+ if (buffer_handle)
+ createParms.gmrid = buffer_handle;
+ else
+ createParms.gmrid = SVGA3D_INVALID_ID;
+ createParms.u64UserAddress = 0; /* out */
+ createParms.u32Sid = 0; /* out */
+
+ createParms.cbGB = svga3dsurface_get_serialized_size(format,
+ size,
+ numMipLevels,
+ numFaces);
+
+ int ret = vws_wddm->pEnv->pfnGBSurfaceDefine(vws_wddm->pEnv->pvEnv, &createParms);
+ if (ret)
+ {
+ FREE(region);
+ return SVGA3D_INVALID_ID;
+ }
+
+ if (p_region)
+ {
+ region->handle = createParms.gmrid;
+ region->map_handle = 0;
+ region->data = (void *)(uintptr_t)createParms.u64UserAddress;
+ region->map_count = 0;
+ region->size = createParms.cbGB;
+ region->vws_wddm = vws_wddm;
+ *p_region = region;
+ }
+ return createParms.u32Sid;
+}
+
+/**
+ * vmw_ioctl_surface_req - Fill in a struct surface_req
+ *
+ * @vws: Winsys screen
+ * @whandle: Surface handle
+ * @req: The struct surface req to fill in
+ * @needs_unref: This call takes a kernel surface reference that needs to
+ * be unreferenced.
+ *
+ * Returns 0 on success, negative error type otherwise.
+ * Fills in the surface_req structure according to handle type and kernel
+ * capabilities.
+ */
+static int
+vmw_ioctl_surface_req(const struct vmw_winsys_screen *vws,
+ const struct winsys_handle *whandle,
+ struct drm_vmw_surface_arg *req,
+ boolean *needs_unref)
+{
+ ASMBreakpoint();
+ RT_NOREF4(vws, whandle, req, needs_unref);
+ return -1;
+}
+
+/**
+ * vmw_ioctl_gb_surface_ref - Put a reference on a guest-backed surface and
+ * get surface information
+ *
+ * @vws: Screen to register the reference on
+ * @handle: Kernel handle of the guest-backed surface
+ * @flags: flags used when the surface was created
+ * @format: Format used when the surface was created
+ * @numMipLevels: Number of mipmap levels of the surface
+ * @p_region: On successful return points to a newly allocated
+ * struct vmw_region holding a reference to the surface backup buffer.
+ *
+ * Returns 0 on success, a system error on failure.
+ */
+int
+vmw_ioctl_gb_surface_ref(struct vmw_winsys_screen *vws,
+ const struct winsys_handle *whandle,
+ SVGA3dSurfaceAllFlags *flags,
+ SVGA3dSurfaceFormat *format,
+ uint32_t *numMipLevels,
+ uint32_t *handle,
+ struct vmw_region **p_region)
+{
+ ASMBreakpoint();
+ RT_NOREF7(vws, whandle, flags, format, numMipLevels, handle, p_region);
+ return -1;
+}
+
+void
+vmw_ioctl_surface_destroy(struct vmw_winsys_screen *vws, uint32 sid)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ vws_wddm->pEnv->pfnSurfaceDestroy(vws_wddm->pEnv->pvEnv, sid);
+}
+
+void
+vmw_ioctl_command(struct vmw_winsys_screen *vws, int32_t cid,
+ uint32_t throttle_us, void *commands, uint32_t size,
+ struct pipe_fence_handle **pfence, int32_t imported_fence_fd,
+ uint32_t flags)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ GAFENCEQUERY FenceQuery;
+ RT_NOREF3(throttle_us, imported_fence_fd, flags);
+#ifdef DEBUG
+ // svga_dump_commands(commands, size);
+#endif
+ memset(&FenceQuery, 0, sizeof(FenceQuery));
+ FenceQuery.u32FenceStatus = GA_FENCE_STATUS_NULL;
+
+ vws_wddm->pEnv->pfnRender(vws_wddm->pEnv->pvEnv, cid, commands, size, pfence? &FenceQuery: NULL);
+ if (FenceQuery.u32FenceStatus == GA_FENCE_STATUS_NULL)
+ {
+ /*
+ * Kernel has already synced, or caller requested no fence.
+ */
+ if (pfence)
+ *pfence = NULL;
+ }
+ else
+ {
+ if (pfence)
+ {
+ vmw_fences_signal(vws->fence_ops, FenceQuery.u32ProcessedSeqNo, FenceQuery.u32SubmittedSeqNo, TRUE);
+
+ *pfence = vmw_fence_create(vws->fence_ops, FenceQuery.u32FenceHandle,
+ FenceQuery.u32SubmittedSeqNo, /* mask */ 0, -1);
+ if (*pfence == NULL)
+ {
+ /*
+ * Fence creation failed. Need to sync.
+ */
+ (void) vmw_ioctl_fence_finish(vws, FenceQuery.u32FenceHandle, /* mask */ 0);
+ vmw_ioctl_fence_unref(vws, FenceQuery.u32FenceHandle);
+ }
+ }
+ }
+}
+
+
+struct vmw_region *
+vmw_ioctl_region_create(struct vmw_winsys_screen *vws, uint32_t size)
+{
+ /* 'region' is a buffer visible both for host and guest */
+ struct vmw_region *region;
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ uint32_t u32GmrId = 0;
+ void *pvMap = NULL;
+ int ret;
+
+ region = CALLOC_STRUCT(vmw_region);
+ if (!region)
+ goto out_err1;
+
+ ret = vws_wddm->pEnv->pfnRegionCreate(vws_wddm->pEnv->pvEnv, size, &u32GmrId, &pvMap);
+
+ if (ret) {
+ vmw_error("IOCTL failed %d: %s\n", ret, strerror(-ret));
+ goto out_err1;
+ }
+
+ region->handle = u32GmrId;
+ region->map_handle = 0;
+ region->data = pvMap;
+ region->map_count = 0;
+ region->size = size;
+ region->vws_wddm = vws_wddm;
+
+ return region;
+
+out_err1:
+ FREE(region);
+ return NULL;
+}
+
+void
+vmw_ioctl_region_destroy(struct vmw_region *region)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = region->vws_wddm;
+
+ vws_wddm->pEnv->pfnRegionDestroy(vws_wddm->pEnv->pvEnv, region->handle, region->data);
+
+ FREE(region);
+}
+
+SVGAGuestPtr
+vmw_ioctl_region_ptr(struct vmw_region *region)
+{
+ SVGAGuestPtr ptr = {region->handle, 0};
+ return ptr;
+}
+
+void *
+vmw_ioctl_region_map(struct vmw_region *region)
+{
+ debug_printf("%s: gmrId = %u\n", __FUNCTION__,
+ region->handle);
+
+ if (region->data == NULL)
+ {
+ /* Should not get here. */
+ return NULL;
+ }
+
+ ++region->map_count;
+
+ return region->data;
+}
+
+void
+vmw_ioctl_region_unmap(struct vmw_region *region)
+{
+ --region->map_count;
+}
+
+/**
+ * vmw_ioctl_syncforcpu - Synchronize a buffer object for CPU usage
+ *
+ * @region: Pointer to a struct vmw_region representing the buffer object.
+ * @dont_block: Dont wait for GPU idle, but rather return -EBUSY if the
+ * GPU is busy with the buffer object.
+ * @readonly: Hint that the CPU access is read-only.
+ * @allow_cs: Allow concurrent command submission while the buffer is
+ * synchronized for CPU. If FALSE command submissions referencing the
+ * buffer will block until a corresponding call to vmw_ioctl_releasefromcpu.
+ *
+ * This function idles any GPU activities touching the buffer and blocks
+ * command submission of commands referencing the buffer, even from
+ * other processes.
+ */
+int
+vmw_ioctl_syncforcpu(struct vmw_region *region,
+ boolean dont_block,
+ boolean readonly,
+ boolean allow_cs)
+{
+ ASMBreakpoint();
+ RT_NOREF4(region, dont_block, readonly, allow_cs);
+ return -1;
+}
+
+/**
+ * vmw_ioctl_releasefromcpu - Undo a previous syncforcpu.
+ *
+ * @region: Pointer to a struct vmw_region representing the buffer object.
+ * @readonly: Should hold the same value as the matching syncforcpu call.
+ * @allow_cs: Should hold the same value as the matching syncforcpu call.
+ */
+void
+vmw_ioctl_releasefromcpu(struct vmw_region *region,
+ boolean readonly,
+ boolean allow_cs)
+{
+ ASMBreakpoint();
+ RT_NOREF3(region, readonly, allow_cs);
+ return;
+}
+
+void
+vmw_ioctl_fence_unref(struct vmw_winsys_screen *vws,
+ uint32_t handle)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ vws_wddm->pEnv->pfnFenceUnref(vws_wddm->pEnv->pvEnv, handle);
+}
+
+static inline uint32_t
+vmw_drm_fence_flags(uint32_t flags)
+{
+ uint32_t dflags = 0;
+
+ if (flags & SVGA_FENCE_FLAG_EXEC)
+ dflags |= DRM_VMW_FENCE_FLAG_EXEC;
+ if (flags & SVGA_FENCE_FLAG_QUERY)
+ dflags |= DRM_VMW_FENCE_FLAG_QUERY;
+
+ return dflags;
+}
+
+
+int
+vmw_ioctl_fence_signalled(struct vmw_winsys_screen *vws,
+ uint32_t handle,
+ uint32_t flags)
+{
+ RT_NOREF(flags);
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ GAFENCEQUERY FenceQuery;
+ int ret;
+
+ memset(&FenceQuery, 0, sizeof(FenceQuery));
+ FenceQuery.u32FenceStatus = GA_FENCE_STATUS_NULL;
+
+ ret = vws_wddm->pEnv->pfnFenceQuery(vws_wddm->pEnv->pvEnv, handle, &FenceQuery);
+
+ if (ret != 0)
+ return ret;
+
+ if (FenceQuery.u32FenceStatus == GA_FENCE_STATUS_NULL)
+ return 0; /* Treat as signalled. */
+
+ vmw_fences_signal(vws->fence_ops, FenceQuery.u32ProcessedSeqNo, FenceQuery.u32SubmittedSeqNo, TRUE);
+
+ return FenceQuery.u32FenceStatus == GA_FENCE_STATUS_SIGNALED ? 0 : -1;
+}
+
+
+
+int
+vmw_ioctl_fence_finish(struct vmw_winsys_screen *vws,
+ uint32_t handle,
+ uint32_t flags)
+{
+ RT_NOREF(flags);
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+
+ vws_wddm->pEnv->pfnFenceWait(vws_wddm->pEnv->pvEnv, handle, VMW_FENCE_TIMEOUT_SECONDS*1000000);
+
+ return 0; /* Regardless. */
+}
+
+uint32
+vmw_ioctl_shader_create(struct vmw_winsys_screen *vws,
+ SVGA3dShaderType type,
+ uint32 code_len)
+{
+ ASMBreakpoint();
+ RT_NOREF3(vws, type, code_len);
+ return 0;
+}
+
+void
+vmw_ioctl_shader_destroy(struct vmw_winsys_screen *vws, uint32 shid)
+{
+ ASMBreakpoint();
+ RT_NOREF2(vws, shid);
+ return;
+}
+
+static int
+vmw_ioctl_parse_caps(struct vmw_winsys_screen *vws,
+ const uint32_t *cap_buffer)
+{
+ unsigned i;
+
+ if (vws->base.have_gb_objects) {
+ for (i = 0; i < vws->ioctl.num_cap_3d; ++i) {
+ vws->ioctl.cap_3d[i].has_cap = TRUE;
+ vws->ioctl.cap_3d[i].result.u = cap_buffer[i];
+ }
+ return 0;
+ } else {
+ const uint32 *capsBlock;
+ const SVGA3dCapsRecord *capsRecord = NULL;
+ uint32 offset;
+ const SVGA3dCapPair *capArray;
+ unsigned numCaps, index;
+
+ /*
+ * Search linearly through the caps block records for the specified type.
+ */
+ capsBlock = cap_buffer;
+ for (offset = 0; capsBlock[offset] != 0; offset += capsBlock[offset]) {
+ const SVGA3dCapsRecord *record;
+ if (offset >= SVGA_FIFO_3D_CAPS_SIZE)
+ break;
+ record = (const SVGA3dCapsRecord *) (capsBlock + offset);
+ if ((record->header.type >= SVGA3DCAPS_RECORD_DEVCAPS_MIN) &&
+ (record->header.type <= SVGA3DCAPS_RECORD_DEVCAPS_MAX) &&
+ (!capsRecord || (record->header.type > capsRecord->header.type))) {
+ capsRecord = record;
+ }
+ }
+
+ if(!capsRecord)
+ return -1;
+
+ /*
+ * Calculate the number of caps from the size of the record.
+ */
+ capArray = (const SVGA3dCapPair *) capsRecord->data;
+ numCaps = (int) ((capsRecord->header.length * sizeof(uint32) -
+ sizeof capsRecord->header) / (2 * sizeof(uint32)));
+
+ for (i = 0; i < numCaps; i++) {
+ index = capArray[i][0];
+ if (index < vws->ioctl.num_cap_3d) {
+ vws->ioctl.cap_3d[index].has_cap = TRUE;
+ vws->ioctl.cap_3d[index].result.u = capArray[i][1];
+ } else {
+ debug_printf("Unknown devcaps seen: %d\n", index);
+ }
+ }
+ }
+ return 0;
+}
+
+#define SVGA_CAP2_DX2 0x00000004
+#define SVGA_CAP2_DX3 0x00000400
+
+enum SVGASHADERMODEL
+{
+ SVGA_SM_LEGACY = 0,
+ SVGA_SM_4,
+ SVGA_SM_4_1,
+ SVGA_SM_5,
+ SVGA_SM_MAX
+};
+
+static enum SVGASHADERMODEL vboxGetShaderModel(struct vmw_winsys_screen_wddm *vws_wddm)
+{
+#if 0
+ (void)vws_wddm;
+ return SVGA_SM_5;
+#else
+ enum SVGASHADERMODEL enmResult = SVGA_SM_LEGACY;
+
+ if ( (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_GBOBJECTS)
+ && (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_CMD_BUFFERS_3 /*=SVGA_CAP_DX*/)
+ && vws_wddm->HwInfo.au32Caps[SVGA3D_DEVCAP_DXCONTEXT])
+ {
+ enmResult = SVGA_SM_4;
+
+ if (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_CAP2_REGISTER)
+ {
+ if ( (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAP2] & SVGA_CAP2_DX2)
+ && vws_wddm->HwInfo.au32Caps[SVGA3D_DEVCAP_SM41])
+ {
+ enmResult = SVGA_SM_4_1;
+
+ if ( (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAP2] & SVGA_CAP2_DX3)
+ && vws_wddm->HwInfo.au32Caps[SVGA3D_DEVCAP_SM5])
+ {
+ enmResult = SVGA_SM_5;
+ }
+ }
+ }
+ }
+
+ return enmResult;
+#endif
+}
+
+static int
+vboxGetParam(struct vmw_winsys_screen_wddm *vws_wddm, struct drm_vmw_getparam_arg *gp_arg)
+{
+ /* DRM_VMW_GET_PARAM */
+ switch (gp_arg->param)
+ {
+ case DRM_VMW_PARAM_NUM_STREAMS:
+ gp_arg->value = 1; /* not used */
+ break;
+ case DRM_VMW_PARAM_NUM_FREE_STREAMS:
+ gp_arg->value = 1; /* not used */
+ break;
+ case DRM_VMW_PARAM_3D:
+ gp_arg->value = (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_3D) != 0;
+ break;
+ case DRM_VMW_PARAM_HW_CAPS:
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES];
+ break;
+ case DRM_VMW_PARAM_FIFO_CAPS:
+ gp_arg->value = vws_wddm->HwInfo.au32Fifo[SVGA_FIFO_CAPABILITIES];
+ break;
+ case DRM_VMW_PARAM_MAX_FB_SIZE:
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM];
+ break;
+ case DRM_VMW_PARAM_FIFO_HW_VERSION:
+ if (vws_wddm->HwInfo.au32Fifo[SVGA_FIFO_CAPABILITIES] & SVGA_FIFO_CAP_3D_HWVERSION_REVISED)
+ {
+ gp_arg->value =
+ vws_wddm->HwInfo.au32Fifo[SVGA_FIFO_3D_HWVERSION_REVISED];
+ }
+ else
+ {
+ gp_arg->value =
+ vws_wddm->HwInfo.au32Fifo[SVGA_FIFO_3D_HWVERSION];
+ }
+ break;
+ case DRM_VMW_PARAM_MAX_SURF_MEMORY:
+ if (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_GBOBJECTS)
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB] * 1024 / 2;
+ else
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_MEMORY_SIZE];
+ break;
+ case DRM_VMW_PARAM_3D_CAPS_SIZE:
+ if (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_GBOBJECTS)
+ gp_arg->value = SVGA3D_DEVCAP_MAX * sizeof(uint32_t);
+ else
+ gp_arg->value = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) * sizeof(uint32_t);
+ break;
+ case DRM_VMW_PARAM_MAX_MOB_MEMORY:
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB] * 1024;
+ break;
+ case DRM_VMW_PARAM_MAX_MOB_SIZE:
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_MOB_MAX_SIZE];
+ break;
+ case DRM_VMW_PARAM_SCREEN_TARGET:
+ gp_arg->value = 1; /* not used */
+ break;
+ case DRM_VMW_PARAM_DX:
+ gp_arg->value = (vboxGetShaderModel(vws_wddm) >= SVGA_SM_4);
+ break;
+ case DRM_VMW_PARAM_HW_CAPS2:
+ if (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_CAP2_REGISTER)
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_CAP2];
+ else
+ gp_arg->value = 0;
+ break;
+ case DRM_VMW_PARAM_SM4_1:
+ gp_arg->value = (vboxGetShaderModel(vws_wddm) >= SVGA_SM_4_1);
+ break;
+ case DRM_VMW_PARAM_SM5:
+ gp_arg->value = (vboxGetShaderModel(vws_wddm) >= SVGA_SM_5);
+ break;
+ default: return -1;
+ }
+ return 0;
+}
+
+static int
+vboxGet3DCap(struct vmw_winsys_screen_wddm *vws_wddm, void *pvCap, size_t cbCap)
+{
+ /* DRM_VMW_GET_3D_CAP */
+ if (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_GBOBJECTS)
+ memcpy(pvCap, vws_wddm->HwInfo.au32Caps, cbCap);
+ else
+ memcpy(pvCap, &vws_wddm->HwInfo.au32Fifo[SVGA_FIFO_3D_CAPS], cbCap);
+ return 0;
+}
+
+boolean
+vmw_ioctl_init(struct vmw_winsys_screen *vws)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+
+ struct drm_vmw_getparam_arg gp_arg;
+ unsigned int size;
+ int ret;
+ uint32_t *cap_buffer;
+ boolean drm_gb_capable;
+ boolean have_drm_2_5;
+
+ VMW_FUNC;
+
+ have_drm_2_5 = 1;
+ vws->ioctl.have_drm_2_6 = 1;
+ vws->ioctl.have_drm_2_9 = 1;
+ vws->ioctl.have_drm_2_15 = 1;
+ vws->ioctl.have_drm_2_16 = 1;
+ vws->ioctl.have_drm_2_17 = 1;
+ vws->ioctl.have_drm_2_18 = 1;
+ vws->ioctl.have_drm_2_19 = 1;
+
+ vws->ioctl.drm_execbuf_version = vws->ioctl.have_drm_2_9 ? 2 : 1;
+
+ drm_gb_capable = have_drm_2_5;
+
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_3D;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret || gp_arg.value == 0) {
+ vmw_error("No 3D enabled (%i, %s).\n", ret, strerror(-ret));
+ goto out_no_3d;
+ }
+
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_FIFO_HW_VERSION;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret) {
+ vmw_error("Failed to get fifo hw version (%i, %s).\n",
+ ret, strerror(-ret));
+ goto out_no_3d;
+ }
+ vws->ioctl.hwversion = gp_arg.value;
+
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_HW_CAPS;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret)
+ vws->base.have_gb_objects = FALSE;
+ else
+ vws->base.have_gb_objects =
+ !!(gp_arg.value & (uint64_t) SVGA_CAP_GBOBJECTS);
+
+ if (vws->base.have_gb_objects && !drm_gb_capable)
+ goto out_no_3d;
+
+ vws->base.have_vgpu10 = FALSE;
+ vws->base.have_sm4_1 = FALSE;
+ vws->base.have_intra_surface_copy = FALSE;
+
+ if (vws->base.have_gb_objects) {
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_MAX_MOB_MEMORY;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret) {
+ /* Just guess a large enough value. */
+ vws->ioctl.max_mob_memory = 256*1024*1024;
+ } else {
+ vws->ioctl.max_mob_memory = gp_arg.value;
+ }
+
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_MAX_MOB_SIZE;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+
+ if (ret || gp_arg.value == 0) {
+ vws->ioctl.max_texture_size = VMW_MAX_DEFAULT_TEXTURE_SIZE;
+ } else {
+ vws->ioctl.max_texture_size = gp_arg.value;
+ }
+
+ /* Never early flush surfaces, mobs do accounting. */
+ vws->ioctl.max_surface_memory = -1;
+
+ if (vws->ioctl.have_drm_2_9) {
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_DX;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret == 0 && gp_arg.value != 0) {
+ const char *vgpu10_val;
+
+ debug_printf("Have VGPU10 interface and hardware.\n");
+ vws->base.have_vgpu10 = TRUE;
+ vgpu10_val = getenv("SVGA_VGPU10");
+ if (vgpu10_val && strcmp(vgpu10_val, "0") == 0) {
+ debug_printf("Disabling VGPU10 interface.\n");
+ vws->base.have_vgpu10 = FALSE;
+ } else {
+ debug_printf("Enabling VGPU10 interface.\n");
+ }
+ }
+ }
+
+ if (vws->ioctl.have_drm_2_15 && vws->base.have_vgpu10) {
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_HW_CAPS2;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret == 0 && gp_arg.value != 0) {
+ vws->base.have_intra_surface_copy = TRUE;
+ }
+
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_SM4_1;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret == 0 && gp_arg.value != 0) {
+ vws->base.have_sm4_1 = TRUE;
+ }
+ }
+
+ if (vws->ioctl.have_drm_2_18 && vws->base.have_sm4_1) {
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_SM5;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret == 0 && gp_arg.value != 0) {
+ vws->base.have_sm5 = TRUE;
+ }
+ }
+
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_3D_CAPS_SIZE;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret)
+ size = SVGA_FIFO_3D_CAPS_SIZE * sizeof(uint32_t);
+ else
+ size = gp_arg.value;
+
+ if (vws->base.have_gb_objects)
+ vws->ioctl.num_cap_3d = size / sizeof(uint32_t);
+ else
+ vws->ioctl.num_cap_3d = SVGA3D_DEVCAP_MAX;
+
+ if (vws->ioctl.have_drm_2_16) {
+ vws->base.have_coherent = TRUE;
+ }
+ } else {
+ vws->ioctl.num_cap_3d = SVGA3D_DEVCAP_MAX;
+
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_MAX_SURF_MEMORY;
+ if (have_drm_2_5)
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (!have_drm_2_5 || ret) {
+ /* Just guess a large enough value, around 800mb. */
+ vws->ioctl.max_surface_memory = 0x30000000;
+ } else {
+ vws->ioctl.max_surface_memory = gp_arg.value;
+ }
+
+ vws->ioctl.max_texture_size = VMW_MAX_DEFAULT_TEXTURE_SIZE;
+
+ size = SVGA_FIFO_3D_CAPS_SIZE * sizeof(uint32_t);
+ }
+
+ debug_printf("VGPU10 interface is %s.\n",
+ vws->base.have_vgpu10 ? "on" : "off");
+
+ cap_buffer = calloc(1, size);
+ if (!cap_buffer) {
+ debug_printf("Failed alloc fifo 3D caps buffer.\n");
+ goto out_no_3d;
+ }
+
+ vws->ioctl.cap_3d = calloc(vws->ioctl.num_cap_3d,
+ sizeof(*vws->ioctl.cap_3d));
+ if (!vws->ioctl.cap_3d) {
+ debug_printf("Failed alloc fifo 3D caps buffer.\n");
+ goto out_no_caparray;
+ }
+
+ /*
+ * This call must always be after DRM_VMW_PARAM_MAX_MOB_MEMORY and
+ * DRM_VMW_PARAM_SM4_1. This is because, based on these calls, kernel
+ * driver sends the supported cap.
+ */
+ ret = vboxGet3DCap(vws_wddm, cap_buffer, size);
+
+ if (ret) {
+ debug_printf("Failed to get 3D capabilities"
+ " (%i, %s).\n", ret, strerror(-ret));
+ goto out_no_caps;
+ }
+
+ ret = vmw_ioctl_parse_caps(vws, cap_buffer);
+ if (ret) {
+ debug_printf("Failed to parse 3D capabilities"
+ " (%i, %s).\n", ret, strerror(-ret));
+ goto out_no_caps;
+ }
+
+ if (vws->ioctl.have_drm_2_15 && vws->base.have_vgpu10) {
+
+ /* support for these commands didn't make it into vmwgfx kernel
+ * modules before 2.10.
+ */
+ vws->base.have_generate_mipmap_cmd = TRUE;
+ vws->base.have_set_predication_cmd = TRUE;
+ }
+
+ if (vws->ioctl.have_drm_2_15) {
+ vws->base.have_fence_fd = TRUE;
+ }
+
+ free(cap_buffer);
+ vmw_printf("%s OK\n", __FUNCTION__);
+ return TRUE;
+ out_no_caps:
+ free(vws->ioctl.cap_3d);
+ out_no_caparray:
+ free(cap_buffer);
+ out_no_3d:
+ vws->ioctl.num_cap_3d = 0;
+ debug_printf("%s Failed\n", __FUNCTION__);
+ return FALSE;
+}
+
+
+
+void
+vmw_ioctl_cleanup(struct vmw_winsys_screen *vws)
+{
+ VMW_FUNC;
+
+ free(vws->ioctl.cap_3d);
+}
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_wddm.c b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_wddm.c
new file mode 100644
index 00000000..1bdd5df9
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_wddm.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+/**********************************************************
+ * Copyright 2009-2015 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **********************************************************/
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+
+#include "vmw_context.h"
+#include "vmw_screen.h"
+#include "vmw_surface.h"
+#include "vmw_buffer.h"
+#include "svga_drm_public.h"
+#include "svga3d_surfacedefs.h"
+
+#include "frontend/drm_driver.h"
+
+#include "vmwgfx_drm.h"
+
+#include "../wddm_screen.h"
+
+#include <iprt/asm.h>
+
+static struct svga_winsys_surface *
+vmw_drm_surface_from_handle(struct svga_winsys_screen *sws,
+ struct winsys_handle *whandle,
+ SVGA3dSurfaceFormat *format);
+
+static struct svga_winsys_surface *
+vmw_drm_gb_surface_from_handle(struct svga_winsys_screen *sws,
+ struct winsys_handle *whandle,
+ SVGA3dSurfaceFormat *format);
+static boolean
+vmw_drm_surface_get_handle(struct svga_winsys_screen *sws,
+ struct svga_winsys_surface *surface,
+ unsigned stride,
+ struct winsys_handle *whandle);
+
+struct vmw_winsys_screen_wddm *
+vmw_winsys_create_wddm(const WDDMGalliumDriverEnv *pEnv);
+
+/* This is actually the entrypoint to the entire driver,
+ * called by the target bootstrap code.
+ */
+struct svga_winsys_screen *
+svga_wddm_winsys_screen_create(const WDDMGalliumDriverEnv *pEnv)
+{
+ struct vmw_winsys_screen_wddm *vws;
+
+ if (pEnv->cb < sizeof(WDDMGalliumDriverEnv))
+ goto out_no_vws;
+
+ vws = vmw_winsys_create_wddm(pEnv);
+ if (!vws)
+ goto out_no_vws;
+
+ /* XXX do this properly */
+ vws->base.base.surface_from_handle = vws->base.base.have_gb_objects ?
+ vmw_drm_gb_surface_from_handle : vmw_drm_surface_from_handle;
+ vws->base.base.surface_get_handle = vmw_drm_surface_get_handle;
+
+ return &vws->base.base;
+
+out_no_vws:
+ return NULL;
+}
+
+static struct svga_winsys_surface *
+vmw_drm_gb_surface_from_handle(struct svga_winsys_screen *sws,
+ struct winsys_handle *whandle,
+ SVGA3dSurfaceFormat *format)
+{
+ RT_NOREF3(sws, whandle, format);
+ return 0;
+}
+
+static struct svga_winsys_surface *
+vmw_drm_surface_from_handle(struct svga_winsys_screen *sws,
+ struct winsys_handle *whandle,
+ SVGA3dSurfaceFormat *format)
+{
+ RT_NOREF3(sws, whandle, format);
+ return 0;
+}
+
+/*
+ * The user mode driver asks the kernel driver to create a resource
+ * (vmw_ioctl_surface_create) and gets a sid (surface id).
+ * This function is supposed to convert the sid to a handle (file descriptor)
+ * which can be used to access the surface.
+ */
+static boolean
+vmw_drm_surface_get_handle(struct svga_winsys_screen *sws,
+ struct svga_winsys_surface *surface,
+ unsigned stride,
+ struct winsys_handle *whandle)
+{
+ struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
+ struct vmw_svga_winsys_surface *vsrf;
+
+ RT_NOREF(vws);
+
+ if (!surface)
+ return FALSE;
+
+ vsrf = vmw_svga_winsys_surface(surface);
+ whandle->handle = vsrf->sid;
+ whandle->stride = stride;
+ whandle->offset = 0;
+
+ switch (whandle->type) {
+ case WINSYS_HANDLE_TYPE_SHARED:
+ case WINSYS_HANDLE_TYPE_KMS:
+ whandle->handle = vsrf->sid;
+ break;
+ case WINSYS_HANDLE_TYPE_FD:
+ whandle->handle = vsrf->sid; /// @todo will this be enough for WDDM?
+ break;
+ default:
+ vmw_error("Attempt to export unsupported handle type %d.\n",
+ whandle->type);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+vmw_svga_winsys_host_log(struct svga_winsys_screen *sws, const char *log)
+{
+ (void)sws;
+ _debug_printf("%s\n", log);
+}
diff --git a/src/VBox/Additions/3D/win/VBoxWddmUmHlp/D3DKMT.cpp b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/D3DKMT.cpp
new file mode 100644
index 00000000..893fac27
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/D3DKMT.cpp
@@ -0,0 +1,260 @@
+/* $Id: D3DKMT.cpp $ */
+/** @file
+ * WDDM Kernel Mode Thunks helpers.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+/* We're unable to use standard r3 vbgl-based backdoor logging API because win8 Metro apps
+ * can not do CreateFile/Read/Write by default.
+ * This is why we use miniport escape functionality to issue backdoor log string to the miniport
+ * and submit it to host via standard r0 backdoor logging api accordingly
+ */
+
+#include "UmHlpInternal.h"
+
+
+/** Loads a system DLL.
+ *
+ * @returns Module handle or NULL
+ * @param pszName The DLL name.
+ */
+DECLCALLBACK(HMODULE) VBoxWddmLoadSystemDll(const char *pszName)
+{
+ char szPath[MAX_PATH];
+ UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath));
+ size_t cbName = strlen(pszName) + 1;
+ if (cchPath + 1 + cbName > sizeof(szPath))
+ {
+ SetLastError(ERROR_FILENAME_EXCED_RANGE);
+ return NULL;
+ }
+ szPath[cchPath] = '\\';
+ memcpy(&szPath[cchPath + 1], pszName, cbName);
+ return LoadLibraryA(szPath);
+}
+
+DECLCALLBACK(void) VBoxWddmLoadAdresses(HMODULE hmod, VBOXWDDMDLLPROC *paProcs)
+{
+ struct VBOXWDDMDLLPROC *pIter = paProcs;
+ while (pIter->pszName)
+ {
+ FARPROC pfn = GetProcAddress(hmod, pIter->pszName);
+ *pIter->ppfn = pfn;
+ ++pIter;
+ }
+}
+
+/*
+ * Kernel Mode Thunks (KMT) initialization.
+ */
+
+#define D3DKMT_LOAD_ENTRY(a) { #a, (FARPROC *)&g_D3DKMT.pfn##a }
+
+static D3DKMTFUNCTIONS g_D3DKMT = { 0 };
+static VBOXWDDMDLLPROC g_D3DKMTLoadTable[] =
+{
+ D3DKMT_LOAD_ENTRY(D3DKMTOpenAdapterFromHdc),
+ D3DKMT_LOAD_ENTRY(D3DKMTOpenAdapterFromDeviceName),
+ D3DKMT_LOAD_ENTRY(D3DKMTCloseAdapter),
+ D3DKMT_LOAD_ENTRY(D3DKMTQueryAdapterInfo),
+ D3DKMT_LOAD_ENTRY(D3DKMTEscape),
+ D3DKMT_LOAD_ENTRY(D3DKMTCreateDevice),
+ D3DKMT_LOAD_ENTRY(D3DKMTDestroyDevice),
+ D3DKMT_LOAD_ENTRY(D3DKMTCreateContext),
+ D3DKMT_LOAD_ENTRY(D3DKMTDestroyContext),
+ D3DKMT_LOAD_ENTRY(D3DKMTCreateAllocation),
+ D3DKMT_LOAD_ENTRY(D3DKMTDestroyAllocation),
+ D3DKMT_LOAD_ENTRY(D3DKMTRender),
+ D3DKMT_LOAD_ENTRY(D3DKMTPresent),
+ D3DKMT_LOAD_ENTRY(D3DKMTGetSharedPrimaryHandle),
+ D3DKMT_LOAD_ENTRY(D3DKMTQueryResourceInfo),
+ D3DKMT_LOAD_ENTRY(D3DKMTOpenResource),
+ D3DKMT_LOAD_ENTRY(D3DKMTEnumAdapters),
+ D3DKMT_LOAD_ENTRY(D3DKMTOpenAdapterFromLuid),
+ {NULL, NULL},
+};
+
+#undef D3DKMT_LOAD_ENTRY
+
+/** Initialize Kernel Mode Thunks (KMT) pointers in the g_D3DKMT structure.
+ *
+ * @returns True if successful.
+ */
+DECLCALLBACK(int) D3DKMTLoad(void)
+{
+ /* Modules which use D3DKMT must link with gdi32. */
+ HMODULE hmod = GetModuleHandleA("gdi32.dll");
+ Assert(hmod);
+ if (hmod)
+ {
+ VBoxWddmLoadAdresses(hmod, g_D3DKMTLoadTable);
+ }
+ return hmod != NULL;
+}
+
+DECLCALLBACK(D3DKMTFUNCTIONS const *) D3DKMTFunctions(void)
+{
+ return &g_D3DKMT;
+}
+
+
+/*
+ * Getting VirtualBox Graphics Adapter handle.
+ */
+
+static NTSTATUS vboxDispKmtOpenAdapterFromHdc(D3DKMT_HANDLE *phAdapter, LUID *pLuid)
+{
+ *phAdapter = 0;
+
+ D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
+ if (d3dkmt->pfnD3DKMTOpenAdapterFromHdc == NULL)
+ return STATUS_NOT_SUPPORTED;
+
+ D3DKMT_OPENADAPTERFROMHDC OpenAdapterData;
+ memset(&OpenAdapterData, 0, sizeof(OpenAdapterData));
+
+ for (int i = 0; ; ++i)
+ {
+ DISPLAY_DEVICEA dd;
+ memset(&dd, 0, sizeof(dd));
+ dd.cb = sizeof(dd);
+
+ if (!EnumDisplayDevicesA(NULL, i, &dd, 0))
+ break;
+
+ if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
+ {
+ OpenAdapterData.hDc = CreateDCA(NULL, dd.DeviceName, NULL, NULL);
+ break;
+ }
+ }
+
+ Assert(OpenAdapterData.hDc);
+
+ NTSTATUS Status;
+ if (OpenAdapterData.hDc)
+ {
+ Status = d3dkmt->pfnD3DKMTOpenAdapterFromHdc(&OpenAdapterData);
+ Assert(Status == STATUS_SUCCESS);
+ if (Status == STATUS_SUCCESS)
+ {
+ *phAdapter = OpenAdapterData.hAdapter;
+ if (pLuid)
+ {
+ *pLuid = OpenAdapterData.AdapterLuid;
+ }
+ }
+
+ DeleteDC(OpenAdapterData.hDc);
+ }
+ else
+ {
+ Status = STATUS_NOT_SUPPORTED;
+ }
+
+ return Status;
+}
+
+static NTSTATUS vboxDispKmtOpenAdapterFromLuid(D3DKMT_HANDLE *phAdapter, LUID *pLuid)
+{
+ *phAdapter = 0;
+
+ D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
+ if ( d3dkmt->pfnD3DKMTOpenAdapterFromLuid == NULL
+ || d3dkmt->pfnD3DKMTEnumAdapters == NULL)
+ return STATUS_NOT_SUPPORTED;
+
+ D3DKMT_ENUMADAPTERS EnumAdaptersData;
+ memset(&EnumAdaptersData, 0, sizeof(EnumAdaptersData));
+ EnumAdaptersData.NumAdapters = RT_ELEMENTS(EnumAdaptersData.Adapters);
+
+ NTSTATUS Status = d3dkmt->pfnD3DKMTEnumAdapters(&EnumAdaptersData);
+ Assert(Status == STATUS_SUCCESS);
+ if (Status == STATUS_SUCCESS)
+ {
+ Assert(EnumAdaptersData.NumAdapters);
+
+ /* Try the same twice: if we fail to open the adapter containing present sources,
+ * then try to open any adapter.
+ */
+ for (int iPass = 0; iPass < 2 && *phAdapter == 0; ++iPass)
+ {
+ for (ULONG i = 0; i < EnumAdaptersData.NumAdapters; ++i)
+ {
+ if (iPass > 0 || EnumAdaptersData.Adapters[i].NumOfSources)
+ {
+ D3DKMT_OPENADAPTERFROMLUID OpenAdapterData;
+ memset(&OpenAdapterData, 0, sizeof(OpenAdapterData));
+ OpenAdapterData.AdapterLuid = EnumAdaptersData.Adapters[i].AdapterLuid;
+
+ Status = d3dkmt->pfnD3DKMTOpenAdapterFromLuid(&OpenAdapterData);
+ Assert(Status == STATUS_SUCCESS);
+ if (Status == STATUS_SUCCESS)
+ {
+ *phAdapter = OpenAdapterData.hAdapter;
+ if (pLuid)
+ {
+ *pLuid = EnumAdaptersData.Adapters[i].AdapterLuid;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return Status;
+}
+
+NTSTATUS vboxDispKmtOpenAdapter2(D3DKMT_HANDLE *phAdapter, LUID *pLuid)
+{
+ NTSTATUS Status = vboxDispKmtOpenAdapterFromLuid(phAdapter, pLuid);
+ if (Status != STATUS_SUCCESS)
+ {
+ /* Fallback for pre-Windows8 */
+ Status = vboxDispKmtOpenAdapterFromHdc(phAdapter, pLuid);
+ }
+
+ return Status;
+}
+
+NTSTATUS vboxDispKmtOpenAdapter(D3DKMT_HANDLE *phAdapter)
+{
+ return vboxDispKmtOpenAdapter2(phAdapter, NULL);
+}
+
+NTSTATUS vboxDispKmtCloseAdapter(D3DKMT_HANDLE hAdapter)
+{
+ D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
+ if (d3dkmt->pfnD3DKMTCloseAdapter == NULL)
+ return STATUS_NOT_SUPPORTED;
+
+ D3DKMT_CLOSEADAPTER CloseAdapterData;
+ CloseAdapterData.hAdapter = hAdapter;
+
+ NTSTATUS Status = d3dkmt->pfnD3DKMTCloseAdapter(&CloseAdapterData);
+ Assert(Status == STATUS_SUCCESS);
+
+ return Status;
+}
diff --git a/src/VBox/Additions/3D/win/VBoxWddmUmHlp/Makefile.kmk b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/Makefile.kmk
new file mode 100644
index 00000000..0437c3bf
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/Makefile.kmk
@@ -0,0 +1,54 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for the VirtualBox WDDM user mode driver
+#
+
+#
+# Copyright (C) 2018-2022 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+LIBRARIES += VBoxWddmUmHlp
+LIBRARIES.amd64 += VBoxWddmUmHlp-x86
+
+#
+# VBoxWddmUmHlp - logger and other helpers for user mode driver
+#
+VBoxWddmUmHlp_TEMPLATE = NewerVccVBoxGuestR3Dll
+VBoxWddmUmHlp_INST = $(INST_ADDITIONS_LIB)
+VBoxWddmUmHlp_DEFS = VBOX_WITH_WDDM
+VBoxWddmUmHlp_INCS = \
+ $(PATH_ROOT)/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/shared \
+ $(VBOX_GRAPHICS_INCS)
+VBoxWddmUmHlp_SOURCES = \
+ D3DKMT.cpp \
+ VBoxMpLogger.cpp
+
+#
+# 64-bit version for 32-bit build.
+#
+VBoxWddmUmHlp-x86_EXTENDS = VBoxWddmUmHlp
+VBoxWddmUmHlp-x86_BLD_TRG_ARCH = x86
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Additions/3D/win/VBoxWddmUmHlp/UmHlpInternal.h b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/UmHlpInternal.h
new file mode 100644
index 00000000..6090eb65
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/UmHlpInternal.h
@@ -0,0 +1,36 @@
+/* $Id: UmHlpInternal.h $ */
+/** @file
+ * VBox WDDM User Mode Driver Helpers
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef GA_INCLUDED_SRC_3D_win_VBoxWddmUmHlp_UmHlpInternal_h
+#define GA_INCLUDED_SRC_3D_win_VBoxWddmUmHlp_UmHlpInternal_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "VBoxWddmUmHlp.h"
+
+#endif /* !GA_INCLUDED_SRC_3D_win_VBoxWddmUmHlp_UmHlpInternal_h */
diff --git a/src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxMpLogger.cpp b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxMpLogger.cpp
new file mode 100644
index 00000000..321ed364
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxMpLogger.cpp
@@ -0,0 +1,167 @@
+/* $Id: VBoxMpLogger.cpp $ */
+/** @file
+ * VBox WDDM Display logger implementation
+ *
+ * We're unable to use standard r3 vbgl-based backdoor logging API because
+ * win8 Metro apps can not do CreateFile/Read/Write by default. This is why
+ * we use miniport escape functionality to issue backdoor log string to the
+ * miniport and submit it to host via standard r0 backdoor logging api
+ * accordingly
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#define IPRT_NO_CRT_FOR_3RD_PARTY /* To get malloc and free wrappers in IPRT_NO_CRT mode. Doesn't link with IPRT in non-no-CRT mode. */
+#include "UmHlpInternal.h"
+
+#include <../../../common/wddm/VBoxMPIf.h>
+#include <stdlib.h>
+#ifdef IPRT_NO_CRT
+# include <iprt/process.h>
+# include <iprt/string.h>
+#else
+# include <stdio.h>
+#endif
+#include <VBox/VBoxGuestLib.h>
+
+
+static void VBoxDispMpLoggerLogN(const char *pchString, size_t cchString)
+{
+ D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
+ if (d3dkmt->pfnD3DKMTEscape == NULL)
+ return;
+
+ D3DKMT_HANDLE hAdapter;
+ NTSTATUS Status = vboxDispKmtOpenAdapter(&hAdapter);
+ Assert(Status == STATUS_SUCCESS);
+ if (Status == 0)
+ {
+ uint32_t cchString2 = (uint32_t)RT_MIN(cchString, _64K - 1U);
+ uint32_t cbCmd = RT_UOFFSETOF_DYN(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[cchString2 + 1]);
+ PVBOXDISPIFESCAPE_DBGPRINT pCmd = (PVBOXDISPIFESCAPE_DBGPRINT)malloc(cbCmd);
+ Assert(pCmd);
+ if (pCmd)
+ {
+ pCmd->EscapeHdr.escapeCode = VBOXESC_DBGPRINT;
+ pCmd->EscapeHdr.u32CmdSpecific = 0;
+ memcpy(pCmd->aStringBuf, pchString, cchString2);
+ pCmd->aStringBuf[cchString2] = '\0';
+
+ D3DKMT_ESCAPE EscapeData;
+ memset(&EscapeData, 0, sizeof(EscapeData));
+ EscapeData.hAdapter = hAdapter;
+ // EscapeData.hDevice = NULL;
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ // EscapeData.Flags.HardwareAccess = 0;
+ EscapeData.pPrivateDriverData = pCmd;
+ EscapeData.PrivateDriverDataSize = cbCmd;
+ // EscapeData.hContext = NULL;
+
+ Status = d3dkmt->pfnD3DKMTEscape(&EscapeData);
+ Assert(Status == STATUS_SUCCESS);
+
+ free(pCmd);
+ }
+
+ Status = vboxDispKmtCloseAdapter(hAdapter);
+ Assert(Status == STATUS_SUCCESS);
+ }
+}
+
+
+DECLCALLBACK(void) VBoxDispMpLoggerLog(const char *pszString)
+{
+ VBoxDispMpLoggerLogN(pszString, strlen(pszString));
+}
+
+
+DECLCALLBACK(void) VBoxDispMpLoggerLogF(const char *pszFormat, ...)
+{
+ /** @todo would make a whole lot more sense to just allocate
+ * VBOXDISPIFESCAPE_DBGPRINT here and printf into it's buffer than
+ * double buffering it like this */
+ char szBuffer[4096];
+ va_list va;
+ va_start(va, pszFormat);
+#ifdef IPRT_NO_CRT
+ RTStrPrintf(szBuffer, sizeof(szBuffer), pszFormat, va);
+#else
+ _vsnprintf(szBuffer, sizeof(szBuffer), pszFormat, va);
+ szBuffer[sizeof(szBuffer) - 1] = '\0'; /* Don't trust the _vsnprintf function terminate the string! */
+#endif
+ va_end(va);
+
+ VBoxDispMpLoggerLog(szBuffer);
+}
+
+
+/* Interface used for backdoor logging. In no-CRT mode we will drag in IPRT
+ logging and it will be used on assertion in the no-CRT and IPRT code. */
+VBGLR3DECL(int) VbglR3WriteLog(const char *pch, size_t cch)
+{
+ VBoxDispMpLoggerLogN(pch, cch);
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * Prefix the output string with exe name and pid/tid.
+ */
+#ifndef IPRT_NO_CRT
+static const char *vboxUmLogGetExeName(void)
+{
+ static int s_fModuleNameInited = 0;
+ static char s_szModuleName[MAX_PATH];
+
+ if (!s_fModuleNameInited)
+ {
+ const DWORD cchName = GetModuleFileNameA(NULL, s_szModuleName, RT_ELEMENTS(s_szModuleName));
+ if (cchName == 0)
+ return "<no module>";
+ s_fModuleNameInited = 1;
+ }
+ return &s_szModuleName[0];
+}
+#endif
+
+DECLCALLBACK(void) VBoxWddmUmLog(const char *pszString)
+{
+ /** @todo Allocate VBOXDISPIFESCAPE_DBGPRINT here and format right into it
+ * instead? That would be a lot more flexible and a little faster. */
+ char szBuffer[4096];
+#ifdef IPRT_NO_CRT
+ /** @todo use RTProcShortName instead of RTProcExecutablePath? Will avoid
+ * chopping off log text if the executable path is too long. */
+ RTStrPrintf(szBuffer, sizeof(szBuffer), "['%s' 0x%lx.0x%lx]: %s",
+ RTProcExecutablePath() /* should've been initialized by nocrt-startup-dll-win.cpp already */,
+ GetCurrentProcessId(), GetCurrentThreadId(), pszString);
+#else
+ int cch = _snprintf(szBuffer, sizeof(szBuffer), "['%s' 0x%lx.0x%lx]: %s",
+ vboxUmLogGetExeName(), GetCurrentProcessId(), GetCurrentThreadId(), pszString);
+ AssertReturnVoid(cch > 0); /* unlikely that we'll have string encoding problems, but just in case. */
+ szBuffer[sizeof(szBuffer) - 1] = '\0'; /* the function doesn't necessarily terminate the buffer on overflow. */
+#endif
+
+ VBoxDispMpLoggerLog(szBuffer);
+}
+
diff --git a/src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxWddmUmHlp.h b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxWddmUmHlp.h
new file mode 100644
index 00000000..03d1584a
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxWddmUmHlp/VBoxWddmUmHlp.h
@@ -0,0 +1,116 @@
+/* $Id: VBoxWddmUmHlp.h $ */
+/** @file
+ * VBox WDDM User Mode Driver Helpers
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef GA_INCLUDED_SRC_3D_win_VBoxWddmUmHlp_VBoxWddmUmHlp_h
+#define GA_INCLUDED_SRC_3D_win_VBoxWddmUmHlp_VBoxWddmUmHlp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/win/d3d9.h>
+#include <d3dumddi.h>
+#include <iprt/win/d3dkmthk.h>
+
+#include <iprt/asm.h>
+#include <iprt/cdefs.h>
+
+/* Do not require IPRT library. */
+/** @todo r=bird: It is *NOT* okay to redefine Assert* (or Log*) macros! It
+ * causes confusing as the code no longer behaves in the way one expect. Thus,
+ * it is strictly forbidden. */
+#ifndef IPRT_NO_CRT
+# undef Assert
+# undef AssertReturnVoid
+# ifdef RT_STRICT
+# define Assert(_e) (void)( (!!(_e)) || (ASMBreakpoint(), 0) )
+# define AssertReturnVoid(a_Expr) do { if (RT_LIKELY(a_Expr)) {} else { ASMBreakpoint(); return; } } while (0)
+# else
+# define Assert(_e) (void)( 0 )
+# define AssertReturnVoid(a_Expr) do { if (RT_LIKELY(a_Expr)) {} else return; } while (0)
+# endif
+#endif
+
+/* Do not require ntstatus.h.
+ * D3DKMT functions return NTSTATUS, but the driver code uses it only as a success/failure indicator.
+ * Therefore define the success and a failure status here.
+ */
+#ifndef STATUS_SUCCESS
+#define STATUS_SUCCESS 0
+#endif
+#ifndef STATUS_NOT_SUPPORTED
+#define STATUS_NOT_SUPPORTED ((NTSTATUS)0xC00000BBL)
+#endif
+
+RT_C_DECLS_BEGIN
+
+typedef struct VBOXWDDMDLLPROC
+{
+ char const *pszName;
+ FARPROC *ppfn;
+} VBOXWDDMDLLPROC;
+
+typedef struct D3DKMTFUNCTIONS
+{
+ PFND3DKMT_OPENADAPTERFROMHDC pfnD3DKMTOpenAdapterFromHdc;
+ PFND3DKMT_OPENADAPTERFROMDEVICENAME pfnD3DKMTOpenAdapterFromDeviceName;
+ PFND3DKMT_CLOSEADAPTER pfnD3DKMTCloseAdapter;
+ PFND3DKMT_QUERYADAPTERINFO pfnD3DKMTQueryAdapterInfo;
+ PFND3DKMT_ESCAPE pfnD3DKMTEscape;
+ PFND3DKMT_CREATEDEVICE pfnD3DKMTCreateDevice;
+ PFND3DKMT_DESTROYDEVICE pfnD3DKMTDestroyDevice;
+ PFND3DKMT_CREATECONTEXT pfnD3DKMTCreateContext;
+ PFND3DKMT_DESTROYCONTEXT pfnD3DKMTDestroyContext;
+ PFND3DKMT_CREATEALLOCATION pfnD3DKMTCreateAllocation;
+ PFND3DKMT_DESTROYALLOCATION pfnD3DKMTDestroyAllocation;
+ PFND3DKMT_RENDER pfnD3DKMTRender;
+ PFND3DKMT_PRESENT pfnD3DKMTPresent;
+ PFND3DKMT_GETSHAREDPRIMARYHANDLE pfnD3DKMTGetSharedPrimaryHandle;
+ PFND3DKMT_QUERYRESOURCEINFO pfnD3DKMTQueryResourceInfo;
+ PFND3DKMT_OPENRESOURCE pfnD3DKMTOpenResource;
+
+ /* Win 8+ */
+ PFND3DKMT_ENUMADAPTERS pfnD3DKMTEnumAdapters;
+ PFND3DKMT_OPENADAPTERFROMLUID pfnD3DKMTOpenAdapterFromLuid;
+} D3DKMTFUNCTIONS;
+
+DECLCALLBACK(HMODULE) VBoxWddmLoadSystemDll(const char *pszName);
+DECLCALLBACK(void) VBoxWddmLoadAdresses(HMODULE hmod, VBOXWDDMDLLPROC *paProcs);
+
+DECLCALLBACK(int) D3DKMTLoad(void);
+DECLCALLBACK(D3DKMTFUNCTIONS const *) D3DKMTFunctions(void);
+
+DECLCALLBACK(void) VBoxDispMpLoggerLogF(const char *pszFormat, ...);
+DECLCALLBACK(void) VBoxWddmUmLog(const char *pszString);
+
+/** @todo Rename to VBoxWddm* */
+NTSTATUS vboxDispKmtOpenAdapter2(D3DKMT_HANDLE *phAdapter, LUID *pLuid);
+NTSTATUS vboxDispKmtOpenAdapter(D3DKMT_HANDLE *phAdapter);
+NTSTATUS vboxDispKmtCloseAdapter(D3DKMT_HANDLE hAdapter);
+
+RT_C_DECLS_END
+
+#endif /* !GA_INCLUDED_SRC_3D_win_VBoxWddmUmHlp_VBoxWddmUmHlp_h */
diff --git a/src/VBox/Additions/3D/win/include/VBoxGaDriver.h b/src/VBox/Additions/3D/win/include/VBoxGaDriver.h
new file mode 100644
index 00000000..8b57ea1c
--- /dev/null
+++ b/src/VBox/Additions/3D/win/include/VBoxGaDriver.h
@@ -0,0 +1,115 @@
+/* $Id: VBoxGaDriver.h $ */
+/** @file
+ * VirtualBox Windows Guest Mesa3D - Gallium driver interface.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef GA_INCLUDED_3D_WIN_VBoxGaDriver_h
+#define GA_INCLUDED_3D_WIN_VBoxGaDriver_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBoxGaHWInfo.h>
+#include <VBoxGaTypes.h>
+
+#include <iprt/win/windows.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct WDDMGalliumDriverEnv
+{
+ /* Size of the structure. */
+ DWORD cb;
+ const VBOXGAHWINFO *pHWInfo;
+ /* The environment context pointer to use in the following callbacks. */
+ void *pvEnv;
+ /* The callbacks to use by the driver. */
+ DECLCALLBACKMEMBER(uint32_t, pfnContextCreate,(void *pvEnv,
+ boolean extended,
+ boolean vgpu10));
+ DECLCALLBACKMEMBER(void, pfnContextDestroy,(void *pvEnv,
+ uint32_t u32Cid));
+ DECLCALLBACKMEMBER(int, pfnSurfaceDefine,(void *pvEnv,
+ GASURFCREATE *pCreateParms,
+ GASURFSIZE *paSizes,
+ uint32_t cSizes,
+ uint32_t *pu32Sid));
+ DECLCALLBACKMEMBER(void, pfnSurfaceDestroy,(void *pvEnv,
+ uint32_t u32Sid));
+ DECLCALLBACKMEMBER(int, pfnRender,(void *pvEnv,
+ uint32_t u32Cid,
+ void *pvCommands,
+ uint32_t cbCommands,
+ GAFENCEQUERY *pFenceQuery));
+ DECLCALLBACKMEMBER(void, pfnFenceUnref,(void *pvEnv,
+ uint32_t u32FenceHandle));
+ DECLCALLBACKMEMBER(int, pfnFenceQuery,(void *pvEnv,
+ uint32_t u32FenceHandle,
+ GAFENCEQUERY *pFenceQuery));
+ DECLCALLBACKMEMBER(int, pfnFenceWait,(void *pvEnv,
+ uint32_t u32FenceHandle,
+ uint32_t u32TimeoutUS));
+ DECLCALLBACKMEMBER(int, pfnRegionCreate,(void *pvEnv,
+ uint32_t u32RegionSize,
+ uint32_t *pu32GmrId,
+ void **ppvMap));
+ DECLCALLBACKMEMBER(void, pfnRegionDestroy,(void *pvEnv,
+ uint32_t u32GmrId,
+ void *pvMap));
+ /* VGPU10 */
+ DECLCALLBACKMEMBER(int, pfnGBSurfaceDefine,(void *pvEnv,
+ SVGAGBSURFCREATE *pCreateParms));
+} WDDMGalliumDriverEnv;
+
+struct pipe_context;
+struct pipe_screen;
+struct pipe_resource;
+
+typedef struct pipe_screen * WINAPI FNGaDrvScreenCreate(const WDDMGalliumDriverEnv *pEnv);
+typedef FNGaDrvScreenCreate *PFNGaDrvScreenCreate;
+
+typedef void WINAPI FNGaDrvScreenDestroy(struct pipe_screen *s);
+typedef FNGaDrvScreenDestroy *PFNGaDrvScreenDestroy;
+
+typedef const WDDMGalliumDriverEnv * WINAPI FNGaDrvGetWDDMEnv(struct pipe_screen *pScreen);
+typedef FNGaDrvGetWDDMEnv *PFNGaDrvGetWDDMEnv;
+
+typedef uint32_t WINAPI FNGaDrvGetContextId(struct pipe_context *pPipeContext);
+typedef FNGaDrvGetContextId *PFNGaDrvGetContextId;
+
+typedef uint32_t WINAPI FNGaDrvGetSurfaceId(struct pipe_screen *pScreen, struct pipe_resource *pResource);
+typedef FNGaDrvGetSurfaceId *PFNGaDrvGetSurfaceId;
+
+typedef void WINAPI FNGaDrvContextFlush(struct pipe_context *pPipeContext);
+typedef FNGaDrvContextFlush *PFNGaDrvContextFlush;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !GA_INCLUDED_3D_WIN_VBoxGaDriver_h */
+
diff --git a/src/VBox/Additions/3D/win/include/VBoxGaHWInfo.h b/src/VBox/Additions/3D/win/include/VBoxGaHWInfo.h
new file mode 100644
index 00000000..09e1f15d
--- /dev/null
+++ b/src/VBox/Additions/3D/win/include/VBoxGaHWInfo.h
@@ -0,0 +1,64 @@
+/* $Id: VBoxGaHWInfo.h $ */
+/** @file
+ * VirtualBox Windows Guest Mesa3D - Gallium driver interface.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef GA_INCLUDED_3D_WIN_VBoxGaHWInfo_h
+#define GA_INCLUDED_3D_WIN_VBoxGaHWInfo_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+
+#include <VBoxGaHwSVGA.h>
+
+/* Gallium virtual hardware supported by the miniport. */
+#define VBOX_GA_HW_TYPE_UNKNOWN 0
+#define VBOX_GA_HW_TYPE_VMSVGA 1
+
+/*
+ * VBOXGAHWINFO contains information about the virtual hardware, which is passed
+ * to the user mode Gallium driver. The driver can not query the info at the initialization time,
+ * therefore we send the complete info to the driver.
+ *
+ * VBOXGAHWINFO struct goes both to 32 and 64 bit user mode binaries, take care of alignment.
+ */
+#pragma pack(1)
+typedef struct VBOXGAHWINFO
+{
+ uint32_t u32HwType; /* VBOX_GA_HW_TYPE_* */
+ uint32_t u32Reserved;
+ union
+ {
+ VBOXGAHWINFOSVGA svga;
+ uint8_t au8Raw[65536];
+ } u;
+} VBOXGAHWINFO;
+#pragma pack()
+
+AssertCompile(RT_SIZEOFMEMB(VBOXGAHWINFO, u) <= RT_SIZEOFMEMB(VBOXGAHWINFO, u.au8Raw));
+
+#endif /* !GA_INCLUDED_3D_WIN_VBoxGaHWInfo_h */
diff --git a/src/VBox/Additions/3D/win/include/VBoxGaHwSVGA.h b/src/VBox/Additions/3D/win/include/VBoxGaHwSVGA.h
new file mode 100644
index 00000000..38c0d9fc
--- /dev/null
+++ b/src/VBox/Additions/3D/win/include/VBoxGaHwSVGA.h
@@ -0,0 +1,66 @@
+/* $Id: VBoxGaHwSVGA.h $ */
+/** @file
+ * VirtualBox Windows Guest Mesa3D - Gallium driver interface.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef GA_INCLUDED_3D_WIN_VBoxGaHwSVGA_h
+#define GA_INCLUDED_3D_WIN_VBoxGaHwSVGA_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/*
+ * VBOXGAHWINFOSVGA contains information about the virtual hardware, which is neede dy the user mode
+ * Gallium driver. The driver can not query the info at the initialization time, therefore
+ * we send the complete info to the driver.
+ *
+ * Since both FIFO and SVGA_REG_ are expanded over time, we reserve some space.
+ * The Gallium user mode driver can figure out which part of au32Regs and au32Fifo
+ * is valid from the raw data.
+ *
+ * VBOXGAHWINFOSVGA struct goes both to 32 and 64 bit user mode binaries, take care of alignment.
+ */
+#pragma pack(1)
+typedef struct VBOXGAHWINFOSVGA
+{
+ uint32_t cbInfoSVGA;
+
+ /* Copy of SVGA_REG_*, up to 256, currently 58 are used. */
+ uint32_t au32Regs[256];
+
+ /* Copy of FIFO registers, up to 1024, currently 290 are used. */
+ uint32_t au32Fifo[1024];
+
+ /* Currently SVGA has 260 caps, 512 should be ok for near future.
+ * This is a copy of SVGA3D_DEVCAP_* values returned by the host.
+ * Only valid if SVGA_CAP_GBOBJECTS is set in SVGA_REG_CAPABILITIES.
+ */
+ uint32_t au32Caps[512];
+} VBOXGAHWINFOSVGA;
+#pragma pack()
+
+#endif /* !GA_INCLUDED_3D_WIN_VBoxGaHwSVGA_h */
diff --git a/src/VBox/Additions/3D/win/include/VBoxGaNine.h b/src/VBox/Additions/3D/win/include/VBoxGaNine.h
new file mode 100644
index 00000000..08cdff80
--- /dev/null
+++ b/src/VBox/Additions/3D/win/include/VBoxGaNine.h
@@ -0,0 +1,58 @@
+/* $Id: VBoxGaNine.h $ */
+/** @file
+ * VirtualBox Windows Guest Mesa3D - Gallium driver interface for WDDM user mode driver.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef GA_INCLUDED_3D_WIN_VBoxGaNine_h
+#define GA_INCLUDED_3D_WIN_VBoxGaNine_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/win/d3d9.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct pipe_screen;
+struct pipe_resource;
+struct pipe_context;
+typedef struct ID3DAdapter9 ID3DAdapter9;
+
+typedef HRESULT WINAPI FNGaNineD3DAdapter9Create(struct pipe_screen *s, ID3DAdapter9 **ppOut);
+typedef FNGaNineD3DAdapter9Create *PFNGaNineD3DAdapter9Create;
+
+typedef struct pipe_resource * WINAPI FNGaNinePipeResourceFromSurface(IUnknown *pSurface);
+typedef FNGaNinePipeResourceFromSurface *PFNGaNinePipeResourceFromSurface;
+
+typedef struct pipe_context * WINAPI FNGaNinePipeContextFromDevice(IDirect3DDevice9 *pDevice);
+typedef FNGaNinePipeContextFromDevice *PFNGaNinePipeContextFromDevice;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !GA_INCLUDED_3D_WIN_VBoxGaNine_h */
diff --git a/src/VBox/Additions/3D/win/include/VBoxGaTypes.h b/src/VBox/Additions/3D/win/include/VBoxGaTypes.h
new file mode 100644
index 00000000..dfee3fa7
--- /dev/null
+++ b/src/VBox/Additions/3D/win/include/VBoxGaTypes.h
@@ -0,0 +1,114 @@
+/* $Id: VBoxGaTypes.h $ */
+/** @file
+ * VirtualBox Windows Guest Mesa3D - Gallium driver interface.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef GA_INCLUDED_3D_WIN_VBoxGaTypes_h
+#define GA_INCLUDED_3D_WIN_VBoxGaTypes_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+#pragma pack(1) /* VMSVGA structures are '__packed'. */
+#include <svga3d_caps.h>
+#include <svga3d_reg.h>
+#pragma pack()
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GA_MAX_SURFACE_FACES 6
+#define GA_MAX_MIP_LEVELS 24
+
+typedef struct GASURFCREATE
+{
+ uint32_t flags; /* SVGA3dSurfaceFlags */
+ uint32_t format; /* SVGA3dSurfaceFormat */
+ uint32_t usage; /* SVGA_SURFACE_USAGE_* */
+ uint32_t mip_levels[GA_MAX_SURFACE_FACES];
+} GASURFCREATE;
+
+typedef struct GASURFSIZE
+{
+ uint32_t cWidth;
+ uint32_t cHeight;
+ uint32_t cDepth;
+ uint32_t u32Reserved;
+} GASURFSIZE;
+
+#define GA_FENCE_STATUS_NULL 0 /* Fence not found */
+#define GA_FENCE_STATUS_IDLE 1
+#define GA_FENCE_STATUS_SUBMITTED 2
+#define GA_FENCE_STATUS_SIGNALED 3
+
+typedef struct GAFENCEQUERY
+{
+ /* IN: The miniport's handle of the fence.
+ * Assigned by the miniport. Not DXGK fence id!
+ */
+ uint32_t u32FenceHandle;
+
+ /* OUT: The miniport's sequence number associated with the command buffer.
+ */
+ uint32_t u32SubmittedSeqNo;
+
+ /* OUT: The miniport's sequence number associated with the last command buffer completed on host.
+ */
+ uint32_t u32ProcessedSeqNo;
+
+ /* OUT: GA_FENCE_STATUS_*. */
+ uint32_t u32FenceStatus;
+} GAFENCEQUERY;
+
+typedef struct SVGAGBSURFCREATE
+{
+ /* Surface data. */
+ struct
+ {
+ SVGA3dSurfaceAllFlags flags;
+ SVGA3dSurfaceFormat format;
+ unsigned usage;
+ SVGA3dSize size;
+ uint32_t numFaces;
+ uint32_t numMipLevels;
+ unsigned sampleCount;
+ SVGA3dMSPattern multisamplePattern;
+ SVGA3dMSQualityLevel qualityLevel;
+ } s;
+ uint32_t gmrid; /* In/Out: Backing GMR. */
+ uint32_t cbGB; /* Out: Size of backing memory. */
+ uint64_t u64UserAddress; /* Out: R3 mapping of the backing memory. */
+ uint32_t u32Sid; /* Out: Surface id. */
+} SVGAGBSURFCREATE, *PSVGAGBSURFCREATE;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !GA_INCLUDED_3D_WIN_VBoxGaTypes_h */
+