diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
commit | 16f504a9dca3fe3b70568f67b7d41241ae485288 (patch) | |
tree | c60f36ada0496ba928b7161059ba5ab1ab224f9d /src/VBox/Additions/3D/win | |
parent | Initial commit. (diff) | |
download | virtualbox-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')
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 */ + |