summaryrefslogtreecommitdiff
path: root/src/VBox/Additions/WINNT/Graphics/Video/mp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-03-26 19:21:20 +0000
committer <>2014-05-08 15:03:54 +0000
commitfb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch)
treec2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Additions/WINNT/Graphics/Video/mp
parent58ed4748338f9466599adfc8a9171280ed99e23f (diff)
downloadVirtualBox-master.tar.gz
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/Additions/WINNT/Graphics/Video/mp')
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/Makefile.kmk16
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.cpp2
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h11
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPDevExt.h67
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.cpp2
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.h2
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.cpp6
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.h10
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp636
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCm.cpp245
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCm.h8
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCr.cpp678
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCr.h212
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCrUtil.cpp5
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPMisc.cpp1088
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPMisc.h53
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPShgsmi.cpp2
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPShgsmi.h11
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPTypes.h36
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.cpp1121
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.h178
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVdma.cpp1257
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVdma.h47
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVhwa.cpp2
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVhwa.h2
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.cpp158
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.h7
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp3320
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.h114
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.rc2
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxVideoWddm.inf2
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPDriver.cpp46
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPIOCTL.cpp46
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPInternal.cpp5
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPInternal.h1
35 files changed, 5712 insertions, 3686 deletions
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/Makefile.kmk b/src/VBox/Additions/WINNT/Graphics/Video/mp/Makefile.kmk
index fa2e1fa4..9cffaf28 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/Makefile.kmk
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/Makefile.kmk
@@ -87,13 +87,9 @@ ifdef VBOX_WITH_WDDM
VBoxVideoWddm_DEFS += LOG_ENABLED
endif
VBoxVideoWddm_DEFS += LOG_TO_BACKDOOR
- ifdef VBOX_WITH_CROGL
- VBoxVideoWddm_DEFS += VBOX_WITH_CROGL
- endif
ifdef VBOX_VDMA_WITH_WATCHDOG
VBoxVideoWddm_DEFS += VBOX_VDMA_WITH_WATCHDOG
endif
-
VBoxVideoWddm_INCS += \
../../../include \
.. \
@@ -121,14 +117,18 @@ ifdef VBOX_WITH_WDDM
common/VBoxMPHGSMI.cpp \
common/VBoxMPVidModes.cpp \
$(PATH_ROOT)/src/VBox/Additions/common/VBoxVideo/HGSMIBase.cpp \
- $(PATH_ROOT)/src/VBox/Additions/common/VBoxVideo/Modesetting.cpp
- if defined(VBOX_WITH_CROGL) && defined(VBOX_WDDM_WITH_CRCMD)
+ $(PATH_ROOT)/src/VBox/Additions/common/VBoxVideo/VBVABase.cpp \
+ $(PATH_ROOT)/src/VBox/Additions/common/VBoxVideo/Modesetting.cpp \
+ $(PATH_ROOT)/src/VBox/GuestHost/OpenGL/util/vreg.cpp
+ if defined(VBOX_WITH_CROGL)
VBoxVideoWddm_SOURCES += \
$(PATH_ROOT)/src/VBox/GuestHost/OpenGL/packer/pack_buffer.c \
$(PATH_ROOT)/src/VBox/GuestHost/OpenGL/packer/pack_bounds.c \
+ $(PATH_ROOT)/src/VBox/GuestHost/OpenGL/packer/pack_visibleregion.c \
+ $(PATH_ROOT)/src/VBox/GuestHost/OpenGL/packer/pack_misc.c \
$(VBOX_PATH_CROGL_GENFILES)/pack_bounds_swap.c \
wddm/VBoxMPCrUtil.cpp
- VBoxVideoWddm_DEFS + VBOX_WDDM_WITH_CRCMD
+ VBoxVideoWddm_DEFS += VBOX_WITH_CROGL
endif
ifdef VBOXWDDM_WITH_VBVA
VBoxVideoWddm_SOURCES += \
@@ -172,7 +172,7 @@ ifdef VBOX_WITH_WDDM
$(PATH_SDK_$(VBOX_WINDDK_GST_W8)_LIB)/displib.lib \
$(PATH_SDK_$(VBOX_WINDDK_GST_W8)_LIB)/BufferOverflowK.lib
endif # VBOX_WITH_WDDM_W8
-
+
endif # VBOX_WITH_WDDM
#
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.cpp
index 7efb22a3..7ff0edcc 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h
index 406d2965..6fe20d93 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -29,22 +29,19 @@ typedef bool(*PFNVIDEOIRQSYNC)(void *);
bool VBoxMPCmnSyncToVideoIRQ(PVBOXMP_COMMON pCommon, PFNVIDEOIRQSYNC pfnSync, void *pvUser);
/* Video modes related */
-#define VBOXMP_MAX_VIDEO_MODES 128
void VBoxMPCmnInitCustomVideoModes(PVBOXMP_DEVEXT pExt);
VIDEO_MODE_INFORMATION* VBoxMPCmnGetCustomVideoModeInfo(ULONG ulIndex);
-VIDEO_MODE_INFORMATION* VBoxMPCmnGetVideoModeInfo(ULONG ulIndex);
#ifdef VBOX_XPDM_MINIPORT
+VIDEO_MODE_INFORMATION* VBoxMPCmnGetVideoModeInfo(PVBOXMP_DEVEXT pExt, ULONG ulIndex);
VIDEO_MODE_INFORMATION* VBoxMPXpdmCurrentVideoMode(PVBOXMP_DEVEXT pExt);
-ULONG VBoxMPXpdmGetVideoModesCount();
+ULONG VBoxMPXpdmGetVideoModesCount(PVBOXMP_DEVEXT pExt);
void VBoxMPXpdmBuildVideoModesTable(PVBOXMP_DEVEXT pExt);
#endif
#ifdef VBOX_WDDM_MINIPORT
-void VBoxWddmInvalidateAllVideoModesInfos(PVBOXMP_DEVEXT pExt);
-void VBoxWddmInvalidateVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId);
PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask);
-PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateAllVideoModesInfos(PVBOXMP_DEVEXT pExt);
+void VBoxWddmInitVideoModes(PVBOXMP_DEVEXT pExt);
NTSTATUS VBoxWddmGetModesForResolution(VIDEO_MODE_INFORMATION *pAllModes, uint32_t cAllModes, int iSearchPreferredMode,
const D3DKMDT_2DREGION *pResolution, VIDEO_MODE_INFORMATION * pModes,
uint32_t cModes, uint32_t *pcModes, int32_t *piPreferrableMode);
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPDevExt.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPDevExt.h
index 965cb528..e61818fe 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPDevExt.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPDevExt.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -30,9 +30,13 @@
#endif
#ifdef VBOX_WDDM_MINIPORT
+# ifdef VBOX_WDDM_WIN8
+extern DWORD g_VBoxDisplayOnly;
+# endif
# include "wddm/VBoxMPTypes.h"
#endif
+#define VBOXMP_MAX_VIDEO_MODES 128
typedef struct VBOXMP_COMMON
{
int cDisplays; /* Number of displays. */
@@ -60,6 +64,8 @@ typedef struct VBOXMP_COMMON
HGSMIHOSTCOMMANDCONTEXT hostCtx;
/** Context information needed to submit commands to the host. */
HGSMIGUESTCOMMANDCONTEXT guestCtx;
+
+ BOOLEAN fAnyX; /* Unrestricted horizontal resolution flag. */
} VBOXMP_COMMON, *PVBOXMP_COMMON;
typedef struct _VBOXMP_DEVEXT
@@ -71,7 +77,13 @@ typedef struct _VBOXMP_DEVEXT
struct _VBOXMP_DEVEXT *pPrimary; /* Pointer to the primary device extension. */
ULONG iDevice; /* Device index: 0 for primary, otherwise a secondary device. */
-
+ /* Standart video modes list.
+ * Additional space is reserved for a custom video mode for this guest monitor.
+ * The custom video mode index is alternating for each mode set and 2 indexes are needed for the custom mode.
+ */
+ VIDEO_MODE_INFORMATION aVideoModes[VBOXMP_MAX_VIDEO_MODES + 2];
+ /* Number of available video modes, set by VBoxMPCmnBuildVideoModesTable. */
+ uint32_t cVideoModes;
ULONG CurrentMode; /* Saved information about video modes */
ULONG CurrentModeWidth;
ULONG CurrentModeHeight;
@@ -79,6 +91,11 @@ typedef struct _VBOXMP_DEVEXT
ULONG ulFrameBufferOffset; /* The framebuffer position in the VRAM. */
ULONG ulFrameBufferSize; /* The size of the current framebuffer. */
+
+ uint8_t iInvocationCounter;
+ uint32_t Prev_xres;
+ uint32_t Prev_yres;
+ uint32_t Prev_bpp;
#endif /*VBOX_XPDM_MINIPORT*/
#ifdef VBOX_WDDM_MINIPORT
@@ -89,22 +106,37 @@ typedef struct _VBOXMP_DEVEXT
uint8_t * pvVisibleVram;
VBOXVIDEOCM_MGR CmMgr;
+ VBOXVIDEOCM_MGR SeamlessCtxMgr;
/* hgsmi allocation manager */
VBOXVIDEOCM_ALLOC_MGR AllocMgr;
VBOXVDMADDI_NODE aNodes[VBOXWDDM_NUM_NODES];
LIST_ENTRY DpcCmdQueue;
LIST_ENTRY SwapchainList3D;
/* mutex for context list operations */
- FAST_MUTEX ContextMutex;
+ KSPIN_LOCK ContextLock;
KSPIN_LOCK SynchLock;
volatile uint32_t cContexts3D;
volatile uint32_t cContexts2D;
+ volatile uint32_t cContextsDispIfResize;
volatile uint32_t cRenderFromShadowDisabledContexts;
volatile uint32_t cUnlockedVBVADisabled;
+
+ volatile uint32_t fCompletingCommands;
+
+ DWORD dwDrvCfgFlags;
/* this is examined and swicthed by DxgkDdiSubmitCommand only! */
volatile BOOLEAN fRenderToShadowDisabled;
+ BOOLEAN f3DEnabled;
+ BOOLEAN fTexPresentEnabled;
+ BOOLEAN fCmdVbvaEnabled;
+
+ uint32_t u32CrConDefaultClientID;
+
+ VBOXCMDVBVA CmdVbva;
+
VBOXMP_CRCTLCON CrCtlCon;
+ VBOXMP_CRSHGSMITRANSPORT CrHgsmiTransport;
VBOXWDDM_GLOBAL_POINTER_INFO PointerInfo;
@@ -119,7 +151,9 @@ typedef struct _VBOXMP_DEVEXT
PKTHREAD pWdThread;
KEVENT WdEvent;
#endif
-
+ BOOL bVSyncTimerEnabled;
+ volatile uint32_t fVSyncInVBlank;
+ volatile LARGE_INTEGER VSyncTime;
KTIMER VSyncTimer;
KDPC VSyncDpc;
@@ -166,7 +200,6 @@ typedef struct _VBOXMP_DEVEXT
} u;
HGSMIAREA areaDisplay; /* Entire VRAM chunk for this display device. */
- BOOLEAN fAnyX; /* Unrestricted horizontal resolution flag. */
} VBOXMP_DEVEXT, *PVBOXMP_DEVEXT;
DECLINLINE(PVBOXMP_DEVEXT) VBoxCommonToPrimaryExt(PVBOXMP_COMMON pCommon)
@@ -186,21 +219,21 @@ DECLINLINE(PVBOXMP_COMMON) VBoxCommonFromDeviceExt(PVBOXMP_DEVEXT pExt)
#ifdef VBOX_WDDM_MINIPORT
DECLINLINE(ULONG) vboxWddmVramCpuVisibleSize(PVBOXMP_DEVEXT pDevExt)
{
-#ifdef VBOXWDDM_RENDER_FROM_SHADOW
- /* all memory layout info should be initialized */
- Assert(pDevExt->aSources[0].Vbva.offVBVA);
- /* page aligned */
- Assert(!(pDevExt->aSources[0].Vbva.offVBVA & 0xfff));
-
- return (ULONG)(pDevExt->aSources[0].Vbva.offVBVA & ~0xfffULL);
-#else
+ if (pDevExt->fCmdVbvaEnabled)
+ {
+ /* all memory layout info should be initialized */
+ Assert(pDevExt->CmdVbva.Vbva.offVRAMBuffer);
+ /* page aligned */
+ Assert(!(pDevExt->CmdVbva.Vbva.offVRAMBuffer & 0xfff));
+
+ return (ULONG)(pDevExt->CmdVbva.Vbva.offVRAMBuffer & ~0xfffULL);
+ }
/* all memory layout info should be initialized */
- Assert(pDevExt->u.primary.Vdma.CmdHeap.Heap.area.offBase);
+ Assert(pDevExt->aSources[0].Vbva.Vbva.offVRAMBuffer);
/* page aligned */
- Assert(!(pDevExt->u.primary.Vdma.CmdHeap.Heap.area.offBase & 0xfff));
+ Assert(!(pDevExt->aSources[0].Vbva.Vbva.offVRAMBuffer & 0xfff));
- return pDevExt->u.primary.Vdma.CmdHeap.Heap.area.offBase & ~0xfffUL;
-#endif
+ return (ULONG)(pDevExt->aSources[0].Vbva.Vbva.offVRAMBuffer & ~0xfffULL);
}
DECLINLINE(ULONG) vboxWddmVramCpuVisibleSegmentSize(PVBOXMP_DEVEXT pDevExt)
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.cpp
index 51f03f8f..608abafb 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.h
index a607463b..6dda2c7b 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.cpp
index d9d353e8..bc7c39d8 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -61,7 +61,9 @@ vboxWinVersion_t VBoxQueryWinVersion()
if(major == 6)
{
- if (minor == 2)
+ if (minor == 3)
+ s_WinVersion = WIN81;
+ else if (minor == 2)
s_WinVersion = WIN8;
else if (minor == 1)
s_WinVersion = WIN7;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.h
index 4e6512ca..85c711cb 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -27,6 +27,11 @@
#define LOG_GROUP LOG_GROUP_DRV_MINIPORT
#include <VBox/log.h>
#define VBOX_VIDEO_LOG_NAME "VBoxMP"
+#ifdef VBOX_WDDM_MINIPORT
+# ifndef VBOX_WDDM_MINIPORT_WITH_FLOW_LOGGING
+# define VBOX_VIDEO_LOGFLOW_LOGGER(_m) do {} while (0)
+# endif
+#endif
#include "common/VBoxVideoLog.h"
#include <iprt/err.h>
#include <iprt/assert.h>
@@ -88,7 +93,8 @@ typedef enum
WINXP = 3,
WINVISTA = 4,
WIN7 = 5,
- WIN8 = 6
+ WIN8 = 6,
+ WIN81 = 7
} vboxWinVersion_t;
RT_C_DECLS_BEGIN
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp
index 697ce0d3..445aea0d 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -23,22 +23,14 @@
extern "C" int __cdecl swprintf(wchar_t *, const wchar_t *, ...);
#endif
#include <wchar.h>
+#include <VBox/Hardware/VBoxVideoVBE.h>
#ifdef VBOX_WITH_WDDM
# define VBOX_WITHOUT_24BPP_MODES
#endif
/* Custom video modes which are being read from registry at driver startup. */
-static VIDEO_MODE_INFORMATION g_CustomVideoModes[64] = { 0 };
-
-/* Standart video modes list.
- * Additional space is reserved for custom video modes for 64 guest monitors.
- * The custom video mode index is alternating and 2 indexes are reserved for the last custom mode.
- */
-static VIDEO_MODE_INFORMATION g_VideoModes[VBOXMP_MAX_VIDEO_MODES + 64 + 2] = { 0 };
-
-/* Number of available video modes, set by VBoxMPCmnBuildVideoModesTable. */
-static uint32_t g_NumVideoModes = 0;
+static VIDEO_MODE_INFORMATION g_CustomVideoModes[VBOX_VIDEO_MAX_SCREENS] = { 0 };
static BOOLEAN
VBoxMPValidateVideoModeParamsGuest(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, uint32_t xres, uint32_t yres, uint32_t bpp)
@@ -209,10 +201,12 @@ VIDEO_MODE_INFORMATION *VBoxMPCmnGetCustomVideoModeInfo(ULONG ulIndex)
return (ulIndex<RT_ELEMENTS(g_CustomVideoModes)) ? &g_CustomVideoModes[ulIndex] : NULL;
}
-VIDEO_MODE_INFORMATION* VBoxMPCmnGetVideoModeInfo(ULONG ulIndex)
+#ifdef VBOX_XPDM_MINIPORT
+VIDEO_MODE_INFORMATION* VBoxMPCmnGetVideoModeInfo(PVBOXMP_DEVEXT pExt, ULONG ulIndex)
{
- return (ulIndex<RT_ELEMENTS(g_VideoModes)) ? &g_VideoModes[ulIndex] : NULL;
+ return (ulIndex<RT_ELEMENTS(pExt->aVideoModes)) ? &pExt->aVideoModes[ulIndex] : NULL;
}
+#endif
static bool VBoxMPVideoModesMatch(const PVIDEO_MODE_INFORMATION pMode1, const PVIDEO_MODE_INFORMATION pMode2)
{
@@ -351,9 +345,13 @@ VBoxMPFillModesTable(PVBOXMP_DEVEXT pExt, int iDisplay, PVIDEO_MODE_INFORMATION
* For small host display resolutions, host will dislike the mode 1024x768 and above
* if the framebuffer window requires scrolling to fit the guest resolution.
* So add 1024x768 resolution for win8 guest to allow user switch to it */
- (VBoxQueryWinVersion() != WIN8 || resolutionMatrix[resIndex].xRes != 1024 || resolutionMatrix[resIndex].yRes != 768) &&
+ ( (VBoxQueryWinVersion() != WIN8 && VBoxQueryWinVersion() != WIN81)
+ || resolutionMatrix[resIndex].xRes != 1024
+ || resolutionMatrix[resIndex].yRes != 768)
+ &&
#endif
- !VBoxLikesVideoMode(iDisplay, resolutionMatrix[resIndex].xRes, resolutionMatrix[resIndex].yRes - yOffset, bitsPerPixel))
+ !VBoxLikesVideoMode(iDisplay, resolutionMatrix[resIndex].xRes,
+ resolutionMatrix[resIndex].yRes - yOffset, bitsPerPixel))
{
/* host doesn't like this mode */
continue;
@@ -414,7 +412,7 @@ VBoxMPFillModesTable(PVBOXMP_DEVEXT pExt, int iDisplay, PVIDEO_MODE_INFORMATION
LOG(("got custom mode[%u]=%ux%u:%u", curKey, xres, yres, bpp));
/* round down width to be a multiple of 8 if necessary */
- if (!pExt->fAnyX)
+ if (!VBoxCommonFromDeviceExt(pExt)->fAnyX)
{
xres &= 0xFFF8;
}
@@ -491,14 +489,41 @@ static BOOLEAN VBoxMPIsStartingUp(PVBOXMP_DEVEXT pExt, uint32_t iDisplay)
{
#ifdef VBOX_XPDM_MINIPORT
return (pExt->CurrentMode == 0);
-#elif defined(VBOX_WDDM_WIN8)
- return FALSE;
-#else /* VBOX_WDDM_MINIPORT && !VBOX_WDDM_MINIPORT */
- return (!VBoxCommonFromDeviceExt(pExt)->cDisplays
- || !pExt->aSources[iDisplay].pPrimaryAllocation);
+#else
+ VBOXWDDM_SOURCE *pSource = &pExt->aSources[iDisplay];
+ return !pSource->AllocData.SurfDesc.width || !pSource->AllocData.SurfDesc.height;
+#endif
+}
+
+#ifdef VBOX_WDDM_MINIPORT
+static const uint32_t g_aVBoxVidModesSupportedBpps[] = {
+ 32
+#ifndef VBOX_WITHOUT_24BPP_MODES
+ , 24
+#endif
+ , 16
+#ifdef VBOX_WITH_8BPP_MODES
+ , 8
#endif
+};
+DECLINLINE(BOOLEAN) VBoxMPIsSupportedBpp(uint32_t bpp)
+{
+ for (int i = 0; i < RT_ELEMENTS(g_aVBoxVidModesSupportedBpps); ++i)
+ {
+ if (bpp == g_aVBoxVidModesSupportedBpps[i])
+ return TRUE;
+ }
+ return FALSE;
}
+DECLINLINE(uint32_t) VBoxMPAdjustBpp(uint32_t bpp)
+{
+ if (VBoxMPIsSupportedBpp(bpp))
+ return bpp;
+ Assert(g_aVBoxVidModesSupportedBpps[0] == 32);
+ return g_aVBoxVidModesSupportedBpps[0];
+}
+#endif
/* Updates missing video mode params with current values,
* Checks if resulting mode is liked by the host and fits into VRAM.
* Returns TRUE if resulting mode could be used.
@@ -527,12 +552,19 @@ VBoxMPValidateVideoModeParams(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, uint32_t &
: &pExt->aSources[iDisplay].AllocData;
xres = xres ? xres:pAllocData->SurfDesc.width;
yres = yres ? yres:pAllocData->SurfDesc.height;
- bpp = bpp ? bpp :pAllocData->SurfDesc.bpp;
+ /* VBox WDDM driver does not allow 24 modes since OS could choose the 24bit mode as default in that case,
+ * the pExt->aSources[iDisplay].AllocData.SurfDesc.bpp could be initially 24 though,
+ * i.e. when driver occurs the current mode on driver load via DxgkCbAcquirePostDisplayOwnership
+ * and until driver reports the supported modes
+ * This is true for Win8 Display-Only driver currently since DxgkCbAcquirePostDisplayOwnership is only used by it
+ *
+ * This is why we need to adjust the current mode bpp to the value we actually report as supported */
+ bpp = bpp ? bpp : VBoxMPAdjustBpp(pAllocData->SurfDesc.bpp);
#endif
}
/* Round down width to be a multiple of 8 if necessary */
- if (!pExt->fAnyX)
+ if (!VBoxCommonFromDeviceExt(pExt)->fAnyX)
{
xres &= 0xFFF8;
}
@@ -544,12 +576,15 @@ VBoxMPValidateVideoModeParams(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, uint32_t &
}
if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, xres, yres, bpp))
+ {
+ WARN(("GUEST does not like special mode %dx%d:%d for display %d", xres, yres, bpp, iDisplay));
return FALSE;
+ }
/* Check if host likes this mode */
if (!VBoxLikesVideoMode(iDisplay, xres, yres, bpp))
{
- WARN_NOBP(("host does not like special mode %dx%d:%d for display %d", xres, yres, bpp, iDisplay));
+ WARN_NOBP(("HOST does not like special mode %dx%d:%d for display %d", xres, yres, bpp, iDisplay));
return FALSE;
}
@@ -557,8 +592,14 @@ VBoxMPValidateVideoModeParams(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, uint32_t &
ULONG vramSize = pExt->pPrimary->u.primary.ulMaxFrameBufferSize;
#else
ULONG vramSize = vboxWddmVramCpuVisibleSegmentSize(pExt);
- /* at least two surfaces will be needed: primary & shadow */
- vramSize /= 2 * pExt->u.primary.commonInfo.cDisplays;
+ vramSize /= pExt->u.primary.commonInfo.cDisplays;
+# ifdef VBOX_WDDM_WIN8
+ if (!g_VBoxDisplayOnly)
+# endif
+ {
+ /* at least two surfaces will be needed: primary & shadow */
+ vramSize /= 2;
+ }
#endif
/* Check that values are valid and mode fits into VRAM */
@@ -609,11 +650,13 @@ VBoxMPCheckPendingVideoMode(PVBOXMP_DEVEXT pExt, PVIDEO_MODE_INFORMATION pPendin
if (display>RT_ELEMENTS(g_CustomVideoModes))
{
/*display = RT_ELEMENTS(g_CustomVideoModes) - 1;*/
+ WARN(("VBoxQueryDisplayRequest returned invalid display number %d", display));
return FALSE;
}
}
else
{
+ LOG(("no pending request"));
return FALSE;
}
@@ -667,12 +710,12 @@ static void VBoxMPRegSaveModeInfo(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, PVIDEO
#ifdef VBOX_XPDM_MINIPORT
VIDEO_MODE_INFORMATION* VBoxMPXpdmCurrentVideoMode(PVBOXMP_DEVEXT pExt)
{
- return VBoxMPCmnGetVideoModeInfo(pExt->CurrentMode - 1);
+ return VBoxMPCmnGetVideoModeInfo(pExt, pExt->CurrentMode - 1);
}
-ULONG VBoxMPXpdmGetVideoModesCount()
+ULONG VBoxMPXpdmGetVideoModesCount(PVBOXMP_DEVEXT pExt)
{
- return g_NumVideoModes;
+ return pExt->cVideoModes;
}
/* Makes a table of video modes consisting of:
@@ -683,85 +726,86 @@ ULONG VBoxMPXpdmGetVideoModesCount()
*/
void VBoxMPXpdmBuildVideoModesTable(PVBOXMP_DEVEXT pExt)
{
- uint32_t cStandartModes, cCustomModes;
+ uint32_t cStandartModes;
BOOLEAN bPending, bHaveSpecial;
VIDEO_MODE_INFORMATION specialMode;
- /* Fill table with standart modes and ones manually added to registry */
- cStandartModes = VBoxMPFillModesTable(pExt, pExt->iDevice, g_VideoModes, RT_ELEMENTS(g_VideoModes), NULL);
+ /* Fill table with standart modes and ones manually added to registry.
+ * Up to VBOXMP_MAX_VIDEO_MODES elements can be used, the rest is reserved
+ * for custom mode alternating indexes.
+ */
+ cStandartModes = VBoxMPFillModesTable(pExt, pExt->iDevice, pExt->aVideoModes, VBOXMP_MAX_VIDEO_MODES, NULL);
- /* Add custom modes for all displays to the table */
- cCustomModes = VBoxCommonFromDeviceExt(pExt)->cDisplays;
- for (uint32_t i=0; i<cCustomModes; i++)
- {
- memcpy(&g_VideoModes[cStandartModes+i], &g_CustomVideoModes[i], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[cStandartModes+i].ModeIndex = cStandartModes+i+1;
- }
+ /* Add custom mode for this display to the table */
+ /* Make 2 entries in the video mode table. */
+ uint32_t iModeBase = cStandartModes;
+
+ /* Take the alternating index into account. */
+ BOOLEAN bAlternativeIndex = (pExt->iInvocationCounter % 2)? TRUE: FALSE;
+
+ uint32_t iSpecialMode = iModeBase + (bAlternativeIndex? 1: 0);
+ uint32_t iStandardMode = iModeBase + (bAlternativeIndex? 0: 1);
+
+ /* Fill the special mode. */
+ memcpy(&pExt->aVideoModes[iSpecialMode], &g_CustomVideoModes[pExt->iDevice], sizeof(VIDEO_MODE_INFORMATION));
+ pExt->aVideoModes[iSpecialMode].ModeIndex = iSpecialMode + 1;
+
+ /* Wipe the other entry so it is not selected. */
+ memcpy(&pExt->aVideoModes[iStandardMode], &pExt->aVideoModes[3], sizeof(VIDEO_MODE_INFORMATION));
+ pExt->aVideoModes[iStandardMode].ModeIndex = iStandardMode + 1;
+
+ LOG(("added special mode[%d] %dx%d:%d for display %d\n",
+ iSpecialMode,
+ pExt->aVideoModes[iSpecialMode].VisScreenWidth,
+ pExt->aVideoModes[iSpecialMode].VisScreenHeight,
+ pExt->aVideoModes[iSpecialMode].BitsPerPlane,
+ pExt->iDevice));
/* Check if host wants us to switch video mode and it's for this adapter */
bPending = VBoxMPCheckPendingVideoMode(pExt, &specialMode);
bHaveSpecial = bPending && (pExt->iDevice == specialMode.ModeIndex);
+ LOG(("bPending %d, pExt->iDevice %d, specialMode.ModeIndex %d",
+ bPending, pExt->iDevice, specialMode.ModeIndex));
/* Check the startup case */
if (!bHaveSpecial && VBoxMPIsStartingUp(pExt, pExt->iDevice))
{
uint32_t xres=0, yres=0, bpp=0;
+ LOG(("Startup for screen %d", pExt->iDevice));
/* Check if we could make valid mode from values stored to registry */
if (VBoxMPValidateVideoModeParams(pExt, pExt->iDevice, xres, yres, bpp))
{
+ LOG(("Startup for screen %d validated %dx%d %d", pExt->iDevice, xres, yres, bpp));
VBoxFillVidModeInfo(&specialMode, xres, yres, bpp, 0, 0);
bHaveSpecial = TRUE;
}
}
- /* Update number of modes */
- g_NumVideoModes = cStandartModes + cCustomModes;
+ /* Update number of modes. Each display has 2 entries for alternating custom mode index. */
+ pExt->cVideoModes = cStandartModes + 2;
- if (!bHaveSpecial)
- {
- /* Just add 2 dummy modes to maintain table size. */
- memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
- g_NumVideoModes++;
- memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
- g_NumVideoModes++;
- }
- else
+ if (bHaveSpecial)
{
/* We need to alternate mode index entry for a pending mode change,
* else windows will ignore actual mode change call.
* Only alternate index if one of mode parameters changed and
* regardless of conditions always add 2 entries to the table.
*/
- static int s_InvocationCounter=0;
BOOLEAN bAlternativeIndex = FALSE;
- static uint32_t s_Prev_xres=0;
- static uint32_t s_Prev_yres=0;
- static uint32_t s_Prev_bpp=0;
- BOOLEAN bChanged = (s_Prev_xres!=specialMode.VisScreenWidth
- || s_Prev_yres!=specialMode.VisScreenHeight
- || s_Prev_bpp!=specialMode.BitsPerPlane);
- if (bChanged)
- {
- s_Prev_xres = specialMode.VisScreenWidth;
- s_Prev_yres = specialMode.VisScreenHeight;
- s_Prev_bpp = specialMode.BitsPerPlane;
- }
+ BOOLEAN bChanged = (pExt->Prev_xres!=specialMode.VisScreenWidth
+ || pExt->Prev_yres!=specialMode.VisScreenHeight
+ || pExt->Prev_bpp!=specialMode.BitsPerPlane);
- /* Make sure there's no other mode in the table with same parameters,
- * because we need windows to pick up a new video mode index otherwise
- * actual mode change wouldn't happen.
- */
- int iFoundIdx;
- uint32_t uiStart=0;
+ LOG(("prev %dx%dx%d, special %dx%dx%d",
+ pExt->Prev_xres, pExt->Prev_yres, pExt->Prev_bpp,
+ specialMode.VisScreenWidth, specialMode.VisScreenHeight, specialMode.BitsPerPlane));
- while (0 <= (iFoundIdx = VBoxMPFindVideoMode(&g_VideoModes[uiStart], g_NumVideoModes-uiStart, &specialMode)))
+ if (bChanged)
{
- memcpy(&g_VideoModes[uiStart+iFoundIdx], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[uiStart+iFoundIdx].ModeIndex = uiStart+iFoundIdx+1;
- uiStart += iFoundIdx+1;
+ pExt->Prev_xres = specialMode.VisScreenWidth;
+ pExt->Prev_yres = specialMode.VisScreenHeight;
+ pExt->Prev_bpp = specialMode.BitsPerPlane;
}
/* Check if we need to alternate the index */
@@ -769,46 +813,34 @@ void VBoxMPXpdmBuildVideoModesTable(PVBOXMP_DEVEXT pExt)
{
if (bChanged)
{
- s_InvocationCounter++;
+ pExt->iInvocationCounter++;
}
- if (s_InvocationCounter % 2)
+ if (pExt->iInvocationCounter % 2)
{
bAlternativeIndex = TRUE;
- memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
- ++g_NumVideoModes;
}
}
- LOG(("add special mode[%d] %dx%d:%d for display %d (bChanged=%d, bAlretnativeIndex=%d)",
- g_NumVideoModes, specialMode.VisScreenWidth, specialMode.VisScreenHeight, specialMode.BitsPerPlane,
+ uint32_t iSpecialModeElement = cStandartModes + (bAlternativeIndex? 1: 0);
+ uint32_t iSpecialModeElementOld = cStandartModes + (bAlternativeIndex? 0: 1);
+
+ LOG(("add special mode[%d] %dx%d:%d for display %d (bChanged=%d, bAlternativeIndex=%d)",
+ iSpecialModeElement, specialMode.VisScreenWidth, specialMode.VisScreenHeight, specialMode.BitsPerPlane,
pExt->iDevice, bChanged, bAlternativeIndex));
/* Add special mode to the table
* Note: Y offset isn't used for a host-supplied modes
*/
- specialMode.ModeIndex = g_NumVideoModes+1;
- memcpy(&g_VideoModes[g_NumVideoModes], &specialMode, sizeof(VIDEO_MODE_INFORMATION));
- ++g_NumVideoModes;
+ specialMode.ModeIndex = iSpecialModeElement + 1;
+ memcpy(&pExt->aVideoModes[iSpecialModeElement], &specialMode, sizeof(VIDEO_MODE_INFORMATION));
/* Save special mode in the custom modes table */
memcpy(&g_CustomVideoModes[pExt->iDevice], &specialMode, sizeof(VIDEO_MODE_INFORMATION));
-
- /* Make sure we've added 2nd mode if necessary to maintain table size */
- if (VBoxMPIsStartingUp(pExt, pExt->iDevice))
- {
- memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[g_NumVideoModes-1], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
- ++g_NumVideoModes;
- }
- else if (!bAlternativeIndex)
- {
- memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
- ++g_NumVideoModes;
- }
+ /* Wipe the old entry so the special mode will be found in the new positions. */
+ memcpy(&pExt->aVideoModes[iSpecialModeElementOld], &pExt->aVideoModes[3], sizeof(VIDEO_MODE_INFORMATION));
+ pExt->aVideoModes[iSpecialModeElementOld].ModeIndex = iSpecialModeElementOld + 1;
/* Save special mode info to registry */
VBoxMPRegSaveModeInfo(pExt, pExt->iDevice, &specialMode);
@@ -817,13 +849,13 @@ void VBoxMPXpdmBuildVideoModesTable(PVBOXMP_DEVEXT pExt)
#if defined(LOG_ENABLED)
do
{
- LOG(("Filled %d modes", g_NumVideoModes));
+ LOG(("Filled %d modes for display %d", pExt->cVideoModes, pExt->iDevice));
- for (uint32_t i=0; i<g_NumVideoModes; ++i)
+ for (uint32_t i=0; i < pExt->cVideoModes; ++i)
{
LOG(("Mode[%2d]: %4dx%4d:%2d (idx=%d)",
- i, g_VideoModes[i].VisScreenWidth, g_VideoModes[i].VisScreenHeight,
- g_VideoModes[i].BitsPerPlane, g_VideoModes[i].ModeIndex));
+ i, pExt->aVideoModes[i].VisScreenWidth, pExt->aVideoModes[i].VisScreenHeight,
+ pExt->aVideoModes[i].BitsPerPlane, pExt->aVideoModes[i].ModeIndex));
}
} while (0);
#endif
@@ -832,6 +864,7 @@ void VBoxMPXpdmBuildVideoModesTable(PVBOXMP_DEVEXT pExt)
#ifdef VBOX_WDDM_MINIPORT
static VBOXWDDM_VIDEOMODES_INFO g_aVBoxVideoModeInfos[VBOX_VIDEO_MAX_SCREENS] = {0};
+static VBOXWDDM_VIDEOMODES_INFO g_VBoxVideoModeTmp;
bool VBoxWddmFillMode(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, VIDEO_MODE_INFORMATION *pInfo, D3DDDIFORMAT enmFormat, ULONG w, ULONG h)
{
@@ -886,6 +919,7 @@ VBoxWddmBuildResolutionTable(PVIDEO_MODE_INFORMATION pModesTable, size_t tableSi
uint32_t cResolutions = 0;
*piPreferredResolution = -1;
+ *pcResolutions = 0;
for (uint32_t i=0; i<tableSize; ++i)
{
@@ -935,6 +969,7 @@ static void VBoxWddmBuildResolutionTableForModes(PVBOXWDDM_VIDEOMODES_INFO pMode
(SIZE*)((void*)pModes->aResolutions), &pModes->cResolutions, &pModes->iPreferredResolution);
Assert(pModes->aResolutions[pModes->iPreferredResolution].cx == pModes->aModes[pModes->iPreferredMode].VisScreenWidth
&& pModes->aResolutions[pModes->iPreferredResolution].cy == pModes->aModes[pModes->iPreferredMode].VisScreenHeight);
+ Assert(pModes->cModes >= pModes->cResolutions);
}
AssertCompile(sizeof (SIZE) == sizeof (D3DKMDT_2DREGION));
@@ -951,6 +986,74 @@ VBoxWddmBuildVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID
pModes->cModes = VBoxMPFillModesTable(pExt, VidPnTargetId, pModes->aModes, RT_ELEMENTS(pModes->aModes), &pModes->iPreferredMode);
Assert(pModes->cModes<=RT_ELEMENTS(pModes->aModes));
+ if (!VBoxMPIsStartingUp(pExt, VidPnTargetId))
+ {
+ /* make sure we keep the current mode to avoid mode flickering */
+ PVBOXWDDM_ALLOC_DATA pAllocData = pExt->aSources[VidPnTargetId].pPrimaryAllocation ?
+ &pExt->aSources[VidPnTargetId].pPrimaryAllocation->AllocData
+ : &pExt->aSources[VidPnTargetId].AllocData;
+ if (pModes->cModes < RT_ELEMENTS(pModes->aModes))
+ {
+ /* VBox WDDM driver does not allow 24 modes since OS could choose the 24bit mode as default in that case,
+ * the pExt->aSources[iDisplay].AllocData.SurfDesc.bpp could be initially 24 though,
+ * i.e. when driver occurs the current mode on driver load via DxgkCbAcquirePostDisplayOwnership
+ * and until driver reports the supported modes
+ * This is true for Win8 Display-Only driver currently since DxgkCbAcquirePostDisplayOwnership is only used by it
+ *
+ * This is why we check the bpp to be supported here and add the current mode to the list only in that case */
+ if (VBoxMPIsSupportedBpp(pAllocData->SurfDesc.bpp))
+ {
+ int foundIdx;
+ VBoxFillVidModeInfo(&pModes->aModes[pModes->cModes], pAllocData->SurfDesc.width, pAllocData->SurfDesc.height, pAllocData->SurfDesc.bpp, 1/*index*/, 0);
+ if ((foundIdx=VBoxMPFindVideoMode(pModes->aModes, pModes->cModes, &pModes->aModes[pModes->cModes]))>=0)
+ {
+ pModes->iPreferredMode = foundIdx;
+ }
+ else
+ {
+ pModes->iPreferredMode = pModes->cModes;
+ ++pModes->cModes;
+ }
+
+#ifdef VBOX_WITH_8BPP_MODES
+ int bytesPerPixel=1;
+#else
+ int bytesPerPixel=2;
+#endif
+ for (; bytesPerPixel<=4; bytesPerPixel++)
+ {
+ int bpp = 8*bytesPerPixel;
+
+ if (bpp == pAllocData->SurfDesc.bpp)
+ continue;
+
+ if (!VBoxMPValidateVideoModeParamsGuest(pExt, VidPnTargetId,
+ pAllocData->SurfDesc.width, pAllocData->SurfDesc.height,
+ bpp))
+ continue;
+
+ if (pModes->cModes >= RT_ELEMENTS(pModes->aModes))
+ {
+ WARN(("ran out of video modes 2"));
+ break;
+ }
+
+ VBoxFillVidModeInfo(&pModes->aModes[pModes->cModes],
+ pAllocData->SurfDesc.width, pAllocData->SurfDesc.height,
+ bpp, pModes->cModes, 0);
+ if (VBoxMPFindVideoMode(pModes->aModes, pModes->cModes, &pModes->aModes[pModes->cModes]) < 0)
+ {
+ ++pModes->cModes;
+ }
+ }
+ }
+ }
+ else
+ {
+ WARN(("ran out of video modes 1"));
+ }
+ }
+
/* Check if there's a pending display change request for this adapter */
VIDEO_MODE_INFORMATION specialMode;
if (VBoxMPCheckPendingVideoMode(pExt, &specialMode) && (specialMode.ModeIndex==VidPnTargetId))
@@ -1064,7 +1167,7 @@ VBoxWddmBuildVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID
AssertRelease(RT_ELEMENTS(pModes->aModes) > pModes->cModes); /* if not - the driver state is screwed up, @todo: better do KeBugCheckEx here */
- if (!pExt->fAnyX)
+ if (!VBoxCommonFromDeviceExt(pExt)->fAnyX)
{
paAddlModes[i].VisScreenWidth &= 0xFFF8;
}
@@ -1089,49 +1192,276 @@ VBoxWddmBuildVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID
VBoxWddmBuildResolutionTableForModes(pModes);
}
-void VBoxWddmInvalidateVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
+static void VBoxWddmInitVideoMode(PVBOXMP_DEVEXT pExt, int i)
+{
+ VBoxWddmBuildVideoModesInfo(pExt, (D3DDDI_VIDEO_PRESENT_TARGET_ID)i, &g_aVBoxVideoModeInfos[i], NULL, 0);
+}
+
+void VBoxWddmInitVideoModes(PVBOXMP_DEVEXT pExt)
+{
+ for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
+ {
+ VBoxWddmInitVideoMode(pExt, i);
+ }
+}
+
+static NTSTATUS vboxWddmChildStatusReportPerform(PVBOXMP_DEVEXT pDevExt, PVBOXVDMA_CHILD_STATUS pChildStatus, D3DDDI_VIDEO_PRESENT_TARGET_ID iChild)
{
- if (VidPnTargetId != D3DDDI_ID_ALL)
+ DXGK_CHILD_STATUS DdiChildStatus;
+
+ Assert(iChild < UINT32_MAX/2);
+ Assert(iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
+
+ PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[iChild];
+
+ if ((pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_DISCONNECTED)
+ && pTarget->fConnected)
{
- if (VidPnTargetId >= RT_ELEMENTS(g_aVBoxVideoModeInfos))
+ /* report disconnected */
+ memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
+ DdiChildStatus.Type = StatusConnection;
+ DdiChildStatus.ChildUid = iChild;
+ DdiChildStatus.HotPlug.Connected = FALSE;
+
+ LOG(("Reporting DISCONNECT to child %d", DdiChildStatus.ChildUid));
+
+ NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
+ if (!NT_SUCCESS(Status))
{
- WARN(("VidPnTargetId (%d) must be less than (%d)", VidPnTargetId, RT_ELEMENTS(g_aVBoxVideoModeInfos)));
- return;
+ WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
+ return Status;
}
- g_aVBoxVideoModeInfos[VidPnTargetId].cModes = 0;
- return;
+ pTarget->fConnected = FALSE;
}
- for (UINT i = 0; i < RT_ELEMENTS(g_aVBoxVideoModeInfos); ++i)
+ if ((pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_CONNECTED)
+ && !pTarget->fConnected)
+ {
+ /* report disconnected */
+ memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
+ DdiChildStatus.Type = StatusConnection;
+ DdiChildStatus.ChildUid = iChild;
+ DdiChildStatus.HotPlug.Connected = TRUE;
+
+ LOG(("Reporting CONNECT to child %d", DdiChildStatus.ChildUid));
+
+ NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
+ return Status;
+ }
+ pTarget->fConnected = TRUE;
+ }
+
+ if (pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_ROTATED)
+ {
+ /* report disconnected */
+ memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
+ DdiChildStatus.Type = StatusRotation;
+ DdiChildStatus.ChildUid = iChild;
+ DdiChildStatus.Rotation.Angle = pChildStatus->u8RotationAngle;
+
+ LOG(("Reporting ROTATED to child %d", DdiChildStatus.ChildUid));
+
+ NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
+ return Status;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS vboxWddmChildStatusHandleRequest(PVBOXMP_DEVEXT pDevExt, VBOXVDMACMD_CHILD_STATUS_IRQ *pBody)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ for (UINT i = 0; i < pBody->cInfos; ++i)
{
- g_aVBoxVideoModeInfos[i].cModes = 0;
+ PVBOXVDMA_CHILD_STATUS pInfo = &pBody->aInfos[i];
+ if (pBody->fFlags & VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL)
+ {
+ for (D3DDDI_VIDEO_PRESENT_TARGET_ID iChild = 0; iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++iChild)
+ {
+ Status = vboxWddmChildStatusReportPerform(pDevExt, pInfo, iChild);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxWddmChildStatusReportPerform failed with Status (0x%x)", Status));
+ break;
+ }
+ }
+ }
+ else
+ {
+ Status = vboxWddmChildStatusReportPerform(pDevExt, pInfo, pInfo->iChild);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxWddmChildStatusReportPerform failed with Status (0x%x)", Status));
+ break;
+ }
+ }
}
+
+ return Status;
}
-void VBoxWddmInvalidateAllVideoModesInfos(PVBOXMP_DEVEXT pExt)
+#ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
+typedef struct VBOXWDDMCHILDSTATUSCB
{
- VBoxWddmInvalidateVideoModesInfo(pExt, D3DDDI_ID_ALL);
+ PVBOXVDMACBUF_DR pDr;
+ PKEVENT pEvent;
+} VBOXWDDMCHILDSTATUSCB, *PVBOXWDDMCHILDSTATUSCB;
+
+static DECLCALLBACK(VOID) vboxWddmChildStatusReportCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
+{
+ /* we should be called from our DPC routine */
+ Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ PVBOXWDDMCHILDSTATUSCB pCtx = (PVBOXWDDMCHILDSTATUSCB)pvContext;
+ PVBOXVDMACBUF_DR pDr = pCtx->pDr;
+ PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
+ VBOXVDMACMD_CHILD_STATUS_IRQ *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHILD_STATUS_IRQ);
+
+ vboxWddmChildStatusHandleRequest(pDevExt, pBody);
+
+ vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
+
+ if (pCtx->pEvent)
+ {
+ KeSetEvent(pCtx->pEvent, 0, FALSE);
+ }
}
+#endif
-PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask)
+static NTSTATUS vboxWddmChildStatusReportReconnected(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID idTarget)
{
- for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
+#ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(sizeof (VBOXVDMACMD_CHILD_STATUS_IRQ));
+
+ PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
+ if (pDr)
{
- if (ASMBitTest(pScreenIdMask, i))
- VBoxWddmInvalidateVideoModesInfo(pExt, i);
+ // vboxVdmaCBufDrCreate zero initializes the pDr
+ /* the command data follows the descriptor */
+ pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
+ pDr->cbBuf = cbCmd;
+ pDr->rc = VERR_NOT_IMPLEMENTED;
+
+ PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
+ pHdr->enmType = VBOXVDMACMD_TYPE_CHILD_STATUS_IRQ;
+ pHdr->u32CmdSpecific = 0;
+ PVBOXVDMACMD_CHILD_STATUS_IRQ pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHILD_STATUS_IRQ);
+ pBody->cInfos = 1;
+ if (idTarget == D3DDDI_ID_ALL)
+ {
+ pBody->fFlags |= VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL;
+ }
+ pBody->aInfos[0].iChild = idTarget;
+ pBody->aInfos[0].fFlags = VBOXVDMA_CHILD_STATUS_F_DISCONNECTED | VBOXVDMA_CHILD_STATUS_F_CONNECTED;
+ /* we're going to KeWaitForSingleObject */
+ Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
+
+ PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
+ VBOXWDDMCHILDSTATUSCB Ctx;
+ KEVENT Event;
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ Ctx.pDr = pDr;
+ Ctx.pEvent = &Event;
+ vboxVdmaDdiCmdInit(pDdiCmd, 0, 0, vboxWddmChildStatusReportCompletion, &Ctx);
+ /* mark command as submitted & invisible for the dx runtime since dx did not originate it */
+ vboxVdmaDdiCmdSubmittedNotDx(pDdiCmd);
+ int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
+ Assert(rc == VINF_SUCCESS);
+ if (RT_SUCCESS(rc))
+ {
+ Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Assert(Status == STATUS_SUCCESS);
+ return STATUS_SUCCESS;
+ }
+
+ Status = STATUS_UNSUCCESSFUL;
+
+ vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
+ }
+ else
+ {
+ /* @todo: try flushing.. */
+ WARN(("vboxVdmaCBufDrCreate returned NULL"));
+ Status = STATUS_INSUFFICIENT_RESOURCES;
}
- /* ensure we have all the rest populated */
- VBoxWddmGetAllVideoModesInfos(pExt);
- return g_aVBoxVideoModeInfos;
+ return Status;
+#else
+ VBOXVDMACMD_CHILD_STATUS_IRQ Body = {0};
+ Body.cInfos = 1;
+ if (idTarget == D3DDDI_ID_ALL)
+ {
+ Body.fFlags |= VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL;
+ }
+ Body.aInfos[0].iChild = idTarget;
+ Body.aInfos[0].fFlags = VBOXVDMA_CHILD_STATUS_F_DISCONNECTED | VBOXVDMA_CHILD_STATUS_F_CONNECTED;
+ Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ return vboxWddmChildStatusHandleRequest(pDevExt, &Body);
+#endif
}
-PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateAllVideoModesInfos(PVBOXMP_DEVEXT pExt)
+NTSTATUS vboxWddmChildStatusConnect(PVBOXMP_DEVEXT pDevExt, uint32_t iChild, BOOLEAN fConnect)
{
- VBoxWddmInvalidateAllVideoModesInfos(pExt);
+#ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
+# error "port me!"
+#else
+ Assert(iChild < (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
+ NTSTATUS Status = STATUS_SUCCESS;
+ VBOXVDMACMD_CHILD_STATUS_IRQ Body = {0};
+ Body.cInfos = 1;
+ Body.aInfos[0].iChild = iChild;
+ Body.aInfos[0].fFlags = fConnect ? VBOXVDMA_CHILD_STATUS_F_CONNECTED : VBOXVDMA_CHILD_STATUS_F_DISCONNECTED;
+ Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ Status = vboxWddmChildStatusHandleRequest(pDevExt, &Body);
+ if (!NT_SUCCESS(Status))
+ WARN(("vboxWddmChildStatusHandleRequest failed Status 0x%x", Status));
+
+ return Status;
+#endif
+}
+
+void VBoxWddmUpdateVideoMode(PVBOXMP_DEVEXT pExt, int i)
+{
+ g_VBoxVideoModeTmp = g_aVBoxVideoModeInfos[i];
+
+ Assert(g_aVBoxVideoModeInfos[i].cModes);
+
+ VBoxWddmInitVideoMode(pExt, i);
+
+ if (!memcmp(&g_VBoxVideoModeTmp, &g_aVBoxVideoModeInfos[i], sizeof (g_VBoxVideoModeTmp)))
+ return;
+
+#ifdef DEBUG_misha
+ g_VBoxDbgBreakModes = 0;
+#endif
+
+#ifdef DEBUG_misha
+ LOGREL(("modes changed for target %d", i));
+#else
+ LOG(("modes changed for target %d", i));
+#endif
+ vboxWddmChildStatusReportReconnected(pExt, (D3DDDI_VIDEO_PRESENT_TARGET_ID)i);
+}
+
+PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask)
+{
+ for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
+ {
+ if (!pScreenIdMask || ASMBitTest(pScreenIdMask, i))
+ {
+ VBoxWddmUpdateVideoMode(pExt, i);
+ }
+ }
- /* ensure we have all the rest populated */
- VBoxWddmGetAllVideoModesInfos(pExt);
return g_aVBoxVideoModeInfos;
}
@@ -1149,14 +1479,6 @@ void VBoxWddmAdjustMode(PVBOXMP_DEVEXT pExt, PVBOXWDDM_ADJUSTVIDEOMODE pMode)
PVBOXWDDM_TARGET pTarget = &pExt->aTargets[pMode->Mode.Id];
/* @todo: this info should go from the target actually */
PVBOXWDDM_SOURCE pSource = &pExt->aSources[pMode->Mode.Id];
- if (pTarget->HeightVisible /* <- active */
- && pSource->AllocData.SurfDesc.width == pMode->Mode.Width
- && pSource->AllocData.SurfDesc.height == pMode->Mode.Height
- && pSource->AllocData.SurfDesc.bpp == pMode->Mode.BitsPerPixel)
- {
- pMode->fFlags = VBOXWDDM_ADJUSTVIDEOMODE_F_CURRENT;
- return;
- }
UINT newWidth = pMode->Mode.Width;
UINT newHeight = pMode->Mode.Height;
@@ -1165,7 +1487,7 @@ void VBoxWddmAdjustMode(PVBOXMP_DEVEXT pExt, PVBOXWDDM_ADJUSTVIDEOMODE pMode)
if (!VBoxMPValidateVideoModeParams(pExt, pMode->Mode.Id, newWidth, newHeight, newBpp))
{
PVBOXWDDM_SOURCE pSource = &pExt->aSources[pMode->Mode.Id];
- pMode->fFlags = VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED;
+ pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED;
}
if (pMode->Mode.Width != newWidth
@@ -1186,8 +1508,7 @@ void VBoxWddmAdjustMode(PVBOXMP_DEVEXT pExt, PVBOXWDDM_ADJUSTVIDEOMODE pMode)
pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_CURRENT;
if (pMode->fFlags & VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED)
{
- WARN(("current mode is reported as unsupported, cleaning the unsupported flag"));
- pMode->fFlags &= ~VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED;
+ WARN(("current mode is reported as unsupported"));
}
}
}
@@ -1234,49 +1555,8 @@ NTSTATUS VBoxWddmGetModesForResolution(VIDEO_MODE_INFORMATION *pAllModes, uint32
return Status;
}
-static PVBOXWDDM_VIDEOMODES_INFO vboxWddmGetVideoModesInfoInternal(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
-{
- Assert(VidPnTargetId < (D3DDDI_VIDEO_PRESENT_TARGET_ID)VBoxCommonFromDeviceExt(pExt)->cDisplays);
- if (VidPnTargetId >= (D3DDDI_VIDEO_PRESENT_TARGET_ID)VBoxCommonFromDeviceExt(pExt)->cDisplays)
- {
- return NULL;
- }
-
- PVBOXWDDM_VIDEOMODES_INFO pInfo = &g_aVBoxVideoModeInfos[VidPnTargetId];
-
- if (!pInfo->cModes)
- {
- VBoxWddmBuildVideoModesInfo(pExt, VidPnTargetId, pInfo, NULL, 0);
- Assert(pInfo->cModes);
- }
-
- return pInfo;
-}
-
-static VOID vboxWddmAddVideoModes(PVBOXMP_DEVEXT pExt, PVBOXWDDM_VIDEOMODES_INFO pDstInfo, PVBOXWDDM_VIDEOMODES_INFO pSrcInfo)
-{
- for (int i = 0; i < (int)pSrcInfo->cModes; ++i)
- {
- int foundIdx = VBoxMPFindVideoMode(pDstInfo->aModes, pDstInfo->cModes, &pSrcInfo->aModes[i]);
- if (foundIdx >= 0)
- continue;
-
- Assert(0);
- pDstInfo->aModes[pDstInfo->cModes] = pSrcInfo->aModes[i];
- ++pDstInfo->cModes;
- }
-
- VBoxWddmBuildResolutionTableForModes(pDstInfo);
-}
-
PVBOXWDDM_VIDEOMODES_INFO VBoxWddmGetAllVideoModesInfos(PVBOXMP_DEVEXT pExt)
{
- /* ensure all modes are initialized */
- for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
- {
- vboxWddmGetVideoModesInfoInternal(pExt, (D3DDDI_VIDEO_PRESENT_TARGET_ID)i);
- }
-
return g_aVBoxVideoModeInfos;
}
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCm.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCm.cpp
index 7448c7b0..0335de34 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCm.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCm.cpp
@@ -71,7 +71,7 @@ typedef struct VBOXVIDEOCM_SESSION
/* event used to notify UMD about pending commands */
PKEVENT pUmEvent;
/* sync lock */
- FAST_MUTEX Mutex;
+ KSPIN_LOCK SynchLock;
/* indicates whether event signaling is needed on cmd add */
bool bEventNeeded;
} VBOXVIDEOCM_SESSION, *PVBOXVIDEOCM_SESSION;
@@ -180,8 +180,10 @@ static void vboxVideoCmCmdPostByHdr(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEOCM_
pHdr->CmdHdr.cbCmd = cbSize;
}
- Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
- ExAcquireFastMutex(&pSession->Mutex);
+ Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+
+ KIRQL OldIrql;
+ KeAcquireSpinLock(&pSession->SynchLock, &OldIrql);
InsertHeadList(&pSession->CommandsList, &pHdr->QueueList);
if (pSession->bEventNeeded)
@@ -190,7 +192,7 @@ static void vboxVideoCmCmdPostByHdr(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEOCM_
bSignalEvent = true;
}
- ExReleaseFastMutex(&pSession->Mutex);
+ KeReleaseSpinLock(&pSession->SynchLock, OldIrql);
if (bSignalEvent)
KeSetEvent(pSession->pUmEvent, 0, FALSE);
@@ -224,7 +226,8 @@ NTSTATUS vboxVideoCmCmdVisit(PVBOXVIDEOCM_CTX pContext, BOOLEAN bEntireSession,
PLIST_ENTRY pCurEntry = NULL;
PVBOXVIDEOCM_CMD_DR pHdr;
- ExAcquireFastMutex(&pSession->Mutex);
+ KIRQL OldIrql;
+ KeAcquireSpinLock(&pSession->SynchLock, &OldIrql);
pCurEntry = pSession->CommandsList.Blink;
do
@@ -259,7 +262,7 @@ NTSTATUS vboxVideoCmCmdVisit(PVBOXVIDEOCM_CTX pContext, BOOLEAN bEntireSession,
} while (1);
- ExReleaseFastMutex(&pSession->Mutex);
+ KeReleaseSpinLock(&pSession->SynchLock, OldIrql);
return STATUS_SUCCESS;
}
@@ -279,11 +282,20 @@ static void vboxVideoCmSessionCtxAddLocked(PVBOXVIDEOCM_SESSION pSession, PVBOXV
void vboxVideoCmSessionCtxAdd(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEOCM_CTX pContext)
{
- Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
- ExAcquireFastMutex(&pSession->Mutex);
+ Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ KIRQL OldIrql;
+ KeAcquireSpinLock(&pSession->SynchLock, &OldIrql);
+
vboxVideoCmSessionCtxAddLocked(pSession, pContext);
- ExReleaseFastMutex(&pSession->Mutex);
+ KeReleaseSpinLock(&pSession->SynchLock, OldIrql);
+}
+
+void vboxVideoCmSessionSignalEvent(PVBOXVIDEOCM_SESSION pSession)
+{
+ Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ if (pSession->pUmEvent)
+ KeSetEvent(pSession->pUmEvent, 0, FALSE);
}
static void vboxVideoCmSessionDestroyLocked(PVBOXVIDEOCM_SESSION pSession)
@@ -345,8 +357,10 @@ bool vboxVideoCmSessionCtxRemoveLocked(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEO
LIST_ENTRY *pCur;
InitializeListHead(&RemainedList);
InitializeListHead(&RemainedPpList);
- Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
- ExAcquireFastMutex(&pSession->Mutex);
+ Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ KIRQL OldIrql;
+ KeAcquireSpinLock(&pSession->SynchLock, &OldIrql);
+
pContext->pSession = NULL;
RemoveEntryList(&pContext->SessionEntry);
bDestroy = !!(IsListEmpty(&pSession->ContextList));
@@ -361,7 +375,8 @@ bool vboxVideoCmSessionCtxRemoveLocked(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEO
vboxVideoCmSessionCtxDetachCmdsLocked(&pSession->CommandsList, pContext, &RemainedList);
vboxVideoCmSessionCtxDetachCmdsLocked(&pSession->PpCommandsList, pContext, &RemainedPpList);
}
- ExReleaseFastMutex(&pSession->Mutex);
+
+ KeReleaseSpinLock(&pSession->SynchLock, OldIrql);
for (pCur = RemainedList.Flink; pCur != &RemainedList; pCur = RemainedList.Flink)
{
@@ -392,8 +407,8 @@ NTSTATUS vboxVideoCmSessionCreateLocked(PVBOXVIDEOCM_MGR pMgr, PVBOXVIDEOCM_SESS
InitializeListHead(&pSession->CommandsList);
InitializeListHead(&pSession->PpCommandsList);
pSession->pUmEvent = pUmEvent;
- Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
- ExInitializeFastMutex(&pSession->Mutex);
+ Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ KeInitializeSpinLock(&pSession->SynchLock);
pSession->bEventNeeded = true;
vboxVideoCmSessionCtxAddLocked(pSession, pContext);
InsertHeadList(&pMgr->SessionList, &pSession->QueueEntry);
@@ -420,44 +435,39 @@ NTSTATUS vboxVideoCmCtxAdd(PVBOXVIDEOCM_MGR pMgr, PVBOXVIDEOCM_CTX pContext, HAN
Assert(Status == STATUS_SUCCESS);
if (Status == STATUS_SUCCESS)
{
- Status = KeWaitForSingleObject(&pMgr->SynchEvent, Executive, KernelMode,
- FALSE, /* BOOLEAN Alertable */
- NULL /* PLARGE_INTEGER Timeout */
- );
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
+ KIRQL OldIrql;
+ KeAcquireSpinLock(&pMgr->SynchLock, &OldIrql);
+
+ bool bFound = false;
+ PVBOXVIDEOCM_SESSION pSession = NULL;
+ for (PLIST_ENTRY pEntry = pMgr->SessionList.Flink; pEntry != &pMgr->SessionList; pEntry = pEntry->Flink)
{
- bool bFound = false;
- PVBOXVIDEOCM_SESSION pSession = NULL;
- for (PLIST_ENTRY pEntry = pMgr->SessionList.Flink; pEntry != &pMgr->SessionList; pEntry = pEntry->Flink)
+ pSession = VBOXCMENTRY_2_SESSION(pEntry);
+ if (pSession->pUmEvent == pUmEvent)
{
- pSession = VBOXCMENTRY_2_SESSION(pEntry);
- if (pSession->pUmEvent == pUmEvent)
- {
- bFound = true;
- break;
- }
+ bFound = true;
+ break;
}
+ }
- pContext->u64UmData = u64UmData;
+ pContext->u64UmData = u64UmData;
- if (!bFound)
- {
- Status = vboxVideoCmSessionCreateLocked(pMgr, &pSession, pUmEvent, pContext);
- Assert(Status == STATUS_SUCCESS);
- }
- else
- {
- /* Status = */vboxVideoCmSessionCtxAdd(pSession, pContext);
- /*Assert(Status == STATUS_SUCCESS);*/
- }
- LONG tstL = KeSetEvent(&pMgr->SynchEvent, 0, FALSE);
- Assert(!tstL);
+ if (!bFound)
+ {
+ Status = vboxVideoCmSessionCreateLocked(pMgr, &pSession, pUmEvent, pContext);
+ Assert(Status == STATUS_SUCCESS);
+ }
+ else
+ {
+ /* Status = */vboxVideoCmSessionCtxAdd(pSession, pContext);
+ /*Assert(Status == STATUS_SUCCESS);*/
+ }
- if (Status == STATUS_SUCCESS)
- {
- return STATUS_SUCCESS;
- }
+ KeReleaseSpinLock(&pMgr->SynchLock, OldIrql);
+
+ if (Status == STATUS_SUCCESS)
+ {
+ return STATUS_SUCCESS;
}
ObDereferenceObject(pUmEvent);
@@ -471,24 +481,19 @@ NTSTATUS vboxVideoCmCtxRemove(PVBOXVIDEOCM_MGR pMgr, PVBOXVIDEOCM_CTX pContext)
if (!pSession)
return STATUS_SUCCESS;
- NTSTATUS Status = KeWaitForSingleObject(&pMgr->SynchEvent, Executive, KernelMode,
- FALSE, /* BOOLEAN Alertable */
- NULL /* PLARGE_INTEGER Timeout */
- );
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
- {
- vboxVideoCmSessionCtxRemoveLocked(pSession, pContext);
- LONG tstL = KeSetEvent(&pMgr->SynchEvent, 0, FALSE);
- Assert(!tstL);
- }
+ KIRQL OldIrql;
+ KeAcquireSpinLock(&pMgr->SynchLock, &OldIrql);
- return Status;
+ vboxVideoCmSessionCtxRemoveLocked(pSession, pContext);
+
+ KeReleaseSpinLock(&pMgr->SynchLock, OldIrql);
+
+ return STATUS_SUCCESS;
}
NTSTATUS vboxVideoCmInit(PVBOXVIDEOCM_MGR pMgr)
{
- KeInitializeEvent(&pMgr->SynchEvent, SynchronizationEvent, TRUE);
+ KeInitializeSpinLock(&pMgr->SynchLock);
InitializeListHead(&pMgr->SessionList);
return STATUS_SUCCESS;
}
@@ -499,6 +504,25 @@ NTSTATUS vboxVideoCmTerm(PVBOXVIDEOCM_MGR pMgr)
return STATUS_SUCCESS;
}
+NTSTATUS vboxVideoCmSignalEvents(PVBOXVIDEOCM_MGR pMgr)
+{
+ Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ PVBOXVIDEOCM_SESSION pSession = NULL;
+
+ KIRQL OldIrql;
+ KeAcquireSpinLock(&pMgr->SynchLock, &OldIrql);
+
+ for (PLIST_ENTRY pEntry = pMgr->SessionList.Flink; pEntry != &pMgr->SessionList; pEntry = pEntry->Flink)
+ {
+ pSession = VBOXCMENTRY_2_SESSION(pEntry);
+ vboxVideoCmSessionSignalEvent(pSession);
+ }
+
+ KeReleaseSpinLock(&pMgr->SynchLock, OldIrql);
+
+ return STATUS_SUCCESS;
+}
+
VOID vboxVideoCmProcessKm(PVBOXVIDEOCM_CTX pContext, PVBOXVIDEOCM_CMD_CTL_KM pCmd)
{
PVBOXVIDEOCM_SESSION pSession = pContext->pSession;
@@ -514,9 +538,10 @@ VOID vboxVideoCmProcessKm(PVBOXVIDEOCM_CTX pContext, PVBOXVIDEOCM_CMD_CTL_KM pCm
case VBOXVIDEOCM_CMD_CTL_KM_TYPE_POST_INVOKE:
{
PVBOXVIDEOCM_CMD_DR pHdr = VBOXVIDEOCM_HEAD(pCmd);
- ExAcquireFastMutex(&pSession->Mutex);
+ KIRQL OldIrql;
+ KeAcquireSpinLock(&pSession->SynchLock, &OldIrql);
InsertTailList(&pSession->PpCommandsList, &pHdr->QueueList);
- ExReleaseFastMutex(&pSession->Mutex);
+ KeReleaseSpinLock(&pSession->SynchLock, OldIrql);
break;
}
@@ -549,8 +574,9 @@ NTSTATUS vboxVideoCmEscape(PVBOXVIDEOCM_CTX pContext, PVBOXDISPIFESCAPE_GETVBOXV
InitializeListHead(&DetachedPpList);
// PVBOXWDDM_GETVBOXVIDEOCMCMD_HDR *pvCmd
- Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
- ExAcquireFastMutex(&pSession->Mutex);
+ Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ KIRQL OldIrql;
+ KeAcquireSpinLock(&pSession->SynchLock, &OldIrql);
vboxVideoCmSessionCtxDetachCmdsLocked(&pSession->PpCommandsList, pContext, &DetachedPpList);
@@ -605,7 +631,7 @@ NTSTATUS vboxVideoCmEscape(PVBOXVIDEOCM_CTX pContext, PVBOXDISPIFESCAPE_GETVBOXV
}
} while (1);
- ExReleaseFastMutex(&pSession->Mutex);
+ KeReleaseSpinLock(&pSession->SynchLock, OldIrql);
vboxVideoCmSessionCtxPpList(pContext, &DetachedPpList);
@@ -646,103 +672,22 @@ NTSTATUS vboxVideoCmEscape(PVBOXVIDEOCM_CTX pContext, PVBOXDISPIFESCAPE_GETVBOXV
return STATUS_SUCCESS;
}
-VOID vboxVideoCmLock(PVBOXVIDEOCM_CTX pContext)
-{
- ExAcquireFastMutex(&pContext->pSession->Mutex);
-}
-
-VOID vboxVideoCmUnlock(PVBOXVIDEOCM_CTX pContext)
-{
- ExReleaseFastMutex(&pContext->pSession->Mutex);
-}
-
static BOOLEAN vboxVideoCmHasUncompletedCmdsLocked(PVBOXVIDEOCM_MGR pMgr)
{
PVBOXVIDEOCM_SESSION pSession = NULL;
for (PLIST_ENTRY pEntry = pMgr->SessionList.Flink; pEntry != &pMgr->SessionList; pEntry = pEntry->Flink)
{
pSession = VBOXCMENTRY_2_SESSION(pEntry);
- ExAcquireFastMutex(&pSession->Mutex);
+ KIRQL OldIrql;
+ KeAcquireSpinLock(&pSession->SynchLock, &OldIrql);
+
if (pSession->bEventNeeded)
{
/* commands still being processed */
- ExReleaseFastMutex(&pSession->Mutex);
+ KeReleaseSpinLock(&pSession->SynchLock, OldIrql);
return TRUE;
}
- ExReleaseFastMutex(&pSession->Mutex);
+ KeReleaseSpinLock(&pSession->SynchLock, OldIrql);
}
return FALSE;
}
-
-/* waits for all outstanding commands to completed by client
- * assumptions here are:
- * 1. no new commands are submitted while we are waiting
- * 2. it is assumed that a client completes all previously received commands
- * once it queries for the new set of commands */
-NTSTATUS vboxVideoCmWaitCompletedCmds(PVBOXVIDEOCM_MGR pMgr, uint32_t msTimeout)
-{
- LARGE_INTEGER Timeout;
- PLARGE_INTEGER pTimeout;
- uint32_t cIters;
-
- if (msTimeout != RT_INDEFINITE_WAIT)
- {
- uint32_t msIter = 2;
- cIters = msTimeout/msIter;
- if (!cIters)
- {
- msIter = msTimeout;
- cIters = 1;
- }
- Timeout.QuadPart = -(int64_t) msIter /* ms */ * 10000;
- pTimeout = &Timeout;
- }
- else
- {
- pTimeout = NULL;
- cIters = 1;
- }
-
- Assert(cIters);
- do
- {
- NTSTATUS Status = KeWaitForSingleObject(&pMgr->SynchEvent, Executive, KernelMode,
- FALSE, /* BOOLEAN Alertable */
- pTimeout /* PLARGE_INTEGER Timeout */
- );
- if (Status == STATUS_TIMEOUT)
- {
- --cIters;
- }
- else
- {
- if (!NT_SUCCESS(Status))
- {
- WARN(("KeWaitForSingleObject failed with Status (0x%x)", Status));
- return Status;
- }
-
- /* succeeded */
- if (!vboxVideoCmHasUncompletedCmdsLocked(pMgr))
- {
- LONG tstL = KeSetEvent(&pMgr->SynchEvent, 0, FALSE);
- Assert(!tstL);
- return STATUS_SUCCESS;
- }
-
- LONG tstL = KeSetEvent(&pMgr->SynchEvent, 0, FALSE);
- Assert(!tstL);
- }
-
- if (!cIters)
- break;
-
- KeDelayExecutionThread(KernelMode, FALSE, pTimeout);
- --cIters;
- if (!cIters)
- break;
- } while (0);
-
- return STATUS_TIMEOUT;
-}
-
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCm.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCm.h
index fcf94bb9..21be672c 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCm.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCm.h
@@ -21,7 +21,7 @@
typedef struct VBOXVIDEOCM_MGR
{
- KEVENT SynchEvent;
+ KSPIN_LOCK SynchLock;
/* session list */
LIST_ENTRY SessionList;
} VBOXVIDEOCM_MGR, *PVBOXVIDEOCM_MGR;
@@ -40,6 +40,7 @@ NTSTATUS vboxVideoCmCtxAdd(PVBOXVIDEOCM_MGR pMgr, PVBOXVIDEOCM_CTX pContext, HAN
NTSTATUS vboxVideoCmCtxRemove(PVBOXVIDEOCM_MGR pMgr, PVBOXVIDEOCM_CTX pContext);
NTSTATUS vboxVideoCmInit(PVBOXVIDEOCM_MGR pMgr);
NTSTATUS vboxVideoCmTerm(PVBOXVIDEOCM_MGR pMgr);
+NTSTATUS vboxVideoCmSignalEvents(PVBOXVIDEOCM_MGR pMgr);
NTSTATUS vboxVideoCmCmdSubmitCompleteEvent(PVBOXVIDEOCM_CTX pContext, PKEVENT pEvent);
void* vboxVideoCmCmdCreate(PVBOXVIDEOCM_CTX pContext, uint32_t cbSize);
@@ -57,9 +58,4 @@ NTSTATUS vboxVideoCmCmdVisit(PVBOXVIDEOCM_CTX pContext, BOOLEAN bEntireSession,
NTSTATUS vboxVideoCmEscape(PVBOXVIDEOCM_CTX pContext, PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pCmd, uint32_t cbCmd);
-NTSTATUS vboxVideoCmWaitCompletedCmds(PVBOXVIDEOCM_MGR pMgr, uint32_t msTimeout);
-
-VOID vboxVideoCmLock(PVBOXVIDEOCM_CTX pContext);
-VOID vboxVideoCmUnlock(PVBOXVIDEOCM_CTX pContext);
-
#endif /* #ifndef ___VBoxMPCm_h___ */
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCr.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCr.cpp
index 070eb30f..0c55676d 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCr.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCr.cpp
@@ -24,35 +24,18 @@
#ifdef VBOX_WITH_CROGL
#include <cr_protocol.h>
-# ifdef VBOX_WDDM_WITH_CRCMD
-# include <cr_pack.h>
+static uint32_t g_VBoxMpCrHostCaps = 0;
+static uint32_t g_VBoxMpCr3DSupported = 0;
-typedef struct VBOXMP_CRSHGSMICON_BUFDR
+uint32_t VBoxMpCrGetHostCaps()
{
- uint32_t cbBuf;
- void *pvBuf;
-} VBOXMP_CRSHGSMICON_BUFDR, *PVBOXMP_CRSHGSMICON_BUFDR;
-
-typedef struct VBOXMP_CRSHGSMICON_BUFDR_CACHE
-{
- volatile PVBOXMP_CRSHGSMICON_BUFDR pBufDr;
-} VBOXMP_CRSHGSMICON_BUFDR_CACHE, *PVBOXMP_CRSHGSMICON_BUFDR_CACHE;
-
-typedef struct VBOXMP_CRSHGSMICON
-{
- PVBOXMP_DEVEXT pDevExt;
- PVBOXMP_CRCTLCON pCtlCon;
- uint32_t u32ClientID;
- VBOXMP_CRSHGSMICON_BUFDR_CACHE CmdDrCache;
- VBOXMP_CRSHGSMICON_BUFDR_CACHE WbDrCache;
-} VBOXMP_CRSHGSMICON, *PVBOXMP_CRSHGSMICON;
+ return g_VBoxMpCrHostCaps;
+}
-typedef struct VBOXMP_CRSHGSMIPACKER
+bool VBoxMpCrCtlConIs3DSupported()
{
- PVBOXMP_CRSHGSMICON pCon;
- CRPackContext CrPacker;
- CRPackBuffer CrBuffer;
-} VBOXMP_CRSHGSMIPACKER, *PVBOXMP_CRSHGSMIPACKER;
+ return !!g_VBoxMpCr3DSupported;
+}
static void* vboxMpCrShgsmiBufferAlloc(PVBOXMP_DEVEXT pDevExt, HGSMISIZE cbData)
{
@@ -61,7 +44,12 @@ static void* vboxMpCrShgsmiBufferAlloc(PVBOXMP_DEVEXT pDevExt, HGSMISIZE cbData)
static VBOXVIDEOOFFSET vboxMpCrShgsmiBufferOffset(PVBOXMP_DEVEXT pDevExt, void *pvBuffer)
{
- return HGSMIPointerToOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, (const HGSMIBUFFERHEADER *)pvBuffer);
+ return (VBOXVIDEOOFFSET)HGSMIPointerToOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, (const HGSMIBUFFERHEADER *)pvBuffer);
+}
+
+static void* vboxMpCrShgsmiBufferFromOffset(PVBOXMP_DEVEXT pDevExt, VBOXVIDEOOFFSET offBuffer)
+{
+ return HGSMIOffsetToPointer(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, (HGSMIOFFSET)offBuffer);
}
static void vboxMpCrShgsmiBufferFree(PVBOXMP_DEVEXT pDevExt, void *pvBuffer)
@@ -69,38 +57,38 @@ static void vboxMpCrShgsmiBufferFree(PVBOXMP_DEVEXT pDevExt, void *pvBuffer)
VBoxSHGSMIHeapBufferFree(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pvBuffer);
}
-static void* vboxMpCrShgsmiConAlloc(PVBOXMP_CRSHGSMICON pCon, uint32_t cbBuffer)
+static VBOXVIDEOOFFSET vboxMpCrShgsmiTransportBufOffset(PVBOXMP_CRSHGSMITRANSPORT pCon, void* pvBuffer)
{
- return vboxMpCrShgsmiBufferAlloc(pCon->pDevExt, cbBuffer);
+ return vboxMpCrShgsmiBufferOffset(pCon->pDevExt, pvBuffer);
}
-static VBOXVIDEOOFFSET vboxMpCrShgsmiConBufOffset(PVBOXMP_CRSHGSMICON pCon, void* pvBuffer)
+static void* vboxMpCrShgsmiTransportBufFromOffset(PVBOXMP_CRSHGSMITRANSPORT pCon, VBOXVIDEOOFFSET offBuffer)
{
- return vboxMpCrShgsmiBufferOffset(pCon->pDevExt, pvBuffer);
+ return vboxMpCrShgsmiBufferFromOffset(pCon->pDevExt, offBuffer);
}
+void* VBoxMpCrShgsmiTransportBufAlloc(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t cbBuffer)
+{
+ return vboxMpCrShgsmiBufferAlloc(pCon->pDevExt, cbBuffer);
+}
-static void vboxMpCrShgsmiConFree(PVBOXMP_CRSHGSMICON pCon, void* pvBuffer)
+void VBoxMpCrShgsmiTransportBufFree(PVBOXMP_CRSHGSMITRANSPORT pCon, void* pvBuffer)
{
vboxMpCrShgsmiBufferFree(pCon->pDevExt, pvBuffer);
}
-#define VBOXMP_CRSHGSMICON_DR_CMDBUF_OFFSET(_cBuffers) VBOXWDDM_ROUNDBOUND((VBOXVDMACMD_SIZE_FROMBODYSIZE(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[_cBuffers]))), 8)
-#define VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(_pDr, _cBuffers, _type) ((_type*)(((uint8_t*)(_pDr)) + VBOXMP_CRSHGSMICON_DR_CMDBUF_OFFSET(_cBuffers)))
-#define VBOXMP_CRSHGSMICON_DR_SIZE(_cBuffers, _cbCmdBuf) ( VBOXMP_CRSHGSMICON_DR_CMDBUF_OFFSET(_cBuffers) + _cbCmdBuf)
-
-static int vboxMpCrShgsmiBufCacheBufReinit(PVBOXMP_CRSHGSMICON pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache, PVBOXMP_CRSHGSMICON_BUFDR pDr, uint32_t cbRequested)
+static int vboxMpCrShgsmiBufCacheBufReinit(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache, PVBOXMP_CRSHGSMICON_BUFDR pDr, uint32_t cbRequested)
{
if (pDr->cbBuf >= cbRequested)
return VINF_SUCCESS;
if (pDr->pvBuf)
- vboxMpCrShgsmiConFree(pCon, pDr->pvBuf);
+ VBoxMpCrShgsmiTransportBufFree(pCon, pDr->pvBuf);
- pDr->pvBuf = vboxMpCrShgsmiConAlloc(pCon, cbRequested);
+ pDr->pvBuf = VBoxMpCrShgsmiTransportBufAlloc(pCon, cbRequested);
if (!pDr->pvBuf)
{
- WARN(("vboxMpCrShgsmiConAlloc failed"));
+ WARN(("VBoxMpCrShgsmiTransportBufAlloc failed"));
pDr->cbBuf = 0;
return VERR_NO_MEMORY;
}
@@ -109,13 +97,13 @@ static int vboxMpCrShgsmiBufCacheBufReinit(PVBOXMP_CRSHGSMICON pCon, PVBOXMP_CRS
return VINF_SUCCESS;
}
-static void vboxMpCrShgsmiBufCacheFree(PVBOXMP_CRSHGSMICON pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache, PVBOXMP_CRSHGSMICON_BUFDR pDr)
+static void vboxMpCrShgsmiBufCacheFree(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache, PVBOXMP_CRSHGSMICON_BUFDR pDr)
{
if (ASMAtomicCmpXchgPtr(&pCache->pBufDr, pDr, NULL))
return;
/* the value is already cached, free the current one */
- vboxMpCrShgsmiConFree(pCon, pDr->pvBuf);
+ VBoxMpCrShgsmiTransportBufFree(pCon, pDr->pvBuf);
vboxWddmMemFree(pDr);
}
@@ -134,7 +122,7 @@ static PVBOXMP_CRSHGSMICON_BUFDR vboxMpCrShgsmiBufCacheGetAllocDr(PVBOXMP_CRSHGS
return pBufDr;
}
-static PVBOXMP_CRSHGSMICON_BUFDR vboxMpCrShgsmiBufCacheAlloc(PVBOXMP_CRSHGSMICON pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache, uint32_t cbBuffer)
+static PVBOXMP_CRSHGSMICON_BUFDR vboxMpCrShgsmiBufCacheAlloc(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache, uint32_t cbBuffer)
{
PVBOXMP_CRSHGSMICON_BUFDR pBufDr = vboxMpCrShgsmiBufCacheGetAllocDr(pCache);
int rc = vboxMpCrShgsmiBufCacheBufReinit(pCon, pCache, pBufDr, cbBuffer);
@@ -147,7 +135,7 @@ static PVBOXMP_CRSHGSMICON_BUFDR vboxMpCrShgsmiBufCacheAlloc(PVBOXMP_CRSHGSMICON
return NULL;
}
-static PVBOXMP_CRSHGSMICON_BUFDR vboxMpCrShgsmiBufCacheAllocAny(PVBOXMP_CRSHGSMICON pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache, uint32_t cbBuffer)
+static PVBOXMP_CRSHGSMICON_BUFDR vboxMpCrShgsmiBufCacheAllocAny(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache, uint32_t cbBuffer)
{
PVBOXMP_CRSHGSMICON_BUFDR pBufDr = vboxMpCrShgsmiBufCacheGetAllocDr(pCache);
@@ -165,128 +153,396 @@ static PVBOXMP_CRSHGSMICON_BUFDR vboxMpCrShgsmiBufCacheAllocAny(PVBOXMP_CRSHGSMI
}
-static int vboxMpCrShgsmiBufCacheInit(PVBOXMP_CRSHGSMICON pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache)
+static int vboxMpCrShgsmiBufCacheInit(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache)
{
memset(pCache, 0, sizeof (*pCache));
return VINF_SUCCESS;
}
-static void vboxMpCrShgsmiBufCacheTerm(PVBOXMP_CRSHGSMICON pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache)
+static void vboxMpCrShgsmiBufCacheTerm(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache)
{
if (pCache->pBufDr)
vboxMpCrShgsmiBufCacheFree(pCon, pCache, pCache->pBufDr);
}
-static int vboxMpCrShgsmiConConnect(PVBOXMP_CRSHGSMICON pCon, PVBOXMP_DEVEXT pDevExt, PVBOXMP_CRCTLCON pCrCtlCon)
+int VBoxMpCrShgsmiTransportCreate(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_DEVEXT pDevExt)
{
memset(pCon, 0, sizeof (*pCon));
- int rc = vboxMpCrShgsmiBufCacheInit(pCon, &pCon->CmdDrCache);
- if (RT_SUCCESS(rc))
+ pCon->pDevExt = pDevExt;
+ return VINF_SUCCESS;
+ int rc;
+// int rc = vboxMpCrShgsmiBufCacheInit(pCon, &pCon->CmdDrCache);
+// if (RT_SUCCESS(rc))
{
rc = vboxMpCrShgsmiBufCacheInit(pCon, &pCon->WbDrCache);
if (RT_SUCCESS(rc))
{
- rc = VBoxMpCrCtlConConnect(pCrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &pCon->u32ClientID);
- if (RT_SUCCESS(rc))
- {
- pCon->pDevExt = pDevExt;
- pCon->pCtlCon = pCrCtlCon;
- return VINF_SUCCESS;
- }
- else
- {
- WARN(("VBoxMpCrCtlConConnect failed rc %d", rc));
- }
- vboxMpCrShgsmiBufCacheTerm(pCon, &pCon->WbDrCache);
}
else
{
WARN(("vboxMpCrShgsmiBufCacheInit2 failed rc %d", rc));
}
- vboxMpCrShgsmiBufCacheTerm(pCon, &pCon->CmdDrCache);
+// vboxMpCrShgsmiBufCacheTerm(pCon, &pCon->CmdDrCache);
}
- else
+// else
+// {
+// WARN(("vboxMpCrShgsmiBufCacheInit1 failed rc %d", rc));
+// }
+
+ return rc;
+}
+
+void VBoxMpCrShgsmiTransportTerm(PVBOXMP_CRSHGSMITRANSPORT pCon)
+{
+ vboxMpCrShgsmiBufCacheTerm(pCon, &pCon->WbDrCache);
+// vboxMpCrShgsmiBufCacheTerm(pCon, &pCon->CmdDrCache);
+}
+
+typedef struct VBOXMP_CRHGSMICMD_BASE
+{
+// VBOXMP_CRHGSMICMD_HDR Hdr;
+ CRVBOXHGSMIHDR CmdHdr;
+} VBOXMP_CRHGSMICMD_BASE, *PVBOXMP_CRHGSMICMD_BASE;
+
+typedef struct VBOXMP_CRHGSMICMD_WRITEREAD
+{
+// VBOXMP_CRHGSMICMD_HDR Hdr;
+ CRVBOXHGSMIWRITEREAD Cmd;
+} VBOXMP_CRHGSMICMD_WRITEREAD, *PVBOXMP_CRHGSMICMD_WRITEREAD;
+
+typedef struct VBOXMP_CRHGSMICMD_READ
+{
+// VBOXMP_CRHGSMICMD_HDR Hdr;
+ CRVBOXHGSMIREAD Cmd;
+} VBOXMP_CRHGSMICMD_READ, *PVBOXMP_CRHGSMICMD_READ;
+
+typedef struct VBOXMP_CRHGSMICMD_WRITE
+{
+// VBOXMP_CRHGSMICMD_HDR Hdr;
+ CRVBOXHGSMIWRITE Cmd;
+} VBOXMP_CRHGSMICMD_WRITE, *PVBOXMP_CRHGSMICMD_WRITE;
+
+#define VBOXMP_CRSHGSMICON_DR_CMDBUF_OFFSET(_cBuffers) VBOXWDDM_ROUNDBOUND((VBOXVDMACMD_SIZE_FROMBODYSIZE(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[_cBuffers]))), 8)
+#define VBOXMP_CRSHGSMICON_DR_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf) ( VBOXMP_CRSHGSMICON_DR_CMDBUF_OFFSET(_cBuffers) + VBOXWDDM_ROUNDBOUND(_cbCmdBuf, 8))
+#define VBOXMP_CRSHGSMICON_DR_GET_CRCMD(_pDr) (VBOXVDMACMD_BODY((_pDr), VBOXVDMACMD_CHROMIUM_CMD))
+#define VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(_pDr, _cBuffers, _type) ((_type*)(((uint8_t*)(_pDr)) + VBOXMP_CRSHGSMICON_DR_CMDBUF_OFFSET(_cBuffers)))
+#define VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(_pDr, _cBuffers, _cbCmdBuf, _type) ((_type*)(((uint8_t*)(_pDr)) + VBOXMP_CRSHGSMICON_DR_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf)))
+#define VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(_pCtx, _cBuffers, _cbCmdBuf) ((VBOXVDMACMD*)(((uint8_t*)(_pCtx)) - VBOXMP_CRSHGSMICON_DR_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf)))
+#define VBOXMP_CRSHGSMICON_DR_SIZE(_cBuffers, _cbCmdBuf, _cbCtx) (VBOXMP_CRSHGSMICON_DR_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf) + (_cbCtx))
+
+
+static int vboxMpCrShgsmiTransportCmdSubmitDr(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXVDMACBUF_DR pDr, PFNVBOXVDMADDICMDCOMPLETE_DPC pfnComplete)
+{
+
+ PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
+ PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
+ vboxVdmaDdiCmdInit(pDdiCmd, 0, 0, pfnComplete, pCon);
+ /* mark command as submitted & invisible for the dx runtime since dx did not originate it */
+ vboxVdmaDdiCmdSubmittedNotDx(pDdiCmd);
+ int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
+ if (RT_SUCCESS(rc))
{
- WARN(("vboxMpCrShgsmiBufCacheInit1 failed rc %d", rc));
+ return VINF_SUCCESS;
}
+ WARN(("vboxVdmaCBufDrSubmit failed rc %d", rc));
return rc;
}
-static int vboxMpCrShgsmiConDisconnect(PVBOXMP_CRSHGSMICON pCon)
+static int vboxMpCrShgsmiTransportCmdSubmitDmaCmd(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXVDMACMD pHdr, PFNVBOXVDMADDICMDCOMPLETE_DPC pfnComplete)
{
- int rc = VBoxMpCrCtlConDisconnect(pCon->pCtlCon, pCon->u32ClientID);
- if (RT_FAILURE(rc))
+ PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_TAIL(pHdr);
+ return vboxMpCrShgsmiTransportCmdSubmitDr(pCon, pDr, pfnComplete);
+}
+
+static void vboxMpCrShgsmiTransportCmdTermDmaCmd(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXVDMACMD pHdr)
+{
+ PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_TAIL(pHdr);
+ PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
+ vboxVdmaCBufDrFree (&pDevExt->u.primary.Vdma, pDr);
+}
+
+
+typedef DECLCALLBACK(void) FNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc, void *pvRx, uint32_t cbRx, void *pvCtx);
+typedef FNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION *PFNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION;
+
+static DECLCALLBACK(VOID) vboxMpCrShgsmiTransportSendReadAsyncCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pDdiCmd, PVOID pvContext)
+{
+ /* we should be called from our DPC routine */
+ Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
+ PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_DDI_CMD(pDdiCmd);
+ PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
+ VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
+ const UINT cBuffers = 2;
+ Assert(pBody->cBuffers == cBuffers);
+ PVBOXMP_CRHGSMICMD_READ pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_READ);
+ CRVBOXHGSMIREAD *pCmd = &pWrData->Cmd;
+ VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
+ Assert(pBufCmd->cbBuffer == sizeof (CRVBOXHGSMIREAD));
+ CRVBOXHGSMIREAD * pWr = (CRVBOXHGSMIREAD*)vboxMpCrShgsmiTransportBufFromOffset(pCon, pBufCmd->offBuffer);
+ PFNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION)pBufCmd->u64GuestData;
+ VBOXVDMACMD_CHROMIUM_BUFFER *pRxBuf = &pBody->aBuffers[1];
+ PVBOXMP_CRSHGSMICON_BUFDR pWbDr = (PVBOXMP_CRSHGSMICON_BUFDR)pRxBuf->u64GuestData;
+ void *pvRx = NULL;
+ uint32_t cbRx = 0;
+
+ int rc = pDr->rc;
+ if (RT_SUCCESS(rc))
{
- WARN(("VBoxMpCrCtlConDisconnect failed rc %d", rc));
- return rc;
+ rc = pWr->hdr.result;
+ if (RT_SUCCESS(rc))
+ {
+ cbRx = pCmd->cbBuffer;
+ if (cbRx)
+ pvRx = pWbDr->pvBuf;
+ }
+ else
+ {
+ WARN(("CRVBOXHGSMIREAD failed, rc %d", rc));
+ }
+ }
+ else
+ {
+ WARN(("dma command buffer failed rc %d!", rc));
}
- vboxMpCrShgsmiBufCacheTerm(pCon, &pCon->WbDrCache);
- vboxMpCrShgsmiBufCacheTerm(pCon, &pCon->CmdDrCache);
+ if (pfnCompletion)
+ {
+ void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_READ), void);
+ pfnCompletion(pCon, rc, pvRx, cbRx, pvCtx);
+ }
- return VINF_SUCCESS;
+ vboxMpCrShgsmiBufCacheFree(pCon, &pCon->WbDrCache, pWbDr);
+}
+
+static void* vboxMpCrShgsmiTransportCmdCreateReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t u32ClientID, PVBOXVDMACBUF_DR pDr, uint32_t cbDrData, PVBOXMP_CRSHGSMICON_BUFDR pWbDr,
+ PFNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION pfnCompletion, uint32_t cbContextData)
+{
+ const uint32_t cBuffers = 2;
+ const uint32_t cbCmd = VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_READ), cbContextData);
+ PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
+ PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
+ VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
+ PVBOXMP_CRHGSMICMD_READ pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_READ);
+ CRVBOXHGSMIREAD *pCmd = &pWrData->Cmd;
+
+ if (cbCmd > cbContextData)
+ {
+ ERR(("the passed descriptor is less than needed!"));
+ return NULL;
+ }
+
+ memset(pDr, 0, VBOXVDMACBUF_DR_SIZE(cbCmd));
+
+ pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET;
+ pDr->cbBuf = cbCmd;
+ pDr->rc = VERR_NOT_IMPLEMENTED;
+ pDr->Location.offVramBuf = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
+
+ pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
+ pHdr->u32CmdSpecific = 0;
+
+ pBody->cBuffers = cBuffers;
+
+ pCmd->hdr.result = VERR_WRONG_ORDER;
+ pCmd->hdr.u32ClientID = u32ClientID;
+ pCmd->hdr.u32Function = SHCRGL_GUEST_FN_WRITE_READ;
+ // pCmd->hdr.u32Reserved = 0;
+ pCmd->iBuffer = 1;
+
+ VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
+ pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
+ pBufCmd->cbBuffer = sizeof (*pCmd);
+ pBufCmd->u32GuestData = 0;
+ pBufCmd->u64GuestData = (uint64_t)pfnCompletion;
+
+ pBufCmd = &pBody->aBuffers[1];
+ pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pWbDr->pvBuf);
+ pBufCmd->cbBuffer = pWbDr->cbBuf;
+ pBufCmd->u32GuestData = 0;
+ pBufCmd->u64GuestData = (uint64_t)pWbDr;
+
+ return VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_READ), void);
}
-typedef DECLCALLBACK(void) FNVBOXMP_CRSHGSMICON_SEND_COMPLETION(PVBOXMP_CRSHGSMICON pCon, void *pvRx, uint32_t cbRx, void *pvCtx);
-typedef FNVBOXMP_CRSHGSMICON_SEND_COMPLETION *PFNVBOXMP_CRSHGSMICON_SEND_COMPLETION;
+static int vboxMpCrShgsmiTransportCmdSubmitReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
+{
+ VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_READ));
+ return vboxMpCrShgsmiTransportCmdSubmitDmaCmd(pCon, pHdr, vboxMpCrShgsmiTransportSendReadAsyncCompletion);
+}
-typedef struct VBOXMP_CRSHGSMICON_SEND_COMPLETION
+typedef struct VBOXMP_CRHGSMICON_WRR_COMPLETION_CTX
{
- PVBOXMP_CRSHGSMICON pCon;
- PFNVBOXMP_CRSHGSMICON_SEND_COMPLETION pvnCompletion;
- void *pvCompletion;
-} VBOXMP_CRSHGSMICON_SEND_COMPLETION, *PVBOXMP_CRSHGSMICON_SEND_COMPLETION;
+ PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion;
+ void *pvContext;
+
+} VBOXMP_CRHGSMICON_WRR_COMPLETION_CTX, *PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX;
-static DECLCALLBACK(VOID) vboxMpCrShgsmiConSendAsyncCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
+static DECLCALLBACK(void) vboxMpCrShgsmiTransportSendWriteReadReadRepostCompletion(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc, void *pvRx, uint32_t cbRx, void *pvCtx)
+{
+ PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX pData = (PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX)pvCtx;
+ PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion = pData->pfnCompletion;
+ if (pfnCompletion)
+ pfnCompletion(pCon, rc, pvRx, cbRx, pData->pvContext);
+}
+
+static DECLCALLBACK(VOID) vboxMpCrShgsmiTransportSendWriteReadAsyncCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pDdiCmd, PVOID pvContext)
{
/* we should be called from our DPC routine */
Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
- PVBOXMP_CRSHGSMICON_SEND_COMPLETION pData = (PVBOXMP_CRSHGSMICON_SEND_COMPLETION)pvContext;
- PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_DDI_CMD(pCmd);
+ PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
+ PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_DDI_CMD(pDdiCmd);
PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
- VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHROMIUM_CMD);
- UINT cBufs = pBody->cBuffers;
- /* the first one is a command buffer: obtain it and get the result */
+ VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
+ const UINT cBuffers = 3;
+ Assert(pBody->cBuffers == cBuffers);
+ PVBOXMP_CRHGSMICMD_WRITEREAD pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITEREAD);
+ CRVBOXHGSMIWRITEREAD *pCmd = &pWrData->Cmd;
+ VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
+ Assert(pBufCmd->cbBuffer == sizeof (CRVBOXHGSMIWRITEREAD));
+ CRVBOXHGSMIWRITEREAD * pWr = (CRVBOXHGSMIWRITEREAD*)vboxMpCrShgsmiTransportBufFromOffset(pCon, pBufCmd->offBuffer);
+ VBOXVDMACMD_CHROMIUM_BUFFER *pRxBuf = &pBody->aBuffers[2];
+ PVBOXMP_CRSHGSMICON_BUFDR pWbDr = (PVBOXMP_CRSHGSMICON_BUFDR)pRxBuf->u64GuestData;
+ PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION)pBufCmd->u64GuestData;
+ void *pvRx = NULL;
+ uint32_t cbRx = 0;
+
+ int rc = pDr->rc;
+ if (RT_SUCCESS(rc))
+ {
+ rc = pWr->hdr.result;
+ if (RT_SUCCESS(rc))
+ {
+ cbRx = pCmd->cbWriteback;
+ if (cbRx)
+ pvRx = pWbDr->pvBuf;
+ }
+ else if (rc == VERR_BUFFER_OVERFLOW)
+ {
+ /* issue read */
+ void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), void);
+ vboxMpCrShgsmiBufCacheFree(pCon, &pCon->WbDrCache, pWbDr);
+ pWbDr = vboxMpCrShgsmiBufCacheAlloc(pCon, &pCon->WbDrCache, pCmd->cbWriteback);
+ if (pWbDr)
+ {
+ /* the Read Command is shorter than WriteRead, so just reuse the Write-Read descriptor here */
+ PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX pReadCtx = (PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX)vboxMpCrShgsmiTransportCmdCreateReadAsync(pCon, pCmd->hdr.u32ClientID,
+ pDr, VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), 0),
+ pWbDr, vboxMpCrShgsmiTransportSendWriteReadReadRepostCompletion, sizeof (*pReadCtx));
+ pReadCtx->pfnCompletion = pfnCompletion;
+ pReadCtx->pvContext = pvCtx;
+ vboxMpCrShgsmiTransportCmdSubmitReadAsync(pCon, pReadCtx);
+ /* don't do completion here, the completion will be called from the read completion we issue here */
+ pfnCompletion = NULL;
+ /* the current pWbDr was already freed, and we'll free the Read dr in the Read Completion */
+ pWbDr = NULL;
+ }
+ else
+ {
+ WARN(("vboxMpCrShgsmiBufCacheAlloc failed for %d", pCmd->cbWriteback));
+ rc = VERR_NO_MEMORY;
+ }
+ }
+ else
+ {
+ WARN(("CRVBOXHGSMIWRITEREAD failed, rc %d", rc));
+ }
+ }
+ else
+ {
+ WARN(("dma command buffer failed rc %d!", rc));
+ }
+
+ if (pfnCompletion)
+ {
+ void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), void);
+ pfnCompletion(pCon, rc, pvRx, cbRx, pvCtx);
+ }
+
+ if (pWbDr)
+ vboxMpCrShgsmiBufCacheFree(pCon, &pCon->WbDrCache, pWbDr);
+}
+
+static DECLCALLBACK(VOID) vboxMpCrShgsmiTransportSendWriteAsyncCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pDdiCmd, PVOID pvContext)
+{
+ /* we should be called from our DPC routine */
+ Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
- /* if write back buffer is too small, issue read command.
- * we can use exactly the same command buffer for it */
- /* impl */
- Assert(0);
+ PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
+ PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_DDI_CMD(pDdiCmd);
+ PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
+ VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
+ const UINT cBuffers = 2;
+ Assert(pBody->cBuffers == cBuffers);
+ PVBOXMP_CRHGSMICMD_WRITE pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITE);
+ CRVBOXHGSMIWRITE *pCmd = &pWrData->Cmd;
+ VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
+ Assert(pBufCmd->cbBuffer == sizeof (CRVBOXHGSMIWRITE));
+ PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION)pBufCmd->u64GuestData;
+
+ int rc = pDr->rc;
+ if (RT_SUCCESS(rc))
+ {
+ rc = pCmd->hdr.result;
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CRVBOXHGSMIWRITE failed, rc %d", rc));
+ }
+ }
+ else
+ {
+ WARN(("dma command buffer failed rc %d!", rc));
+ }
+
+ if (pfnCompletion)
+ {
+ void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), void);
+ pfnCompletion(pCon, rc, pvCtx);
+ }
}
-static int vboxMpCrShgsmiConSendAsync(PVBOXMP_CRSHGSMICON pCon, void *pvTx, uint32_t cbTx, PFNVBOXMP_CRSHGSMICON_SEND_COMPLETION pfnCompletion, void *pvCompletion)
+void* VBoxMpCrShgsmiTransportCmdCreateWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t u32ClientID, void *pvBuffer, uint32_t cbBuffer,
+ PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion, uint32_t cbContextData)
{
const uint32_t cBuffers = 3;
- const uint32_t cbCmd = VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof (CRVBOXHGSMIWRITEREAD));
- PVBOXMP_CRSHGSMICON_BUFDR pCmdDr = vboxMpCrShgsmiBufCacheAlloc(pCon, &pCon->CmdDrCache, cbCmd);
- if (!pCmdDr)
+ const uint32_t cbCmd = VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), cbContextData);
+ PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
+ PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
+ if (!pDr)
{
- WARN(("vboxMpCrShgsmiBufCacheAlloc for cmd dr failed"));
- return VERR_NO_MEMORY;
+ WARN(("vboxVdmaCBufDrCreate failed"));
+ return NULL;
}
+
PVBOXMP_CRSHGSMICON_BUFDR pWbDr = vboxMpCrShgsmiBufCacheAllocAny(pCon, &pCon->WbDrCache, 1000);
if (!pWbDr)
{
WARN(("vboxMpCrShgsmiBufCacheAlloc for wb dr failed"));
- vboxMpCrShgsmiBufCacheFree(pCon, &pCon->CmdDrCache, pCmdDr);
- return VERR_NO_MEMORY;
+ vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
+ return NULL;
}
- PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)pCmdDr->pvBuf;
+ PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
+ VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
+ PVBOXMP_CRHGSMICMD_WRITEREAD pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITEREAD);
+ CRVBOXHGSMIWRITEREAD *pCmd = &pWrData->Cmd;
+
pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
pDr->cbBuf = cbCmd;
pDr->rc = VERR_NOT_IMPLEMENTED;
+// pDr->Location.offVramBuf = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
+
- PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
pHdr->u32CmdSpecific = 0;
- VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHROMIUM_CMD);
+
pBody->cBuffers = cBuffers;
- CRVBOXHGSMIWRITEREAD *pCmd = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pDr, cBuffers, CRVBOXHGSMIWRITEREAD);
+
pCmd->hdr.result = VERR_WRONG_ORDER;
- pCmd->hdr.u32ClientID = pCon->u32ClientID;
+ pCmd->hdr.u32ClientID = u32ClientID;
pCmd->hdr.u32Function = SHCRGL_GUEST_FN_WRITE_READ;
// pCmd->hdr.u32Reserved = 0;
pCmd->iBuffer = 1;
@@ -294,105 +550,99 @@ static int vboxMpCrShgsmiConSendAsync(PVBOXMP_CRSHGSMICON pCon, void *pvTx, uint
pCmd->cbWriteback = 0;
VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
- pBufCmd->offBuffer = vboxMpCrShgsmiConBufOffset(pCon, pCmd);
+ pBufCmd->offBuffer = vboxVdmaCBufDrPtrOffset(&pDevExt->u.primary.Vdma, pCmd);
pBufCmd->cbBuffer = sizeof (*pCmd);
pBufCmd->u32GuestData = 0;
- pBufCmd->u64GuestData = (uint64_t)pCmdDr;
+ pBufCmd->u64GuestData = (uint64_t)pfnCompletion;
pBufCmd = &pBody->aBuffers[1];
- pBufCmd->offBuffer = vboxMpCrShgsmiConBufOffset(pCon, pvTx);
- pBufCmd->cbBuffer = cbTx;
+ pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pvBuffer);
+ pBufCmd->cbBuffer = cbBuffer;
pBufCmd->u32GuestData = 0;
pBufCmd->u64GuestData = 0;
pBufCmd = &pBody->aBuffers[2];
- pBufCmd->offBuffer = vboxMpCrShgsmiConBufOffset(pCon, pWbDr->pvBuf);
+ pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pWbDr->pvBuf);
pBufCmd->cbBuffer = pWbDr->cbBuf;
pBufCmd->u32GuestData = 0;
pBufCmd->u64GuestData = (uint64_t)pWbDr;
+ return VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), void);
+}
+
+void* VBoxMpCrShgsmiTransportCmdCreateWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t u32ClientID, void *pvBuffer, uint32_t cbBuffer,
+ PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion, uint32_t cbContextData)
+{
+ const uint32_t cBuffers = 2;
+ const uint32_t cbCmd = VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), cbContextData);
PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
- PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
- vboxVdmaDdiCmdInit(pDdiCmd, 0, 0, vboxMpCrShgsmiConSendAsyncCompletion, pDr);
- /* mark command as submitted & invisible for the dx runtime since dx did not originate it */
- vboxVdmaDdiCmdSubmittedNotDx(pDdiCmd);
- int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
- if (RT_SUCCESS(rc))
+ PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
+ if (!pDr)
{
- return STATUS_SUCCESS;
+ WARN(("vboxVdmaCBufDrCreate failed"));
+ return NULL;
}
- /* impl failure branch */
- Assert(0);
- return rc;
-}
+ PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
+ VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
+ PVBOXMP_CRHGSMICMD_WRITE pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITE);
+ CRVBOXHGSMIWRITE *pCmd = &pWrData->Cmd;
-static CRMessageOpcodes *
-vboxMpCrPackerPrependHeader( CRPackBuffer *buf, unsigned int *len, unsigned int senderID )
-{
- UINT num_opcodes;
- CRMessageOpcodes *hdr;
+ pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
+ pDr->cbBuf = cbCmd;
+ pDr->rc = VERR_NOT_IMPLEMENTED;
+// pDr->Location.offVramBuf = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
- Assert(buf);
- Assert(buf->opcode_current < buf->opcode_start);
- Assert(buf->opcode_current >= buf->opcode_end);
- Assert(buf->data_current > buf->data_start);
- Assert(buf->data_current <= buf->data_end);
+ pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
+ pHdr->u32CmdSpecific = 0;
- num_opcodes = (UINT)(buf->opcode_start - buf->opcode_current);
- hdr = (CRMessageOpcodes *)
- ( buf->data_start - ( ( num_opcodes + 3 ) & ~0x3 ) - sizeof(*hdr) );
+ pBody->cBuffers = cBuffers;
- Assert((void *) hdr >= buf->pack);
+ pCmd->hdr.result = VERR_WRONG_ORDER;
+ pCmd->hdr.u32ClientID = u32ClientID;
+ pCmd->hdr.u32Function = SHCRGL_GUEST_FN_WRITE;
+ // pCmd->hdr.u32Reserved = 0;
+ pCmd->iBuffer = 1;
- hdr->header.type = CR_MESSAGE_OPCODES;
- hdr->numOpcodes = num_opcodes;
+ VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
+ pBufCmd->offBuffer = vboxVdmaCBufDrPtrOffset(&pDevExt->u.primary.Vdma, pCmd);
+ pBufCmd->cbBuffer = sizeof (*pCmd);
+ pBufCmd->u32GuestData = 0;
+ pBufCmd->u64GuestData = (uint64_t)pfnCompletion;
- *len = (UINT)(buf->data_current - (unsigned char *) hdr);
+ pBufCmd = &pBody->aBuffers[1];
+ pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pvBuffer);
+ pBufCmd->cbBuffer = cbBuffer;
+ pBufCmd->u32GuestData = 0;
+ pBufCmd->u64GuestData = 0;
- return hdr;
+ return VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), void);
}
-static void vboxMpCrShgsmiPackerCbFlush(void *pvFlush)
+int VBoxMpCrShgsmiTransportCmdSubmitWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
{
- PVBOXMP_CRSHGSMIPACKER pPacker = (PVBOXMP_CRSHGSMIPACKER)pvFlush;
-
- crPackReleaseBuffer(&pPacker->CrPacker);
-
- if (pPacker->CrBuffer.opcode_current != pPacker->CrBuffer.opcode_start)
- {
- CRMessageOpcodes *pHdr;
- unsigned int len;
- pHdr = vboxMpCrPackerPrependHeader(&pPacker->CrBuffer, &len, 0);
-
- /*Send*/
- }
-
+ VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 3, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD));
+ return vboxMpCrShgsmiTransportCmdSubmitDmaCmd(pCon, pHdr, vboxMpCrShgsmiTransportSendWriteReadAsyncCompletion);
+}
- crPackSetBuffer(&pPacker->CrPacker, &pPacker->CrBuffer);
- crPackResetPointers(&pPacker->CrPacker);
+int VBoxMpCrShgsmiTransportCmdSubmitWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
+{
+ VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE));
+ return vboxMpCrShgsmiTransportCmdSubmitDmaCmd(pCon, pHdr, vboxMpCrShgsmiTransportSendWriteAsyncCompletion);
}
-int vboxMpCrShgsmiPackerInit(PVBOXMP_CRSHGSMIPACKER pPacker, PVBOXMP_CRSHGSMICON pCon)
+void VBoxMpCrShgsmiTransportCmdTermWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
{
- memset(pPacker, 0, sizeof (*pPacker));
+ VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 3, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD));
+ vboxMpCrShgsmiTransportCmdTermDmaCmd(pCon, pHdr);
+}
- static const HGSMISIZE cbBuffer = 1000;
- void *pvBuffer = vboxMpCrShgsmiConAlloc(pCon, cbBuffer);
- if (!pvBuffer)
- {
- WARN(("vboxMpCrShgsmiConAlloc failed"));
- return VERR_NO_MEMORY;
- }
- pPacker->pCon = pCon;
- crPackInitBuffer(&pPacker->CrBuffer, pvBuffer, cbBuffer, cbBuffer);
- crPackSetBuffer(&pPacker->CrPacker, &pPacker->CrBuffer);
- crPackFlushFunc(&pPacker->CrPacker, vboxMpCrShgsmiPackerCbFlush);
- crPackFlushArg(&pPacker->CrPacker, pPacker);
-// crPackSendHugeFunc( thread->packer, packspuHuge );
- return VINF_SUCCESS;
+void VBoxMpCrShgsmiTransportCmdTermWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
+{
+ VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE));
+ vboxMpCrShgsmiTransportCmdTermDmaCmd(pCon, pHdr);
}
-# endif
+
#endif
static int vboxMpCrCtlAddRef(PVBOXMP_CRCTLCON pCrCtlCon)
@@ -464,6 +714,39 @@ static int vboxMpCrCtlConSetVersion(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32Clie
return VINF_SUCCESS;
}
+static int vboxMpCrCtlConGetCaps(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID, uint32_t *pu32Caps)
+{
+ CRVBOXHGCMGETCAPS parms;
+ int rc;
+
+ parms.hdr.result = VERR_WRONG_ORDER;
+ parms.hdr.u32ClientID = u32ClientID;
+ parms.hdr.u32Function = SHCRGL_GUEST_FN_GET_CAPS;
+ parms.hdr.cParms = SHCRGL_CPARMS_GET_CAPS;
+
+ parms.Caps.type = VMMDevHGCMParmType_32bit;
+ parms.Caps.u.value32 = 0;
+
+ *pu32Caps = 0;
+
+ rc = vboxCrCtlConCall(pCrCtlCon->hCrCtl, &parms.hdr, sizeof (parms));
+ if (RT_FAILURE(rc))
+ {
+ WARN(("vboxCrCtlConCall failed, rc (%d)", rc));
+ return rc;
+ }
+
+ if (RT_FAILURE(parms.hdr.result))
+ {
+ WARN(("SHCRGL_GUEST_FN_GET_CAPS failed, rc (%d)", parms.hdr.result));
+ return parms.hdr.result;
+ }
+
+ *pu32Caps = parms.Caps.u.value32;
+
+ return VINF_SUCCESS;
+}
+
static int vboxMpCrCtlConSetPID(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID)
{
CRVBOXHGCMSETPID parms;
@@ -576,8 +859,11 @@ int VBoxMpCrCtlConCallUserData(PVBOXMP_CRCTLCON pCrCtlCon, VBoxGuestHGCMCallInfo
return rc;
}
-bool VBoxMpCrCtlConIs3DSupported()
+void VBoxMpCrCtlConInit()
{
+ g_VBoxMpCr3DSupported = 0;
+ g_VBoxMpCrHostCaps = 0;
+
#ifdef VBOX_WITH_CROGL
VBOXMP_CRCTLCON CrCtlCon = {0};
uint32_t u32ClientID = 0;
@@ -585,15 +871,57 @@ bool VBoxMpCrCtlConIs3DSupported()
if (RT_FAILURE(rc))
{
LOGREL(("VBoxMpCrCtlConConnect failed with rc(%d), 3D not supported!"));
- return false;
+ return;
}
- rc = VBoxMpCrCtlConDisconnect(&CrCtlCon, u32ClientID);
+ g_VBoxMpCr3DSupported = 1;
+
+ rc = vboxMpCrCtlConGetCaps(&CrCtlCon, u32ClientID, &g_VBoxMpCrHostCaps);
if (RT_FAILURE(rc))
- WARN(("VBoxMpCrCtlConDisconnect failed, ignoring.."));
+ {
+ WARN(("vboxMpCrCtlConGetCaps failed rc (%d), ignoring..", rc));
+ g_VBoxMpCrHostCaps = 0;
+ }
- return true;
-#else
- return false;
+#if 1 /*def DEBUG_misha*/
+ g_VBoxMpCrHostCaps &= ~CR_VBOX_CAP_CMDVBVA;
#endif
+
+ rc = VBoxMpCrCtlConDisconnect(&CrCtlCon, u32ClientID);
+ if (RT_FAILURE(rc))
+ WARN(("VBoxMpCrCtlConDisconnect failed rc (%d), ignoring..", rc));
+#endif
+}
+
+int VBoxMpCrCmdRxReadbackHandler(CRMessageReadback *pRx, uint32_t cbRx)
+{
+ if (cbRx < sizeof (*pRx))
+ {
+ WARN(("invalid rx size %d", cbRx));
+ return VERR_INVALID_PARAMETER;
+ }
+ void* pvData = VBoxMpCrCmdRxReadbackData(pRx);
+ uint32_t cbData = VBoxMpCrCmdRxReadbackDataSize(pRx, cbRx);
+ void *pvDataPtr = *((void**)&pRx->readback_ptr);
+ memcpy(pvDataPtr, pvData, cbData);
+ return VINF_SUCCESS;
}
+
+int VBoxMpCrCmdRxHandler(CRMessageHeader *pRx, uint32_t cbRx)
+{
+ if (cbRx < sizeof (*pRx))
+ {
+ WARN(("invalid rx size %d", cbRx));
+ return VERR_INVALID_PARAMETER;
+ }
+ CRMessageHeader *pHdr = (CRMessageHeader*)pRx;
+ switch (pHdr->type)
+ {
+ case CR_MESSAGE_READBACK:
+ return VBoxMpCrCmdRxReadbackHandler((CRMessageReadback*)pRx, cbRx);
+ default:
+ WARN(("unsupported rx message type: %d", pHdr->type));
+ return VERR_INVALID_PARAMETER;
+ }
+}
+
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCr.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCr.h
index 4bf2ab98..cc00f90d 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCr.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCr.h
@@ -27,6 +27,8 @@ typedef struct VBOXMP_CRCTLCON
uint32_t cCrCtlRefs;
} VBOXMP_CRCTLCON, *PVBOXMP_CRCTLCON;
+void VBoxMpCrCtlConInit();
+
bool VBoxMpCrCtlConIs3DSupported();
int VBoxMpCrCtlConConnect(PVBOXMP_CRCTLCON pCrCtlCon,
@@ -36,4 +38,214 @@ int VBoxMpCrCtlConDisconnect(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID);
int VBoxMpCrCtlConCall(PVBOXMP_CRCTLCON pCrCtlCon, struct VBoxGuestHGCMCallInfo *pData, uint32_t cbData);
int VBoxMpCrCtlConCallUserData(PVBOXMP_CRCTLCON pCrCtlCon, struct VBoxGuestHGCMCallInfo *pData, uint32_t cbData);
+# include <cr_pack.h>
+
+typedef struct VBOXMP_CRDATACON
+{
+ PVBOXMP_CRCTLCON pCtl;
+ uint32_t u32ClientID;
+} VBOXMP_CRDATACON, *PVBOXMP_CRDATACON;
+
+DECLINLINE(int) VBoxMpCrDataConCreate(PVBOXMP_CRDATACON pDataCon, PVBOXMP_CRCTLCON pCtlCon)
+{
+ int rc = VBoxMpCrCtlConConnect(pCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &pDataCon->u32ClientID);
+ if (RT_SUCCESS(rc))
+ {
+ Assert(pDataCon->u32ClientID);
+ pDataCon->pCtl = pCtlCon;
+ return VINF_SUCCESS;
+ }
+ WARN(("VBoxMpCrCtlConConnect failed, rc %d", rc));
+ return rc;
+}
+
+DECLINLINE(int) VBoxMpCrDataConDestroy(PVBOXMP_CRDATACON pDataCon)
+{
+ int rc = VBoxMpCrCtlConDisconnect(pDataCon->pCtl, pDataCon->u32ClientID);
+ if (RT_SUCCESS(rc))
+ {
+ /* sanity */
+ pDataCon->pCtl = NULL;
+ pDataCon->u32ClientID = 0;
+ return VINF_SUCCESS;
+ }
+ WARN(("VBoxMpCrCtlConDisconnect failed, rc %d", rc));
+ return rc;
+}
+
+typedef struct VBOXMP_CRSHGSMICON_BUFDR
+{
+ uint32_t cbBuf;
+ void *pvBuf;
+} VBOXMP_CRSHGSMICON_BUFDR, *PVBOXMP_CRSHGSMICON_BUFDR;
+
+typedef struct VBOXMP_CRSHGSMICON_BUFDR_CACHE
+{
+ volatile PVBOXMP_CRSHGSMICON_BUFDR pBufDr;
+} VBOXMP_CRSHGSMICON_BUFDR_CACHE, *PVBOXMP_CRSHGSMICON_BUFDR_CACHE;
+
+typedef struct VBOXMP_CRSHGSMITRANSPORT
+{
+ PVBOXMP_DEVEXT pDevExt;
+ VBOXMP_CRSHGSMICON_BUFDR_CACHE WbDrCache;
+} VBOXMP_CRSHGSMITRANSPORT, *PVBOXMP_CRSHGSMITRANSPORT;
+
+/** the rx buffer passed here is only valid in the context of the callback.
+ * the callee must NOT free it or use outside of the callback context.
+ * */
+typedef DECLCALLBACK(void) FNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc, void *pvRx, uint32_t cbRx, void *pvCtx);
+typedef FNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION *PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION;
+
+typedef DECLCALLBACK(void) FNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc, void *pvCtx);
+typedef FNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION *PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION;
+
+int VBoxMpCrShgsmiTransportCreate(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_DEVEXT pDevExt);
+void VBoxMpCrShgsmiTransportTerm(PVBOXMP_CRSHGSMITRANSPORT pCon);
+void* VBoxMpCrShgsmiTransportCmdCreateWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t u32ClientID, void *pvBuffer, uint32_t cbBuffer,
+ PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion, uint32_t cbContextData);
+void* VBoxMpCrShgsmiTransportCmdCreateWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t u32ClientID, void *pvBuffer, uint32_t cbBuffer,
+ PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion, uint32_t cbContextData);
+int VBoxMpCrShgsmiTransportCmdSubmitWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext);
+int VBoxMpCrShgsmiTransportCmdSubmitWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext);
+void VBoxMpCrShgsmiTransportCmdTermWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext);
+void VBoxMpCrShgsmiTransportCmdTermWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext);
+
+void* VBoxMpCrShgsmiTransportBufAlloc(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t cbBuffer);
+void VBoxMpCrShgsmiTransportBufFree(PVBOXMP_CRSHGSMITRANSPORT pCon, void* pvBuffer);
+
+typedef struct VBOXMP_CRPACKER
+{
+ CRPackContext CrPacker;
+ CRPackBuffer CrBuffer;
+} VBOXMP_CRPACKER, *PVBOXMP_CRPACKER;
+
+DECLINLINE(void) VBoxMpCrPackerInit(PVBOXMP_CRPACKER pPacker)
+{
+ memset(pPacker, 0, sizeof (*pPacker));
+}
+
+DECLINLINE(void) VBoxMpCrPackerTerm(PVBOXMP_CRPACKER pPacker)
+{}
+
+DECLINLINE(void) VBoxMpCrPackerTxBufferInit(PVBOXMP_CRPACKER pPacker, void *pvBuffer, uint32_t cbBuffer, uint32_t cCommands)
+{
+ crPackInitBuffer(&pPacker->CrBuffer, pvBuffer, cbBuffer, cbBuffer, cCommands);
+ crPackSetBuffer(&pPacker->CrPacker, &pPacker->CrBuffer);
+}
+
+DECLINLINE(CRMessageOpcodes*) vboxMpCrPackerPrependHeader( const CRPackBuffer *pBuffer, uint32_t *cbData, void **ppvPackBuffer)
+{
+ UINT num_opcodes;
+ CRMessageOpcodes *hdr;
+
+ Assert(pBuffer);
+ Assert(pBuffer->opcode_current < pBuffer->opcode_start);
+ Assert(pBuffer->opcode_current >= pBuffer->opcode_end);
+ Assert(pBuffer->data_current > pBuffer->data_start);
+ Assert(pBuffer->data_current <= pBuffer->data_end);
+
+ num_opcodes = (UINT)(pBuffer->opcode_start - pBuffer->opcode_current);
+ hdr = (CRMessageOpcodes *)
+ ( pBuffer->data_start - ( ( num_opcodes + 3 ) & ~0x3 ) - sizeof(*hdr) );
+
+ Assert((void *) hdr >= pBuffer->pack);
+
+ hdr->header.type = CR_MESSAGE_OPCODES;
+ hdr->numOpcodes = num_opcodes;
+
+ *cbData = (UINT)(pBuffer->data_current - (unsigned char *) hdr);
+ *ppvPackBuffer = pBuffer->pack;
+
+ return hdr;
+}
+
+DECLINLINE(void*) VBoxMpCrPackerTxBufferComplete(PVBOXMP_CRPACKER pPacker, uint32_t *pcbBuffer, void **ppvPackBuffer)
+{
+ crPackReleaseBuffer(&pPacker->CrPacker);
+ uint32_t cbData;
+ CRMessageOpcodes *pHdr;
+ void *pvPackBuffer;
+ if (pPacker->CrBuffer.opcode_current != pPacker->CrBuffer.opcode_start)
+ pHdr = vboxMpCrPackerPrependHeader(&pPacker->CrBuffer, &cbData, &pvPackBuffer);
+ else
+ {
+ cbData = 0;
+ pHdr = NULL;
+ pvPackBuffer = NULL;
+ }
+ *pcbBuffer = cbData;
+ *ppvPackBuffer = pvPackBuffer;
+ return pHdr;
+}
+
+DECLINLINE(uint32_t) VBoxMpCrPackerTxBufferGetFreeBufferSize(PVBOXMP_CRPACKER pPacker)
+{
+ return (uint32_t)(pPacker->CrBuffer.data_end - pPacker->CrBuffer.data_start);
+}
+
+DECLINLINE(void) vboxMpCrUnpackerRxWriteback(CRMessageWriteback *pWb)
+{
+ int *pWriteback;
+ memcpy(&pWriteback, &(pWb->writeback_ptr), sizeof (pWriteback));
+ (*pWriteback)--;
+}
+
+DECLINLINE(void) vboxMpCrUnpackerRxReadback(CRMessageReadback *pRb, uint32_t cbRx)
+{
+ int cbPayload = cbRx - sizeof (*pRb);
+ int *pWriteback;
+ void *pDst;
+ memcpy(&pWriteback, &(pRb->writeback_ptr), sizeof (pWriteback));
+ memcpy(&pDst, &(pRb->readback_ptr), sizeof (pDst));
+
+ (*pWriteback)--;
+ memcpy(pDst, ((uint8_t*)pRb) + sizeof (*pRb), cbPayload);
+}
+
+DECLINLINE(int) VBoxMpCrUnpackerRxBufferProcess(void *pvBuffer, uint32_t cbBuffer)
+{
+ CRMessage *pMsg = (CRMessage*)pvBuffer;
+ switch (pMsg->header.type)
+ {
+ case CR_MESSAGE_WRITEBACK:
+ vboxMpCrUnpackerRxWriteback(&(pMsg->writeback));
+ return VINF_SUCCESS;
+ case CR_MESSAGE_READBACK:
+ vboxMpCrUnpackerRxReadback(&(pMsg->readback), cbBuffer);
+ return VINF_SUCCESS;
+ default:
+ WARN(("unknown msg code %d", pMsg->header.type));
+ return VERR_NOT_SUPPORTED;
+ }
+}
+
+DECLINLINE(void*) VBoxMpCrCmdRxReadbackData(CRMessageReadback *pRx)
+{
+ return (void*)(pRx+1);
+}
+
+DECLINLINE(uint32_t) VBoxMpCrCmdRxReadbackDataSize(CRMessageReadback *pRx, uint32_t cbRx)
+{
+ return cbRx - sizeof (*pRx);
+}
+int VBoxMpCrCmdRxReadbackHandler(CRMessageReadback *pRx, uint32_t cbRx);
+int VBoxMpCrCmdRxHandler(CRMessageHeader *pRx, uint32_t cbRx);
+
+/* must be called after calling VBoxMpCrCtlConIs3DSupported only */
+uint32_t VBoxMpCrGetHostCaps();
+
+#define VBOXMP_CRCMD_HEADER_SIZE sizeof (CRMessageOpcodes)
+/* last +4 below is 4-aligned command opcode size (i.e. ((1 + 3) & ~3)) */
+#define VBOXMP_CRCMD_SIZE_WINDOWPOSITION (20 + 4)
+#define VBOXMP_CRCMD_SIZE_WINDOWVISIBLEREGIONS(_cRects) (16 + (_cRects) * 4 * sizeof (GLint) + 4)
+#define VBOXMP_CRCMD_SIZE_VBOXTEXPRESENT(_cRects) (28 + (_cRects) * 4 * sizeof (GLint) + 4)
+#define VBOXMP_CRCMD_SIZE_WINDOWSHOW (16 + 4)
+#define VBOXMP_CRCMD_SIZE_WINDOWSIZE (20 + 4)
+#define VBOXMP_CRCMD_SIZE_GETCHROMIUMPARAMETERVCR (36 + 4)
+#define VBOXMP_CRCMD_SIZE_CHROMIUMPARAMETERICR (16 + 4)
+#define VBOXMP_CRCMD_SIZE_WINDOWCREATE (256 + 28 + 4)
+#define VBOXMP_CRCMD_SIZE_WINDOWDESTROY (12 + 4)
+#define VBOXMP_CRCMD_SIZE_CREATECONTEXT (256 + 32 + 4)
+#define VBOXMP_CRCMD_SIZE_DESTROYCONTEXT (12 + 4)
+
#endif /* #ifndef ___VBoxMPCr_h__ */
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCrUtil.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCrUtil.cpp
index fdcea8d3..0eca622c 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCrUtil.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCrUtil.cpp
@@ -31,7 +31,10 @@ DECLEXPORT(void) crMemset( void *ptr, int value, unsigned int bytes );
DECLEXPORT(void) crMemZero( void *ptr, unsigned int bytes );
DECLEXPORT(int) crMemcmp( const void *p1, const void *p2, unsigned int bytes );
DECLEXPORT(void) crDebug(const char *format, ... );
+#ifndef DEBUG_misha
DECLEXPORT(void) crWarning(const char *format, ... );
+#endif
+
DECLEXPORT(void) crInfo(const char *format, ... );
DECLEXPORT(void) crError(const char *format, ... );
@@ -73,10 +76,12 @@ DECLEXPORT(void) crDebug(const char *format, ... )
}
+#ifndef DEBUG_misha
DECLEXPORT(void) crWarning(const char *format, ... )
{
}
+#endif
DECLEXPORT(void) crInfo(const char *format, ... )
{
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPMisc.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPMisc.cpp
index 83f8ca21..b6d74cd6 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPMisc.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPMisc.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -193,7 +193,7 @@ PVBOXWDDM_SWAPCHAIN vboxWddmSwapchainCreate(UINT w, UINT h)
pSwapchain->Pos.x = pSwapchain->Pos.y = VBOXWDDM_INVALID_COORD;
pSwapchain->width = w;
pSwapchain->height = h;
- VBoxWddmVrListInit(&pSwapchain->VisibleRegions);
+ VBoxVrListInit(&pSwapchain->VisibleRegions);
}
return pSwapchain;
}
@@ -208,7 +208,7 @@ DECLINLINE(BOOLEAN) vboxWddmSwapchainRetainLocked(PVBOXWDDM_SWAPCHAIN pSwapchain
return FALSE;
}
-DECLINLINE(BOOLEAN) vboxWddmSwapchainRetain(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain)
+BOOLEAN vboxWddmSwapchainRetain(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain)
{
KIRQL OldIrql;
BOOLEAN bRc;
@@ -218,35 +218,40 @@ DECLINLINE(BOOLEAN) vboxWddmSwapchainRetain(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SW
return bRc;
}
-DECLINLINE(VOID) vboxWddmSwapchainRelease(PVBOXWDDM_SWAPCHAIN pSwapchain)
+VOID vboxWddmSwapchainRelease(PVBOXWDDM_SWAPCHAIN pSwapchain)
{
const uint32_t cRefs = ASMAtomicDecU32(&pSwapchain->cRefs);
Assert(cRefs < UINT32_MAX/2);
if (!cRefs)
{
- VBoxWddmVrListClear(&pSwapchain->VisibleRegions);
+ VBoxVrListClear(&pSwapchain->VisibleRegions);
vboxWddmMemFree(pSwapchain);
}
}
-PVBOXWDDM_SWAPCHAIN vboxWddmSwapchainRetainByAlloc(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAlloc)
+PVBOXWDDM_SWAPCHAIN vboxWddmSwapchainRetainByAllocData(PVBOXMP_DEVEXT pDevExt, const struct VBOXWDDM_ALLOC_DATA *pAllocData)
{
KIRQL OldIrql;
PVBOXWDDM_SWAPCHAIN pSwapchain;
KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
- pSwapchain = pAlloc->pSwapchain;
+ pSwapchain = pAllocData->pSwapchain;
if (pSwapchain && !vboxWddmSwapchainRetainLocked(pSwapchain))
pSwapchain = NULL;
KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
return pSwapchain;
}
+PVBOXWDDM_SWAPCHAIN vboxWddmSwapchainRetainByAlloc(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOCATION *pAlloc)
+{
+ return vboxWddmSwapchainRetainByAllocData(pDevExt, &pAlloc->AllocData);
+}
+
VOID vboxWddmSwapchainAllocRemove(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain, PVBOXWDDM_ALLOCATION pAlloc)
{
KIRQL OldIrql;
KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
- Assert(pAlloc->pSwapchain == pSwapchain);
- pAlloc->pSwapchain = NULL;
+ Assert(pAlloc->AllocData.pSwapchain == pSwapchain);
+ pAlloc->AllocData.pSwapchain = NULL;
RemoveEntryList(&pAlloc->SwapchainEntry);
KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
vboxWddmSwapchainRelease(pSwapchain);
@@ -256,17 +261,17 @@ BOOLEAN vboxWddmSwapchainAllocAdd(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pS
{
KIRQL OldIrql;
BOOLEAN bRc;
- Assert(!pAlloc->pSwapchain);
+ Assert(!pAlloc->AllocData.pSwapchain);
KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
bRc = vboxWddmSwapchainRetainLocked(pSwapchain);
if (bRc)
{
- if (pAlloc->pSwapchain)
+ if (pAlloc->AllocData.pSwapchain)
{
RemoveEntryList(&pAlloc->SwapchainEntry);
}
InsertTailList(&pSwapchain->AllocList, &pAlloc->SwapchainEntry);
- pAlloc->pSwapchain = pSwapchain;
+ pAlloc->AllocData.pSwapchain = pSwapchain;
}
KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
return bRc;
@@ -286,8 +291,8 @@ static VOID vboxWddmSwapchainAllocRemoveAllInternal(PVBOXMP_DEVEXT pDevExt, PVBO
{
PVBOXWDDM_ALLOCATION pAlloc = VBOXSCENTRY_2_ALLOC(pEntry);
pEntry = pEntry->Flink;
- Assert(pAlloc->pSwapchain == pSwapchain);
- pAlloc->pSwapchain = NULL;
+ Assert(pAlloc->AllocData.pSwapchain == pSwapchain);
+ pAlloc->AllocData.pSwapchain = NULL;
RemoveEntryList(&pAlloc->SwapchainEntry);
++cRemoved;
}
@@ -312,16 +317,6 @@ VOID vboxWddmSwapchainDestroy(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapc
{
vboxWddmSwapchainAllocRemoveAllInternal(pDevExt, pSwapchain, TRUE);
- Assert(pSwapchain->pContext);
- if (pSwapchain->pContext)
- {
- NTSTATUS tmpStatus = vboxVdmaGgCmdCancel(pDevExt, pSwapchain->pContext, pSwapchain);
- if (tmpStatus != STATUS_SUCCESS)
- {
- WARN(("vboxVdmaGgCmdCancel returned Status (0x%x)", tmpStatus));
- }
- }
-
vboxWddmSwapchainRelease(pSwapchain);
}
@@ -347,7 +342,7 @@ static VOID vboxWddmSwapchainCtxRemoveLocked(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_C
Assert(pTst == pSwapchain);
RemoveEntryList(&pSwapchain->DevExtListEntry);
pSwapchain->hSwapchainKm = NULL;
- VBoxWddmVrListClear(&pSwapchain->VisibleRegions);
+ VBoxVrListClear(&pSwapchain->VisibleRegions);
vboxWddmSwapchainRelease(pSwapchain);
}
@@ -356,9 +351,10 @@ static VOID vboxWddmSwapchainCtxRemoveLocked(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_C
BOOLEAN vboxWddmSwapchainCtxAdd(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
{
BOOLEAN bRc;
- ExAcquireFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_DATA
+ VBOXWDDM_CTXLOCK_LOCK(pDevExt);
bRc = vboxWddmSwapchainCtxAddLocked(pDevExt, pContext, pSwapchain);
- ExReleaseFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_UNLOCK(pDevExt);
return bRc;
}
@@ -366,9 +362,10 @@ BOOLEAN vboxWddmSwapchainCtxAdd(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pConte
* */
VOID vboxWddmSwapchainCtxRemove(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
{
- ExAcquireFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_DATA
+ VBOXWDDM_CTXLOCK_LOCK(pDevExt);
vboxWddmSwapchainCtxRemoveLocked(pDevExt, pContext, pSwapchain);
- ExReleaseFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_UNLOCK(pDevExt);
}
/* destroys all swapchains for the given context
@@ -376,9 +373,10 @@ VOID vboxWddmSwapchainCtxRemove(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pConte
VOID vboxWddmSwapchainCtxDestroyAll(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext)
{
VBOXWDDM_HTABLE_ITERATOR Iter;
+ VBOXWDDM_CTXLOCK_DATA
do
{
- ExAcquireFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_LOCK(pDevExt);
vboxWddmHTableIterInit(&pContext->Swapchains, &Iter);
PVBOXWDDM_SWAPCHAIN pSwapchain = (PVBOXWDDM_SWAPCHAIN)vboxWddmHTableIterNext(&Iter, NULL);
if (!pSwapchain)
@@ -387,30 +385,48 @@ VOID vboxWddmSwapchainCtxDestroyAll(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pC
/* yes, we can call remove locked even when using iterator */
vboxWddmSwapchainCtxRemoveLocked(pDevExt, pContext, pSwapchain);
- ExReleaseFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_UNLOCK(pDevExt);
/* we must not do vboxWddmSwapchainDestroy inside a context mutex */
vboxWddmSwapchainDestroy(pDevExt, pSwapchain);
/* start from the very beginning, we will quit the loop when no swapchains left */
} while (1);
/* no swapchains left, we exiteed the while loop via the "break", and we still owning the mutex */
- ExReleaseFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_UNLOCK(pDevExt);
}
/* process the swapchain info passed from user-mode display driver & synchronizes the driver state with it */
NTSTATUS vboxWddmSwapchainCtxEscape(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXDISPIFESCAPE_SWAPCHAININFO pSwapchainInfo, UINT cbSize)
{
- Assert((cbSize >= RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[0])));
if (cbSize < RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[0]))
+ {
+ WARN(("invalid cbSize1 %d", cbSize));
return STATUS_INVALID_PARAMETER;
- Assert(cbSize >= RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[pSwapchainInfo->SwapchainInfo.cAllocs]));
+ }
+
if (cbSize < RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[pSwapchainInfo->SwapchainInfo.cAllocs]))
+ {
return STATUS_INVALID_PARAMETER;
+ WARN(("invalid cbSize2 %d", cbSize));
+ }
+
+ if (!pSwapchainInfo->SwapchainInfo.winHostID)
+ {
+ WARN(("Zero winHostID specified!"));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (!pContext)
+ {
+ WARN(("vboxWddmSwapchainCtxEscape: no context specified"));
+ return STATUS_INVALID_PARAMETER;
+ }
PVBOXWDDM_SWAPCHAIN pSwapchain = NULL;
PVBOXWDDM_ALLOCATION *apAlloc = NULL;
Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
NTSTATUS Status = STATUS_SUCCESS;
+ VBOXWDDM_CTXLOCK_DATA
do {
if (pSwapchainInfo->SwapchainInfo.cAllocs)
@@ -452,12 +468,12 @@ NTSTATUS vboxWddmSwapchainCtxEscape(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pC
if (pSwapchainInfo->SwapchainInfo.hSwapchainKm)
{
- ExAcquireFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_LOCK(pDevExt);
pSwapchain = (PVBOXWDDM_SWAPCHAIN)vboxWddmHTableGet(&pContext->Swapchains, (VBOXWDDM_HANDLE)pSwapchainInfo->SwapchainInfo.hSwapchainKm);
Assert(pSwapchain);
if (!pSwapchain)
{
- ExReleaseFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_UNLOCK(pDevExt);
Status = STATUS_INVALID_PARAMETER;
break;
}
@@ -465,7 +481,7 @@ NTSTATUS vboxWddmSwapchainCtxEscape(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pC
Assert(pSwapchain->pContext == pContext);
if (pSwapchain->pContext != pContext)
{
- ExReleaseFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_UNLOCK(pDevExt);
Status = STATUS_INVALID_PARAMETER;
break;
}
@@ -479,7 +495,7 @@ NTSTATUS vboxWddmSwapchainCtxEscape(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pC
break;
}
- ExAcquireFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_LOCK(pDevExt);
BOOLEAN bRc = vboxWddmSwapchainCtxAddLocked(pDevExt, pContext, pSwapchain);
Assert(bRc);
}
@@ -492,7 +508,7 @@ NTSTATUS vboxWddmSwapchainCtxEscape(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pC
/* do not zero up the view rect since it may still be valid */
// memset(&pSwapchain->ViewRect, 0, sizeof (pSwapchain->ViewRect));
/* @todo: do we really need to zero this up here ? */
- VBoxWddmVrListClear(&pSwapchain->VisibleRegions);
+ VBoxVrListClear(&pSwapchain->VisibleRegions);
vboxWddmSwapchainAllocRemoveAll(pDevExt, pSwapchain);
@@ -503,13 +519,18 @@ NTSTATUS vboxWddmSwapchainCtxEscape(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pC
vboxWddmSwapchainAllocAdd(pDevExt, pSwapchain, apAlloc[i]);
}
pSwapchain->hSwapchainUm = pSwapchainInfo->SwapchainInfo.hSwapchainUm;
+ if (pSwapchain->winHostID != pSwapchainInfo->SwapchainInfo.winHostID)
+ {
+ pSwapchain->fExposed = FALSE;
+ pSwapchain->winHostID = pSwapchainInfo->SwapchainInfo.winHostID;
+ }
}
else
{
vboxWddmSwapchainCtxRemoveLocked(pDevExt, pContext, pSwapchain);
}
- ExReleaseFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_UNLOCK(pDevExt);
if (pSwapchainInfo->SwapchainInfo.cAllocs)
{
@@ -551,8 +572,6 @@ VOID vboxWddmSwapchainCtxTerm(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext
vboxWddmHTableDestroy(&pContext->Swapchains);
}
-#define VBOXWDDM_REG_DRVKEY_PREFIX L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\"
-
NTSTATUS vboxWddmRegQueryDrvKeyName(PVBOXMP_DEVEXT pDevExt, ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult)
{
WCHAR fallBackBuf[2];
@@ -585,13 +604,6 @@ NTSTATUS vboxWddmRegQueryDrvKeyName(PVBOXMP_DEVEXT pDevExt, ULONG cbBuf, PWCHAR
return Status;
}
-#define VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_VISTA L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Control\\VIDEO\\"
-#define VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7 L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\UnitedVideo\\CONTROL\\VIDEO\\"
-
-#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELX L"Attach.RelativeX"
-#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELY L"Attach.RelativeY"
-#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_DESKTOP L"Attach.ToDesktop"
-
NTSTATUS vboxWddmRegQueryDisplaySettingsKeyName(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult)
{
@@ -613,7 +625,7 @@ NTSTATUS vboxWddmRegQueryDisplaySettingsKeyName(PVBOXMP_DEVEXT pDevExt, D3DDDI_V
}
else
{
- Assert(ver == WIN7 || ver == WIN8);
+ Assert(ver == WIN7 || ver == WIN8 || ver == WIN81);
pKeyPrefix = VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7;
cbKeyPrefix = sizeof (VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7);
}
@@ -639,13 +651,61 @@ NTSTATUS vboxWddmRegQueryDisplaySettingsKeyName(PVBOXMP_DEVEXT pDevExt, D3DDDI_V
return Status;
}
-#define VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\"
-#define VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY L"\\Video"
-
-NTSTATUS vboxWddmRegQueryVideoGuidString(ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult)
+NTSTATUS vboxWddmRegQueryVideoGuidString(PVBOXMP_DEVEXT pDevExt, ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult)
{
- HANDLE hKey;
- NTSTATUS Status = vboxWddmRegOpenKey(&hKey, VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY, GENERIC_READ);
+ BOOLEAN fNewMethodSucceeded = FALSE;
+ HANDLE hKey = NULL;
+ NTSTATUS Status = IoOpenDeviceRegistryKey(pDevExt->pPDO, PLUGPLAY_REGKEY_DEVICE, GENERIC_READ, &hKey);
+ if (NT_SUCCESS(Status))
+ {
+ struct
+ {
+ KEY_VALUE_PARTIAL_INFORMATION Info;
+ UCHAR Buf[1024]; /* should be enough */
+ } KeyData;
+ ULONG cbResult;
+ UNICODE_STRING RtlStr;
+ RtlInitUnicodeString(&RtlStr, L"VideoID");
+ Status = ZwQueryValueKey(hKey,
+ &RtlStr,
+ KeyValuePartialInformation,
+ &KeyData.Info,
+ sizeof(KeyData),
+ &cbResult);
+ if (NT_SUCCESS(Status))
+ {
+ if (KeyData.Info.Type == REG_SZ)
+ {
+ fNewMethodSucceeded = TRUE;
+ *pcbResult = KeyData.Info.DataLength + 2;
+ if (cbBuf >= KeyData.Info.DataLength)
+ {
+ memcpy(pBuf, KeyData.Info.Data, KeyData.Info.DataLength + 2);
+ Status = STATUS_SUCCESS;
+ }
+ else
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+ }
+ else
+ {
+ WARN(("ZwQueryValueKey failed, Status 0x%x", Status));
+ }
+
+ NTSTATUS tmpStatus = ZwClose(hKey);
+ Assert(tmpStatus == STATUS_SUCCESS);
+ }
+ else
+ {
+ WARN(("IoOpenDeviceRegistryKey failed Status 0x%x", Status));
+ }
+
+ if (fNewMethodSucceeded)
+ return Status;
+ else
+ WARN(("failed to acquire the VideoID, falling back to the old impl"));
+
+ Status = vboxWddmRegOpenKey(&hKey, VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY, GENERIC_READ);
Assert(Status == STATUS_SUCCESS);
if (Status == STATUS_SUCCESS)
{
@@ -727,17 +787,22 @@ NTSTATUS vboxWddmRegQueryVideoGuidString(ULONG cbBuf, PWCHAR pBuf, PULONG pcbRes
return Status;
}
-NTSTATUS vboxWddmRegOpenKey(OUT PHANDLE phKey, IN PWCHAR pName, IN ACCESS_MASK fAccess)
+NTSTATUS vboxWddmRegOpenKeyEx(OUT PHANDLE phKey, IN HANDLE hRootKey, IN PWCHAR pName, IN ACCESS_MASK fAccess)
{
OBJECT_ATTRIBUTES ObjAttr;
UNICODE_STRING RtlStr;
RtlInitUnicodeString(&RtlStr, pName);
- InitializeObjectAttributes(&ObjAttr, &RtlStr, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
+ InitializeObjectAttributes(&ObjAttr, &RtlStr, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, hRootKey, NULL);
return ZwOpenKey(phKey, fAccess, &ObjAttr);
}
+NTSTATUS vboxWddmRegOpenKey(OUT PHANDLE phKey, IN PWCHAR pName, IN ACCESS_MASK fAccess)
+{
+ return vboxWddmRegOpenKeyEx(phKey, NULL, pName, fAccess);
+}
+
NTSTATUS vboxWddmRegOpenDisplaySettingsKey(IN PVBOXMP_DEVEXT pDeviceExtension, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, OUT PHANDLE phKey)
{
WCHAR Buf[512];
@@ -813,6 +878,50 @@ NTSTATUS vboxWddmDisplaySettingsQueryPos(IN PVBOXMP_DEVEXT pDeviceExtension, D3D
return Status;
}
+NTSTATUS vboxWddmRegDrvFlagsSet(PVBOXMP_DEVEXT pDevExt, DWORD fVal)
+{
+ HANDLE hKey = NULL;
+ NTSTATUS Status = IoOpenDeviceRegistryKey(pDevExt->pPDO, PLUGPLAY_REGKEY_DRIVER, GENERIC_WRITE, &hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("IoOpenDeviceRegistryKey failed, Status = 0x%x", Status));
+ return Status;
+ }
+
+ Status = vboxWddmRegSetValueDword(hKey, VBOXWDDM_REG_DRV_FLAGS_NAME, fVal);
+ if (!NT_SUCCESS(Status))
+ WARN(("vboxWddmRegSetValueDword failed, Status = 0x%x", Status));
+
+ NTSTATUS tmpStatus = ZwClose(hKey);
+ Assert(tmpStatus == STATUS_SUCCESS);
+
+ return Status;
+}
+
+DWORD vboxWddmRegDrvFlagsGet(PVBOXMP_DEVEXT pDevExt, DWORD fDefault)
+{
+ HANDLE hKey = NULL;
+ NTSTATUS Status = IoOpenDeviceRegistryKey(pDevExt->pPDO, PLUGPLAY_REGKEY_DRIVER, GENERIC_READ, &hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("IoOpenDeviceRegistryKey failed, Status = 0x%x", Status));
+ return fDefault;
+ }
+
+ DWORD dwVal = 0;
+ Status = vboxWddmRegQueryValueDword(hKey, VBOXWDDM_REG_DRV_FLAGS_NAME, &dwVal);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxWddmRegQueryValueDword failed, Status = 0x%x", Status));
+ dwVal = fDefault;
+ }
+
+ NTSTATUS tmpStatus = ZwClose(hKey);
+ Assert(tmpStatus == STATUS_SUCCESS);
+
+ return dwVal;
+}
+
NTSTATUS vboxWddmRegQueryValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT PDWORD pDword)
{
struct
@@ -842,7 +951,7 @@ NTSTATUS vboxWddmRegQueryValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT PDWORD
return STATUS_INVALID_PARAMETER;
}
-NTSTATUS vboxWddmRegSetValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT DWORD val)
+NTSTATUS vboxWddmRegSetValueDword(IN HANDLE hKey, IN PWCHAR pName, IN DWORD val)
{
UNICODE_STRING RtlStr;
RtlInitUnicodeString(&RtlStr, pName);
@@ -861,7 +970,7 @@ UNICODE_STRING* vboxWddmVGuidGet(PVBOXMP_DEVEXT pDevExt)
Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
WCHAR VideoGuidBuf[512];
ULONG cbVideoGuidBuf = sizeof (VideoGuidBuf);
- NTSTATUS Status = vboxWddmRegQueryVideoGuidString(cbVideoGuidBuf, VideoGuidBuf, &cbVideoGuidBuf);
+ NTSTATUS Status = vboxWddmRegQueryVideoGuidString(pDevExt ,cbVideoGuidBuf, VideoGuidBuf, &cbVideoGuidBuf);
Assert(Status == STATUS_SUCCESS);
if (Status == STATUS_SUCCESS)
{
@@ -1240,7 +1349,7 @@ NTSTATUS vboxVideoAMgrCtxAllocSubmit(PVBOXMP_DEVEXT pDevExt, PVBOXVIDEOCM_ALLOC_
NTSTATUS Status = STATUS_SUCCESS;
UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[cBuffers]));
- PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, cbCmd);
+ PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
if (pDr)
{
// vboxVdmaCBufDrCreate zero initializes the pDr
@@ -1265,7 +1374,7 @@ NTSTATUS vboxVideoAMgrCtxAllocSubmit(PVBOXMP_DEVEXT pDevExt, PVBOXVIDEOCM_ALLOC_
#endif
pBufCmd->offBuffer = pRef->pAlloc->offData + pBufInfo->Info.offData;
pBufCmd->cbBuffer = pBufInfo->Info.cbData;
- pBufCmd->u32GuestData = pBufInfo->Info.bDoNotSignalCompletion;
+ pBufCmd->u32GuestData = 0;
pBufCmd->u64GuestData = (uint64_t)pRef;
}
else
@@ -1402,6 +1511,8 @@ NTSTATUS vboxVideoAMgrCtxDestroy(PVBOXVIDEOCM_ALLOC_CONTEXT pCtx)
if (!pRef)
break;
+ Assert(0);
+
Status = vboxVideoAMgrCtxAllocDestroy(pCtx, pRef->hSessionHandle);
Assert(Status == STATUS_SUCCESS);
if (Status != STATUS_SUCCESS)
@@ -1598,750 +1709,6 @@ BOOLEAN vboxShRcTreeRemove(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAlloc)
}
#endif
-
-/* visible rects */
-typedef struct VBOXWDDMVR_REG
-{
- LIST_ENTRY ListEntry;
- RECT Rect;
-} VBOXWDDMVR_REG, *PVBOXWDDMVR_REG;
-
-#define PVBOXWDDMVR_REG_FROM_ENTRY(_pEntry) ((PVBOXWDDMVR_REG)(((uint8_t*)(_pEntry)) - RT_OFFSETOF(VBOXWDDMVR_REG, ListEntry)))
-
-#ifdef DEBUG_misha
-//# define VBOXVDBG_VR_LAL_DISABLE
-#endif
-
-#ifndef VBOXVDBG_VR_LAL_DISABLE
-static LOOKASIDE_LIST_EX g_VBoxWddmVrLookasideList;
-#endif
-
-static PVBOXWDDMVR_REG vboxWddmVrRegCreate()
-{
-#ifndef VBOXVDBG_VR_LAL_DISABLE
- PVBOXWDDMVR_REG pReg = (PVBOXWDDMVR_REG)ExAllocateFromLookasideListEx(&g_VBoxWddmVrLookasideList);
- if (!pReg)
- {
- WARN(("ExAllocateFromLookasideListEx failed!"));
- }
- return pReg;
-#else
- return (PVBOXWDDMVR_REG)vboxWddmMemAlloc(sizeof (VBOXWDDMVR_REG));
-#endif
-}
-
-static void vboxWddmVrRegTerm(PVBOXWDDMVR_REG pReg)
-{
-#ifndef VBOXVDBG_VR_LAL_DISABLE
- ExFreeToLookasideListEx(&g_VBoxWddmVrLookasideList, pReg);
-#else
- vboxWddmMemFree(pReg);
-#endif
-}
-
-void VBoxWddmVrListClear(PVBOXWDDMVR_LIST pList)
-{
- PLIST_ENTRY pNext;
- for (PLIST_ENTRY pEntry = pList->ListHead.Flink; pEntry != &pList->ListHead; pEntry = pNext)
- {
- pNext = pEntry->Flink;
- PVBOXWDDMVR_REG pReg = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry);
- vboxWddmVrRegTerm(pReg);
- }
- VBoxWddmVrListInit(pList);
-}
-
-#define VBOXWDDMVR_MEMTAG 'vDBV'
-
-NTSTATUS VBoxWddmVrInit()
-{
-#ifndef VBOXVDBG_VR_LAL_DISABLE
- NTSTATUS Status = ExInitializeLookasideListEx(&g_VBoxWddmVrLookasideList,
- NULL, /* PALLOCATE_FUNCTION_EX Allocate */
- NULL, /* PFREE_FUNCTION_EX Free */
- NonPagedPool,
- 0, /* ULONG Flags */
- sizeof (VBOXWDDMVR_REG),
- VBOXWDDMVR_MEMTAG,
- 0 /* USHORT Depth - reserved, must be null */
- );
- if (!NT_SUCCESS(Status))
- {
- WARN(("ExInitializeLookasideListEx failed, Status (0x%x)", Status));
- return Status;
- }
-#endif
-
- return STATUS_SUCCESS;
-}
-
-void VBoxWddmVrTerm()
-{
-#ifndef VBOXVDBG_VR_LAL_DISABLE
- ExDeleteLookasideListEx(&g_VBoxWddmVrLookasideList);
-#endif
-}
-
-typedef DECLCALLBACK(int) FNVBOXWDDMVR_CB_COMPARATOR(const PVBOXWDDMVR_REG pReg1, const PVBOXWDDMVR_REG pReg2);
-typedef FNVBOXWDDMVR_CB_COMPARATOR *PFNVBOXWDDMVR_CB_COMPARATOR;
-
-static DECLCALLBACK(int) vboxWddmVrRegNonintersectedComparator(const RECT* pRect1, const RECT* pRect2)
-{
- Assert(!vboxWddmRectIsIntersect(pRect1, pRect2));
- if (pRect1->top != pRect2->top)
- return pRect1->top - pRect2->top;
- return pRect1->left - pRect2->left;
-}
-
-#ifdef DEBUG_misha
-static void vboxWddmVrDbgListDoVerify(PVBOXWDDMVR_LIST pList)
-{
- PLIST_ENTRY pEntry1 = pList->ListHead.Flink;
-
- for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->Flink)
- {
- PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
- for (PLIST_ENTRY pEntry2 = pEntry1->Flink; pEntry2 != &pList->ListHead; pEntry2 = pEntry2->Flink)
- {
- PVBOXWDDMVR_REG pReg2 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry2);
- Assert(vboxWddmVrRegNonintersectedComparator(&pReg1->Rect, &pReg2->Rect) < 0);
- }
- }
-}
-
-#define vboxWddmVrDbgListVerify vboxWddmVrDbgListDoVerify
-#else
-#define vboxWddmVrDbgListVerify(_p) do {} while (0)
-#endif
-
-static NTSTATUS vboxWddmVrListUniteIntersection(PVBOXWDDMVR_LIST pList, PVBOXWDDMVR_LIST pIntersection);
-
-#define VBOXWDDMVR_INVALID_COORD (~0UL)
-
-DECLINLINE(void) vboxWddmVrListRegAdd(PVBOXWDDMVR_LIST pList, PVBOXWDDMVR_REG pReg, PLIST_ENTRY pPlace, BOOLEAN fAfter)
-{
- if (fAfter)
- InsertHeadList(pPlace, &pReg->ListEntry);
- else
- InsertTailList(pPlace, &pReg->ListEntry);
- ++pList->cEntries;
- vboxWddmVrDbgListVerify(pList);
-}
-
-DECLINLINE(void) vboxWddmVrListRegRemove(PVBOXWDDMVR_LIST pList, PVBOXWDDMVR_REG pReg)
-{
- RemoveEntryList(&pReg->ListEntry);
- --pList->cEntries;
-}
-
-static void vboxWddmVrListRegAddOrder(PVBOXWDDMVR_LIST pList, PLIST_ENTRY pMemberEntry, PVBOXWDDMVR_REG pReg)
-{
- do
- {
- if (pMemberEntry != &pList->ListHead)
- {
- PVBOXWDDMVR_REG pMemberReg = PVBOXWDDMVR_REG_FROM_ENTRY(pMemberEntry);
- if (vboxWddmVrRegNonintersectedComparator(&pMemberReg->Rect, &pReg->Rect) < 0)
- {
- pMemberEntry = pMemberEntry->Flink;
- continue;
- }
- }
- vboxWddmVrListRegAdd(pList, pReg, pMemberEntry, FALSE);
- break;
- } while (1);
-}
-
-static void vboxWddmVrListAddNonintersected(PVBOXWDDMVR_LIST pList1, PVBOXWDDMVR_LIST pList2)
-{
- PLIST_ENTRY pEntry1 = pList1->ListHead.Flink;
-
- for (PLIST_ENTRY pEntry2 = pList2->ListHead.Flink; pEntry2 != &pList2->ListHead; pEntry2 = pList2->ListHead.Flink)
- {
- PVBOXWDDMVR_REG pReg2 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry2);
- do {
- if (pEntry1 != &pList1->ListHead)
- {
- PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
- if (vboxWddmVrRegNonintersectedComparator(&pReg1->Rect, &pReg2->Rect) < 0)
- {
- pEntry1 = pEntry1->Flink;
- continue;
- }
- }
- vboxWddmVrListRegRemove(pList2, pReg2);
- vboxWddmVrListRegAdd(pList1, pReg2, pEntry1, FALSE);
- break;
- } while (1);
- }
-
- Assert(VBoxWddmVrListIsEmpty(pList2));
-}
-
-static NTSTATUS vboxWddmVrListRegIntersectSubstNoJoin(PVBOXWDDMVR_LIST pList1, PVBOXWDDMVR_REG pReg1, const RECT * pRect2)
-{
- UINT topLim = VBOXWDDMVR_INVALID_COORD;
- UINT bottomLim = VBOXWDDMVR_INVALID_COORD;
- LIST_ENTRY List;
- PVBOXWDDMVR_REG pBottomReg = NULL;
-#ifdef DEBUG_misha
- RECT tmpRect = pReg1->Rect;
- vboxWddmVrDbgListVerify(pList1);
-#endif
-
- InitializeListHead(&List);
-
- Assert(vboxWddmRectIsIntersect(&pReg1->Rect, pRect2));
-
- if (pReg1->Rect.top < pRect2->top)
- {
- Assert(pRect2->top < pReg1->Rect.bottom);
- PVBOXWDDMVR_REG pRegResult = vboxWddmVrRegCreate();
- pRegResult->Rect.top = pReg1->Rect.top;
- pRegResult->Rect.left = pReg1->Rect.left;
- pRegResult->Rect.bottom = pRect2->top;
- pRegResult->Rect.right = pReg1->Rect.right;
- topLim = pRect2->top;
- InsertTailList(&List, &pRegResult->ListEntry);
- }
-
- if (pReg1->Rect.bottom > pRect2->bottom)
- {
- Assert(pRect2->bottom > pReg1->Rect.top);
- PVBOXWDDMVR_REG pRegResult = vboxWddmVrRegCreate();
- pRegResult->Rect.top = pRect2->bottom;
- pRegResult->Rect.left = pReg1->Rect.left;
- pRegResult->Rect.bottom = pReg1->Rect.bottom;
- pRegResult->Rect.right = pReg1->Rect.right;
- bottomLim = pRect2->bottom;
- pBottomReg = pRegResult;
- }
-
- if (pReg1->Rect.left < pRect2->left)
- {
- Assert(pRect2->left < pReg1->Rect.right);
- PVBOXWDDMVR_REG pRegResult = vboxWddmVrRegCreate();
- pRegResult->Rect.top = topLim == VBOXWDDMVR_INVALID_COORD ? pReg1->Rect.top : topLim;
- pRegResult->Rect.left = pReg1->Rect.left;
- pRegResult->Rect.bottom = bottomLim == VBOXWDDMVR_INVALID_COORD ? pReg1->Rect.bottom : bottomLim;
- pRegResult->Rect.right = pRect2->left;
- InsertTailList(&List, &pRegResult->ListEntry);
- }
-
- if (pReg1->Rect.right > pRect2->right)
- {
- Assert(pRect2->right > pReg1->Rect.left);
- PVBOXWDDMVR_REG pRegResult = vboxWddmVrRegCreate();
- pRegResult->Rect.top = topLim == VBOXWDDMVR_INVALID_COORD ? pReg1->Rect.top : topLim;
- pRegResult->Rect.left = pRect2->right;
- pRegResult->Rect.bottom = bottomLim == VBOXWDDMVR_INVALID_COORD ? pReg1->Rect.bottom : bottomLim;
- pRegResult->Rect.right = pReg1->Rect.right;
- InsertTailList(&List, &pRegResult->ListEntry);
- }
-
- if (pBottomReg)
- InsertTailList(&List, &pBottomReg->ListEntry);
-
- PLIST_ENTRY pMemberEntry = pReg1->ListEntry.Flink;
- vboxWddmVrListRegRemove(pList1, pReg1);
- vboxWddmVrRegTerm(pReg1);
-
- if (IsListEmpty(&List))
- return STATUS_SUCCESS; /* the region is covered by the pRect2 */
-
- PLIST_ENTRY pEntry = List.Flink, pNext;
- for (; pEntry != &List; pEntry = pNext)
- {
- pNext = pEntry->Flink;
- PVBOXWDDMVR_REG pReg = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry);
-
- vboxWddmVrListRegAddOrder(pList1, pMemberEntry, pReg);
- pMemberEntry = pEntry->Flink; /* the following elements should go after the given pEntry since they are ordered already */
- }
- return STATUS_SUCCESS;
-}
-
-typedef DECLCALLBACK(PLIST_ENTRY) FNVBOXWDDMVR_CB_INTERSECTED_VISITOR(PVBOXWDDMVR_LIST pList1, PVBOXWDDMVR_REG pReg1, const RECT * pRect2, void *pvContext, PLIST_ENTRY *ppNext);
-typedef FNVBOXWDDMVR_CB_INTERSECTED_VISITOR *PFNVBOXWDDMVR_CB_INTERSECTED_VISITOR;
-
-static void vboxWddmVrListVisitIntersected(PVBOXWDDMVR_LIST pList1, UINT cRects, const RECT *aRects, PFNVBOXWDDMVR_CB_INTERSECTED_VISITOR pfnVisitor, void* pvVisitor)
-{
- PLIST_ENTRY pEntry1 = pList1->ListHead.Flink;
- PLIST_ENTRY pNext1;
- UINT iFirst2 = 0;
-
- for (; pEntry1 != &pList1->ListHead; pEntry1 = pNext1)
- {
- pNext1 = pEntry1->Flink;
- PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
- for (UINT i = iFirst2; i < cRects; ++i)
- {
- const RECT *pRect2 = &aRects[i];
- if (pReg1->Rect.bottom <= pRect2->top)
- continue;
- else if (pRect2->bottom <= pReg1->Rect.top)
- continue;
- /* y coords intersect */
- else if (pReg1->Rect.right <= pRect2->left)
- continue;
- else if (pRect2->right <= pReg1->Rect.left)
- continue;
- /* x coords intersect */
-
- /* the visitor can modify the list 1, apply necessary adjustments after it */
- PLIST_ENTRY pEntry1 = pfnVisitor (pList1, pReg1, pRect2, pvVisitor, &pNext1);
- if (pEntry1 == &pList1->ListHead)
- break;
- }
- }
-}
-
-
-static void vboxWddmVrListJoinRectsHV(PVBOXWDDMVR_LIST pList, BOOLEAN fHorizontal)
-{
- PLIST_ENTRY pNext1, pNext2;
-
- for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pNext1)
- {
- PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
- pNext1 = pEntry1->Flink;
- for (PLIST_ENTRY pEntry2 = pEntry1->Flink; pEntry2 != &pList->ListHead; pEntry2 = pNext2)
- {
- PVBOXWDDMVR_REG pReg2 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry2);
- pNext2 = pEntry2->Flink;
- if (fHorizontal)
- {
- if (pReg1->Rect.top == pReg2->Rect.top)
- {
- if (pReg1->Rect.right == pReg2->Rect.left)
- {
- /* join rectangles */
- vboxWddmVrListRegRemove(pList, pReg2);
- if (pReg1->Rect.bottom > pReg2->Rect.bottom)
- {
- LONG oldRight1 = pReg1->Rect.right;
- LONG oldBottom1 = pReg1->Rect.bottom;
- pReg1->Rect.right = pReg2->Rect.right;
- pReg1->Rect.bottom = pReg2->Rect.bottom;
-
- vboxWddmVrDbgListVerify(pList);
-
- pReg2->Rect.left = pReg1->Rect.left;
- pReg2->Rect.top = pReg1->Rect.bottom;
- pReg2->Rect.right = oldRight1;
- pReg2->Rect.bottom = oldBottom1;
- vboxWddmVrListRegAddOrder(pList, pReg1->ListEntry.Flink, pReg2);
- /* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
- * and thus can match one of the previous rects */
- pNext1 = pList->ListHead.Flink;
- break;
- }
- else if (pReg1->Rect.bottom < pReg2->Rect.bottom)
- {
- pReg1->Rect.right = pReg2->Rect.right;
- vboxWddmVrDbgListVerify(pList);
- pReg2->Rect.top = pReg1->Rect.bottom;
- vboxWddmVrListRegAddOrder(pList, pReg1->ListEntry.Flink, pReg2);
- /* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
- * and thus can match one of the previous rects */
- pNext1 = pList->ListHead.Flink;
- break;
- }
- else
- {
- pReg1->Rect.right = pReg2->Rect.right;
- vboxWddmVrDbgListVerify(pList);
- /* reset the pNext1 since it could be the pReg2 being destroyed */
- pNext1 = pEntry1->Flink;
- /* pNext2 stays the same since it is pReg2->ListEntry.pNext, which is kept intact */
- vboxWddmVrRegTerm(pReg2);
- }
- }
- continue;
- }
- else if (pReg1->Rect.bottom == pReg2->Rect.bottom)
- {
- Assert(pReg1->Rect.top < pReg2->Rect.top); /* <- since pReg1 > pReg2 && pReg1->Rect.top != pReg2->Rect.top*/
- if (pReg1->Rect.right == pReg2->Rect.left)
- {
- /* join rectangles */
- vboxWddmVrListRegRemove(pList, pReg2);
-
- pReg1->Rect.bottom = pReg2->Rect.top;
- vboxWddmVrDbgListVerify(pList);
- pReg2->Rect.left = pReg1->Rect.left;
-
- vboxWddmVrListRegAddOrder(pList, pReg2->ListEntry.Flink, pReg2);
-
- /* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
- * and thus can match one of the previous rects */
- pNext1 = pList->ListHead.Flink;
- break;
- }
- else if (pReg1->Rect.left == pReg2->Rect.right)
- {
- /* join rectangles */
- vboxWddmVrListRegRemove(pList, pReg2);
-
- pReg1->Rect.bottom = pReg2->Rect.top;
- vboxWddmVrDbgListVerify(pList);
- pReg2->Rect.right = pReg1->Rect.right;
-
- vboxWddmVrListRegAddOrder(pList, pReg2->ListEntry.Flink, pReg2);
-
- /* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
- * and thus can match one of the previous rects */
- pNext1 = pList->ListHead.Flink;
- break;
- }
- continue;
- }
- }
- else
- {
- if (pReg1->Rect.bottom == pReg2->Rect.top)
- {
- if (pReg1->Rect.left == pReg2->Rect.left)
- {
- if (pReg1->Rect.right == pReg2->Rect.right)
- {
- /* join rects */
- vboxWddmVrListRegRemove(pList, pReg2);
-
- pReg1->Rect.bottom = pReg2->Rect.bottom;
- vboxWddmVrDbgListVerify(pList);
-
- /* reset the pNext1 since it could be the pReg2 being destroyed */
- pNext1 = pEntry1->Flink;
- /* pNext2 stays the same since it is pReg2->ListEntry.pNext, which is kept intact */
- vboxWddmVrRegTerm(pReg2);
- continue;
- }
- /* no more to be done for for pReg1 */
- break;
- }
- else if (pReg1->Rect.right > pReg2->Rect.left)
- {
- /* no more to be done for for pReg1 */
- break;
- }
-
- continue;
- }
- else if (pReg1->Rect.bottom < pReg2->Rect.top)
- {
- /* no more to be done for for pReg1 */
- break;
- }
- }
- }
- }
-}
-
-static void vboxWddmVrListJoinRects(PVBOXWDDMVR_LIST pList)
-{
- vboxWddmVrListJoinRectsHV(pList, TRUE);
- vboxWddmVrListJoinRectsHV(pList, FALSE);
-}
-
-typedef struct VBOXWDDMVR_CBDATA_SUBST
-{
- NTSTATUS Status;
- BOOLEAN fChanged;
-} VBOXWDDMVR_CBDATA_SUBST, *PVBOXWDDMVR_CBDATA_SUBST;
-
-static DECLCALLBACK(PLIST_ENTRY) vboxWddmVrListSubstNoJoinCb(PVBOXWDDMVR_LIST pList, PVBOXWDDMVR_REG pReg1, const RECT *pRect2, void *pvContext, PLIST_ENTRY *ppNext)
-{
- PVBOXWDDMVR_CBDATA_SUBST pData = (PVBOXWDDMVR_CBDATA_SUBST)pvContext;
- /* store the prev to get the new Flink out of it*/
- PLIST_ENTRY pPrev = pReg1->ListEntry.Blink;
- pData->fChanged = TRUE;
-
- Assert(vboxWddmRectIsIntersect(&pReg1->Rect, pRect2));
-
- /* NOTE: the pReg1 will be invalid after the vboxWddmVrListRegIntersectSubstNoJoin call!!! */
- NTSTATUS Status = vboxWddmVrListRegIntersectSubstNoJoin(pList, pReg1, pRect2);
- if (NT_SUCCESS(Status))
- {
- *ppNext = pPrev->Flink;
- return &pList->ListHead;
- }
- WARN(("vboxWddmVrListRegIntersectSubstNoJoin failed!"));
- Assert(!NT_SUCCESS(Status));
- pData->Status = Status;
- *ppNext = &pList->ListHead;
- return &pList->ListHead;
-}
-
-static NTSTATUS vboxWddmVrListSubstNoJoin(PVBOXWDDMVR_LIST pList, UINT cRects, const PRECT aRects, BOOLEAN *pfChanged)
-{
- if (VBoxWddmVrListIsEmpty(pList))
- return STATUS_SUCCESS;
-
- VBOXWDDMVR_CBDATA_SUBST Data;
- Data.Status = STATUS_SUCCESS;
- Data.fChanged = FALSE;
-
- *pfChanged = FALSE;
-
- vboxWddmVrListVisitIntersected(pList, cRects, aRects, vboxWddmVrListSubstNoJoinCb, &Data);
- if (!NT_SUCCESS(Data.Status))
- {
- WARN(("vboxWddmVrListVisitIntersected failed!"));
- return Data.Status;
- }
-
- *pfChanged = Data.fChanged;
- return STATUS_SUCCESS;
-}
-
-#if 0
-static const PRECT vboxWddmVrRectsOrder(UINT cRects, const PRECT aRects)
-{
-#ifdef DEBUG
- {
- for (UINT i = 0; i < cRects; ++i)
- {
- RECT *pRectI = &aRects[i];
- for (UINT j = i + 1; j < cRects; ++j)
- {
- RECT *pRectJ = &aRects[j];
- Assert(!vboxWddmRectIsIntersect(pRectI, pRectJ));
- }
- }
- }
-#endif
-
- RECT * pRects = (RECT *)aRects;
- /* check if rects are ordered already */
- for (UINT i = 0; i < cRects - 1; ++i)
- {
- RECT *pRect1 = &pRects[i];
- RECT *pRect2 = &pRects[i+1];
- if (vboxWddmVrRegNonintersectedComparator(pRect1, pRect2) < 0)
- continue;
-
- WARN(("rects are unoreded!"));
-
- if (pRects == aRects)
- {
- pRects = (RECT *)vboxWddmMemAlloc(sizeof (RECT) * cRects);
- if (!pRects)
- {
- WARN(("vboxWddmMemAlloc failed!"));
- return NULL;
- }
-
- memcpy(pRects, aRects, sizeof (RECT) * cRects);
- }
-
- Assert(pRects != aRects);
-
- int j = (int)i - 1;
- do {
- RECT Tmp = *pRect1;
- *pRect1 = *pRect2;
- *pRect2 = Tmp;
-
- if (j < 0)
- break;
-
- if (vboxWddmVrRegNonintersectedComparator(pRect1, pRect1-1) > 0)
- break;
-
- pRect2 = pRect1--;
- --j;
- } while (1);
- }
-
- return pRects;
-}
-#endif
-
-void VBoxWddmVrListTranslate(PVBOXWDDMVR_LIST pList, LONG x, LONG y)
-{
- for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->Flink)
- {
- PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
- vboxWddmRectTranslate(&pReg1->Rect, x, y);
- }
-}
-
-NTSTATUS VBoxWddmVrListRectsSubst(PVBOXWDDMVR_LIST pList, UINT cRects, const PRECT aRects, BOOLEAN *pfChanged)
-{
-#if 0
- const PRECT pRects = vboxWddmVrRectsOrder(cRects, aRects);
- if (!pRects)
- {
- WARN(("vboxWddmVrRectsOrder failed!"));
- return STATUS_NO_MEMORY;
- }
-#endif
-
- NTSTATUS Status = vboxWddmVrListSubstNoJoin(pList, cRects, aRects, pfChanged);
- if (!NT_SUCCESS(Status))
- {
- WARN(("vboxWddmVrListSubstNoJoin failed!"));
- goto done;
- }
-
- if (!*pfChanged)
- goto done;
-
- vboxWddmVrListJoinRects(pList);
-
-done:
-#if 0
- if (pRects != aRects)
- vboxWddmMemFree(pRects);
-#endif
- return Status;
-}
-
-NTSTATUS VBoxWddmVrListRectsAdd(PVBOXWDDMVR_LIST pList, UINT cRects, const PRECT aRects, BOOLEAN *pfChanged)
-{
- UINT cCovered = 0;
-
-#if 0
-#ifdef DEBUG
- {
- for (UINT i = 0; i < cRects; ++i)
- {
- RECT *pRectI = &aRects[i];
- for (UINT j = i + 1; j < cRects; ++j)
- {
- RECT *pRectJ = &aRects[j];
- Assert(!vboxWddmRectIsIntersect(pRectI, pRectJ));
- }
- }
- }
-#endif
-#endif
-
- /* early sort out the case when there are no new rects */
- for (UINT i = 0; i < cRects; ++i)
- {
- for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->Flink)
- {
- PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
- if (vboxWddmRectIsCoveres(&pReg1->Rect, &aRects[i]))
- {
- cCovered++;
- break;
- }
- }
- }
-
- if (cCovered == cRects)
- {
- *pfChanged = FALSE;
- return STATUS_SUCCESS;
- }
-
- /* rects are not covered, need to go the slow way */
-
- VBOXWDDMVR_LIST DiffList;
- VBoxWddmVrListInit(&DiffList);
- PRECT pListRects = NULL;
- UINT cAllocatedRects = 0;
- BOOLEAN fNeedRectreate = TRUE;
- BOOLEAN fChanged = FALSE;
- NTSTATUS Status = STATUS_SUCCESS;
-
- for (UINT i = 0; i < cRects; ++i)
- {
- PVBOXWDDMVR_REG pReg = vboxWddmVrRegCreate();
- if (!pReg)
- {
- WARN(("vboxWddmVrRegCreate failed!"));
- Status = STATUS_NO_MEMORY;
- break;
- }
- pReg->Rect = aRects[i];
-
- UINT cListRects = VBoxWddmVrListRectsCount(pList);
- if (!cListRects)
- {
- vboxWddmVrListRegAdd(pList, pReg, &pList->ListHead, FALSE);
- fChanged = TRUE;
- continue;
- }
- else
- {
- Assert(VBoxWddmVrListIsEmpty(&DiffList));
- vboxWddmVrListRegAdd(&DiffList, pReg, &DiffList.ListHead, FALSE);
- }
-
- if (cAllocatedRects < cListRects)
- {
- cAllocatedRects = cListRects + cRects;
- Assert(fNeedRectreate);
- if (pListRects)
- vboxWddmMemFree(pListRects);
- pListRects = (PRECT)vboxWddmMemAlloc(sizeof (RECT) * cAllocatedRects);
- if (!pListRects)
- {
- WARN(("vboxWddmMemAllocZero failed!"));
- Status = STATUS_NO_MEMORY;
- break;
- }
- }
-
-
- if (fNeedRectreate)
- {
- Status = VBoxWddmVrListRectsGet(pList, cListRects, pListRects);
- Assert(Status == STATUS_SUCCESS);
- fNeedRectreate = FALSE;
- }
-
- BOOLEAN fDummyChanged = FALSE;
- Status = vboxWddmVrListSubstNoJoin(&DiffList, cListRects, pListRects, &fDummyChanged);
- if (!NT_SUCCESS(Status))
- {
- WARN(("vboxWddmVrListSubstNoJoin failed!"));
- Status = STATUS_NO_MEMORY;
- break;
- }
-
- if (!VBoxWddmVrListIsEmpty(&DiffList))
- {
- vboxWddmVrListAddNonintersected(pList, &DiffList);
- fNeedRectreate = TRUE;
- fChanged = TRUE;
- }
-
- Assert(VBoxWddmVrListIsEmpty(&DiffList));
- }
-
- if (pListRects)
- vboxWddmMemFree(pListRects);
-
- Assert(VBoxWddmVrListIsEmpty(&DiffList) || Status != STATUS_SUCCESS);
- VBoxWddmVrListClear(&DiffList);
-
- if (fChanged)
- vboxWddmVrListJoinRects(pList);
-
- *pfChanged = fChanged;
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS VBoxWddmVrListRectsGet(PVBOXWDDMVR_LIST pList, UINT cRects, PRECT aRects)
-{
- if (cRects < VBoxWddmVrListRectsCount(pList))
- return STATUS_BUFFER_TOO_SMALL;
-
- UINT i = 0;
- for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->Flink, ++i)
- {
- PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
- aRects[i] = pReg1->Rect;
- }
- return STATUS_SUCCESS;
-}
-
NTSTATUS vboxWddmDrvCfgInit(PUNICODE_STRING pRegStr)
{
HANDLE hKey;
@@ -2527,16 +1894,24 @@ static int vboxWddmSlConfigure(PVBOXMP_DEVEXT pDevExt, uint32_t fFlags)
NTSTATUS VBoxWddmSlEnableVSyncNotification(PVBOXMP_DEVEXT pDevExt, BOOLEAN fEnable)
{
+ if (!pDevExt->bVSyncTimerEnabled == !fEnable)
+ return STATUS_SUCCESS;
+
if (!fEnable)
{
KeCancelTimer(&pDevExt->VSyncTimer);
}
else
{
+ KeQuerySystemTime((PLARGE_INTEGER)&pDevExt->VSyncTime);
+
LARGE_INTEGER DueTime;
DueTime.QuadPart = -166666LL; /* 60 Hz */
KeSetTimerEx(&pDevExt->VSyncTimer, DueTime, 16, &pDevExt->VSyncDpc);
}
+
+ pDevExt->bVSyncTimerEnabled = !!fEnable;
+
return STATUS_SUCCESS;
}
@@ -2547,16 +1922,37 @@ NTSTATUS VBoxWddmSlGetScanLine(PVBOXMP_DEVEXT pDevExt, DXGKARG_GETSCANLINE *pGet
Assert(pTarget->HeightTotal);
Assert(pTarget->HeightVisible);
Assert(pTarget->HeightTotal >= pTarget->HeightVisible);
- Assert(pTarget->ScanLineState < pTarget->HeightTotal);
if (pTarget->HeightTotal)
{
- uint32_t curScanLine = pTarget->ScanLineState;
- ++pTarget->ScanLineState;
- if (pTarget->ScanLineState >= pTarget->HeightTotal)
- pTarget->ScanLineState = 0;
+ uint32_t curScanLine;
+ BOOL bVBlank;
+ LARGE_INTEGER DevVSyncTime;
+ DevVSyncTime.QuadPart = ASMAtomicReadU64((volatile uint64_t*)&pDevExt->VSyncTime.QuadPart);
+ LARGE_INTEGER VSyncTime;
+ KeQuerySystemTime(&VSyncTime);
+ if (VSyncTime.QuadPart < DevVSyncTime.QuadPart)
+ {
+ WARN(("vsync time is less than the one stored in device"));
+ curScanLine = 0;
+ }
+ else
+ {
+ VSyncTime.QuadPart = VSyncTime.QuadPart - DevVSyncTime.QuadPart;
+ /* time is in 100ns, */
+ curScanLine = (uint32_t)((pTarget->HeightTotal * VSyncTime.QuadPart) / DevVSyncTime.QuadPart);
+ if (pDevExt->bVSyncTimerEnabled)
+ {
+ if (curScanLine >= pTarget->HeightTotal)
+ curScanLine = 0;
+ }
+ else
+ {
+ curScanLine %= pTarget->HeightTotal;
+ }
+ }
- BOOL bVBlank = (!curScanLine || curScanLine > pTarget->HeightVisible);
+ bVBlank = (!curScanLine || curScanLine > pTarget->HeightVisible);
pGetScanLine->ScanLine = curScanLine;
pGetScanLine->InVerticalBlank = bVBlank;
}
@@ -2568,36 +1964,21 @@ NTSTATUS VBoxWddmSlGetScanLine(PVBOXMP_DEVEXT pDevExt, DXGKARG_GETSCANLINE *pGet
return STATUS_SUCCESS;
}
-static VOID vboxWddmSlVSyncDpc(
- __in struct _KDPC *Dpc,
- __in_opt PVOID DeferredContext,
- __in_opt PVOID SystemArgument1,
- __in_opt PVOID SystemArgument2
-)
+static BOOLEAN vboxWddmSlVSyncIrqCb(PVOID pvContext)
{
- PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)DeferredContext;
+ PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)pvContext;
DXGKARGCB_NOTIFY_INTERRUPT_DATA notify;
BOOLEAN bNeedDpc = FALSE;
for (UINT i = 0; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
{
- PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
- PVBOXWDDM_ALLOCATION pPrimary = vboxWddmAquirePrimary(pDevExt, pSource, i);
- if (pPrimary)
+ PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
+ if (pTarget->fConnected)
{
- VBOXVIDEOOFFSET offVram = pPrimary->AllocData.Addr.offVram;
- if (offVram != VBOXVIDEOOFFSET_VOID)
- {
- memset(&notify, 0, sizeof(DXGKARGCB_NOTIFY_INTERRUPT_DATA));
- notify.InterruptType = DXGK_INTERRUPT_CRTC_VSYNC;
- /* @todo: !!!this is not correct in case we want source[i]->target[i!=j] mapping */
- notify.CrtcVsync.VidPnTargetId = i;
- notify.CrtcVsync.PhysicalAddress.QuadPart = offVram;
- /* yes, we can report VSync at dispatch */
- pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, &notify);
- bNeedDpc = TRUE;
- }
-
- vboxWddmAllocationRelease(pPrimary);
+ memset(&notify, 0, sizeof(DXGKARGCB_NOTIFY_INTERRUPT_DATA));
+ notify.InterruptType = DXGK_INTERRUPT_CRTC_VSYNC;
+ notify.CrtcVsync.VidPnTargetId = i;
+ pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, &notify);
+ bNeedDpc = TRUE;
}
}
@@ -2605,10 +1986,43 @@ static VOID vboxWddmSlVSyncDpc(
{
pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
}
+
+ return FALSE;
+}
+
+static VOID vboxWddmSlVSyncDpc(
+ __in struct _KDPC *Dpc,
+ __in_opt PVOID DeferredContext,
+ __in_opt PVOID SystemArgument1,
+ __in_opt PVOID SystemArgument2
+)
+{
+ PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)DeferredContext;
+ Assert(!pDevExt->fVSyncInVBlank);
+ ASMAtomicWriteU32(&pDevExt->fVSyncInVBlank, 1);
+
+ BOOLEAN bDummy;
+ NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
+ pDevExt->u.primary.DxgkInterface.DeviceHandle,
+ vboxWddmSlVSyncIrqCb,
+ pDevExt,
+ 0, /* IN ULONG MessageNumber */
+ &bDummy);
+ if (!NT_SUCCESS(Status))
+ WARN(("DxgkCbSynchronizeExecution failed Status %#x", Status));
+
+ LARGE_INTEGER VSyncTime;
+ KeQuerySystemTime(&VSyncTime);
+ ASMAtomicWriteU64((volatile uint64_t*)&pDevExt->VSyncTime.QuadPart, VSyncTime.QuadPart);
+
+ ASMAtomicWriteU32(&pDevExt->fVSyncInVBlank, 0);
}
NTSTATUS VBoxWddmSlInit(PVBOXMP_DEVEXT pDevExt)
{
+ pDevExt->bVSyncTimerEnabled = FALSE;
+ pDevExt->fVSyncInVBlank = 0;
+ KeQuerySystemTime((PLARGE_INTEGER)&pDevExt->VSyncTime);
KeInitializeTimer(&pDevExt->VSyncTimer);
KeInitializeDpc(&pDevExt->VSyncDpc, vboxWddmSlVSyncDpc, pDevExt);
return STATUS_SUCCESS;
@@ -2667,7 +2081,7 @@ void vboxWddmDmAdjustDefaultVramLocations(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_P
pSource = &pDevExt->aSources[i];
if (pSource->AllocData.Addr.offVram != PhAddr.QuadPart
|| pSource->AllocData.Addr.SegmentId != 1)
- pSource->bGhSynced = FALSE;
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
pSource->AllocData.Addr.SegmentId = 1;
pSource->AllocData.Addr.offVram = PhAddr.QuadPart;
}
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPMisc.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPMisc.h
index 27a919c0..742ecc22 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPMisc.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPMisc.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -71,9 +71,10 @@ PVOID vboxWddmHTableGet(PVBOXWDDM_HTABLE pTbl, VBOXWDDM_HANDLE hHandle);
PVBOXWDDM_SWAPCHAIN vboxWddmSwapchainCreate();
-DECLINLINE(BOOLEAN) vboxWddmSwapchainRetain(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain);
-DECLINLINE(VOID) vboxWddmSwapchainRelease(PVBOXWDDM_SWAPCHAIN pSwapchain);
-PVBOXWDDM_SWAPCHAIN vboxWddmSwapchainRetainByAlloc(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAlloc);
+BOOLEAN vboxWddmSwapchainRetain(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain);
+VOID vboxWddmSwapchainRelease(PVBOXWDDM_SWAPCHAIN pSwapchain);
+PVBOXWDDM_SWAPCHAIN vboxWddmSwapchainRetainByAlloc(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOCATION *pAlloc);
+PVBOXWDDM_SWAPCHAIN vboxWddmSwapchainRetainByAllocData(PVBOXMP_DEVEXT pDevExt, const struct VBOXWDDM_ALLOC_DATA *pAllocData);
VOID vboxWddmSwapchainAllocRemove(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain, PVBOXWDDM_ALLOCATION pAlloc);
BOOLEAN vboxWddmSwapchainAllocAdd(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain, PVBOXWDDM_ALLOCATION pAlloc);
VOID vboxWddmSwapchainAllocRemoveAll(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain);
@@ -90,13 +91,17 @@ NTSTATUS vboxWddmRegOpenDisplaySettingsKey(IN PVBOXMP_DEVEXT pDeviceExtension, D
NTSTATUS vboxWddmRegDisplaySettingsQueryRelX(HANDLE hKey, int * pResult);
NTSTATUS vboxWddmRegDisplaySettingsQueryRelY(HANDLE hKey, int * pResult);
NTSTATUS vboxWddmDisplaySettingsQueryPos(IN PVBOXMP_DEVEXT pDeviceExtension, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, POINT * pPos);
-NTSTATUS vboxWddmRegQueryVideoGuidString(ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult);
+NTSTATUS vboxWddmRegQueryVideoGuidString(PVBOXMP_DEVEXT pDevExt, ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult);
NTSTATUS vboxWddmRegQueryDrvKeyName(PVBOXMP_DEVEXT pDevExt, ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult);
+NTSTATUS vboxWddmRegOpenKeyEx(OUT PHANDLE phKey, IN HANDLE hRootKey, IN PWCHAR pName, IN ACCESS_MASK fAccess);
NTSTATUS vboxWddmRegOpenKey(OUT PHANDLE phKey, IN PWCHAR pName, IN ACCESS_MASK fAccess);
NTSTATUS vboxWddmRegQueryValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT PDWORD pDword);
-NTSTATUS vboxWddmRegSetValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT DWORD val);
+NTSTATUS vboxWddmRegSetValueDword(IN HANDLE hKey, IN PWCHAR pName, IN DWORD val);
+
+NTSTATUS vboxWddmRegDrvFlagsSet(PVBOXMP_DEVEXT pDevExt, DWORD fVal);
+DWORD vboxWddmRegDrvFlagsGet(PVBOXMP_DEVEXT pDevExt, DWORD fDefault);
UNICODE_STRING* vboxWddmVGuidGet(PVBOXMP_DEVEXT pDevExt);
VOID vboxWddmVGuidFree(PVBOXMP_DEVEXT pDevExt);
@@ -163,40 +168,6 @@ PVBOXWDDM_ALLOCATION vboxShRcTreeGet(PVBOXMP_DEVEXT pDevExt, HANDLE hSharedRc);
BOOLEAN vboxShRcTreeRemove(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAlloc);
#endif
-/* visible rects */
-typedef struct VBOXWDDMVR_LIST
-{
- LIST_ENTRY ListHead;
- UINT cEntries;
-} VBOXWDDMVR_LIST, *PVBOXWDDMVR_LIST;
-
-DECLINLINE(UINT) VBoxWddmVrListRectsCount(PVBOXWDDMVR_LIST pList)
-{
- return pList->cEntries;
-}
-
-DECLINLINE(BOOLEAN) VBoxWddmVrListIsEmpty(PVBOXWDDMVR_LIST pList)
-{
- return !VBoxWddmVrListRectsCount(pList);
-}
-
-DECLINLINE(void) VBoxWddmVrListInit(PVBOXWDDMVR_LIST pList)
-{
- InitializeListHead(&pList->ListHead);
- pList->cEntries = 0;
-}
-
-void VBoxWddmVrListClear(PVBOXWDDMVR_LIST pList);
-
-void VBoxWddmVrListTranslate(PVBOXWDDMVR_LIST pList, LONG x, LONG y);
-
-NTSTATUS VBoxWddmVrListRectsAdd(PVBOXWDDMVR_LIST pList, UINT cRects, const PRECT aRects, BOOLEAN *pfChanged);
-NTSTATUS VBoxWddmVrListRectsSubst(PVBOXWDDMVR_LIST pList, UINT cRects, const PRECT aRects, BOOLEAN *pfChanged);
-NTSTATUS VBoxWddmVrListRectsGet(PVBOXWDDMVR_LIST pList, UINT cRects, PRECT aRects);
-
-NTSTATUS VBoxWddmVrInit();
-void VBoxWddmVrTerm();
-
NTSTATUS vboxWddmDrvCfgInit(PUNICODE_STRING pRegStr);
#ifdef VBOX_VDMA_WITH_WATCHDOG
@@ -215,4 +186,6 @@ void vboxWddmDiToAllocData(PVBOXMP_DEVEXT pDevExt, const DXGK_DISPLAY_INFORMATIO
void vboxWddmDmAdjustDefaultVramLocations(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID ModifiedVidPnSourceId);
#endif
+NTSTATUS vboxWddmChildStatusConnect(PVBOXMP_DEVEXT pDevExt, uint32_t iChild, BOOLEAN fConnect);
+
#endif /* #ifndef ___VBoxMPMisc_h__ */
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPShgsmi.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPShgsmi.cpp
index b38c5587..d10580d7 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPShgsmi.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPShgsmi.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPShgsmi.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPShgsmi.h
index 4fdc1f3e..491498f6 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPShgsmi.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPShgsmi.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -48,11 +48,18 @@ int VBoxSHGSMICommandDoneSynch(PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER* pHeade
void VBoxSHGSMICommandCancelAsynch(PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER* pHeader);
void VBoxSHGSMICommandCancelSynch(PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER* pHeader);
-DECLINLINE(HGSMIOFFSET) VBoxSHGSMICommandOffset(PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER* pHeader)
+DECLINLINE(HGSMIOFFSET) VBoxSHGSMICommandOffset(const PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER* pHeader)
{
return HGSMIHeapBufferOffset(&pHeap->Heap, (void*)pHeader);
}
+/* allows getting VRAM offset of arbitrary pointer within the SHGSMI command
+ * if invalid pointer is passed in, behavior is undefined */
+DECLINLINE(HGSMIOFFSET) VBoxSHGSMICommandPtrOffset(const PVBOXSHGSMI pHeap, const void * pvPtr)
+{
+ return HGSMIPointerToOffset (&pHeap->Heap.area, (const HGSMIBUFFERHEADER *)pvPtr);
+}
+
int VBoxSHGSMIInit(PVBOXSHGSMI pHeap, void *pvBase, HGSMISIZE cbArea, HGSMIOFFSET offBase, bool fOffsetBased);
void VBoxSHGSMITerm(PVBOXSHGSMI pHeap);
void* VBoxSHGSMIHeapAlloc(PVBOXSHGSMI pHeap, HGSMISIZE cbData, uint8_t u8Channel, uint16_t u16ChannelInfo);
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPTypes.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPTypes.h
index 701dfb78..061bc7f4 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPTypes.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPTypes.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -32,6 +32,12 @@ typedef struct VBOXWDDM_ALLOCATION *PVBOXWDDM_ALLOCATION;
#include "VBoxMPVbva.h"
#include "VBoxMPCr.h"
+#include <cr_vreg.h>
+
+#ifdef DEBUG_misha
+extern DWORD g_VBoxDbgBreakModes;
+#endif
+
#if 0
#include <iprt/avl.h>
#endif
@@ -100,8 +106,16 @@ typedef struct VBOXWDDM_ALLOC_DATA
{
VBOXWDDM_SURFACE_DESC SurfDesc;
VBOXWDDM_ADDR Addr;
+ uint32_t hostID;
+ uint32_t cHostIDRefs;
+ struct VBOXWDDM_SWAPCHAIN *pSwapchain;
} VBOXWDDM_ALLOC_DATA, *PVBOXWDDM_ALLOC_DATA;
+#define VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS 0x01
+#define VBOXWDDM_HGSYNC_F_SYNCED_LOCATION 0x02
+#define VBOXWDDM_HGSYNC_F_SYNCED_ALL (VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS | VBOXWDDM_HGSYNC_F_SYNCED_LOCATION)
+#define VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY (VBOXWDDM_HGSYNC_F_SYNCED_ALL & ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION)
+
typedef struct VBOXWDDM_SOURCE
{
struct VBOXWDDM_ALLOCATION * pPrimaryAllocation;
@@ -109,8 +123,11 @@ typedef struct VBOXWDDM_SOURCE
struct VBOXWDDM_ALLOCATION * pShadowAllocation;
#endif
VBOXWDDM_ALLOC_DATA AllocData;
+ uint8_t u8SyncState;
BOOLEAN bVisible;
- BOOLEAN bGhSynced;
+ /* specifies whether the source has 3D overlay data visible */
+ BOOLEAN fHas3DVrs;
+ VBOXVR_LIST VrList;
VBOXVBVAINFO Vbva;
#ifdef VBOX_WITH_VIDEOHWACCEL
/* @todo: in our case this seems more like a target property,
@@ -127,9 +144,13 @@ typedef struct VBOXWDDM_SOURCE
typedef struct VBOXWDDM_TARGET
{
- uint32_t ScanLineState;
uint32_t HeightVisible;
uint32_t HeightTotal;
+ /* since there coul be multiple state changes on auto-resize,
+ * we pend notifying host to avoid flickering */
+ volatile bool fStateSyncPening;
+ bool fConnected;
+ bool fConfigured;
} VBOXWDDM_TARGET, *PVBOXWDDM_TARGET;
/* allocation */
@@ -137,7 +158,6 @@ typedef struct VBOXWDDM_TARGET
typedef struct VBOXWDDM_ALLOCATION
{
LIST_ENTRY SwapchainEntry;
- struct VBOXWDDM_SWAPCHAIN *pSwapchain;
VBOXWDDM_ALLOC_TYPE enmType;
volatile uint32_t cRefs;
D3DDDI_RESOURCEFLAGS fRcFlags;
@@ -166,7 +186,6 @@ typedef struct VBOXWDDM_ALLOCATION
AVLPVNODECORE ShRcTreeEntry;
#endif
VBOXUHGSMI_BUFFER_TYPE_FLAGS fUhgsmiType;
- PKEVENT pSynchEvent;
} VBOXWDDM_ALLOCATION, *PVBOXWDDM_ALLOCATION;
typedef struct VBOXWDDM_RESOURCE
@@ -220,10 +239,12 @@ typedef struct VBOXWDDM_SWAPCHAIN
volatile uint32_t cRefs;
VBOXDISP_UMHANDLE hSwapchainUm;
VBOXDISP_KMHANDLE hSwapchainKm;
+ int32_t winHostID;
+ BOOLEAN fExposed;
POINT Pos;
UINT width;
UINT height;
- VBOXWDDMVR_LIST VisibleRegions;
+ VBOXVR_LIST VisibleRegions;
}VBOXWDDM_SWAPCHAIN, *PVBOXWDDM_SWAPCHAIN;
typedef struct VBOXWDDM_CONTEXT
@@ -234,7 +255,9 @@ typedef struct VBOXWDDM_CONTEXT
UINT NodeOrdinal;
UINT EngineAffinity;
BOOLEAN fRenderFromShadowDisabled;
+ int32_t hostID;
uint32_t u32CrConClientID;
+ VBOXMP_CRPACKER CrPacker;
VBOXWDDM_HTABLE Swapchains;
VBOXVIDEOCM_CTX CmContext;
VBOXVIDEOCM_ALLOC_CONTEXT AllocContext;
@@ -300,6 +323,7 @@ typedef struct VBOXWDDM_OPENALLOCATION
PVBOXWDDM_DEVICE pDevice;
uint32_t cShRcRefs;
uint32_t cOpens;
+ uint32_t cHostIDRefs;
} VBOXWDDM_OPENALLOCATION, *PVBOXWDDM_OPENALLOCATION;
#define VBOXWDDM_MAX_VIDEOMODES 128
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.cpp
index 93ff48f4..ac7e908c 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -19,85 +19,23 @@
#include "VBoxMPWddm.h"
#include "common/VBoxMPCommon.h"
-static int vboxVBVAInformHost (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO * pVbva, BOOL bEnable)
-{
- int rc = VERR_NO_MEMORY;
- void *p = VBoxHGSMIBufferAlloc (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
- sizeof (VBVAENABLE_EX),
- HGSMI_CH_VBVA,
- VBVA_ENABLE);
- Assert(p);
- if (!p)
- {
- LOGREL(("HGSMIHeapAlloc failed"));
- rc = VERR_NO_MEMORY;
- }
- else
- {
- VBVAENABLE_EX *pEnableEx = (VBVAENABLE_EX *)p;
- pEnableEx->u32ScreenId = pVbva->srcId;
-
- VBVAENABLE *pEnable = &pEnableEx->Base;
- pEnable->u32Flags = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
- pEnable->u32Flags |= VBVA_F_EXTENDED | VBVA_F_ABSOFFSET;
- pEnable->u32Offset = (uint32_t)pVbva->offVBVA;
- pEnable->i32Result = VERR_NOT_SUPPORTED;
-
- VBoxHGSMIBufferSubmit (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
-
- if (bEnable)
- {
- rc = pEnable->i32Result;
- AssertRC(rc);
- }
- else
- rc = VINF_SUCCESS;
-
- VBoxHGSMIBufferFree (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
- }
- return rc;
-}
-
/*
* Public hardware buffer methods.
*/
int vboxVbvaEnable (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva)
{
- VBVABUFFER *pVBVA = pVbva->pVBVA;
-
-// DISPDBG((1, "VBoxDisp::vboxVbvaEnable screen %p vbva off 0x%x\n", ppdev->pjScreen, ppdev->layout.offVBVABuffer));
-
- pVBVA->hostFlags.u32HostEvents = 0;
- pVBVA->hostFlags.u32SupportedOrders = 0;
- pVBVA->off32Data = 0;
- pVBVA->off32Free = 0;
- RtlZeroMemory (pVBVA->aRecords, sizeof (pVBVA->aRecords));
- pVBVA->indexRecordFirst = 0;
- pVBVA->indexRecordFree = 0;
- pVBVA->cbPartialWriteThreshold = 256;
- pVBVA->cbData = pVbva->cbVBVA - sizeof (VBVABUFFER) + sizeof (pVBVA->au8Data);
+ if (VBoxVBVAEnable(&pVbva->Vbva, &VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
+ pVbva->Vbva.pVBVA, pVbva->srcId))
+ return VINF_SUCCESS;
- pVbva->fHwBufferOverflow = FALSE;
- pVbva->pRecord = NULL;
-
- int rc = vboxVBVAInformHost (pDevExt, pVbva, TRUE);
- AssertRC(rc);
-
- if (!RT_SUCCESS(rc))
- vboxVbvaDisable (pDevExt, pVbva);
-
- return rc;
+ WARN(("VBoxVBVAEnable failed!"));
+ return VERR_GENERAL_FAILURE;
}
int vboxVbvaDisable (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva)
{
-// DISPDBG((1, "VBoxDisp::vbvaDisable called.\n"));
-
- pVbva->fHwBufferOverflow = FALSE;
- pVbva->pRecord = NULL;
-// ppdev->pVBVA = NULL;
-
- return vboxVBVAInformHost (pDevExt, pVbva, FALSE);
+ VBoxVBVADisable(&pVbva->Vbva, &VBoxCommonFromDeviceExt(pDevExt)->guestCtx, pVbva->srcId);
+ return VINF_SUCCESS;
}
int vboxVbvaCreate(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, ULONG offBuffer, ULONG cbBuffer, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
@@ -107,17 +45,20 @@ int vboxVbvaCreate(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, ULONG offBuffer,
KeInitializeSpinLock(&pVbva->Lock);
int rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt),
- (void**)&pVbva->pVBVA,
+ (void**)&pVbva->Vbva.pVBVA,
offBuffer,
cbBuffer);
- AssertRC(rc);
if (RT_SUCCESS(rc))
{
- Assert(pVbva->pVBVA);
- pVbva->offVBVA = offBuffer;
- pVbva->cbVBVA = cbBuffer;
+ Assert(pVbva->Vbva.pVBVA);
+ VBoxVBVASetupBufferContext(&pVbva->Vbva, offBuffer, cbBuffer);
pVbva->srcId = srcId;
}
+ else
+ {
+ WARN(("VBoxMPCmnMapAdapterMemory failed rc %d", rc));
+ }
+
return rc;
}
@@ -125,188 +66,421 @@ int vboxVbvaCreate(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, ULONG offBuffer,
int vboxVbvaDestroy(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva)
{
int rc = VINF_SUCCESS;
- VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pVbva->pVBVA);
- memset(pVbva, 0, sizeof(VBOXVBVAINFO));
+ VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pVbva->Vbva.pVBVA);
+ memset(pVbva, 0, sizeof (VBOXVBVAINFO));
return rc;
}
-/*
- * Private operations.
- */
-static uint32_t vboxHwBufferAvail (const VBVABUFFER *pVBVA)
+int vboxVbvaReportDirtyRect (PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSrc, RECT *pRectOrig)
{
- int32_t i32Diff = pVBVA->off32Data - pVBVA->off32Free;
+ VBVACMDHDR hdr;
- return i32Diff > 0? i32Diff: pVBVA->cbData + i32Diff;
+ RECT rect = *pRectOrig;
+
+// if (rect.left < 0) rect.left = 0;
+// if (rect.top < 0) rect.top = 0;
+// if (rect.right > (int)ppdev->cxScreen) rect.right = ppdev->cxScreen;
+// if (rect.bottom > (int)ppdev->cyScreen) rect.bottom = ppdev->cyScreen;
+
+ hdr.x = (int16_t)rect.left;
+ hdr.y = (int16_t)rect.top;
+ hdr.w = (uint16_t)(rect.right - rect.left);
+ hdr.h = (uint16_t)(rect.bottom - rect.top);
+
+ hdr.x += (int16_t)pSrc->VScreenPos.x;
+ hdr.y += (int16_t)pSrc->VScreenPos.y;
+
+ if (VBoxVBVAWrite(&pSrc->Vbva.Vbva, &VBoxCommonFromDeviceExt(pDevExt)->guestCtx, &hdr, sizeof(hdr)))
+ return VINF_SUCCESS;
+
+ WARN(("VBoxVBVAWrite failed"));
+ return VERR_GENERAL_FAILURE;
}
-static void vboxHwBufferFlush (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva)
+/* command vbva ring buffer */
+
+/* customized VBVA implementation */
+
+/* Forward declarations of internal functions. */
+static void vboxHwBufferPlaceDataAt(PVBVAEXBUFFERCONTEXT pCtx, const void *p,
+ uint32_t cb, uint32_t offset);
+static bool vboxHwBufferWrite(PVBVAEXBUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ const void *p, uint32_t cb);
+
+DECLINLINE(void) vboxVBVAExFlush(struct VBVAEXBUFFERCONTEXT *pCtx, PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx)
{
- /* Issue the flush command. */
- void *p = VBoxHGSMIBufferAlloc (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
- sizeof (VBVAFLUSH),
- HGSMI_CH_VBVA,
- VBVA_FLUSH);
- Assert(p);
- if (!p)
+ pCtx->pfnFlush(pCtx, pHGSMICtx, pCtx->pvFlush);
+}
+
+static int vboxCmdVbvaSubmitHgsmi(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, HGSMIOFFSET offDr)
+{
+ VBoxVideoCmnPortWriteUlong(pHGSMICtx->port, offDr);
+ return VINF_SUCCESS;
+}
+#define vboxCmdVbvaSubmit vboxCmdVbvaSubmitHgsmi
+
+static VBOXCMDVBVA_CTL * vboxCmdVbvaCtlCreate(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, uint32_t cbCtl)
+{
+ Assert(cbCtl >= sizeof (VBOXCMDVBVA_CTL));
+ return (VBOXCMDVBVA_CTL*)VBoxSHGSMICommandAlloc(&pHGSMICtx->heapCtx, cbCtl, HGSMI_CH_VBVA, VBVA_CMDVBVA_CTL);
+}
+
+static void vboxCmdVbvaCtlFree(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, VBOXCMDVBVA_CTL * pCtl)
+{
+ VBoxSHGSMICommandFree(&pHGSMICtx->heapCtx, pCtl);
+}
+
+static int vboxCmdVbvaCtlSubmitSync(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, VBOXCMDVBVA_CTL * pCtl)
+{
+ const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepSynch(&pHGSMICtx->heapCtx, pCtl);
+ if (!pHdr)
{
- LOGREL(("HGSMIHeapAlloc failed"));
+ WARN(("VBoxSHGSMICommandPrepSynch returnd NULL"));
+ return VERR_INVALID_PARAMETER;
}
- else
+
+ HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pHGSMICtx->heapCtx, pHdr);
+ if (offCmd == HGSMIOFFSET_VOID)
{
- VBVAFLUSH *pFlush = (VBVAFLUSH *)p;
+ WARN(("VBoxSHGSMICommandOffset returnd NULL"));
+ VBoxSHGSMICommandCancelSynch(&pHGSMICtx->heapCtx, pHdr);
+ return VERR_INVALID_PARAMETER;
+ }
+
+ int rc = vboxCmdVbvaSubmit(pHGSMICtx, offCmd);
+ if (RT_SUCCESS(rc))
+ {
+ rc = VBoxSHGSMICommandDoneSynch(&pHGSMICtx->heapCtx, pHdr);
+ if (RT_SUCCESS(rc))
+ {
+ rc = pCtl->i32Result;
+ if (!RT_SUCCESS(rc))
+ WARN(("pCtl->i32Result %d", pCtl->i32Result));
+
+ return rc;
+ }
+ else
+ WARN(("VBoxSHGSMICommandDoneSynch returnd %d", rc));
+ }
+ else
+ WARN(("vboxCmdVbvaSubmit returnd %d", rc));
+
+ VBoxSHGSMICommandCancelSynch(&pHGSMICtx->heapCtx, pHdr);
- pFlush->u32Reserved = 0;
+ return rc;
+}
- VBoxHGSMIBufferSubmit (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
+static int vboxCmdVbvaCtlSubmitAsync(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, VBOXCMDVBVA_CTL * pCtl, PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCompletionIrq, void *pvCompletionIrq)
+{
+ const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepAsynchIrq(&pHGSMICtx->heapCtx, pCtl, pfnCompletionIrq, pvCompletionIrq, VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE);
+ if (!pHdr)
+ {
+ WARN(("VBoxSHGSMICommandPrepAsynchIrq returnd NULL"));
+ return VERR_INVALID_PARAMETER;
+ }
- VBoxHGSMIBufferFree (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
+ HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pHGSMICtx->heapCtx, pHdr);
+ if (offCmd == HGSMIOFFSET_VOID)
+ {
+ WARN(("VBoxSHGSMICommandOffset returnd NULL"));
+ VBoxSHGSMICommandCancelAsynch(&pHGSMICtx->heapCtx, pHdr);
+ return VERR_INVALID_PARAMETER;
}
- return;
+ int rc = vboxCmdVbvaSubmit(pHGSMICtx, offCmd);
+ if (RT_SUCCESS(rc))
+ {
+ VBoxSHGSMICommandDoneAsynch(&pHGSMICtx->heapCtx, pHdr);
+ return rc;
+ }
+ else
+ WARN(("vboxCmdVbvaSubmit returnd %d", rc));
+
+ VBoxSHGSMICommandCancelAsynch(&pHGSMICtx->heapCtx, pHdr);
+
+ return rc;
}
-static void vboxHwBufferPlaceDataAt (VBVABUFFER *pVBVA, const void *p, uint32_t cb, uint32_t offset)
+static int vboxVBVAExCtlSubmitEnableDisable(PVBVAEXBUFFERCONTEXT pCtx, PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, bool fEnable)
{
- uint32_t u32BytesTillBoundary = pVBVA->cbData - offset;
- uint8_t *dst = &pVBVA->au8Data[offset];
- int32_t i32Diff = cb - u32BytesTillBoundary;
+ VBOXCMDVBVA_CTL_ENABLE *pCtl = (VBOXCMDVBVA_CTL_ENABLE*)vboxCmdVbvaCtlCreate(pHGSMICtx, sizeof (*pCtl));
+ if (!pCtl)
+ {
+ WARN(("vboxCmdVbvaCtlCreate failed"));
+ return VERR_NO_MEMORY;
+ }
- if (i32Diff <= 0)
+ pCtl->Hdr.u32Type = VBOXCMDVBVACTL_TYPE_ENABLE;
+ pCtl->Hdr.i32Result = VERR_NOT_IMPLEMENTED;
+ memset(&pCtl->Enable, 0, sizeof (pCtl->Enable));
+ pCtl->Enable.u32Flags = fEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
+ pCtl->Enable.u32Offset = pCtx->offVRAMBuffer;
+ pCtl->Enable.i32Result = VERR_NOT_SUPPORTED;
+ pCtl->Enable.u32Flags |= VBVA_F_ABSOFFSET;
+
+ int rc = vboxCmdVbvaCtlSubmitSync(pHGSMICtx, &pCtl->Hdr);
+ if (RT_SUCCESS(rc))
{
- /* Chunk will not cross buffer boundary. */
- memcpy (dst, p, cb);
+ rc = pCtl->Hdr.i32Result;
+ if (!RT_SUCCESS(rc))
+ WARN(("vboxCmdVbvaCtlSubmitSync Disable failed %d", rc));
}
else
+ WARN(("vboxCmdVbvaCtlSubmitSync returnd %d", rc));
+
+ vboxCmdVbvaCtlFree(pHGSMICtx, &pCtl->Hdr);
+
+ return rc;
+}
+
+/*
+ * Public hardware buffer methods.
+ */
+RTDECL(int) VBoxVBVAExEnable(PVBVAEXBUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ VBVABUFFER *pVBVA)
+{
+ int rc = VERR_GENERAL_FAILURE;
+
+ LogFlowFunc(("pVBVA %p\n", pVBVA));
+
+#if 0 /* All callers check this */
+ if (ppdev->bHGSMISupported)
+#endif
{
- /* Chunk crosses buffer boundary. */
- memcpy (dst, p, u32BytesTillBoundary);
- memcpy (&pVBVA->au8Data[0], (uint8_t *)p + u32BytesTillBoundary, i32Diff);
+ LogFunc(("pVBVA %p vbva off 0x%x\n", pVBVA, pCtx->offVRAMBuffer));
+
+ pVBVA->hostFlags.u32HostEvents = 0;
+ pVBVA->hostFlags.u32SupportedOrders = 0;
+ pVBVA->off32Data = 0;
+ pVBVA->off32Free = 0;
+ memset(pVBVA->aRecords, 0, sizeof (pVBVA->aRecords));
+ pVBVA->indexRecordFirst = 0;
+ pVBVA->indexRecordFree = 0;
+ pVBVA->cbPartialWriteThreshold = 256;
+ pVBVA->cbData = pCtx->cbBuffer - sizeof (VBVABUFFER) + sizeof (pVBVA->au8Data);
+
+ pCtx->fHwBufferOverflow = false;
+ pCtx->pRecord = NULL;
+ pCtx->pVBVA = pVBVA;
+
+ rc = vboxVBVAExCtlSubmitEnableDisable(pCtx, pHGSMICtx, true);
+ }
+
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("enable failed %d", rc));
+ VBoxVBVAExDisable(pCtx, pHGSMICtx);
}
+ return rc;
+}
+
+RTDECL(void) VBoxVBVAExDisable(PVBVAEXBUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx)
+{
+ LogFlowFunc(("\n"));
+
+ pCtx->fHwBufferOverflow = false;
+ pCtx->pRecord = NULL;
+ pCtx->pVBVA = NULL;
+
+ vboxVBVAExCtlSubmitEnableDisable(pCtx, pHGSMICtx, false);
+
return;
}
-BOOL vboxVbvaBufferBeginUpdate (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva)
+RTDECL(bool) VBoxVBVAExBufferBeginUpdate(PVBVAEXBUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx)
{
- BOOL bRc = FALSE;
+ bool bRc = false;
- // DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate called flags = 0x%08X\n",
- // ppdev->pVBVA? ppdev->pVBVA->u32HostEvents: -1));
+ // LogFunc(("flags = 0x%08X\n", pCtx->pVBVA? pCtx->pVBVA->u32HostEvents: -1));
- if ( pVbva->pVBVA
- && (pVbva->pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
+ if ( pCtx->pVBVA
+ && (pCtx->pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
{
uint32_t indexRecordNext;
- Assert (!pVbva->fHwBufferOverflow);
- Assert (pVbva->pRecord == NULL);
+ Assert(!pCtx->fHwBufferOverflow);
+ Assert(pCtx->pRecord == NULL);
- indexRecordNext = (pVbva->pVBVA->indexRecordFree + 1) % VBVA_MAX_RECORDS;
+ indexRecordNext = (pCtx->pVBVA->indexRecordFree + 1) % VBVA_MAX_RECORDS;
- if (indexRecordNext == pVbva->pVBVA->indexRecordFirst)
+ if (indexRecordNext == pCtx->indexRecordFirstUncompleted)
{
/* All slots in the records queue are used. */
- vboxHwBufferFlush (pDevExt, pVbva);
+ vboxVBVAExFlush (pCtx, pHGSMICtx);
}
- if (indexRecordNext == pVbva->pVBVA->indexRecordFirst)
+ if (indexRecordNext == pCtx->indexRecordFirstUncompleted)
{
-// /* Even after flush there is no place. Fail the request. */
-// LOG(("no space in the queue of records!!! first %d, last %d",
-// ppdev->pVBVA->indexRecordFirst, ppdev->pVBVA->indexRecordFree));
+ /* Even after flush there is no place. Fail the request. */
+ LogFunc(("no space in the queue of records!!! first %d, last %d\n",
+ indexRecordNext, pCtx->pVBVA->indexRecordFree));
}
else
{
/* Initialize the record. */
- VBVARECORD *pRecord = &pVbva->pVBVA->aRecords[pVbva->pVBVA->indexRecordFree];
+ VBVARECORD *pRecord = &pCtx->pVBVA->aRecords[pCtx->pVBVA->indexRecordFree];
pRecord->cbRecord = VBVA_F_RECORD_PARTIAL;
- pVbva->pVBVA->indexRecordFree = indexRecordNext;
+ pCtx->pVBVA->indexRecordFree = indexRecordNext;
- // LOG(("indexRecordNext = %d\n", indexRecordNext));
+ // LogFunc(("indexRecordNext = %d\n", indexRecordNext));
/* Remember which record we are using. */
- pVbva->pRecord = pRecord;
+ pCtx->pRecord = pRecord;
- bRc = TRUE;
+ bRc = true;
}
}
return bRc;
}
-void vboxVbvaBufferEndUpdate (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva)
+RTDECL(void) VBoxVBVAExBufferEndUpdate(PVBVAEXBUFFERCONTEXT pCtx)
{
VBVARECORD *pRecord;
- // LOG(("VBoxDisp::vboxHwBufferEndUpdate called"));
+ // LogFunc(("\n"));
- Assert(pVbva->pVBVA);
+ Assert(pCtx->pVBVA);
- pRecord = pVbva->pRecord;
- Assert (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
+ pRecord = pCtx->pRecord;
+ Assert(pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
/* Mark the record completed. */
pRecord->cbRecord &= ~VBVA_F_RECORD_PARTIAL;
- pVbva->fHwBufferOverflow = FALSE;
- pVbva->pRecord = NULL;
+ pCtx->fHwBufferOverflow = false;
+ pCtx->pRecord = NULL;
+
+ return;
+}
+
+DECLINLINE(bool) vboxVBVAExIsEntryInRange(uint32_t u32First, uint32_t u32Entry, uint32_t u32Free)
+{
+ return ( u32First != u32Free
+ && (
+ (u32First < u32Free && u32Entry >= u32First && u32Entry < u32Free)
+ || (u32First > u32Free && (u32Entry >= u32First || u32Entry < u32Free))
+ )
+ );
+}
+
+#ifdef DEBUG
+
+DECLINLINE(void) vboxHwBufferVerifyCompleted(PVBVAEXBUFFERCONTEXT pCtx)
+{
+ VBVABUFFER *pVBVA = pCtx->pVBVA;
+ if (!vboxVBVAExIsEntryInRange(pCtx->indexRecordFirstUncompleted, pVBVA->indexRecordFirst, pVBVA->indexRecordFree))
+ {
+ WARN(("invalid record set"));
+ }
+
+ if (!vboxVBVAExIsEntryInRange(pCtx->off32DataUncompleted, pVBVA->off32Data, pVBVA->off32Free))
+ {
+ WARN(("invalid data set"));
+ }
+}
+#endif
+
+/*
+ * Private operations.
+ */
+static uint32_t vboxHwBufferAvail(PVBVAEXBUFFERCONTEXT pCtx, const VBVABUFFER *pVBVA)
+{
+ int32_t i32Diff = pCtx->off32DataUncompleted - pVBVA->off32Free;
+
+ return i32Diff > 0? i32Diff: pVBVA->cbData + i32Diff;
+}
+
+static uint32_t vboxHwBufferContiguousAvail(PVBVAEXBUFFERCONTEXT pCtx, const VBVABUFFER *pVBVA)
+{
+ int32_t i32Diff = pCtx->off32DataUncompleted - pVBVA->off32Free;
+
+ return i32Diff > 0 ? i32Diff: pVBVA->cbData - pVBVA->off32Free;
+}
+
+static void vboxHwBufferPlaceDataAt(PVBVAEXBUFFERCONTEXT pCtx, const void *p,
+ uint32_t cb, uint32_t offset)
+{
+ VBVABUFFER *pVBVA = pCtx->pVBVA;
+ uint32_t u32BytesTillBoundary = pVBVA->cbData - offset;
+ uint8_t *dst = &pVBVA->au8Data[offset];
+ int32_t i32Diff = cb - u32BytesTillBoundary;
+
+ if (i32Diff <= 0)
+ {
+ /* Chunk will not cross buffer boundary. */
+ memcpy (dst, p, cb);
+ }
+ else
+ {
+ /* Chunk crosses buffer boundary. */
+ memcpy (dst, p, u32BytesTillBoundary);
+ memcpy (&pVBVA->au8Data[0], (uint8_t *)p + u32BytesTillBoundary, i32Diff);
+ }
return;
}
-static int vboxHwBufferWrite (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, const void *p, uint32_t cb)
+static bool vboxHwBufferWrite(PVBVAEXBUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ const void *p, uint32_t cb)
{
VBVARECORD *pRecord;
uint32_t cbHwBufferAvail;
uint32_t cbWritten = 0;
- VBVABUFFER *pVBVA = pVbva->pVBVA;
+ VBVABUFFER *pVBVA = pCtx->pVBVA;
Assert(pVBVA);
- if (!pVBVA || pVbva->fHwBufferOverflow)
+ if (!pVBVA || pCtx->fHwBufferOverflow)
{
- return VERR_INVALID_STATE;
+ return false;
}
- Assert (pVBVA->indexRecordFirst != pVBVA->indexRecordFree);
+ Assert(pVBVA->indexRecordFirst != pVBVA->indexRecordFree);
+ Assert(pCtx->indexRecordFirstUncompleted != pVBVA->indexRecordFree);
- pRecord = pVbva->pRecord;
- Assert (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
+ pRecord = pCtx->pRecord;
+ Assert(pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
-// LOGF(("VW %d", cb));
+ // LogFunc(("%d\n", cb));
- cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
+ cbHwBufferAvail = vboxHwBufferAvail(pCtx, pVBVA);
while (cb > 0)
{
uint32_t cbChunk = cb;
- // LOG(("pVBVA->off32Free %d, pRecord->cbRecord 0x%08X, cbHwBufferAvail %d, cb %d, cbWritten %d\n",
- // pVBVA->off32Free, pRecord->cbRecord, cbHwBufferAvail, cb, cbWritten));
+ // LogFunc(("pVBVA->off32Free %d, pRecord->cbRecord 0x%08X, cbHwBufferAvail %d, cb %d, cbWritten %d\n",
+ // pVBVA->off32Free, pRecord->cbRecord, cbHwBufferAvail, cb, cbWritten));
if (cbChunk >= cbHwBufferAvail)
{
- LOGF(("1) avail %d, chunk %d", cbHwBufferAvail, cbChunk));
+ LogFunc(("1) avail %d, chunk %d\n", cbHwBufferAvail, cbChunk));
- vboxHwBufferFlush (pDevExt, pVbva);
+ vboxVBVAExFlush(pCtx, pHGSMICtx);
- cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
+ cbHwBufferAvail = vboxHwBufferAvail(pCtx, pVBVA);
if (cbChunk >= cbHwBufferAvail)
{
- LOG(("no place for %d bytes. Only %d bytes available after flush. Going to partial writes.",
- cb, cbHwBufferAvail));
+ WARN(("no place for %d bytes. Only %d bytes available after flush. Going to partial writes.\n",
+ cb, cbHwBufferAvail));
if (cbHwBufferAvail <= pVBVA->cbPartialWriteThreshold)
{
- LOGREL(("Buffer overflow!!!"));
- pVbva->fHwBufferOverflow = TRUE;
- Assert(FALSE);
- return VERR_NO_MEMORY;
+ WARN(("Buffer overflow!!!\n"));
+ pCtx->fHwBufferOverflow = true;
+ Assert(false);
+ return false;
}
cbChunk = cbHwBufferAvail - pVBVA->cbPartialWriteThreshold;
@@ -314,9 +488,9 @@ static int vboxHwBufferWrite (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, const
}
Assert(cbChunk <= cb);
- Assert(cbChunk <= vboxHwBufferAvail (pVBVA));
+ Assert(cbChunk <= vboxHwBufferAvail(pCtx, pVBVA));
- vboxHwBufferPlaceDataAt (pVbva->pVBVA, (uint8_t *)p + cbWritten, cbChunk, pVBVA->off32Free);
+ vboxHwBufferPlaceDataAt (pCtx, (uint8_t *)p + cbWritten, cbChunk, pVBVA->off32Free);
pVBVA->off32Free = (pVBVA->off32Free + cbChunk) % pVBVA->cbData;
pRecord->cbRecord += cbChunk;
@@ -326,45 +500,632 @@ static int vboxHwBufferWrite (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, const
cbWritten += cbChunk;
}
- return VINF_SUCCESS;
+ return true;
}
/*
* Public writer to the hardware buffer.
*/
-int vboxWrite (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, const void *pv, uint32_t cb)
+RTDECL(uint32_t) VBoxVBVAExGetFreeTail(PVBVAEXBUFFERCONTEXT pCtx)
{
- return vboxHwBufferWrite (pDevExt, pVbva, pv, cb);
+ VBVABUFFER *pVBVA = pCtx->pVBVA;
+ if (pVBVA->off32Data <= pVBVA->off32Free)
+ return pVBVA->cbData - pVBVA->off32Free;
+ return 0;
}
-
-int vboxVbvaReportDirtyRect (PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSrc, RECT *pRectOrig)
+RTDECL(void*) VBoxVBVAExAllocContiguous(PVBVAEXBUFFERCONTEXT pCtx, PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, uint32_t cb)
{
- VBVACMDHDR hdr;
+ VBVARECORD *pRecord;
+ uint32_t cbHwBufferContiguousAvail;
+ uint32_t offset;
- RECT rect = *pRectOrig;
+ VBVABUFFER *pVBVA = pCtx->pVBVA;
+ Assert(pVBVA);
-// if (rect.left < 0) rect.left = 0;
-// if (rect.top < 0) rect.top = 0;
-// if (rect.right > (int)ppdev->cxScreen) rect.right = ppdev->cxScreen;
-// if (rect.bottom > (int)ppdev->cyScreen) rect.bottom = ppdev->cyScreen;
+ if (!pVBVA || pCtx->fHwBufferOverflow)
+ {
+ return NULL;
+ }
+
+ Assert(pVBVA->indexRecordFirst != pVBVA->indexRecordFree);
+ Assert(pCtx->indexRecordFirstUncompleted != pVBVA->indexRecordFree);
- hdr.x = (int16_t)rect.left;
- hdr.y = (int16_t)rect.top;
- hdr.w = (uint16_t)(rect.right - rect.left);
- hdr.h = (uint16_t)(rect.bottom - rect.top);
+ pRecord = pCtx->pRecord;
+ Assert(pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
- hdr.x += (int16_t)pSrc->VScreenPos.x;
- hdr.y += (int16_t)pSrc->VScreenPos.y;
+ // LogFunc(("%d\n", cb));
- return vboxWrite (pDevExt, &pSrc->Vbva, &hdr, sizeof(hdr));
+ if (pVBVA->cbData < cb)
+ {
+ WARN(("requested to allocate buffer of size %d bigger than the VBVA ring buffer size %d", cb, pVBVA->cbData));
+ return NULL;
+ }
+
+ cbHwBufferContiguousAvail = vboxHwBufferContiguousAvail(pCtx, pVBVA);
+
+ if (cbHwBufferContiguousAvail < cb)
+ {
+ if (cb < pVBVA->cbData - pVBVA->off32Free)
+ {
+ /* the entire contiguous part is smaller than the requested buffer */
+ return NULL;
+ }
+
+ vboxVBVAExFlush(pCtx, pHGSMICtx);
+
+ cbHwBufferContiguousAvail = vboxHwBufferContiguousAvail(pCtx, pVBVA);
+ if (cbHwBufferContiguousAvail < cb)
+ {
+ /* this is really bad - the host did not clean up buffer even after we requested it to flush */
+ WARN(("Host did not clean up the buffer!"));
+ return NULL;
+ }
+ }
+
+ offset = pVBVA->off32Free;
+
+ pVBVA->off32Free = (pVBVA->off32Free + cb) % pVBVA->cbData;
+ pRecord->cbRecord += cb;
+
+ return &pVBVA->au8Data[offset];
}
-#ifdef VBOXVDMA_WITH_VBVA
-int vboxVbvaReportCmdOffset (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, uint32_t offCmd)
+RTDECL(bool) VBoxVBVAExIsProcessing(PVBVAEXBUFFERCONTEXT pCtx)
{
- VBOXVDMAVBVACMD cmd;
- cmd.offCmd = offCmd;
- return vboxWrite (pDevExt, pVbva, &cmd, sizeof(cmd));
+ uint32_t u32HostEvents = pCtx->pVBVA->hostFlags.u32HostEvents;
+ return !!(u32HostEvents & VBVA_F_STATE_PROCESSING);
}
+
+RTDECL(void) VBoxVBVAExCBufferCompleted(PVBVAEXBUFFERCONTEXT pCtx)
+{
+ VBVABUFFER *pVBVA = pCtx->pVBVA;
+ uint32_t cbBuffer = pVBVA->aRecords[pCtx->indexRecordFirstUncompleted].cbRecord;
+ pCtx->indexRecordFirstUncompleted = (pCtx->indexRecordFirstUncompleted + 1) % VBVA_MAX_RECORDS;
+ pCtx->off32DataUncompleted = (pCtx->off32DataUncompleted + cbBuffer) % pVBVA->cbData;
+#ifdef DEBUG
+ vboxHwBufferVerifyCompleted(pCtx);
#endif
+}
+
+RTDECL(bool) VBoxVBVAExWrite(PVBVAEXBUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ const void *pv, uint32_t cb)
+{
+ return vboxHwBufferWrite(pCtx, pHGSMICtx, pv, cb);
+}
+
+RTDECL(bool) VBoxVBVAExOrderSupported(PVBVAEXBUFFERCONTEXT pCtx, unsigned code)
+{
+ VBVABUFFER *pVBVA = pCtx->pVBVA;
+
+ if (!pVBVA)
+ {
+ return false;
+ }
+
+ if (pVBVA->hostFlags.u32SupportedOrders & (1 << code))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+RTDECL(void) VBoxVBVAExSetupBufferContext(PVBVAEXBUFFERCONTEXT pCtx,
+ uint32_t offVRAMBuffer,
+ uint32_t cbBuffer,
+ PFNVBVAEXBUFFERFLUSH pfnFlush,
+ void *pvFlush)
+{
+ memset(pCtx, 0, RT_OFFSETOF(VBVAEXBUFFERCONTEXT, pVBVA));
+ pCtx->offVRAMBuffer = offVRAMBuffer;
+ pCtx->cbBuffer = cbBuffer;
+ pCtx->pfnFlush = pfnFlush;
+ pCtx->pvFlush = pvFlush;
+}
+
+static void* vboxVBVAExIterCur(PVBVAEXBUFFERITERBASE pIter, struct VBVABUFFER *pVBVA, uint32_t *pcbBuffer, bool *pfProcessed)
+{
+ uint32_t cbRecord = pVBVA->aRecords[pIter->iCurRecord].cbRecord;
+ if (cbRecord == VBVA_F_RECORD_PARTIAL)
+ return NULL;
+ if (pcbBuffer)
+ *pcbBuffer = cbRecord;
+ if (pfProcessed)
+ *pfProcessed = !vboxVBVAExIsEntryInRange(pVBVA->indexRecordFirst, pIter->iCurRecord, pVBVA->indexRecordFree);
+ return &pVBVA->au8Data[pIter->off32CurCmd];
+}
+
+DECLINLINE(uint32_t) vboxVBVAExSubst(uint32_t x, uint32_t val, uint32_t maxVal)
+{
+ int32_t result = (int32_t)(x - val);
+ return result >= 0 ? (uint32_t)result : maxVal - (((uint32_t)(-result)) % maxVal);
+}
+
+RTDECL(void) VBoxVBVAExBIterInit(PVBVAEXBUFFERCONTEXT pCtx, PVBVAEXBUFFERBACKWARDITER pIter)
+{
+ struct VBVABUFFER *pVBVA = pCtx->pVBVA;
+ pIter->Base.pCtx = pCtx;
+ uint32_t iCurRecord = vboxVBVAExSubst(pVBVA->indexRecordFree, 1, VBVA_MAX_RECORDS);
+ if (vboxVBVAExIsEntryInRange(pCtx->indexRecordFirstUncompleted, iCurRecord, pVBVA->indexRecordFree))
+ {
+ /* even if the command gets completed by the time we're doing the pCtx->pVBVA->aRecords[iCurRecord].cbRecord below,
+ * the pCtx->pVBVA->aRecords[iCurRecord].cbRecord will still be valid, as it can only be modified by a submitter,
+ * and we are in a submitter context now */
+ pIter->Base.iCurRecord = iCurRecord;
+ pIter->Base.off32CurCmd = vboxVBVAExSubst(pVBVA->off32Free, pCtx->pVBVA->aRecords[iCurRecord].cbRecord, pVBVA->cbData);
+ }
+ else
+ {
+ /* no data */
+ pIter->Base.iCurRecord = pVBVA->indexRecordFree;
+ pIter->Base.off32CurCmd = pVBVA->off32Free;
+ }
+}
+
+RTDECL(void*) VBoxVBVAExBIterNext(PVBVAEXBUFFERBACKWARDITER pIter, uint32_t *pcbBuffer, bool *pfProcessed)
+{
+ PVBVAEXBUFFERCONTEXT pCtx = pIter->Base.pCtx;
+ struct VBVABUFFER *pVBVA = pCtx->pVBVA;
+ uint32_t indexRecordFirstUncompleted = pCtx->indexRecordFirstUncompleted;
+ if (!vboxVBVAExIsEntryInRange(indexRecordFirstUncompleted, pIter->Base.iCurRecord, pVBVA->indexRecordFree))
+ return NULL;
+
+ void *pvBuffer = vboxVBVAExIterCur(&pIter->Base, pVBVA, pcbBuffer, pfProcessed);
+ AssertRelease(pvBuffer);
+
+ /* even if the command gets completed by the time we're doing the pCtx->pVBVA->aRecords[pIter->Base.iCurRecord].cbRecord below,
+ * the pCtx->pVBVA->aRecords[pIter->Base.iCurRecord].cbRecord will still be valid, as it can only be modified by a submitter,
+ * and we are in a submitter context now */
+ pIter->Base.iCurRecord = vboxVBVAExSubst(pIter->Base.iCurRecord, 1, VBVA_MAX_RECORDS);
+ pIter->Base.off32CurCmd = vboxVBVAExSubst(pIter->Base.off32CurCmd, pCtx->pVBVA->aRecords[pIter->Base.iCurRecord].cbRecord, pVBVA->cbData);
+
+ return pvBuffer;
+}
+
+RTDECL(void) VBoxVBVAExCFIterInit(PVBVAEXBUFFERCONTEXT pCtx, PVBVAEXBUFFERFORWARDITER pIter)
+{
+ pIter->Base.pCtx = pCtx;
+ pIter->Base.iCurRecord = pCtx->indexRecordFirstUncompleted;
+ pIter->Base.off32CurCmd = pCtx->off32DataUncompleted;
+}
+
+RTDECL(void*) VBoxVBVAExCFIterNext(PVBVAEXBUFFERFORWARDITER pIter, uint32_t *pcbBuffer, bool *pfProcessed)
+{
+ PVBVAEXBUFFERCONTEXT pCtx = pIter->Base.pCtx;
+ struct VBVABUFFER *pVBVA = pCtx->pVBVA;
+ uint32_t indexRecordFree = pVBVA->indexRecordFree;
+ if (!vboxVBVAExIsEntryInRange(pCtx->indexRecordFirstUncompleted, pIter->Base.iCurRecord, indexRecordFree))
+ return NULL;
+
+ uint32_t cbBuffer;
+ void *pvData = vboxVBVAExIterCur(&pIter->Base, pVBVA, &cbBuffer, pfProcessed);
+ if (!pvData)
+ return NULL;
+
+ pIter->Base.iCurRecord = (pIter->Base.iCurRecord + 1) % VBVA_MAX_RECORDS;
+ pIter->Base.off32CurCmd = (pIter->Base.off32CurCmd + cbBuffer) % pVBVA->cbData;
+
+ if (pcbBuffer)
+ *pcbBuffer = cbBuffer;
+
+ return pvData;
+}
+
+/**/
+
+int VBoxCmdVbvaEnable(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva)
+{
+ return VBoxVBVAExEnable(&pVbva->Vbva, &VBoxCommonFromDeviceExt(pDevExt)->guestCtx, pVbva->Vbva.pVBVA);
+}
+
+int VBoxCmdVbvaDisable(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva)
+{
+ VBoxVBVAExDisable(&pVbva->Vbva, &VBoxCommonFromDeviceExt(pDevExt)->guestCtx);
+ return VINF_SUCCESS;
+}
+
+int VBoxCmdVbvaDestroy(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva)
+{
+ int rc = VINF_SUCCESS;
+ VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pVbva->Vbva.pVBVA);
+ memset(pVbva, 0, sizeof (*pVbva));
+ return rc;
+}
+
+static void vboxCmdVbvaDdiNotifyCompleteIrq(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, UINT u32FenceId, DXGK_INTERRUPT_TYPE enmComplType)
+{
+ DXGKARGCB_NOTIFY_INTERRUPT_DATA notify;
+ memset(&notify, 0, sizeof(DXGKARGCB_NOTIFY_INTERRUPT_DATA));
+ switch (enmComplType)
+ {
+ case DXGK_INTERRUPT_DMA_COMPLETED:
+ notify.InterruptType = DXGK_INTERRUPT_DMA_COMPLETED;
+ notify.DmaCompleted.SubmissionFenceId = u32FenceId;
+ notify.DmaCompleted.NodeOrdinal = pVbva->idNode;
+ break;
+
+ case DXGK_INTERRUPT_DMA_PREEMPTED:
+ notify.InterruptType = DXGK_INTERRUPT_DMA_PREEMPTED;
+ notify.DmaPreempted.PreemptionFenceId = u32FenceId;
+ notify.DmaPreempted.NodeOrdinal = pVbva->idNode;
+ notify.DmaPreempted.LastCompletedFenceId = pVbva->u32FenceCompleted;
+ break;
+
+ case DXGK_INTERRUPT_DMA_FAULTED:
+ Assert(0);
+ notify.InterruptType = DXGK_INTERRUPT_DMA_FAULTED;
+ notify.DmaFaulted.FaultedFenceId = u32FenceId;
+ notify.DmaFaulted.Status = STATUS_UNSUCCESSFUL; /* @todo: better status ? */
+ notify.DmaFaulted.NodeOrdinal = pVbva->idNode;
+ break;
+
+ default:
+ WARN(("unrecognized completion type %d", enmComplType));
+ break;
+ }
+
+ pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, &notify);
+}
+
+typedef struct VBOXCMDVBVA_NOTIFYCOMPLETED_CB
+{
+ PVBOXMP_DEVEXT pDevExt;
+ VBOXCMDVBVA *pVbva;
+ volatile UINT *pu32FenceId;
+ DXGK_INTERRUPT_TYPE enmComplType;
+} VBOXCMDVBVA_NOTIFYCOMPLETED_CB, *PVBOXCMDVBVA_NOTIFYCOMPLETED_CB;
+
+static BOOLEAN vboxCmdVbvaDdiNotifyCompleteCb(PVOID pvContext)
+{
+ PVBOXCMDVBVA_NOTIFYCOMPLETED_CB pData = (PVBOXCMDVBVA_NOTIFYCOMPLETED_CB)pvContext;
+ if (*pData->pu32FenceId)
+ {
+ UINT u32FenceId = *pData->pu32FenceId;
+ *pData->pu32FenceId = 0;
+
+ vboxCmdVbvaDdiNotifyCompleteIrq(pData->pDevExt, pData->pVbva, u32FenceId, pData->enmComplType);
+
+ pData->pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pData->pDevExt->u.primary.DxgkInterface.DeviceHandle);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static int vboxCmdVbvaDdiNotifyComplete(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, volatile UINT *pu32FenceId, DXGK_INTERRUPT_TYPE enmComplType)
+{
+ VBOXCMDVBVA_NOTIFYCOMPLETED_CB Data;
+ Data.pDevExt = pDevExt;
+ Data.pVbva = pVbva;
+ Data.pu32FenceId = pu32FenceId;
+ Data.enmComplType = enmComplType;
+ BOOLEAN bDummy;
+ NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
+ pDevExt->u.primary.DxgkInterface.DeviceHandle,
+ vboxCmdVbvaDdiNotifyCompleteCb,
+ &Data,
+ 0, /* IN ULONG MessageNumber */
+ &bDummy);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("DxgkCbSynchronizeExecution failed Status %#x", Status));
+ return VERR_GENERAL_FAILURE;
+ }
+ return Status;
+}
+
+static int vboxCmdVbvaFlush(PVBOXMP_DEVEXT pDevExt, HGSMIGUESTCOMMANDCONTEXT *pCtx, bool fBufferOverflow)
+{
+ /* Issue the flush command. */
+ VBVACMDVBVAFLUSH *pFlush = (VBVACMDVBVAFLUSH*)VBoxHGSMIBufferAlloc(pCtx,
+ sizeof (VBVACMDVBVAFLUSH),
+ HGSMI_CH_VBVA,
+ VBVA_CMDVBVA_FLUSH);
+ if (!pFlush)
+ {
+ WARN(("VBoxHGSMIBufferAlloc failed\n"));
+ return VERR_OUT_OF_RESOURCES;
+ }
+
+ pFlush->u32Flags = fBufferOverflow ? VBVACMDVBVAFLUSH_F_GUEST_BUFFER_OVERFLOW : 0;
+
+ VBoxHGSMIBufferSubmit(pCtx, pFlush);
+
+ VBoxHGSMIBufferFree(pCtx, pFlush);
+
+ return VINF_SUCCESS;
+}
+
+typedef struct VBOXCMDVBVA_CHECK_COMPLETED_CB
+{
+ PVBOXMP_DEVEXT pDevExt;
+ VBOXCMDVBVA *pVbva;
+ uint32_t u32FenceID;
+} VBOXCMDVBVA_CHECK_COMPLETED_CB;
+
+static BOOLEAN vboxCmdVbvaCheckCompletedIrqCb(PVOID pContext)
+{
+ VBOXCMDVBVA_CHECK_COMPLETED_CB *pCompleted = (VBOXCMDVBVA_CHECK_COMPLETED_CB*)pContext;
+ BOOLEAN bRc = DxgkDdiInterruptRoutineNew(pCompleted->pDevExt, 0);
+ if (pCompleted->pVbva)
+ pCompleted->u32FenceID = pCompleted->pVbva->u32FenceCompleted;
+ return bRc;
+}
+
+
+static uint32_t vboxCmdVbvaCheckCompleted(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, bool fPingHost, HGSMIGUESTCOMMANDCONTEXT *pCtx, bool fBufferOverflow)
+{
+ if (fPingHost)
+ vboxCmdVbvaFlush(pDevExt, pCtx, fBufferOverflow);
+
+ VBOXCMDVBVA_CHECK_COMPLETED_CB context;
+ context.pDevExt = pDevExt;
+ context.pVbva = pVbva;
+ context.u32FenceID = 0;
+ BOOLEAN bRet;
+ NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
+ pDevExt->u.primary.DxgkInterface.DeviceHandle,
+ vboxCmdVbvaCheckCompletedIrqCb,
+ &context,
+ 0, /* IN ULONG MessageNumber */
+ &bRet);
+ Assert(Status == STATUS_SUCCESS);
+
+ return context.u32FenceID;
+}
+
+DECLCALLBACK(void) voxCmdVbvaFlushCb(struct VBVAEXBUFFERCONTEXT *pCtx, PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, void *pvFlush)
+{
+ PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)pvFlush;
+
+ vboxCmdVbvaCheckCompleted(pDevExt, NULL, true /*fPingHost*/, pHGSMICtx, true /*fBufferOverflow*/);
+}
+
+int VBoxCmdVbvaCreate(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, ULONG offBuffer, ULONG cbBuffer)
+{
+ memset(pVbva, 0, sizeof (*pVbva));
+
+ int rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt),
+ (void**)&pVbva->Vbva.pVBVA,
+ offBuffer,
+ cbBuffer);
+ if (RT_SUCCESS(rc))
+ {
+ Assert(pVbva->Vbva.pVBVA);
+ VBoxVBVAExSetupBufferContext(&pVbva->Vbva, offBuffer, cbBuffer, voxCmdVbvaFlushCb, pDevExt);
+ }
+ else
+ {
+ WARN(("VBoxMPCmnMapAdapterMemory failed rc %d", rc));
+ }
+
+ return rc;
+}
+
+int VBoxCmdVbvaSubmit(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, struct VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd)
+{
+ int rc = VINF_SUCCESS;
+
+ pCmd->u8State = VBOXCMDVBVA_STATE_SUBMITTED;
+ pVbva->u32FenceSubmitted = pCmd->u32FenceID;
+
+ if (VBoxVBVAExGetSize(&pVbva->Vbva) > cbCmd)
+ {
+ WARN(("buffer does not fit the vbva buffer, we do not support splitting buffers"));
+ return VERR_NOT_SUPPORTED;
+ }
+
+ if (!VBoxVBVAExBufferBeginUpdate(&pVbva->Vbva, &VBoxCommonFromDeviceExt(pDevExt)->guestCtx))
+ {
+ WARN(("VBoxVBVAExBufferBeginUpdate failed!"));
+ return VERR_GENERAL_FAILURE;
+ }
+
+ void* pvBuffer = VBoxVBVAExAllocContiguous(&pVbva->Vbva, &VBoxCommonFromDeviceExt(pDevExt)->guestCtx, cbCmd);
+ if (!pvBuffer)
+ {
+ WARN(("failed to allocate contiguous buffer, trying nopping the tail"));
+ uint32_t cbTail = VBoxVBVAExGetFreeTail(&pVbva->Vbva);
+ if (!cbTail)
+ {
+ WARN(("this is not a free tail case, cbTail is NULL"));
+ return VERR_BUFFER_OVERFLOW;
+ }
+
+ Assert(cbTail < cbCmd);
+
+ pvBuffer = VBoxVBVAExAllocContiguous(&pVbva->Vbva, &VBoxCommonFromDeviceExt(pDevExt)->guestCtx, cbTail);
+
+ Assert(pvBuffer);
+
+ *((uint8_t*)pvBuffer) = VBOXCMDVBVA_OPTYPE_NOP;
+
+ VBoxVBVAExBufferEndUpdate(&pVbva->Vbva);
+
+ if (!VBoxVBVAExBufferBeginUpdate(&pVbva->Vbva, &VBoxCommonFromDeviceExt(pDevExt)->guestCtx))
+ {
+ WARN(("VBoxVBVAExBufferBeginUpdate 2 failed!"));
+ return VERR_GENERAL_FAILURE;
+ }
+
+ pvBuffer = VBoxVBVAExAllocContiguous(&pVbva->Vbva, &VBoxCommonFromDeviceExt(pDevExt)->guestCtx, cbCmd);
+ if (!pvBuffer)
+ {
+ WARN(("failed to allocate contiguous buffer, failing"));
+ return VERR_GENERAL_FAILURE;
+ }
+ }
+
+ Assert(pvBuffer);
+
+ memcpy(pvBuffer, pCmd, cbCmd);
+
+ VBoxVBVAExBufferEndUpdate(&pVbva->Vbva);
+
+ if (!VBoxVBVAExIsProcessing(&pVbva->Vbva))
+ {
+ /* Issue the submit command. */
+ HGSMIGUESTCOMMANDCONTEXT *pCtx = &VBoxCommonFromDeviceExt(pDevExt)->guestCtx;
+ VBVACMDVBVASUBMIT *pSubmit = (VBVACMDVBVASUBMIT*)VBoxHGSMIBufferAlloc(pCtx,
+ sizeof (VBVACMDVBVASUBMIT),
+ HGSMI_CH_VBVA,
+ VBVA_CMDVBVA_SUBMIT);
+ if (!pSubmit)
+ {
+ WARN(("VBoxHGSMIBufferAlloc failed\n"));
+ return VERR_OUT_OF_RESOURCES;
+ }
+
+ pSubmit->u32Reserved = 0;
+
+ VBoxHGSMIBufferSubmit(pCtx, pSubmit);
+
+ VBoxHGSMIBufferFree(pCtx, pSubmit);
+ }
+
+ return VINF_SUCCESS;
+}
+
+bool VBoxCmdVbvaPreempt(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, uint32_t u32FenceID)
+{
+ VBVAEXBUFFERBACKWARDITER Iter;
+ VBoxVBVAExBIterInit(&pVbva->Vbva, &Iter);
+
+ uint32_t cbBuffer;
+ bool fProcessed;
+ uint8_t* pu8Cmd;
+
+ while ((pu8Cmd = (uint8_t*)VBoxVBVAExBIterNext(&Iter, &cbBuffer, &fProcessed)) != NULL)
+ {
+ if (*pu8Cmd == VBOXCMDVBVA_OPTYPE_NOP)
+ continue;
+
+ VBOXCMDVBVA_HDR *pCmd = (VBOXCMDVBVA_HDR*)pu8Cmd;
+
+ if (pCmd->u32FenceID != u32FenceID)
+ continue;
+
+ if (!ASMAtomicCmpXchgU8(&pCmd->u8State, VBOXCMDVBVA_STATE_CANCELLED, VBOXCMDVBVA_STATE_SUBMITTED))
+ {
+ Assert(pCmd->u8State == VBOXCMDVBVA_STATE_IN_PROGRESS);
+ break;
+ }
+
+ /* we have canceled the command successfully */
+ vboxCmdVbvaDdiNotifyComplete(pDevExt, pVbva, &pCmd->u32FenceID, DXGK_INTERRUPT_DMA_PREEMPTED);
+ return true;
+ }
+
+ return false;
+}
+
+bool VBoxCmdVbvaCheckCompletedIrq(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva)
+{
+ VBVAEXBUFFERFORWARDITER Iter;
+ VBoxVBVAExCFIterInit(&pVbva->Vbva, &Iter);
+
+ bool fHasCommandsCompletedPreempted = false;
+ bool fProcessed;
+ uint8_t* pu8Cmd;
+
+
+ while ((pu8Cmd = (uint8_t*)VBoxVBVAExCFIterNext(&Iter, NULL, &fProcessed)) != NULL)
+ {
+ if (!fProcessed)
+ break;
+
+ if (*pu8Cmd == VBOXCMDVBVA_OPTYPE_NOP)
+ continue;
+
+ VBOXCMDVBVA_HDR *pCmd = (VBOXCMDVBVA_HDR*)pu8Cmd;
+ uint8_t u8State = pCmd->u8State;
+ uint32_t u32FenceID = pCmd->u32FenceID;
+
+ Assert(u8State == VBOXCMDVBVA_STATE_IN_PROGRESS
+ || u8State == VBOXCMDVBVA_STATE_CANCELLED);
+ Assert(u32FenceID);
+ VBoxVBVAExCBufferCompleted(&pVbva->Vbva);
+ DXGK_INTERRUPT_TYPE enmDdiNotify;
+
+ if (u8State == VBOXCMDVBVA_STATE_IN_PROGRESS)
+ {
+ if (u32FenceID)
+ pVbva->u32FenceCompleted = u32FenceID;
+ enmDdiNotify = DXGK_INTERRUPT_DMA_COMPLETED;
+ }
+ else
+ {
+ Assert(u8State == VBOXCMDVBVA_STATE_CANCELLED);
+ enmDdiNotify = DXGK_INTERRUPT_DMA_PREEMPTED;
+ /* to prevent concurrent notifications from DdiPreemptCommand */
+ pCmd->u32FenceID = 0;
+ }
+
+ if (u32FenceID)
+ vboxCmdVbvaDdiNotifyCompleteIrq(pDevExt, pVbva, u32FenceID, enmDdiNotify);
+
+ fHasCommandsCompletedPreempted = true;
+ }
+
+ return fHasCommandsCompletedPreempted;
+}
+
+uint32_t VBoxCmdVbvaCheckCompleted(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, bool fPingHost)
+{
+ return vboxCmdVbvaCheckCompleted(pDevExt, pVbva, fPingHost, &VBoxCommonFromDeviceExt(pDevExt)->guestCtx, false /* fBufferOverflow */);
+}
+
+
+static uint32_t vboxCVDdiSysMemElBuild(VBOXCMDVBVA_SYSMEMEL *pEl, PMDL pMdl, uint32_t iPfn, uint32_t cPages)
+{
+ PFN_NUMBER cur = MmGetMdlPfnArray(pMdl)[iPfn];
+ uint32_t cbEl = sizeof (*pEl);
+ uint32_t cStoredPages = 1;
+ PFN_NUMBER next;
+ pEl->iPage1 = (uint32_t)(cur & 0xfffff);
+ pEl->iPage2 = (uint32_t)(cur >> 20);
+ --cPages;
+ for ( ; cPages && cStoredPages < VBOXCMDVBVA_SYSMEMEL_CPAGES_MAX; --cPages, ++cStoredPages, cur = next)
+ {
+ next = MmGetMdlPfnArray(pMdl)[iPfn+cStoredPages];
+ if (next != cur+1)
+ break;
+ }
+
+ Assert(cStoredPages);
+ pEl->cPagesAfterFirst = cStoredPages - 1;
+
+ return cPages;
+}
+
+uint32_t VBoxCVDdiPTransferVRamSysBuildEls(VBOXCMDVBVA_PAGING_TRANSFER *pCmd, PMDL pMdl, uint32_t iPfn, uint32_t cPages, uint32_t cbBuffer, uint32_t *pcPagesWritten)
+{
+ uint32_t cInitPages = cPages;
+ uint32_t cbInitBuffer = cbBuffer;
+ uint32_t cEls = 0;
+ VBOXCMDVBVA_SYSMEMEL *pEl = pCmd->aSysMem;
+
+ if (cbBuffer < sizeof (VBOXCMDVBVA_PAGING_TRANSFER))
+ {
+ WARN(("cbBuffer < sizeof (VBOXCMDVBVA_PAGING_TRANSFER)"));
+ goto done;
+ }
+
+ cbBuffer -= RT_OFFSETOF(VBOXCMDVBVA_PAGING_TRANSFER, aSysMem);
+ uint32_t i = 0;
+
+ for (; cPages && cbBuffer >= sizeof (VBOXCMDVBVA_PAGING_TRANSFER); ++cEls, cbBuffer-=sizeof (VBOXCMDVBVA_SYSMEMEL), ++pEl, ++i)
+ {
+ cPages = vboxCVDdiSysMemElBuild(pEl, pMdl, iPfn + cInitPages - cPages, cPages);
+ }
+
+ pCmd->cSysMem = i;
+
+done:
+ *pcPagesWritten = cInitPages - cPages;
+ return cbInitBuffer - cbBuffer;
+}
+
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.h
index 90b2a911..46bb2459 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.h
@@ -21,11 +21,7 @@
typedef struct VBOXVBVAINFO
{
- VBOXVIDEOOFFSET offVBVA;
- uint32_t cbVBVA;
- VBVABUFFER *pVBVA;
- BOOL fHwBufferOverflow;
- VBVARECORD *pRecord;
+ VBVABUFFERCONTEXT Vbva;
D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId;
KSPIN_LOCK Lock;
} VBOXVBVAINFO;
@@ -34,17 +30,14 @@ int vboxVbvaEnable(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva);
int vboxVbvaDisable(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva);
int vboxVbvaDestroy(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva);
int vboxVbvaCreate(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, ULONG offBuffer, ULONG cbBuffer, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId);
-int vboxVbvaReportCmdOffset(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, uint32_t offCmd);
int vboxVbvaReportDirtyRect(PVBOXMP_DEVEXT pDevExt, struct VBOXWDDM_SOURCE *pSrc, RECT *pRectOrig);
-BOOL vboxVbvaBufferBeginUpdate(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva);
-void vboxVbvaBufferEndUpdate(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva);
#define VBOXVBVA_OP(_op, _pdext, _psrc, _arg) \
do { \
- if (vboxVbvaBufferBeginUpdate(_pdext, &(_psrc)->Vbva)) \
+ if (VBoxVBVABufferBeginUpdate(&(_psrc)->Vbva.Vbva, &VBoxCommonFromDeviceExt(_pdext)->guestCtx)) \
{ \
vboxVbva##_op(_pdext, _psrc, _arg); \
- vboxVbvaBufferEndUpdate(_pdext, &(_psrc)->Vbva); \
+ VBoxVBVABufferEndUpdate(&(_psrc)->Vbva.Vbva); \
} \
} while (0)
@@ -65,4 +58,169 @@ void vboxVbvaBufferEndUpdate(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva);
} while (0)
+/* customized VBVA implementation */
+struct VBVAEXBUFFERCONTEXT;
+
+typedef DECLCALLBACKPTR(void, PFNVBVAEXBUFFERFLUSH) (struct VBVAEXBUFFERCONTEXT *pCtx, PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, void *pvFlush);
+
+/**
+ * Structure grouping the context needed for sending graphics acceleration
+ * information to the host via VBVA. Each screen has its own VBVA buffer.
+ */
+typedef struct VBVAEXBUFFERCONTEXT
+{
+ /** Offset of the buffer in the VRAM section for the screen */
+ uint32_t offVRAMBuffer;
+ /** Length of the buffer in bytes */
+ uint32_t cbBuffer;
+ /** This flag is set if we wrote to the buffer faster than the host could
+ * read it. */
+ bool fHwBufferOverflow;
+ /* the window between indexRecordFirstUncompleted and pVBVA->::indexRecordFirst represents
+ * command records processed by the host, but not completed by the guest yet */
+ volatile uint32_t indexRecordFirstUncompleted;
+ /* the window between off32DataUncompleted and pVBVA->::off32Data represents
+ * command data processed by the host, but not completed by the guest yet */
+ uint32_t off32DataUncompleted;
+ /* flush function */
+ PFNVBVAEXBUFFERFLUSH pfnFlush;
+ void *pvFlush;
+ /** The VBVA record that we are currently preparing for the host, NULL if
+ * none. */
+ struct VBVARECORD *pRecord;
+ /** Pointer to the VBVA buffer mapped into the current address space. Will
+ * be NULL if VBVA is not enabled. */
+ struct VBVABUFFER *pVBVA;
+} VBVAEXBUFFERCONTEXT, *PVBVAEXBUFFERCONTEXT;
+
+typedef struct VBVAEXBUFFERITERBASE
+{
+ struct VBVAEXBUFFERCONTEXT *pCtx;
+ /* index of the current record */
+ uint32_t iCurRecord;
+ /* offset of the current command */
+ uint32_t off32CurCmd;
+} VBVAEXBUFFERITERBASE, *PVBVAEXBUFFERITERBASE;
+
+typedef struct VBVAEXBUFFERFORWARDITER
+{
+ VBVAEXBUFFERITERBASE Base;
+} VBVAEXBUFFERFORWARDITER, *PVBVAEXBUFFERFORWARDITER;
+
+typedef struct VBVAEXBUFFERBACKWARDITER
+{
+ VBVAEXBUFFERITERBASE Base;
+} VBVAEXBUFFERBACKWARDITER, *PVBVAEXBUFFERBACKWARDITER;
+
+#define VBOXCMDVBVA_BUFFERSIZE(_cbCmdApprox) (RT_OFFSETOF(VBVABUFFER, au8Data) + ((RT_SIZEOFMEMB(VBVABUFFER, aRecords)/RT_SIZEOFMEMB(VBVABUFFER, aRecords[0])) * (_cbCmdApprox)))
+
+typedef struct VBOXCMDVBVA
+{
+ VBVAEXBUFFERCONTEXT Vbva;
+
+ /* last completted fence id */
+ uint32_t u32FenceCompleted;
+ /* last submitted fence id */
+ uint32_t u32FenceSubmitted;
+
+ /* node ordinal */
+ uint32_t idNode;
+} VBOXCMDVBVA;
+
+/** @name VBVAEx APIs
+ * @{ */
+RTDECL(int) VBoxVBVAExEnable(PVBVAEXBUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ struct VBVABUFFER *pVBVA);
+RTDECL(void) VBoxVBVAExDisable(PVBVAEXBUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx);
+RTDECL(bool) VBoxVBVAExBufferBeginUpdate(PVBVAEXBUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx);
+RTDECL(void) VBoxVBVAExBufferEndUpdate(PVBVAEXBUFFERCONTEXT pCtx);
+RTDECL(bool) VBoxVBVAExWrite(PVBVAEXBUFFERCONTEXT pCtx,
+ PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
+ const void *pv, uint32_t cb);
+
+RTDECL(bool) VBoxVBVAExOrderSupported(PVBVAEXBUFFERCONTEXT pCtx, unsigned code);
+
+RTDECL(void) VBoxVBVAExSetupBufferContext(PVBVAEXBUFFERCONTEXT pCtx,
+ uint32_t offVRAMBuffer,
+ uint32_t cbBuffer,
+ PFNVBVAEXBUFFERFLUSH pfnFlush,
+ void *pvFlush);
+
+DECLINLINE(uint32_t) VBoxVBVAExGetSize(PVBVAEXBUFFERCONTEXT pCtx)
+{
+ return pCtx->pVBVA->cbData;
+}
+
+/* can be used to ensure the command will not cross the ring buffer boundary,
+ * and thus will not be splitted */
+RTDECL(uint32_t) VBoxVBVAExGetFreeTail(PVBVAEXBUFFERCONTEXT pCtx);
+/* allocates a contiguous buffer of a given size, i.e. the one that is not splitted across ringbuffer boundaries */
+RTDECL(void*) VBoxVBVAExAllocContiguous(PVBVAEXBUFFERCONTEXT pCtx, PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, uint32_t cb);
+/* answers whether host is in "processing" state now,
+ * i.e. if "processing" is true after the command is submitted, no notification is required to be posted to host to make the commandbe processed,
+ * otherwise, host should be notified about the command */
+RTDECL(bool) VBoxVBVAExIsProcessing(PVBVAEXBUFFERCONTEXT pCtx);
+
+/* initializes iterator that starts with free record,
+ * i.e. VBoxVBVAExIterNext would return the first uncompleted record.
+ *
+ * can be used by submitter only */
+RTDECL(void) VBoxVBVAExBIterInit(PVBVAEXBUFFERCONTEXT pCtx, PVBVAEXBUFFERBACKWARDITER pIter);
+/* can be used by submitter only */
+RTDECL(void*) VBoxVBVAExBIterNext(PVBVAEXBUFFERBACKWARDITER pIter, uint32_t *pcbBuffer, bool *pfProcessed);
+
+/* completer functions
+ * completer can only use below ones, and submitter is NOT allowed to use them.
+ * Completter functions are prefixed with VBoxVBVAExC as opposed to submitter ones,
+ * that do not have the last "C" in the prefix */
+/* initializes iterator that starts with completed record,
+ * i.e. VBoxVBVAExIterPrev would return the first uncompleted record.
+ * note that we can not have iterator that starts at processed record
+ * (i.e. the one processed by host, but not completed by guest, since host modifies
+ * VBVABUFFER::off32Data and VBVABUFFER::indexRecordFirst concurrently,
+ * and so we may end up with inconsistent index-offData pair
+ *
+ * can be used by completter only */
+RTDECL(void) VBoxVBVAExCFIterInit(PVBVAEXBUFFERCONTEXT pCtx, PVBVAEXBUFFERFORWARDITER pIter);
+/* can be used by completter only */
+RTDECL(void*) VBoxVBVAExCFIterNext(PVBVAEXBUFFERFORWARDITER pIter, uint32_t *pcbBuffer, bool *pfProcessed);
+
+RTDECL(void) VBoxVBVAExCBufferCompleted(PVBVAEXBUFFERCONTEXT pCtx);
+
+/** @} */
+
+struct VBOXCMDVBVA_HDR;
+
+int VBoxCmdVbvaEnable(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva);
+int VBoxCmdVbvaDisable(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva);
+int VBoxCmdVbvaDestroy(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva);
+int VBoxCmdVbvaCreate(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, ULONG offBuffer, ULONG cbBuffer);
+int VBoxCmdVbvaSubmit(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, struct VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd);
+bool VBoxCmdVbvaPreempt(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, uint32_t u32FenceID);
+uint32_t VBoxCmdVbvaCheckCompleted(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, bool fPingHost);
+bool VBoxCmdVbvaCheckCompletedIrq(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva);
+
+/*helper functions for filling vbva commands */
+DECLINLINE(void) VBoxCVDdiPackRect(VBOXCMDVBVA_RECT *pVbvaRect, const RECT *pRect)
+{
+ pVbvaRect->xLeft = (int16_t)pRect->left;
+ pVbvaRect->yTop = (int16_t)pRect->top;
+ pVbvaRect->xRight = (int16_t)pRect->right;
+ pVbvaRect->yBottom = (int16_t)pRect->bottom;
+}
+
+DECLINLINE(void) VBoxCVDdiPackRects(VBOXCMDVBVA_RECT *paVbvaRects, const RECT *paRects, uint32_t cRects)
+{
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ VBoxCVDdiPackRect(&paVbvaRects[i], &paRects[i]);
+ }
+
+}
+
+uint32_t VBoxCVDdiPTransferVRamSysBuildEls(VBOXCMDVBVA_PAGING_TRANSFER *pCmd, PMDL pMdl, uint32_t iPfn, uint32_t cPages, uint32_t cbBuffer, uint32_t *pcPagesWritten);
+
#endif /* #ifndef ___VBoxMPVbva_h___ */
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVdma.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVdma.cpp
index 373a8fcf..0036147e 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVdma.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVdma.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -21,6 +21,9 @@
#include "VBoxMPVdma.h"
#include "VBoxMPVhwa.h"
#include <iprt/asm.h>
+#include "VBoxMPCr.h"
+
+# include <packer.h>
NTSTATUS vboxVdmaPipeConstruct(PVBOXVDMAPIPE pPipe)
{
@@ -212,106 +215,7 @@ NTSTATUS vboxVdmaPipeCltCmdPut(PVBOXVDMAPIPE pPipe, PVBOXVDMAPIPE_CMD_HDR pCmd)
return Status;
}
-PVBOXVDMAPIPE_CMD_DR vboxVdmaGgCmdCreate(PVBOXMP_DEVEXT pDevExt, VBOXVDMAPIPE_CMD_TYPE enmType, uint32_t cbCmd)
-{
- PVBOXVDMAPIPE_CMD_DR pHdr;
-#ifdef VBOX_WDDM_IRQ_COMPLETION
- if (enmType == VBOXVDMAPIPE_CMD_TYPE_DMACMD)
- {
- UINT cbAlloc = VBOXVDMACMD_SIZE_FROMBODYSIZE(cbCmd);
- VBOXVDMACBUF_DR* pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbAlloc);
- if (!pDr)
- {
- WARN(("dr allocation failed"));
- return NULL;
- }
- pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
- pDr->cbBuf = VBOXVDMACMD_HEADER_SIZE();
- pDr->rc = VINF_SUCCESS;
-
-
- PVBOXVDMACMD pDmaHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
- pDmaHdr->enmType = VBOXVDMACMD_TYPE_DMA_NOP;
- pDmaHdr->u32CmdSpecific = 0;
-
- pHdr = VBOXVDMACMD_BODY(pDmaHdr, VBOXVDMAPIPE_CMD_DR);
- }
- else
-#endif
- {
- pHdr = (PVBOXVDMAPIPE_CMD_DR)vboxWddmMemAllocZero(cbCmd);
- if (!pHdr)
- {
- WARN(("cmd allocation failed"));
- return NULL;
- }
- }
- pHdr->enmType = enmType;
- pHdr->cRefs = 1;
- return pHdr;
-}
-
-#ifdef VBOX_WDDM_IRQ_COMPLETION
-DECLINLINE(VBOXVDMACBUF_DR*) vboxVdmaGgCmdDmaGetDr(PVBOXVDMAPIPE_CMD_DMACMD pDr)
-{
- VBOXVDMACMD* pDmaCmd = VBOXVDMACMD_FROM_BODY(pDr);
- VBOXVDMACBUF_DR* pDmaDr = VBOXVDMACBUF_DR_FROM_TAIL(pDmaCmd);
- return pDmaDr;
-}
-
-DECLINLINE(PVBOXVDMADDI_CMD) vboxVdmaGgCmdDmaGetDdiCmd(PVBOXVDMAPIPE_CMD_DMACMD pDr)
-{
- VBOXVDMACBUF_DR* pDmaDr = vboxVdmaGgCmdDmaGetDr(pDr);
- return VBOXVDMADDI_CMD_FROM_BUF_DR(pDmaDr);
-}
-
-#endif
-
-void vboxVdmaGgCmdDestroy(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DR pDr)
-{
-#ifdef VBOX_WDDM_IRQ_COMPLETION
- if (pDr->enmType == VBOXVDMAPIPE_CMD_TYPE_DMACMD)
- {
- VBOXVDMACBUF_DR* pDmaDr = vboxVdmaGgCmdDmaGetDr((PVBOXVDMAPIPE_CMD_DMACMD)pDr);
- vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDmaDr);
- return;
- }
-#endif
- vboxWddmMemFree(pDr);
-}
-
-DECLCALLBACK(VOID) vboxVdmaGgDdiCmdRelease(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
-{
- vboxVdmaGgCmdRelease(pDevExt, (PVBOXVDMAPIPE_CMD_DR)pvContext);
-}
-
-/**
- * helper function used for system thread creation
- */
-static NTSTATUS vboxVdmaGgThreadCreate(PKTHREAD * ppThread, PKSTART_ROUTINE pStartRoutine, PVOID pStartContext)
-{
- NTSTATUS fStatus;
- HANDLE hThread;
- OBJECT_ATTRIBUTES fObjectAttributes;
-
- Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
-
- InitializeObjectAttributes(&fObjectAttributes, NULL, OBJ_KERNEL_HANDLE,
- NULL, NULL);
-
- fStatus = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS,
- &fObjectAttributes, NULL, NULL,
- (PKSTART_ROUTINE) pStartRoutine, pStartContext);
- if (!NT_SUCCESS(fStatus))
- return fStatus;
-
- ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL,
- KernelMode, (PVOID*) ppThread, NULL);
- ZwClose(hThread);
- return STATUS_SUCCESS;
-}
-
-DECLINLINE(void) vboxVdmaDirtyRectsCalcIntersection(const RECT *pArea, const PVBOXWDDM_RECTS_INFO pRects, PVBOXWDDM_RECTS_INFO pResult)
+DECLINLINE(void) vboxVdmaDirtyRectsCalcIntersection(const RECT *pArea, const VBOXWDDM_RECTS_INFO *pRects, PVBOXWDDM_RECTS_INFO pResult)
{
uint32_t cRects = 0;
for (uint32_t i = 0; i < pRects->cRects; ++i)
@@ -379,20 +283,196 @@ NTSTATUS vboxVdmaPostHideSwapchain(PVBOXWDDM_SWAPCHAIN pSwapchain)
return STATUS_NO_MEMORY;
}
+static VOID vboxWddmBltPipeRectsTranslate(VBOXVDMAPIPE_RECTS *pRects, int x, int y)
+{
+ vboxWddmRectTranslate(&pRects->ContextRect, x, y);
+
+ for (UINT i = 0; i < pRects->UpdateRects.cRects; ++i)
+ {
+ vboxWddmRectTranslate(&pRects->UpdateRects.aRects[i], x, y);
+ }
+}
+
+static VBOXVDMAPIPE_RECTS * vboxWddmBltPipeRectsDup(const VBOXVDMAPIPE_RECTS *pRects)
+{
+ const size_t cbDup = RT_OFFSETOF(VBOXVDMAPIPE_RECTS, UpdateRects.aRects[pRects->UpdateRects.cRects]);
+ VBOXVDMAPIPE_RECTS *pDup = (VBOXVDMAPIPE_RECTS*)vboxWddmMemAllocZero(cbDup);
+ if (!pDup)
+ {
+ WARN(("vboxWddmMemAllocZero failed"));
+ return NULL;
+ }
+ memcpy(pDup, pRects, cbDup);
+ return pDup;
+}
+
+typedef struct VBOXMP_VDMACR_WRITECOMPLETION
+{
+ void *pvBufferToFree;
+} VBOXMP_VDMACR_WRITECOMPLETION, *PVBOXMP_VDMACR_WRITECOMPLETION;
+
+static DECLCALLBACK(void) vboxVdmaCrWriteCompletion(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc, void *pvCtx)
+{
+ PVBOXMP_VDMACR_WRITECOMPLETION pData = (PVBOXMP_VDMACR_WRITECOMPLETION)pvCtx;
+ void* pvBufferToFree = pData->pvBufferToFree;
+ if (pvBufferToFree)
+ VBoxMpCrShgsmiTransportBufFree(pCon, pvBufferToFree);
+
+ VBoxMpCrShgsmiTransportCmdTermWriteAsync(pCon, pvCtx);
+}
+
+typedef struct VBOXMP_VDMACR_WRITEREADCOMPLETION
+{
+ void *pvBufferToFree;
+ void *pvContext;
+} VBOXMP_VDMACR_WRITEREADCOMPLETION, *PVBOXMP_VDMACR_WRITEREADCOMPLETION;
+
+void vboxVdmaCrSubmitWriteReadAsyncGenericCompletion(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvCtx)
+{
+ PVBOXMP_VDMACR_WRITEREADCOMPLETION pData = (PVBOXMP_VDMACR_WRITEREADCOMPLETION)pvCtx;
+ void* pvBufferToFree = pData->pvBufferToFree;
+ if (pvBufferToFree)
+ VBoxMpCrShgsmiTransportBufFree(pCon, pvBufferToFree);
+
+ VBoxMpCrShgsmiTransportCmdTermWriteReadAsync(pCon, pvCtx);
+}
+
+NTSTATUS vboxVdmaCrSubmitWriteReadAsync(PVBOXMP_DEVEXT pDevExt, VBOXMP_CRPACKER *pCrPacker, uint32_t u32CrConClientID, PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion, void *pvCompletion)
+{
+ Assert(u32CrConClientID);
+ NTSTATUS Status = STATUS_SUCCESS;
+ uint32_t cbBuffer;
+ void * pvPackBuffer;
+ void * pvBuffer = VBoxMpCrPackerTxBufferComplete(pCrPacker, &cbBuffer, &pvPackBuffer);
+ if (pvBuffer)
+ {
+ PVBOXMP_VDMACR_WRITEREADCOMPLETION pvCompletionData = (PVBOXMP_VDMACR_WRITEREADCOMPLETION)VBoxMpCrShgsmiTransportCmdCreateWriteReadAsync(&pDevExt->CrHgsmiTransport, u32CrConClientID, pvBuffer, cbBuffer,
+ pfnCompletion, sizeof (*pvCompletionData));
+ if (pvCompletionData)
+ {
+ pvCompletionData->pvBufferToFree = pvPackBuffer;
+ pvCompletionData->pvContext = pvCompletion;
+ int rc = VBoxMpCrShgsmiTransportCmdSubmitWriteReadAsync(&pDevExt->CrHgsmiTransport, pvCompletionData);
+ if (RT_SUCCESS(rc))
+ {
+ return STATUS_SUCCESS;
+ }
+ WARN(("VBoxMpCrShgsmiTransportCmdSubmitWriteAsync failed, rc %d", rc));
+ Status = STATUS_UNSUCCESSFUL;
+ VBoxMpCrShgsmiTransportCmdTermWriteReadAsync(&pDevExt->CrHgsmiTransport, pvCompletionData);
+ }
+ else
+ {
+ WARN(("VBoxMpCrShgsmiTransportCmdCreateWriteAsync failed"));
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ return Status;
+}
+
+NTSTATUS vboxVdmaCrSubmitWriteAsync(PVBOXMP_DEVEXT pDevExt, VBOXMP_CRPACKER *pCrPacker, uint32_t u32CrConClientID)
+{
+ Assert(u32CrConClientID);
+ NTSTATUS Status = STATUS_SUCCESS;
+ uint32_t cbBuffer;
+ void * pvPackBuffer;
+ void * pvBuffer = VBoxMpCrPackerTxBufferComplete(pCrPacker, &cbBuffer, &pvPackBuffer);
+ if (pvBuffer)
+ {
+ PVBOXMP_VDMACR_WRITECOMPLETION pvCompletionData = (PVBOXMP_VDMACR_WRITECOMPLETION)VBoxMpCrShgsmiTransportCmdCreateWriteAsync(&pDevExt->CrHgsmiTransport, u32CrConClientID, pvBuffer, cbBuffer,
+ vboxVdmaCrWriteCompletion, sizeof (*pvCompletionData));
+ if (pvCompletionData)
+ {
+ pvCompletionData->pvBufferToFree = pvPackBuffer;
+ int rc = VBoxMpCrShgsmiTransportCmdSubmitWriteAsync(&pDevExt->CrHgsmiTransport, pvCompletionData);
+ if (RT_SUCCESS(rc))
+ {
+ return STATUS_SUCCESS;
+ }
+ WARN(("VBoxMpCrShgsmiTransportCmdSubmitWriteAsync failed, rc %d", rc));
+ Status = STATUS_UNSUCCESSFUL;
+ VBoxMpCrShgsmiTransportCmdTermWriteAsync(&pDevExt->CrHgsmiTransport, pvCompletionData);
+ }
+ else
+ {
+ WARN(("VBoxMpCrShgsmiTransportCmdCreateWriteAsync failed"));
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ return Status;
+}
+
+static NTSTATUS vboxVdmaVRegGet(PVBOXWDDM_SWAPCHAIN pSwapchain, const RTRECT *pCtxRect, uint32_t *pcVRects, RTRECT **ppVRectsBuff, uint32_t *pcVRectsBuff)
+{
+ RTRECT *pVRectsBuff = *ppVRectsBuff;
+ uint32_t cVRectsBuff = *pcVRectsBuff;
+ uint32_t cVRects = VBoxVrListRectsCount(&pSwapchain->VisibleRegions);
+ if (cVRectsBuff < cVRects)
+ {
+ if (pVRectsBuff)
+ vboxWddmMemFree(pVRectsBuff);
+ pVRectsBuff = (RTRECT*)vboxWddmMemAlloc(cVRects * sizeof (pVRectsBuff[0]));
+ if (!pVRectsBuff)
+ {
+ WARN(("vboxWddmMemAlloc failed"));
+ *pcVRectsBuff = 0;
+ *ppVRectsBuff = NULL;
+ *pcVRects = NULL;
+ return STATUS_NO_MEMORY;
+ }
+
+ cVRectsBuff = cVRects;
+ *pcVRectsBuff = cVRectsBuff;
+ *ppVRectsBuff = pVRectsBuff;
+ }
+
+ int rc = VBoxVrListRectsGet(&pSwapchain->VisibleRegions, cVRects, pVRectsBuff);
+ AssertRC(rc);
+ if (pCtxRect->xLeft || pCtxRect->yTop)
+ {
+ for (UINT i = 0; i < cVRects; ++i)
+ {
+ VBoxRectTranslate(&pVRectsBuff[i], -pCtxRect->xLeft, -pCtxRect->yTop);
+ }
+ }
+
+ *pcVRects = cVRects;
+ return STATUS_SUCCESS;
+}
+
+
/**
* @param pDevExt
*/
-static NTSTATUS vboxVdmaGgDirtyRectsProcess(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain, RECT *pSrcRect, VBOXVDMAPIPE_RECTS *pContextRects)
-{
- PVBOXWDDM_RECTS_INFO pRects = &pContextRects->UpdateRects;
+static NTSTATUS vboxVdmaProcessVRegCmdLegacy(PVBOXMP_DEVEXT pDevExt,
+ VBOXMP_CRPACKER *pCrPacker,
+ uint32_t u32CrConClientID,
+ PVBOXWDDM_SOURCE pSource,
+ PVBOXWDDM_SWAPCHAIN pSwapchain,
+ const RECT *pSrcRect,
+ const VBOXVDMAPIPE_RECTS *pContextRects)
+{
+ VBOXVDMAPIPE_RECTS *pRectsToFree = NULL;
+ POINT pos = pSource->VScreenPos;
+ if (pos.x || pos.y)
+ {
+ pRectsToFree = vboxWddmBltPipeRectsDup(pContextRects);
+ /* note: do NOT translate the src rect since it is used for screen pos calculation */
+ vboxWddmBltPipeRectsTranslate(pRectsToFree, pos.x, pos.y);
+ pContextRects = pRectsToFree;
+ }
+ const VBOXWDDM_RECTS_INFO *pRects = &pContextRects->UpdateRects;
NTSTATUS Status = STATUS_SUCCESS;
- PVBOXVIDEOCM_CMD_RECTS_INTERNAL pCmdInternal = NULL;
- uint32_t cbCmdInternal = VBOXVIDEOCM_CMD_RECTS_INTERNAL_SIZE4CRECTS(pRects->cRects);
- BOOLEAN fCurChanged = FALSE, fCurRectChanged = FALSE;
+ int rc;
+ bool fCurChanged = FALSE, fCurRectChanged = FALSE;
POINT CurPos;
- Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
+ RTRECT *pVRectsBuff = NULL;
+ uint32_t cVRectsBuff = 0;
+ VBOXWDDM_CTXLOCK_DATA
- ExAcquireFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_LOCK(pDevExt);
if (pSwapchain)
{
@@ -403,18 +483,19 @@ static NTSTATUS vboxVdmaGgDirtyRectsProcess(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CO
{
#if 0
if (pSwapchain->Pos.x != VBOXWDDM_INVALID_COORD)
- VBoxWddmVrListTranslate(&pSwapchain->VisibleRegions, pSwapchain->Pos.x - CurPos.x, pSwapchain->Pos.y - CurPos.y);
+ VBoxVrListTranslate(&pSwapchain->VisibleRegions, pSwapchain->Pos.x - CurPos.x, pSwapchain->Pos.y - CurPos.y);
else
#endif
- VBoxWddmVrListClear(&pSwapchain->VisibleRegions);
+ VBoxVrListClear(&pSwapchain->VisibleRegions);
fCurRectChanged = TRUE;
pSwapchain->Pos = CurPos;
}
- Status = VBoxWddmVrListRectsAdd(&pSwapchain->VisibleRegions, pRects->cRects, pRects->aRects, &fCurChanged);
- if (!NT_SUCCESS(Status))
+ rc = VBoxVrListRectsAdd(&pSwapchain->VisibleRegions, pRects->cRects, (const RTRECT*)pRects->aRects, &fCurChanged);
+ if (!RT_SUCCESS(rc))
{
- WARN(("VBoxWddmVrListRectsAdd failed!"));
+ WARN(("VBoxWddmVrListRectsAdd failed, rc %d!", rc));
+ Status = STATUS_UNSUCCESSFUL;
goto done;
}
@@ -432,113 +513,140 @@ static NTSTATUS vboxVdmaGgDirtyRectsProcess(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CO
if (pCur != &pSwapchain->DevExtListEntry)
{
PVBOXWDDM_SWAPCHAIN pCurSwapchain = VBOXWDDMENTRY_2_SWAPCHAIN(pCur);
- BOOLEAN fChanged = FALSE;
+ PVBOXWDDM_CONTEXT pCurContext = pCurSwapchain->pContext;
+ PVBOXMP_CRPACKER pCurPacker = &pCurContext->CrPacker;
+ bool fChanged = FALSE;
- Status = VBoxWddmVrListRectsSubst(&pCurSwapchain->VisibleRegions, pRects->cRects, pRects->aRects, &fChanged);
- if (!NT_SUCCESS(Status))
+ rc = VBoxVrListRectsSubst(&pCurSwapchain->VisibleRegions, pRects->cRects, (const RTRECT*)pRects->aRects, &fChanged);
+ if (!RT_SUCCESS(rc))
{
- WARN(("vboxWddmVrListRectsAdd failed!"));
+ WARN(("VBoxWddmVrListRectsAdd failed, rc %d!", rc));
+ Status = STATUS_UNSUCCESSFUL;
goto done;
}
if (!fChanged)
continue;
- if (!pCmdInternal)
+ uint32_t cVRects;
+ RTRECT CurCtxRect;
+ CurCtxRect.xLeft = pCurSwapchain->Pos.x;
+ CurCtxRect.yTop = pCurSwapchain->Pos.y;
+ CurCtxRect.xRight = CurCtxRect.xLeft + pCurSwapchain->width;
+ CurCtxRect.yBottom = CurCtxRect.yTop + pCurSwapchain->height;
+ Status = vboxVdmaVRegGet(pCurSwapchain, &CurCtxRect, &cVRects, &pVRectsBuff, &cVRectsBuff);
+ if (!NT_SUCCESS(Status))
{
- pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pCurSwapchain->pContext->CmContext, cbCmdInternal);
- if (!pCmdInternal)
- {
- WARN(("vboxVideoCmCmdCreate failed!"));
- Status = STATUS_NO_MEMORY;
- goto done;
- }
+ WARN(("vboxVdmaVRegGet Status 0x%x", Status));
+ goto done;
}
- else
+
+ void *pvCommandBuffer = NULL;
+ uint32_t cbCommandBuffer = VBOXMP_CRCMD_HEADER_SIZE;
+ cbCommandBuffer += VBOXMP_CRCMD_SIZE_WINDOWVISIBLEREGIONS(cVRects);
+
+ pvCommandBuffer = VBoxMpCrShgsmiTransportBufAlloc(&pDevExt->CrHgsmiTransport, cbCommandBuffer);
+ if (!pvCommandBuffer)
{
- pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdReinitForContext(pCmdInternal, &pCurSwapchain->pContext->CmContext);
+ WARN(("VBoxMpCrShgsmiTransportBufAlloc failed!"));
+ Status = VERR_OUT_OF_RESOURCES;
+ goto done;
}
- pCmdInternal->Cmd.fFlags.Value = 0;
- pCmdInternal->Cmd.fFlags.bAddHiddenRects = 1;
- memcpy(&pCmdInternal->Cmd.RectsInfo, pRects, RT_OFFSETOF(VBOXWDDM_RECTS_INFO, aRects[pRects->cRects]));
+ VBoxMpCrPackerTxBufferInit(pCurPacker, pvCommandBuffer, cbCommandBuffer, 1);
- pCmdInternal->hSwapchainUm = pCurSwapchain->hSwapchainUm;
+ Assert(pCurSwapchain->winHostID);
+ crPackWindowVisibleRegion(&pCurPacker->CrPacker, pCurSwapchain->winHostID, cVRects, (GLint*)pVRectsBuff);
- vboxVideoCmCmdSubmit(pCmdInternal, VBOXVIDEOCM_CMD_RECTS_INTERNAL_SIZE4CRECTS(pCmdInternal->Cmd.RectsInfo.cRects));
- pCmdInternal = NULL;
+ Status = vboxVdmaCrSubmitWriteAsync(pDevExt, pCurPacker, pCurContext->u32CrConClientID);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxVdmaCrSubmitWriteAsync failed Status 0x%x", Status));
+ VBoxMpCrShgsmiTransportBufFree(&pDevExt->CrHgsmiTransport, pvCommandBuffer);
+ }
}
}
if (!pSwapchain)
goto done;
- RECT *pVisRects;
+ uint32_t cbCommandBuffer = VBOXMP_CRCMD_HEADER_SIZE, cCommands = 0;
+
+ uint32_t cVRects;
+ Status = vboxVdmaVRegGet(pSwapchain, (const RTRECT *)&pContextRects->ContextRect, &cVRects, &pVRectsBuff, &cVRectsBuff);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxVdmaVRegGet Status 0x%x", Status));
+ goto done;
+ }
+
+ ++cCommands;
+ cbCommandBuffer += VBOXMP_CRCMD_SIZE_WINDOWVISIBLEREGIONS(cVRects);
if (fCurRectChanged && fCurChanged)
{
- cbCmdInternal = VBOXVIDEOCM_CMD_RECTS_INTERNAL_SIZE4CRECTS(pRects->cRects + 1);
- if (pCmdInternal)
- vboxVideoCmCmdRelease(pCmdInternal);
- pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pContext->CmContext, cbCmdInternal);
- pCmdInternal->Cmd.fFlags.Value = 0;
- pCmdInternal->Cmd.fFlags.bSetViewRect = 1;
- pCmdInternal->Cmd.fFlags.bAddVisibleRects = 1;
- pCmdInternal->Cmd.RectsInfo.cRects = pRects->cRects + 1;
- pCmdInternal->Cmd.RectsInfo.aRects[0].left = CurPos.x;
- pCmdInternal->Cmd.RectsInfo.aRects[0].top = CurPos.y;
- pCmdInternal->Cmd.RectsInfo.aRects[0].right = CurPos.x + pSwapchain->width;
- pCmdInternal->Cmd.RectsInfo.aRects[0].bottom = CurPos.y + pSwapchain->height;
- pVisRects = &pCmdInternal->Cmd.RectsInfo.aRects[1];
+ ++cCommands;
+ cbCommandBuffer += VBOXMP_CRCMD_SIZE_WINDOWPOSITION;
}
- else
+
+ if (!pSwapchain->fExposed)
{
- if (!pCmdInternal)
- {
- Assert(pContext == pSwapchain->pContext);
- pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pContext->CmContext, cbCmdInternal);
- if (!pCmdInternal)
- {
- WARN(("vboxVideoCmCmdCreate failed!"));
- Status = STATUS_NO_MEMORY;
- goto done;
- }
- }
- else
- {
- pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdReinitForContext(pCmdInternal, &pContext->CmContext);
- }
+ ++cCommands;
+ cbCommandBuffer += VBOXMP_CRCMD_SIZE_WINDOWSHOW;
+ ++cCommands;
+ cbCommandBuffer += VBOXMP_CRCMD_SIZE_WINDOWSIZE;
+ }
- pCmdInternal->Cmd.fFlags.Value = 0;
- pCmdInternal->Cmd.fFlags.bAddVisibleRects = 1;
- pCmdInternal->Cmd.RectsInfo.cRects = pRects->cRects;
- pVisRects = &pCmdInternal->Cmd.RectsInfo.aRects[0];
+ void *pvCommandBuffer = VBoxMpCrShgsmiTransportBufAlloc(&pDevExt->CrHgsmiTransport, cbCommandBuffer);
+ if (!pvCommandBuffer)
+ {
+ WARN(("VBoxMpCrShgsmiTransportBufAlloc failed!"));
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
}
- pCmdInternal->hSwapchainUm = pSwapchain->hSwapchainUm;
+ VBoxMpCrPackerTxBufferInit(pCrPacker, pvCommandBuffer, cbCommandBuffer, cCommands);
+
+ Assert(pSwapchain->winHostID);
+
+ if (fCurRectChanged && fCurChanged)
+ crPackWindowPosition(&pCrPacker->CrPacker, pSwapchain->winHostID, CurPos.x, CurPos.y);
+
+ if (!pSwapchain->fExposed)
+ {
+ crPackWindowSize(&pCrPacker->CrPacker, pSwapchain->winHostID, pSwapchain->width, pSwapchain->height);
+ crPackWindowShow(&pCrPacker->CrPacker, pSwapchain->winHostID, TRUE);
+ pSwapchain->fExposed = TRUE;
+ }
- if (pRects->cRects)
- memcpy(pVisRects, pRects->aRects, sizeof (RECT) * pRects->cRects);
+ crPackWindowVisibleRegion(&pCrPacker->CrPacker, pSwapchain->winHostID, cVRects, (GLint*)pVRectsBuff);
- vboxVideoCmCmdSubmit(pCmdInternal, VBOXVIDEOCM_CMD_RECTS_INTERNAL_SIZE4CRECTS(pCmdInternal->Cmd.RectsInfo.cRects));
- pCmdInternal = NULL;
+ Status = vboxVdmaCrSubmitWriteAsync(pDevExt, pCrPacker, u32CrConClientID);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxVdmaCrSubmitWriteAsync failed Status 0x%x", Status));
+ VBoxMpCrShgsmiTransportBufFree(&pDevExt->CrHgsmiTransport, pvCommandBuffer);
+ }
done:
- ExReleaseFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_UNLOCK(pDevExt);
- if (pCmdInternal)
- vboxVideoCmCmdRelease(pCmdInternal);
+ if (pRectsToFree)
+ vboxWddmMemFree(pRectsToFree);
+
+ if (pVRectsBuff)
+ vboxWddmMemFree(pVRectsBuff);
return Status;
}
-static NTSTATUS vboxVdmaGgDmaColorFill(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL pCF)
+static NTSTATUS vboxVdmaGgDmaColorFill(PVBOXMP_DEVEXT pDevExt, VBOXVDMA_CLRFILL *pCF)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
Assert (pDevExt->pvVisibleVram);
if (pDevExt->pvVisibleVram)
{
- PVBOXWDDM_ALLOCATION pAlloc = pCF->ClrFill.Alloc.pAlloc;
+ PVBOXWDDM_ALLOCATION pAlloc = pCF->Alloc.pAlloc;
Assert(pAlloc->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID);
if (pAlloc->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID)
{
@@ -552,9 +660,9 @@ static NTSTATUS vboxVdmaGgDmaColorFill(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD
case 32:
{
uint8_t bytestPP = bpp >> 3;
- for (UINT i = 0; i < pCF->ClrFill.Rects.cRects; ++i)
+ for (UINT i = 0; i < pCF->Rects.cRects; ++i)
{
- RECT *pRect = &pCF->ClrFill.Rects.aRects[i];
+ RECT *pRect = &pCF->Rects.aRects[i];
for (LONG ir = pRect->top; ir < pRect->bottom; ++ir)
{
uint32_t * pvU32Mem = (uint32_t*)(pvMem + (ir * pAlloc->AllocData.SurfDesc.pitch) + (pRect->left * bytestPP));
@@ -565,7 +673,7 @@ static NTSTATUS vboxVdmaGgDmaColorFill(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD
Assert(pRect->bottom <= (LONG)pAlloc->AllocData.SurfDesc.height);
for (UINT j = 0; j < cRaw; ++j)
{
- *pvU32Mem = pCF->ClrFill.Color;
+ *pvU32Mem = pCF->Color;
++pvU32Mem;
}
}
@@ -590,7 +698,7 @@ static NTSTATUS vboxVdmaGgDmaColorFill(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD
{
if (!vboxWddmRectIsEmpty(&UnionRect))
{
- PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pCF->ClrFill.Alloc.pAlloc->AllocData.SurfDesc.VidPnSourceId];
+ PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pCF->Alloc.pAlloc->AllocData.SurfDesc.VidPnSourceId];
uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
if (!cUnlockedVBVADisabled)
{
@@ -736,464 +844,524 @@ static NTSTATUS vboxVdmaGgDmaBlt(PVBOXMP_DEVEXT pDevExt, PVBOXVDMA_BLT pBlt)
return Status;
}
-static VOID vboxWddmBltPipeRectsTranslate(VBOXVDMAPIPE_RECTS *pRects, int x, int y)
+typedef struct VBOXVDMA_CRRXGENERICSYNC
{
- vboxWddmRectTranslate(&pRects->ContextRect, x, y);
+ int rc;
+ KEVENT Event;
+} VBOXVDMA_CRRXGENERICSYNC, *PVBOXVDMA_CRRXGENERICSYNC;
- for (UINT i = 0; i < pRects->UpdateRects.cRects; ++i)
+static DECLCALLBACK(void) vboxVdmaCrRxGenericSyncCompletion(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc, void *pvRx, uint32_t cbRx, void *pvCtx)
+{
+ PVBOXMP_VDMACR_WRITEREADCOMPLETION pvCompletionData = (PVBOXMP_VDMACR_WRITEREADCOMPLETION)pvCtx;
+ PVBOXVDMA_CRRXGENERICSYNC pData = (PVBOXVDMA_CRRXGENERICSYNC)pvCompletionData->pvContext;
+ if (RT_SUCCESS(rc))
{
- vboxWddmRectTranslate(&pRects->UpdateRects.aRects[i], x, y);
+ rc = VBoxMpCrCmdRxHandler((CRMessageHeader*)pvRx, cbRx);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("VBoxMpCrCmdRxHandler failed %d", rc));
+ }
}
+ else
+ {
+ WARN(("rx failure %d", rc));
+ }
+
+ pData->rc = rc;
+
+ KeSetEvent(&pData->Event, 0, FALSE);
+
+ vboxVdmaCrSubmitWriteReadAsyncGenericCompletion(pCon, pvCtx);
}
-static NTSTATUS vboxVdmaGgDmaCmdProcessFast(PVBOXMP_DEVEXT pDevExt, VBOXVDMAPIPE_CMD_DMACMD *pDmaCmd)
+NTSTATUS vboxVdmaCrRxGenericSync(PVBOXMP_DEVEXT pDevExt, VBOXMP_CRPACKER *pCrPacker, uint32_t u32CrConClientID)
{
- NTSTATUS Status = STATUS_SUCCESS;
- PVBOXWDDM_CONTEXT pContext = pDmaCmd->pContext;
- DXGK_INTERRUPT_TYPE enmComplType = DXGK_INTERRUPT_DMA_COMPLETED;
- switch (pDmaCmd->enmCmd)
+ VBOXVDMA_CRRXGENERICSYNC Data;
+ Data.rc = VERR_NOT_SUPPORTED;
+ KeInitializeEvent(&Data.Event, SynchronizationEvent, FALSE);
+ NTSTATUS Status = vboxVdmaCrSubmitWriteReadAsync(pDevExt, pCrPacker, u32CrConClientID, vboxVdmaCrRxGenericSyncCompletion, &Data);
+ if (!NT_SUCCESS(Status))
{
- case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
- {
- PVBOXVDMAPIPE_CMD_DMACMD_BLT pBlt = (PVBOXVDMAPIPE_CMD_DMACMD_BLT)pDmaCmd;
- PVBOXWDDM_ALLOCATION pDstAlloc = pBlt->Blt.DstAlloc.pAlloc;
- PVBOXWDDM_ALLOCATION pSrcAlloc = pBlt->Blt.SrcAlloc.pAlloc;
+ WARN(("vboxVdmaCrSubmitWriteAsync failed Status 0x%x", Status));
+ return Status;
+ }
- if (pBlt->Hdr.fFlags.fRealOp)
- {
- vboxVdmaGgDmaBlt(pDevExt, &pBlt->Blt);
+ Status = KeWaitForSingleObject(&Data.Event, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("KeWaitForSingleObject failed Status 0x%x", Status));
+ return Status;
+ }
- if (VBOXWDDM_IS_FB_ALLOCATION(pDevExt, pDstAlloc)
- && pDstAlloc->bVisible)
- {
- VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->AllocData.SurfDesc.VidPnSourceId];
- Assert(pDstAlloc->AllocData.SurfDesc.VidPnSourceId < VBOX_VIDEO_MAX_SCREENS);
- Assert(pSource->pPrimaryAllocation == pDstAlloc);
+ return STATUS_SUCCESS;
+}
- RECT UpdateRect;
- UpdateRect = pBlt->Blt.DstRects.UpdateRects.aRects[0];
- for (UINT i = 1; i < pBlt->Blt.DstRects.UpdateRects.cRects; ++i)
- {
- vboxWddmRectUnite(&UpdateRect, &pBlt->Blt.DstRects.UpdateRects.aRects[i]);
- }
+typedef struct VBOXMP_CRHGSMIMGR
+{
+ VBOXMP_CRPACKER CrPacker;
+ void *pvCommandBuffer;
+} VBOXMP_CRHGSMIMGR;
- uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
- if (!cUnlockedVBVADisabled)
- {
- VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &UpdateRect);
- }
- else
- {
- VBOXVBVA_OP_WITHLOCK(ReportDirtyRect, pDevExt, pSource, &UpdateRect);
- }
- }
- }
+DECLINLINE(CRPackContext*) vboxVdmaCrHmGetPackContext(VBOXMP_CRHGSMIMGR *pMgr)
+{
+ return &pMgr->CrPacker.CrPacker;
+}
- if (pBlt->Hdr.fFlags.fVisibleRegions)
- {
- Status = STATUS_MORE_PROCESSING_REQUIRED;
- vboxWddmAllocationRetain(pDstAlloc);
- vboxWddmAllocationRetain(pSrcAlloc);
- }
- break;
- }
+NTSTATUS vboxVdmaCrHmCreate(PVBOXMP_DEVEXT pDevExt, VBOXMP_CRHGSMIMGR *pMgr, uint32_t cbCommandBuffer, uint32_t cCommands)
+{
+ pMgr->pvCommandBuffer = VBoxMpCrShgsmiTransportBufAlloc(&pDevExt->CrHgsmiTransport, cbCommandBuffer);
+ if (!pMgr->pvCommandBuffer)
+ {
+ WARN(("VBoxMpCrShgsmiTransportBufAlloc failed!"));
+ return VERR_OUT_OF_RESOURCES;
+ }
- case VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP:
- {
- PVBOXVDMAPIPE_CMD_DMACMD_FLIP pFlip = (PVBOXVDMAPIPE_CMD_DMACMD_FLIP)pDmaCmd;
- Assert(pFlip->Hdr.fFlags.fVisibleRegions);
- Assert(!pFlip->Hdr.fFlags.fRealOp);
- PVBOXWDDM_ALLOCATION pAlloc = pFlip->Flip.Alloc.pAlloc;
- VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pAlloc->AllocData.SurfDesc.VidPnSourceId];
- vboxWddmAssignPrimary(pDevExt, pSource, pAlloc, pAlloc->AllocData.SurfDesc.VidPnSourceId);
- if (pFlip->Hdr.fFlags.fVisibleRegions)
- {
- Status = STATUS_MORE_PROCESSING_REQUIRED;
- vboxWddmAllocationRetain(pFlip->Flip.Alloc.pAlloc);
- }
+ VBoxMpCrPackerInit(&pMgr->CrPacker);
- break;
- }
- case VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL:
- {
- PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL pCF = (PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL)pDmaCmd;
- Assert(pCF->Hdr.fFlags.fRealOp);
- Assert(!pCF->Hdr.fFlags.fVisibleRegions);
- Status = vboxVdmaGgDmaColorFill(pDevExt, pCF);
- Assert(Status == STATUS_SUCCESS);
- break;
- }
+ VBoxMpCrPackerTxBufferInit(&pMgr->CrPacker, pMgr->pvCommandBuffer, cbCommandBuffer, cCommands);
- default:
- Assert(0);
- break;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS vboxVdmaCrHmSubmitWrSync(PVBOXMP_DEVEXT pDevExt, VBOXMP_CRHGSMIMGR *pMgr, uint32_t u32CrConClientID)
+{
+ NTSTATUS Status = vboxVdmaCrRxGenericSync(pDevExt, &pMgr->CrPacker, u32CrConClientID);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxVdmaCrRxGenericSync failed Status 0x%x", Status));
+ VBoxMpCrShgsmiTransportBufFree(&pDevExt->CrHgsmiTransport, pMgr->pvCommandBuffer);
+ return Status;
+ }
+
+ return STATUS_SUCCESS;
+}
+#if 0
+NTSTATUS vboxVdmaCrCmdGetChromiumParametervCR(PVBOXMP_DEVEXT pDevExt, uint32_t u32CrConClientID, GLenum target, GLuint index, GLenum type, GLsizei count, GLvoid * values)
+{
+ uint32_t cbCommandBuffer = VBOXMP_CRCMD_HEADER_SIZE + VBOXMP_CRCMD_SIZE_GETCHROMIUMPARAMETERVCR;
+ uint32_t cCommands = 1;
+
+ VBOXMP_CRHGSMIMGR Mgr;
+ NTSTATUS Status = vboxVdmaCrHmCreate(pDevExt, &Mgr, cbCommandBuffer, cCommands);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxVdmaCrHmCreate failed Status 0x%x", Status));
+ return Status;
}
- /* Corresponding Release is done by dma command completion handler */
- vboxVdmaGgCmdAddRef(&pDmaCmd->Hdr);
+ int dummy = 1;
- NTSTATUS tmpStatus = vboxVdmaGgCmdDmaNotifyCompleted(pDevExt, pDmaCmd, enmComplType);
- if (!NT_SUCCESS(tmpStatus))
+ crPackGetChromiumParametervCR(vboxVdmaCrHmGetPackContext(&Mgr), target, index, type, count, values, &dummy);
+
+ Status = vboxVdmaCrHmSubmitWrSync(pDevExt, &Mgr, u32CrConClientID);
+ if (!NT_SUCCESS(Status))
{
- WARN(("vboxVdmaGgCmdDmaNotifyCompleted failed, Status 0x%x", tmpStatus));
- /* the command was NOT submitted, and thus will not be released, release it here */
- vboxVdmaGgCmdRelease(pDevExt, &pDmaCmd->Hdr);
- Status = tmpStatus;
+ WARN(("vboxVdmaCrHmSubmitWrSync failed Status 0x%x", Status));
+ return Status;
}
- return Status;
+ return STATUS_SUCCESS;
}
-static NTSTATUS vboxVdmaGgDmaCmdProcessSlow(PVBOXMP_DEVEXT pDevExt, VBOXVDMAPIPE_CMD_DMACMD *pDmaCmd)
+static NTSTATUS vboxVdmaCrCmdCreateContext(PVBOXMP_DEVEXT pDevExt, int32_t visualBits, int32_t *pi32CtxID)
{
- NTSTATUS Status = STATUS_SUCCESS;
- PVBOXWDDM_CONTEXT pContext = pDmaCmd->pContext;
- DXGK_INTERRUPT_TYPE enmComplType = DXGK_INTERRUPT_DMA_COMPLETED;
+ uint32_t cbCommandBuffer = VBOXMP_CRCMD_HEADER_SIZE + VBOXMP_CRCMD_SIZE_CREATECONTEXT;
+ uint32_t cCommands = 1;
+
+ VBOXMP_CRHGSMIMGR Mgr;
+ NTSTATUS Status = vboxVdmaCrHmCreate(pDevExt, &Mgr, cbCommandBuffer, cCommands);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxVdmaCrHmCreate failed Status 0x%x", Status));
+ return Status;
+ }
+
+ int dummy = 1;
- Assert(pDmaCmd->fFlags.Value);
- Assert(!pDmaCmd->fFlags.fRealOp);
+ crPackCreateContext(&CrPacker.CrPacker, "", visualBits, 0, &pi32CtxID, &dummy);
- switch (pDmaCmd->enmCmd)
+ Status = vboxVdmaCrHmSubmitWrSync(pDevExt, &Mgr, u32CrConClientID);
+ if (!NT_SUCCESS(Status))
{
- case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
- {
- PVBOXVDMAPIPE_CMD_DMACMD_BLT pBlt = (PVBOXVDMAPIPE_CMD_DMACMD_BLT)pDmaCmd;
- PVBOXWDDM_ALLOCATION pDstAlloc = pBlt->Blt.DstAlloc.pAlloc;
- PVBOXWDDM_ALLOCATION pSrcAlloc = pBlt->Blt.SrcAlloc.pAlloc;
- BOOLEAN bComplete = TRUE;
- VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->AllocData.SurfDesc.VidPnSourceId];
- Assert(pDstAlloc->AllocData.SurfDesc.VidPnSourceId < VBOX_VIDEO_MAX_SCREENS);
-
- if (pBlt->Hdr.fFlags.fVisibleRegions)
- {
- PVBOXWDDM_SWAPCHAIN pSwapchain = vboxWddmSwapchainRetainByAlloc(pDevExt, pSrcAlloc);
- POINT pos = pSource->VScreenPos;
- if (pos.x || pos.y)
- {
- /* note: do NOT translate the src rect since it is used for screen pos calculation */
- vboxWddmBltPipeRectsTranslate(&pBlt->Blt.DstRects, pos.x, pos.y);
- }
+ WARN(("vboxVdmaCrHmSubmitWrSync failed Status 0x%x", Status));
+ return Status;
+ }
- Status = vboxVdmaGgDirtyRectsProcess(pDevExt, pContext, pSwapchain, &pBlt->Blt.SrcRect, &pBlt->Blt.DstRects);
- Assert(Status == STATUS_SUCCESS);
+ return STATUS_SUCCESS;
+}
- if (pSwapchain)
- vboxWddmSwapchainRelease(pSwapchain);
- }
- else
- {
- WARN(("not expected!"));
- }
+static NTSTATUS vboxVdmaCrCmdWindowCreate(PVBOXMP_DEVEXT pDevExt, int32_t visualBits, int32_t *pi32WinID)
+{
+ uint32_t cbCommandBuffer = VBOXMP_CRCMD_HEADER_SIZE + VBOXMP_CRCMD_SIZE_WINDOWCREATE;
+ uint32_t cCommands = 1;
- vboxWddmAllocationRelease(pDstAlloc);
- vboxWddmAllocationRelease(pSrcAlloc);
+ VBOXMP_CRHGSMIMGR Mgr;
+ NTSTATUS Status = vboxVdmaCrHmCreate(pDevExt, &Mgr, cbCommandBuffer, cCommands);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxVdmaCrHmCreate failed Status 0x%x", Status));
+ return Status;
+ }
- break;
+ int dummy = 1;
+
+ crPackWindowCreate(&CrPacker.CrPacker, "", visualBits, 0, &pi32CtxID, &dummy);
+
+ Status = vboxVdmaCrHmSubmitWrSync(pDevExt, &Mgr, u32CrConClientID);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxVdmaCrHmSubmitWrSync failed Status 0x%x", Status));
+ return Status;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS vboxVdmaCrCtlGetDefaultCtxId(PVBOXMP_DEVEXT pDevExt, int32_t *pi32CtxID)
+{
+ if (!pDevExt->i32CrConDefaultCtxID)
+ {
+ if (!pDevExt->f3DEnabled)
+ {
+ WARN(("3D disabled, should not be here!"));
+ return STATUS_UNSUCCESSFUL;
}
- case VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP:
+ uint32_t u32ClienID;
+ NTSTATUS Status = vboxVdmaCrCtlGetDefaultClientId(pDevExt, &u32ClienID);
+ if (!NT_SUCCESS(Status))
{
- PVBOXVDMAPIPE_CMD_DMACMD_FLIP pFlip = (PVBOXVDMAPIPE_CMD_DMACMD_FLIP)pDmaCmd;
- PVBOXWDDM_ALLOCATION pAlloc = pFlip->Flip.Alloc.pAlloc;
- VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pAlloc->AllocData.SurfDesc.VidPnSourceId];
- if (pFlip->Hdr.fFlags.fVisibleRegions)
- {
- PVBOXWDDM_SWAPCHAIN pSwapchain;
- pSwapchain = vboxWddmSwapchainRetainByAlloc(pDevExt, pAlloc);
- if (pSwapchain)
- {
- POINT pos = pSource->VScreenPos;
- RECT SrcRect;
- VBOXVDMAPIPE_RECTS Rects;
- SrcRect.left = 0;
- SrcRect.top = 0;
- SrcRect.right = pAlloc->AllocData.SurfDesc.width;
- SrcRect.bottom = pAlloc->AllocData.SurfDesc.height;
- Rects.ContextRect.left = pos.x;
- Rects.ContextRect.top = pos.y;
- Rects.ContextRect.right = pAlloc->AllocData.SurfDesc.width + pos.x;
- Rects.ContextRect.bottom = pAlloc->AllocData.SurfDesc.height + pos.y;
- Rects.UpdateRects.cRects = 1;
- Rects.UpdateRects.aRects[0] = Rects.ContextRect;
- Status = vboxVdmaGgDirtyRectsProcess(pDevExt, pContext, pSwapchain, &SrcRect, &Rects);
- Assert(Status == STATUS_SUCCESS);
- vboxWddmSwapchainRelease(pSwapchain);
- }
- }
- else
- {
- WARN(("not expected!"));
- }
+ WARN(("vboxVdmaCrCtlGetDefaultClientId failed, Status %#x", Status));
+ return Status;
+ }
- vboxWddmAllocationRelease(pAlloc);
+ Status = vboxVdmaCrCmdWindowCreate(PVBOXMP_DEVEXT pDevExt, int32_t visualBits, int32_t *pi32WinID)
- break;
- }
+ VBOXMP_CRPACKER CrPacker;
+ VBoxMpCrPackerInit(&CrPacker);
- default:
+ int rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &pDevExt->u32CrConDefaultClientID);
+ if (!RT_SUCCESS(rc))
{
- WARN(("not expected!"));
- break;
+ WARN(("VBoxMpCrCtlConConnect failed, rc %d", rc));
+ return STATUS_UNSUCCESSFUL;
}
}
- vboxVdmaGgCmdRelease(pDevExt, &pDmaCmd->Hdr);
+ *pi32CtxID = pDevExt->i32CrConDefaultCtxID;
+ return STATUS_SUCCESS;
+}
+#endif
+
+static NTSTATUS vboxVdmaTexPresentSubmit(PVBOXMP_DEVEXT pDevExt,
+ VBOXMP_CRPACKER *pCrPacker,
+ uint32_t u32CrConClientID,
+ uint32_t hostID,
+ uint32_t cfg,
+ int32_t posX,
+ int32_t posY,
+ uint32_t cRects,
+ const RTRECT*paRects)
+{
+ Assert(pDevExt->fTexPresentEnabled);
+
+ uint32_t cbCommandBuffer = VBOXMP_CRCMD_HEADER_SIZE + VBOXMP_CRCMD_SIZE_VBOXTEXPRESENT(cRects);
+ uint32_t cCommands = 1;
+ void *pvCommandBuffer = VBoxMpCrShgsmiTransportBufAlloc(&pDevExt->CrHgsmiTransport, cbCommandBuffer);
+ if (!pvCommandBuffer)
+ {
+ WARN(("VBoxMpCrShgsmiTransportBufAlloc failed!"));
+ return VERR_OUT_OF_RESOURCES;
+ }
+
+ VBoxMpCrPackerTxBufferInit(pCrPacker, pvCommandBuffer, cbCommandBuffer, cCommands);
+
+ crPackVBoxTexPresent(&pCrPacker->CrPacker, hostID, cfg, posX, posY, cRects, (int32_t*)paRects);
+
+ NTSTATUS Status = vboxVdmaCrSubmitWriteAsync(pDevExt, pCrPacker, u32CrConClientID);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxVdmaCrSubmitWriteAsync failed Status 0x%x", Status));
+ VBoxMpCrShgsmiTransportBufFree(&pDevExt->CrHgsmiTransport, pvCommandBuffer);
+ }
return Status;
}
-static DECLCALLBACK(UINT) vboxVdmaGgCmdCancelVisitor(PVBOXVIDEOCM_CTX pContext, PVOID pvCmd, uint32_t cbCmd, PVOID pvVisitor)
+static NTSTATUS vboxVdmaCrCtlGetDefaultClientId(PVBOXMP_DEVEXT pDevExt, uint32_t *pu32ClienID)
{
- PVBOXWDDM_SWAPCHAIN pSwapchain = (PVBOXWDDM_SWAPCHAIN)pvVisitor;
- if (!pSwapchain)
- return VBOXVIDEOCMCMDVISITOR_RETURN_RMCMD;
- PVBOXVIDEOCM_CMD_RECTS_INTERNAL pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)pvCmd;
- if (pCmdInternal->hSwapchainUm == pSwapchain->hSwapchainUm)
- return VBOXVIDEOCMCMDVISITOR_RETURN_RMCMD;
- return 0;
+ if (!pDevExt->u32CrConDefaultClientID)
+ {
+ if (!pDevExt->f3DEnabled)
+ {
+ WARN(("3D disabled, should not be here!"));
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ int rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &pDevExt->u32CrConDefaultClientID);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("VBoxMpCrCtlConConnect failed, rc %d", rc));
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ *pu32ClienID = pDevExt->u32CrConDefaultClientID;
+ return STATUS_SUCCESS;
}
-static VOID vboxVdmaGgWorkerThread(PVOID pvUser)
+static NTSTATUS vboxVdmaProcessVReg(PVBOXMP_DEVEXT pDevExt,
+ VBOXMP_CRPACKER *pCrPacker,
+ uint32_t u32CrConClientID,
+ const VBOXWDDM_ALLOCATION *pSrcAlloc,
+ const VBOXWDDM_ALLOCATION *pDstAlloc,
+ const RECT *pSrcRect, const VBOXVDMAPIPE_RECTS *pDstRects)
{
- PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)pvUser;
- PVBOXVDMAGG pVdma = &pDevExt->u.primary.Vdma.DmaGg;
+ D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId = pDstAlloc->AllocData.SurfDesc.VidPnSourceId;
+ VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[srcId];
+ NTSTATUS Status = STATUS_SUCCESS;
- NTSTATUS Status = vboxVdmaPipeSvrOpen(&pVdma->CmdPipe);
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
+ if (pDevExt->fTexPresentEnabled)
{
- do
+ /* we care only about screen regions */
+ if (pDstAlloc != pSource->pPrimaryAllocation)
{
- LIST_ENTRY CmdList;
- Status = vboxVdmaPipeSvrCmdGetList(&pVdma->CmdPipe, &CmdList);
- Assert(Status == STATUS_SUCCESS || Status == STATUS_PIPE_CLOSING);
- if (Status == STATUS_SUCCESS)
+ WARN(("non-primary allocation passed to vboxWddmSubmitBltCmd!"));
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ uint32_t hostID = pSrcAlloc->AllocData.hostID;
+ int rc;
+ if (hostID)
+ {
+// Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
+ int32_t posX = pDstRects->ContextRect.left - pSrcRect->left;
+ int32_t posY = pDstRects->ContextRect.top - pSrcRect->top;
+
+ Status = vboxVdmaTexPresentSubmit(pDevExt, pCrPacker, u32CrConClientID, hostID, srcId, posX, posY, pDstRects->UpdateRects.cRects, (const RTRECT*)pDstRects->UpdateRects.aRects);
+ if (NT_SUCCESS(Status))
{
- for (PLIST_ENTRY pCur = CmdList.Blink; pCur != &CmdList;)
+ rc = VBoxVrListRectsSubst(&pSource->VrList, pDstRects->UpdateRects.cRects, (const RTRECT*)pDstRects->UpdateRects.aRects, NULL);
+ if (RT_SUCCESS(rc))
+ pSource->fHas3DVrs = TRUE;
+ else
+ WARN(("VBoxVrListRectsSubst failed rc %d, ignoring..", rc));
+ }
+ else
+ WARN(("vboxVdmaTexPresentSubmit failed Status 0x%x", Status));
+ }
+ else if (pSource->pPrimaryAllocation == pDstAlloc)
+ {
+ bool fChanged = false;
+ Assert(pSource->pPrimaryAllocation->bVisible);
+ rc = VBoxVrListRectsAdd(&pSource->VrList, pDstRects->UpdateRects.cRects, (const RTRECT*)pDstRects->UpdateRects.aRects, &fChanged);
+ if (RT_SUCCESS(rc))
+ {
+ if (fChanged)
{
- PVBOXVDMAPIPE_CMD_DR pDr = VBOXVDMAPIPE_CMD_DR_FROM_ENTRY(pCur);
- RemoveEntryList(pCur);
- pCur = CmdList.Blink;
- switch (pDr->enmType)
+ Status = vboxVdmaTexPresentSubmit(pDevExt, pCrPacker, u32CrConClientID, hostID, srcId, 0, 0, pDstRects->UpdateRects.cRects, (const RTRECT*)pDstRects->UpdateRects.aRects);
+ if (NT_SUCCESS(Status))
{
- case VBOXVDMAPIPE_CMD_TYPE_DMACMD:
- {
- PVBOXVDMAPIPE_CMD_DMACMD pDmaCmd = (PVBOXVDMAPIPE_CMD_DMACMD)pDr;
- Status = vboxVdmaGgDmaCmdProcessSlow(pDevExt, pDmaCmd);
- Assert(Status == STATUS_SUCCESS);
- } break;
-#if 0
- case VBOXVDMAPIPE_CMD_TYPE_RECTSINFO:
+ if (pSource->fHas3DVrs)
{
- PVBOXVDMAPIPE_CMD_RECTSINFO pRects = (PVBOXVDMAPIPE_CMD_RECTSINFO)pDr;
- Status = vboxVdmaGgDirtyRectsProcess(pDevExt, pRects->pContext, pRects->pSwapchain, &pRects->ContextsRects);
- Assert(Status == STATUS_SUCCESS);
- vboxVdmaGgCmdRelease(pDevExt, pDr);
- break;
- }
-#endif
- case VBOXVDMAPIPE_CMD_TYPE_FINISH:
- {
- PVBOXVDMAPIPE_CMD_FINISH pCmd = (PVBOXVDMAPIPE_CMD_FINISH)pDr;
- PVBOXWDDM_CONTEXT pContext = pCmd->pContext;
- Assert(pCmd->pEvent);
- Status = vboxVideoCmCmdSubmitCompleteEvent(&pContext->CmContext, pCmd->pEvent);
- if (Status != STATUS_SUCCESS)
- {
- WARN(("vboxVideoCmCmdWaitCompleted failedm Status (0x%x)", Status));
- }
- vboxVdmaGgCmdRelease(pDevExt, &pCmd->Hdr);
- break;
- }
- case VBOXVDMAPIPE_CMD_TYPE_CANCEL:
- {
- PVBOXVDMAPIPE_CMD_CANCEL pCmd = (PVBOXVDMAPIPE_CMD_CANCEL)pDr;
- PVBOXWDDM_CONTEXT pContext = pCmd->pContext;
- Status = vboxVideoCmCmdVisit(&pContext->CmContext, FALSE, vboxVdmaGgCmdCancelVisitor, pCmd->pSwapchain);
- if (Status != STATUS_SUCCESS)
+ if (VBoxVrListRectsCount(&pSource->VrList) == 1)
{
- WARN(("vboxVideoCmCmdWaitCompleted failedm Status (0x%x)", Status));
+ RTRECT Rect;
+ VBoxVrListRectsGet(&pSource->VrList, 1, &Rect);
+ if (Rect.xLeft == 0
+ && Rect.yTop == 0
+ && Rect.xRight == pDstAlloc->AllocData.SurfDesc.width
+ && Rect.yBottom == pDstAlloc->AllocData.SurfDesc.height)
+ {
+ pSource->fHas3DVrs = FALSE;
+ }
}
- Assert(pCmd->pEvent);
- KeSetEvent(pCmd->pEvent, 0, FALSE);
- vboxVdmaGgCmdRelease(pDevExt, &pCmd->Hdr);
- break;
}
- default:
- AssertBreakpoint();
}
+ else
+ WARN(("vboxVdmaTexPresentSubmit failed Status 0x%x", Status));
}
}
else
- break;
- } while (1);
+ WARN(("VBoxVrListRectsAdd failed rc %d, ignoring..", rc));
+ }
+ else
+ {
+ WARN(("unexpected"));
+ Status = STATUS_INVALID_PARAMETER;
+ }
}
+ else
+ {
+ PVBOXWDDM_SWAPCHAIN pSwapchain = vboxWddmSwapchainRetainByAlloc(pDevExt, pSrcAlloc);
- /* always try to close the pipe to make sure the client side is notified */
- Status = vboxVdmaPipeSvrClose(&pVdma->CmdPipe);
- Assert(Status == STATUS_SUCCESS);
-}
+ if (pSwapchain)
+ {
+ Assert(pSrcAlloc->AllocData.SurfDesc.width == pSwapchain->width);
+ Assert(pSrcAlloc->AllocData.SurfDesc.height == pSwapchain->height);
+ }
-NTSTATUS vboxVdmaGgConstruct(PVBOXMP_DEVEXT pDevExt)
-{
- PVBOXVDMAGG pVdma = &pDevExt->u.primary.Vdma.DmaGg;
- NTSTATUS Status = vboxVdmaPipeConstruct(&pVdma->CmdPipe);
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
- {
- Status = vboxVdmaGgThreadCreate(&pVdma->pThread, vboxVdmaGgWorkerThread, pDevExt);
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
- return STATUS_SUCCESS;
+ Status = vboxVdmaProcessVRegCmdLegacy(pDevExt, pCrPacker, u32CrConClientID, pSource, pSwapchain, pSrcRect, pDstRects);
+ if (!NT_SUCCESS(Status))
+ WARN(("vboxVdmaProcessVRegCmdLegacy failed Status 0x%x", Status));
- NTSTATUS tmpStatus = vboxVdmaPipeDestruct(&pVdma->CmdPipe);
- Assert(tmpStatus == STATUS_SUCCESS);
+ if (pSwapchain)
+ vboxWddmSwapchainRelease(pSwapchain);
}
- /* we're here ONLY in case of an error */
- Assert(Status != STATUS_SUCCESS);
return Status;
}
-NTSTATUS vboxVdmaGgDestruct(PVBOXMP_DEVEXT pDevExt)
+NTSTATUS vboxVdmaTexPresentSetAlloc(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pRealFbAlloc)
{
- PVBOXVDMAGG pVdma = &pDevExt->u.primary.Vdma.DmaGg;
- /* this informs the server thread that it should complete all current commands and exit */
- NTSTATUS Status = vboxVdmaPipeCltClose(&pVdma->CmdPipe);
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
+ VBOXMP_CRPACKER CrPacker;
+ VBoxMpCrPackerInit(&CrPacker);
+ uint32_t u32CrConClientID;
+
+ NTSTATUS Status = vboxVdmaCrCtlGetDefaultClientId(pDevExt, &u32CrConClientID);
+ if (!NT_SUCCESS(Status))
{
- Status = KeWaitForSingleObject(pVdma->pThread, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
- {
- Status = vboxVdmaPipeDestruct(&pVdma->CmdPipe);
- Assert(Status == STATUS_SUCCESS);
- }
+ WARN(("vboxVdmaCrCtlGetDefaultClientId failed Status 0x%x", Status));
+ return Status;
}
- return Status;
-}
+ RECT Rect;
+ Rect.left = 0;
+ Rect.top = 0;
+ Rect.right = pRealFbAlloc->AllocData.SurfDesc.width;
+ Rect.bottom = pRealFbAlloc->AllocData.SurfDesc.height;
-NTSTATUS vboxVdmaGgCmdSubmit(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DR pCmd)
-{
- switch (pCmd->enmType)
- {
- case VBOXVDMAPIPE_CMD_TYPE_DMACMD:
- {
- PVBOXVDMAPIPE_CMD_DMACMD pDmaCmd = (PVBOXVDMAPIPE_CMD_DMACMD)pCmd;
- NTSTATUS Status = vboxVdmaGgDmaCmdProcessFast(pDevExt, pDmaCmd);
- if (Status == STATUS_MORE_PROCESSING_REQUIRED)
- break;
- return Status;
- }
- default:
- break;
- }
- /* correspondinf Release is done by the pipe command handler */
- vboxVdmaGgCmdAddRef(pCmd);
- return vboxVdmaPipeCltCmdPut(&pDevExt->u.primary.Vdma.DmaGg.CmdPipe, &pCmd->PipeHdr);
+ VBOXVDMAPIPE_RECTS RectInfo;
+ RectInfo.ContextRect = Rect;
+ RectInfo.UpdateRects.cRects = 1;
+ RectInfo.UpdateRects.aRects[0] = Rect;
+
+ return vboxVdmaProcessVReg(pDevExt, &CrPacker, u32CrConClientID,
+ pRealFbAlloc, pRealFbAlloc,
+ &Rect, &RectInfo);
}
-NTSTATUS vboxVdmaGgCmdDmaNotifySubmitted(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DMACMD pCmd)
+static NTSTATUS vboxVdmaProcessVRegCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext,
+ const VBOXWDDM_DMA_ALLOCINFO *pSrcAllocInfo,
+ const VBOXWDDM_DMA_ALLOCINFO *pDstAllocInfo,
+ const RECT *pSrcRect, const VBOXVDMAPIPE_RECTS *pDstRects)
{
- PVBOXVDMADDI_CMD pDdiCmd;
-#ifdef VBOX_WDDM_IRQ_COMPLETION
- pDdiCmd = vboxVdmaGgCmdDmaGetDdiCmd(pCmd);
-#else
- pDdiCmd = &pCmd->DdiCmd;
-#endif
- NTSTATUS Status = vboxVdmaDdiCmdSubmitted(pDevExt, pDdiCmd);
- Assert(Status == STATUS_SUCCESS);
- return Status;
+ return vboxVdmaProcessVReg(pDevExt, &pContext->CrPacker, pContext->u32CrConClientID,
+ pSrcAllocInfo->pAlloc, pDstAllocInfo->pAlloc,
+ pSrcRect, pDstRects);
}
-NTSTATUS vboxVdmaGgCmdDmaNotifyCompleted(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DMACMD pCmd, DXGK_INTERRUPT_TYPE enmComplType)
+static void vboxVdmaBltDirtyRectsUpdate(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_SOURCE *pSource, uint32_t cRects, const RECT *paRects)
{
-#ifdef VBOX_WDDM_IRQ_COMPLETION
- VBOXVDMACBUF_DR* pDr = vboxVdmaGgCmdDmaGetDr(pCmd);
- int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
- Assert(rc == VINF_SUCCESS);
- if (RT_SUCCESS(rc))
+ if (!cRects)
{
- return STATUS_SUCCESS;
+ WARN(("vboxVdmaBltDirtyRectsUpdate: no rects specified"));
+ return;
}
- return STATUS_UNSUCCESSFUL;
-#else
- return vboxVdmaDdiCmdCompleted(pDevExt, &pCmd->DdiCmd, enmComplType);
-#endif
-}
-VOID vboxVdmaGgCmdDmaNotifyInit(PVBOXVDMAPIPE_CMD_DMACMD pCmd,
- uint32_t u32NodeOrdinal, uint32_t u32FenceId,
- PFNVBOXVDMADDICMDCOMPLETE_DPC pfnComplete, PVOID pvComplete)
-{
- PVBOXVDMADDI_CMD pDdiCmd;
-#ifdef VBOX_WDDM_IRQ_COMPLETION
- pDdiCmd = vboxVdmaGgCmdDmaGetDdiCmd(pCmd);
-#else
- pDdiCmd = &pCmd->DdiCmd;
-#endif
- vboxVdmaDdiCmdInit(pDdiCmd, u32NodeOrdinal, u32FenceId, pfnComplete, pvComplete);
+ RECT rect;
+ rect = paRects[0];
+ for (UINT i = 1; i < cRects; ++i)
+ {
+ vboxWddmRectUnited(&rect, &rect, &paRects[i]);
+ }
+
+ uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
+ if (!cUnlockedVBVADisabled)
+ {
+ VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &rect);
+ }
+ else
+ {
+ VBOXVBVA_OP_WITHLOCK_ATDPC(ReportDirtyRect, pDevExt, pSource, &rect);
+ }
}
-NTSTATUS vboxVdmaGgCmdFinish(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, PKEVENT pEvent)
+NTSTATUS vboxVdmaProcessBltCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, VBOXWDDM_DMA_PRIVATEDATA_BLT *pBlt)
{
NTSTATUS Status = STATUS_SUCCESS;
+ PVBOXWDDM_ALLOCATION pDstAlloc = pBlt->Blt.DstAlloc.pAlloc;
+ PVBOXWDDM_ALLOCATION pSrcAlloc = pBlt->Blt.SrcAlloc.pAlloc;
+ BOOLEAN fRenderFromSharedDisabled = pDevExt->fRenderToShadowDisabled;
+ BOOLEAN fVRAMUpdated = FALSE;
- PVBOXVDMAPIPE_CMD_FINISH pCmd = (PVBOXVDMAPIPE_CMD_FINISH)vboxVdmaGgCmdCreate(pDevExt, VBOXVDMAPIPE_CMD_TYPE_FINISH, sizeof (*pCmd));
- if (pCmd)
+ if (!pDstAlloc->AllocData.hostID && !pSrcAlloc->AllocData.hostID)
{
- pCmd->pContext = pContext;
- pCmd->pEvent = pEvent;
- Status = vboxVdmaGgCmdSubmit(pDevExt, &pCmd->Hdr);
- if (!NT_SUCCESS(Status))
+ /* the allocations contain a real data in VRAM, do blitting */
+ vboxVdmaGgDmaBlt(pDevExt, &pBlt->Blt);
+ fVRAMUpdated = TRUE;
+ }
+
+ if (VBOXWDDM_IS_REAL_FB_ALLOCATION(pDevExt, pDstAlloc)
+ && pDstAlloc->bVisible)
+ {
+ VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->AllocData.SurfDesc.VidPnSourceId];
+ Assert(pDstAlloc->AllocData.SurfDesc.VidPnSourceId < VBOX_VIDEO_MAX_SCREENS);
+ Assert(pSource->pPrimaryAllocation == pDstAlloc);
+
+
+ if (fVRAMUpdated)
+ vboxVdmaBltDirtyRectsUpdate(pDevExt, pSource, pBlt->Blt.DstRects.UpdateRects.cRects, pBlt->Blt.DstRects.UpdateRects.aRects);
+
+ if (pSrcAlloc->AllocData.hostID || (pDevExt->fTexPresentEnabled ? pSource->fHas3DVrs : !!pDevExt->cContexts3D))
{
- WARN(("vboxVdmaGgCmdSubmit returned 0x%x", Status));
+ Status = vboxVdmaProcessVRegCmd(pDevExt, pContext, &pBlt->Blt.SrcAlloc, &pBlt->Blt.DstAlloc, &pBlt->Blt.SrcRect, &pBlt->Blt.DstRects);
+ if (!NT_SUCCESS(Status))
+ WARN(("vboxVdmaProcessVRegCmd failed Status 0x%x", Status));
}
- vboxVdmaGgCmdRelease(pDevExt, &pCmd->Hdr);
}
- else
+
+ return Status;
+}
+
+NTSTATUS vboxVdmaProcessFlipCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, VBOXWDDM_DMA_PRIVATEDATA_FLIP *pFlip)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PVBOXWDDM_ALLOCATION pAlloc = pFlip->Flip.Alloc.pAlloc;
+ VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pAlloc->AllocData.SurfDesc.VidPnSourceId];
+ vboxWddmAssignPrimary(pDevExt, pSource, pAlloc, pAlloc->AllocData.SurfDesc.VidPnSourceId);
+ if (pAlloc->AllocData.hostID)
{
- WARN(("vboxVdmaGgCmdCreate failed"));
- Status = STATUS_NO_MEMORY;
+ RECT SrcRect;
+ VBOXVDMAPIPE_RECTS Rects;
+ SrcRect.left = 0;
+ SrcRect.top = 0;
+ SrcRect.right = pAlloc->AllocData.SurfDesc.width;
+ SrcRect.bottom = pAlloc->AllocData.SurfDesc.height;
+ Rects.ContextRect.left = 0;
+ Rects.ContextRect.top = 0;
+ Rects.ContextRect.right = pAlloc->AllocData.SurfDesc.width;
+ Rects.ContextRect.bottom = pAlloc->AllocData.SurfDesc.height;
+ Rects.UpdateRects.cRects = 1;
+ Rects.UpdateRects.aRects[0] = Rects.ContextRect;
+
+ Status = vboxVdmaProcessVRegCmd(pDevExt, pContext, &pFlip->Flip.Alloc, &pFlip->Flip.Alloc, &SrcRect, &Rects);
+ if (!NT_SUCCESS(Status))
+ WARN(("vboxVdmaProcessVRegCmd failed Status 0x%x", Status));
}
+ else
+ WARN(("unexpected flip request"));
+
return Status;
}
-NTSTATUS vboxVdmaGgCmdCancel(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
+NTSTATUS vboxVdmaProcessClrFillCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, VBOXWDDM_DMA_PRIVATEDATA_CLRFILL *pCF)
{
NTSTATUS Status = STATUS_SUCCESS;
+ PVBOXWDDM_ALLOCATION pAlloc = pCF->ClrFill.Alloc.pAlloc;
- PVBOXVDMAPIPE_CMD_CANCEL pCmd = (PVBOXVDMAPIPE_CMD_CANCEL)vboxVdmaGgCmdCreate(pDevExt, VBOXVDMAPIPE_CMD_TYPE_CANCEL, sizeof (*pCmd));
- if (pCmd)
+ if (!pAlloc->AllocData.hostID)
{
- KEVENT Event;
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- pCmd->pContext = pContext;
- pCmd->pSwapchain = pSwapchain;
- pCmd->pEvent = &Event;
- Status = vboxVdmaGgCmdSubmit(pDevExt, &pCmd->Hdr);
- if (NT_SUCCESS(Status))
- {
- Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
- Assert(Status == STATUS_SUCCESS);
- }
- else
- {
- WARN(("vboxVdmaGgCmdSubmit returned 0x%x", Status));
- }
- vboxVdmaGgCmdRelease(pDevExt, &pCmd->Hdr);
+ Status = vboxVdmaGgDmaColorFill(pDevExt, &pCF->ClrFill);
+ if (!NT_SUCCESS(Status))
+ WARN(("vboxVdmaGgDmaColorFill failed Status 0x%x", Status));
}
else
- {
- WARN(("vboxVdmaGgCmdCreate failed"));
- Status = STATUS_NO_MEMORY;
- }
+ WARN(("unexpected clrfill request"));
+
return Status;
}
-/* end */
#ifdef VBOX_WITH_VDMA
/*
@@ -1325,11 +1493,7 @@ int vboxVdmaCreate(PVBOXMP_DEVEXT pDevExt, VBOXVDMAINFO *pInfo
if(RT_SUCCESS(rc))
#endif
{
- NTSTATUS Status = vboxVdmaGgConstruct(pDevExt);
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
- return VINF_SUCCESS;
- rc = VERR_GENERAL_FAILURE;
+ return VINF_SUCCESS;
}
#ifdef VBOX_WITH_VDMA
else
@@ -1345,8 +1509,6 @@ int vboxVdmaCreate(PVBOXMP_DEVEXT pDevExt, VBOXVDMAINFO *pInfo
int vboxVdmaDisable (PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo)
{
- LOGF(("."));
-
Assert(pInfo->fEnabled);
if (!pInfo->fEnabled)
return VINF_ALREADY_INITIALIZED;
@@ -1364,8 +1526,6 @@ int vboxVdmaDisable (PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo)
int vboxVdmaEnable (PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo)
{
- LOGF(("."));
-
Assert(!pInfo->fEnabled);
if (pInfo->fEnabled)
return VINF_ALREADY_INITIALIZED;
@@ -1384,8 +1544,6 @@ int vboxVdmaEnable (PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo)
#ifdef VBOX_WITH_VDMA
int vboxVdmaFlush (PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo)
{
- LOGF(("."));
-
Assert(pInfo->fEnabled);
if (!pInfo->fEnabled)
return VINF_ALREADY_INITIALIZED;
@@ -1400,20 +1558,13 @@ int vboxVdmaFlush (PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo)
int vboxVdmaDestroy (PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo)
{
int rc = VINF_SUCCESS;
- NTSTATUS Status = vboxVdmaGgDestruct(pDevExt);
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
- {
- Assert(!pInfo->fEnabled);
- if (pInfo->fEnabled)
- rc = vboxVdmaDisable (pDevExt, pInfo);
+ Assert(!pInfo->fEnabled);
+ if (pInfo->fEnabled)
+ rc = vboxVdmaDisable (pDevExt, pInfo);
#ifdef VBOX_WITH_VDMA
- VBoxSHGSMITerm(&pInfo->CmdHeap);
- VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pInfo->CmdHeap.Heap.area.pu8Base);
+ VBoxSHGSMITerm(&pInfo->CmdHeap);
+ VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pInfo->CmdHeap.Heap.area.pu8Base);
#endif
- }
- else
- rc = VERR_GENERAL_FAILURE;
return rc;
}
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVdma.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVdma.h
index 653520fd..4b544ac5 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVdma.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVdma.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -211,19 +211,6 @@ typedef struct VBOXVDMAPIPE_CMD_CANCEL
PKEVENT pEvent;
} VBOXVDMAPIPE_CMD_CANCEL, *PVBOXVDMAPIPE_CMD_CANCEL;
-typedef struct VBOXVDMAPIPE_FLAGS_DMACMD
-{
- union
- {
- struct
- {
- UINT fRealOp : 1;
- UINT fVisibleRegions : 1;
- UINT Reserve : 30;
- };
- UINT Value;
- };
-} VBOXVDMAPIPE_FLAGS_DMACMD, *PVBOXVDMAPIPE_FLAGS_DMACMD;
typedef struct VBOXVDMAPIPE_CMD_DMACMD
{
VBOXVDMAPIPE_CMD_DR Hdr;
@@ -232,7 +219,7 @@ typedef struct VBOXVDMAPIPE_CMD_DMACMD
#endif
PVBOXWDDM_CONTEXT pContext;
VBOXVDMACMD_TYPE enmCmd;
- VBOXVDMAPIPE_FLAGS_DMACMD fFlags;
+// VBOXVDMAPIPE_FLAGS_DMACMD fFlags;
} VBOXVDMAPIPE_CMD_DMACMD, *PVBOXVDMAPIPE_CMD_DMACMD;
typedef struct VBOXVDMA_CLRFILL
@@ -294,8 +281,6 @@ typedef struct VBOXVDMAINFO
#endif
UINT uLastCompletedPagingBufferCmdFenceId;
BOOL fEnabled;
- /* dma-related commands list processed on the guest w/o host part involvement (guest-guest commands) */
- VBOXVDMAGG DmaGg;
} VBOXVDMAINFO, *PVBOXVDMAINFO;
int vboxVdmaCreate (PVBOXMP_DEVEXT pDevExt, VBOXVDMAINFO *pInfo
@@ -312,6 +297,10 @@ int vboxVdmaDestroy(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo);
#ifdef VBOX_WITH_VDMA
int vboxVdmaFlush(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo);
+DECLINLINE(HGSMIOFFSET) vboxVdmaCBufDrPtrOffset(const PVBOXVDMAINFO pInfo, const void* pvPtr)
+{
+ return VBoxSHGSMICommandPtrOffset(&pInfo->CmdHeap, pvPtr);
+}
int vboxVdmaCBufDrSubmit(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr);
int vboxVdmaCBufDrSubmitSynch(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr);
struct VBOXVDMACBUF_DR* vboxVdmaCBufDrCreate(PVBOXVDMAINFO pInfo, uint32_t cbTrailingData);
@@ -326,22 +315,6 @@ AssertCompile(sizeof (VBOXVDMADDI_CMD) <= RT_SIZEOFMEMB(VBOXVDMACBUF_DR, aGuestD
#define VBOXVDMACBUF_DR_FROM_DDI_CMD(_pCmd) ((PVBOXVDMACBUF_DR)(((uint8_t*)(_pCmd)) - RT_OFFSETOF(VBOXVDMACBUF_DR, aGuestData)))
#endif
-NTSTATUS vboxVdmaGgCmdSubmit(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DR pCmd);
-PVBOXVDMAPIPE_CMD_DR vboxVdmaGgCmdCreate(PVBOXMP_DEVEXT pDevExt, VBOXVDMAPIPE_CMD_TYPE enmType, uint32_t cbCmd);
-DECLINLINE(void) vboxVdmaGgCmdAddRef(PVBOXVDMAPIPE_CMD_DR pDr)
-{
- ASMAtomicIncU32(&pDr->cRefs);
-}
-void vboxVdmaGgCmdDestroy(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DR pDr);
-DECLINLINE(void) vboxVdmaGgCmdRelease(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DR pDr)
-{
- uint32_t cRefs = ASMAtomicDecU32(&pDr->cRefs);
- Assert(cRefs < UINT32_MAX/2);
- if (!cRefs)
- vboxVdmaGgCmdDestroy(pDevExt, pDr);
-}
-NTSTATUS vboxVdmaGgCmdFinish(PVBOXMP_DEVEXT pDevExt, struct VBOXWDDM_CONTEXT *pContext, PKEVENT pEvent);
-NTSTATUS vboxVdmaGgCmdCancel(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, PVBOXWDDM_SWAPCHAIN pSwapchain);
NTSTATUS vboxVdmaPostHideSwapchain(PVBOXWDDM_SWAPCHAIN pSwapchain);
@@ -355,5 +328,11 @@ NTSTATUS vboxVdmaGgDmaBltPerform(PVBOXMP_DEVEXT pDevExt, struct VBOXWDDM_ALLOC_D
struct VBOXWDDM_ALLOC_DATA *pDstAlloc, RECT* pDstRect);
#define VBOXVDMAPIPE_CMD_DR_FROM_DDI_CMD(_pCmd) ((PVBOXVDMAPIPE_CMD_DR)(((uint8_t*)(_pCmd)) - RT_OFFSETOF(VBOXVDMAPIPE_CMD_DR, DdiCmd)))
-DECLCALLBACK(VOID) vboxVdmaGgDdiCmdRelease(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext);
+
+NTSTATUS vboxVdmaProcessBltCmd(PVBOXMP_DEVEXT pDevExt, struct VBOXWDDM_CONTEXT *pContext, struct VBOXWDDM_DMA_PRIVATEDATA_BLT *pBlt);
+NTSTATUS vboxVdmaProcessFlipCmd(PVBOXMP_DEVEXT pDevExt, struct VBOXWDDM_CONTEXT *pContext, struct VBOXWDDM_DMA_PRIVATEDATA_FLIP *pFlip);
+NTSTATUS vboxVdmaProcessClrFillCmd(PVBOXMP_DEVEXT pDevExt, struct VBOXWDDM_CONTEXT *pContext, struct VBOXWDDM_DMA_PRIVATEDATA_CLRFILL *pCF);
+
+NTSTATUS vboxVdmaTexPresentSetAlloc(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pRealFbAlloc);
+
#endif /* #ifndef ___VBoxMPVdma_h___ */
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVhwa.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVhwa.cpp
index d948ea97..a6deff29 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVhwa.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVhwa.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVhwa.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVhwa.h
index e4279154..ca08d756 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVhwa.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVhwa.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.cpp
index 4813f818..a9e1d8e3 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -552,6 +552,10 @@ static DECLCALLBACK(BOOLEAN) vboxFidPnMatchMonitorModesEnum(D3DKMDT_HMONITORSOUR
if (!fFound)
pInfo->fMatched = FALSE;
+ if (!pInfo->fMatched)
+ LOG(("Found non-matching mode (%d X %d)",
+ pMonitorSMI->VideoSignalInfo.ActiveSize.cx, pMonitorSMI->VideoSignalInfo.ActiveSize.cy));
+
pMonitorSMSIf->pfnReleaseModeInfo(hMonitorSMS, pMonitorSMI);
return pInfo->fMatched;
@@ -596,7 +600,10 @@ NTSTATUS vboxVidPnMatchMonitorModes(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT
if (NT_SUCCESS(Status))
{
if (cModes < cResolutions)
+ {
*pfMatch = FALSE;
+ LOG(("num modes(%d) and resolutions(%d) do not match, treat as not matched..", cModes, cResolutions));
+ }
else
{
VBOXVIDPNMATCHMONMODESENUM Info;
@@ -606,7 +613,12 @@ NTSTATUS vboxVidPnMatchMonitorModes(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT
Status = vboxVidPnEnumMonitorSourceModes(hMonitorSMS, pMonitorSMSIf, vboxFidPnMatchMonitorModesEnum, &Info);
if (NT_SUCCESS(Status))
+ {
*pfMatch = Info.fMatched;
+ LOG(("modes %smatched", Info.fMatched ? "" : "NOT "));
+ }
+ else
+ WARN(("vboxVidPnEnumMonitorSourceModes failed, Status 0x%x", Status));
}
}
else
@@ -1250,10 +1262,7 @@ static NTSTATUS vboxVidPnCofuncModalityForPathTarget(PVBOXVIDPNCOFUNCMODALITY pC
D3DKMDT_HVIDPNTARGETMODESET hNewVidPnTargetModeSet = NULL;
const DXGK_VIDPNTARGETMODESET_INTERFACE *pNewVidPnTargetModeSetInterface;
- if (VidPnSourceId != VidPnTargetId || pCbContext->apPathInfos[VidPnTargetId].enmState != VBOXVIDPNPATHITEM_STATE_PRESENT)
- {
- return STATUS_SUCCESS;
- }
+ Assert(VidPnSourceId == VidPnTargetId);
D3DKMDT_HVIDPNSOURCEMODESET hCurVidPnSourceModeSet;
const DXGK_VIDPNSOURCEMODESET_INTERFACE *pCurVidPnSourceModeSetInterface;
@@ -1293,10 +1302,9 @@ static NTSTATUS vboxVidPnCofuncModalityForPathTarget(PVBOXVIDPNCOFUNCMODALITY pC
if (NT_SUCCESS(Status))
{
Assert(hNewVidPnTargetModeSet);
- if (VidPnSourceId == VidPnTargetId && pCbContext->apPathInfos[VidPnTargetId].enmState == VBOXVIDPNPATHITEM_STATE_PRESENT)
+ Assert(VidPnSourceId == VidPnTargetId);
+// if (VidPnSourceId == VidPnTargetId && pCbContext->apPathInfos[VidPnTargetId].enmState == VBOXVIDPNPATHITEM_STATE_PRESENT)
{
- Assert(VidPnSourceId == VidPnTargetId);
-
for (uint32_t i = 0; i < pInfo->cResolutions; ++i)
{
D3DKMDT_2DREGION *pResolution = &pInfo->aResolutions[i];
@@ -1385,10 +1393,7 @@ static NTSTATUS vboxVidPnCofuncModalityForPathSource(PVBOXVIDPNCOFUNCMODALITY pC
D3DKMDT_HVIDPNSOURCEMODESET hNewVidPnSourceModeSet = NULL;
const DXGK_VIDPNSOURCEMODESET_INTERFACE *pNewVidPnSourceModeSetInterface;
- if (VidPnSourceId != VidPnTargetId || pCbContext->apPathInfos[VidPnSourceId].enmState != VBOXVIDPNPATHITEM_STATE_PRESENT)
- {
- return STATUS_SUCCESS;
- }
+ Assert(VidPnSourceId == VidPnTargetId);
D3DKMDT_HVIDPNTARGETMODESET hCurVidPnTargetModeSet;
const DXGK_VIDPNTARGETMODESET_INTERFACE *pCurVidPnTargetModeSetInterface;
@@ -1428,9 +1433,9 @@ static NTSTATUS vboxVidPnCofuncModalityForPathSource(PVBOXVIDPNCOFUNCMODALITY pC
if (NT_SUCCESS(Status))
{
Assert(hNewVidPnSourceModeSet);
- if (VidPnSourceId == VidPnTargetId && pCbContext->apPathInfos[VidPnSourceId].enmState == VBOXVIDPNPATHITEM_STATE_PRESENT)
+ Assert(VidPnSourceId == VidPnTargetId);
+// if (VidPnSourceId == VidPnTargetId && pCbContext->apPathInfos[VidPnSourceId].enmState == VBOXVIDPNPATHITEM_STATE_PRESENT)
{
- Assert(VidPnSourceId == VidPnTargetId);
for (uint32_t i = 0; i < pInfo->cModes; ++i)
{
VIDEO_MODE_INFORMATION *pMode = &pInfo->aModes[i];
@@ -1742,7 +1747,7 @@ static DECLCALLBACK(BOOLEAN) vboxVidPnCheckTopologyEnum(D3DKMDT_HVIDPNTOPOLOGY h
}
else
{
- AssertFailed();
+ WARN(("cItems(%d) <= VidPnSourceId(%d)", pCbContext->cItems, VidPnSourceId));
Status = STATUS_BUFFER_OVERFLOW;
break;
}
@@ -1753,7 +1758,7 @@ static DECLCALLBACK(BOOLEAN) vboxVidPnCheckTopologyEnum(D3DKMDT_HVIDPNTOPOLOGY h
}
else
{
- AssertFailed();
+ WARN(("cItems(%d) <= VidPnTargetId(%d)", pCbContext->cItems, VidPnTargetId));
Status = STATUS_BUFFER_OVERFLOW;
break;
}
@@ -1762,6 +1767,7 @@ static DECLCALLBACK(BOOLEAN) vboxVidPnCheckTopologyEnum(D3DKMDT_HVIDPNTOPOLOGY h
}
/* VidPnSourceId == VidPnTargetId */
+ Assert(VidPnSourceId == VidPnTargetId);
if (pCbContext->cItems > VidPnSourceId)
{
if (pCbContext->paItems[VidPnSourceId].enmState != VBOXVIDPNPATHITEM_STATE_DISABLED)
@@ -1772,7 +1778,7 @@ static DECLCALLBACK(BOOLEAN) vboxVidPnCheckTopologyEnum(D3DKMDT_HVIDPNTOPOLOGY h
}
else
{
- AssertFailed();
+ WARN(("cItems(%d) <= VidPnSource/TargetId(%d)", pCbContext->cItems, VidPnSourceId));
Status = STATUS_BUFFER_OVERFLOW;
break;
}
@@ -1788,20 +1794,21 @@ static DECLCALLBACK(BOOLEAN) vboxVidPnCheckTopologyEnum(D3DKMDT_HVIDPNTOPOLOGY h
/* we currently support only 0 -> 0, 1 -> 1, 2 -> 2 paths, AND 0 -> 0 must be present
* this routine disables all paths unsupported */
-NTSTATUS vboxVidPnCheckTopology(D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
- BOOLEAN fBreakOnDisabled, UINT cItems, PVBOXVIDPNPATHITEM paItems, BOOLEAN *pfDisabledFound)
+NTSTATUS vboxVidPnCheckTopology(D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface, BOOLEAN *pfSupported)
{
+ VBOXVIDPNPATHITEM aItems[VBOX_VIDEO_MAX_SCREENS];
+ const uint32_t cItems = RT_ELEMENTS(aItems);
UINT i;
for (i = 0; i < cItems; ++i)
{
- paItems[i].enmState = VBOXVIDPNPATHITEM_STATE_NOT_EXISTS;
+ aItems[i].enmState = VBOXVIDPNPATHITEM_STATE_NOT_EXISTS;
}
VBOXVIDPNGETPATHSINFO CbContext = {0};
CbContext.Status = STATUS_SUCCESS;
- CbContext.fBreakOnDisabled = fBreakOnDisabled;
+ CbContext.fBreakOnDisabled = FALSE;
CbContext.fDisabledFound = FALSE;
CbContext.cItems = cItems;
- CbContext.paItems = paItems;
+ CbContext.paItems = aItems;
NTSTATUS Status = vboxVidPnEnumPaths(hVidPnTopology, pVidPnTopologyInterface, vboxVidPnCheckTopologyEnum, &CbContext);
if (!NT_SUCCESS(Status))
{
@@ -1816,22 +1823,22 @@ NTSTATUS vboxVidPnCheckTopology(D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXG
return Status;
}
- if (pfDisabledFound)
- *pfDisabledFound = CbContext.fDisabledFound;
+ BOOLEAN fSupported = !CbContext.fDisabledFound;
- if (!fBreakOnDisabled)
- {
- /* now check if 0->0 path is present and enabled, and if not, disable everything */
- if (cItems && paItems[0].enmState != VBOXVIDPNPATHITEM_STATE_PRESENT)
- {
- LOGREL(("path 0 not set to present\n"));
- for (i = 0; i < cItems; ++i)
- {
- if (paItems[i].enmState == VBOXVIDPNPATHITEM_STATE_PRESENT)
- paItems[i].enmState = VBOXVIDPNPATHITEM_STATE_DISABLED;
- }
- }
- }
+ /* now check if 0->0 path is present and enabled, and if not, disable everything */
+// if (cItems && aItems[0].enmState != VBOXVIDPNPATHITEM_STATE_PRESENT)
+// {
+// LOG(("path 0 not set to present\n"));
+//// for (i = 0; i < cItems; ++i)
+//// {
+//// if (aItems[i].enmState == VBOXVIDPNPATHITEM_STATE_PRESENT)
+//// aItems[i].enmState = VBOXVIDPNPATHITEM_STATE_DISABLED;
+//// }
+// fSupported = FALSE;
+// }
+
+ if (pfSupported)
+ *pfSupported = fSupported;
return Status;
}
@@ -2050,9 +2057,8 @@ NTSTATUS vboxVidPnEnumPaths(D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VI
pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pNextVidPnPresentPathInfo);
else
{
- Assert(Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET);
if (Status != STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
- LOGREL(("pfnAcquireNextPathInfo Failed Status(0x%x), ignored since callback returned false", Status));
+ WARN(("pfnAcquireNextPathInfo Failed Status(0x%x), ignored since callback returned false", Status));
Status = STATUS_SUCCESS;
}
@@ -2067,8 +2073,7 @@ NTSTATUS vboxVidPnEnumPaths(D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VI
}
else
{
- AssertBreakpoint();
- LOGREL(("pfnAcquireNextPathInfo Failed Status(0x%x)", Status));
+ WARN(("pfnAcquireNextPathInfo Failed Status(0x%x)", Status));
pNewVidPnPresentPathInfo = NULL;
break;
}
@@ -2077,26 +2082,54 @@ NTSTATUS vboxVidPnEnumPaths(D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VI
else if (Status == STATUS_GRAPHICS_DATASET_IS_EMPTY)
Status = STATUS_SUCCESS;
else
- LOGREL(("pfnAcquireFirstModeInfo failed Status(0x%x)", Status));
+ WARN(("pfnAcquireFirstModeInfo failed Status(0x%x)", Status));
return Status;
}
NTSTATUS vboxVidPnSetupSourceInfo(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId, PVBOXWDDM_SOURCE pSource, CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo, PVBOXWDDM_ALLOCATION pAllocation)
{
- vboxWddmAssignPrimary(pDevExt, pSource, pAllocation, srcId);
/* pVidPnSourceModeInfo could be null if STATUS_GRAPHICS_MODE_NOT_PINNED,
* see vboxVidPnCommitSourceModeForSrcId */
+ uint8_t fChanges = 0;
if (pVidPnSourceModeInfo)
{
- pSource->AllocData.SurfDesc.width = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx;
- pSource->AllocData.SurfDesc.height = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy;
- pSource->AllocData.SurfDesc.format = pVidPnSourceModeInfo->Format.Graphics.PixelFormat;
- pSource->AllocData.SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pVidPnSourceModeInfo->Format.Graphics.PixelFormat);
- pSource->AllocData.SurfDesc.pitch = pVidPnSourceModeInfo->Format.Graphics.Stride;
+ if (pSource->AllocData.SurfDesc.width != pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx)
+ {
+ fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
+ pSource->AllocData.SurfDesc.width = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx;
+ }
+ if (pSource->AllocData.SurfDesc.height != pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy)
+ {
+ fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
+ pSource->AllocData.SurfDesc.height = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy;
+ }
+ if (pSource->AllocData.SurfDesc.format != pVidPnSourceModeInfo->Format.Graphics.PixelFormat)
+ {
+ fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
+ pSource->AllocData.SurfDesc.format = pVidPnSourceModeInfo->Format.Graphics.PixelFormat;
+ }
+ if (pSource->AllocData.SurfDesc.bpp != vboxWddmCalcBitsPerPixel(pVidPnSourceModeInfo->Format.Graphics.PixelFormat))
+ {
+ fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
+ pSource->AllocData.SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pVidPnSourceModeInfo->Format.Graphics.PixelFormat);
+ }
+ if(pSource->AllocData.SurfDesc.pitch != pVidPnSourceModeInfo->Format.Graphics.Stride)
+ {
+ fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
+ pSource->AllocData.SurfDesc.pitch = pVidPnSourceModeInfo->Format.Graphics.Stride;
+ }
pSource->AllocData.SurfDesc.depth = 1;
- pSource->AllocData.SurfDesc.slicePitch = pVidPnSourceModeInfo->Format.Graphics.Stride;
- pSource->AllocData.SurfDesc.cbSize = pVidPnSourceModeInfo->Format.Graphics.Stride * pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy;
+ if (pSource->AllocData.SurfDesc.slicePitch != pVidPnSourceModeInfo->Format.Graphics.Stride)
+ {
+ fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
+ pSource->AllocData.SurfDesc.slicePitch = pVidPnSourceModeInfo->Format.Graphics.Stride;
+ }
+ if (pSource->AllocData.SurfDesc.cbSize != pVidPnSourceModeInfo->Format.Graphics.Stride * pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy)
+ {
+ fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
+ pSource->AllocData.SurfDesc.cbSize = pVidPnSourceModeInfo->Format.Graphics.Stride * pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy;
+ }
#ifdef VBOX_WDDM_WIN8
if (g_VBoxDisplayOnly)
{
@@ -2107,9 +2140,13 @@ NTSTATUS vboxVidPnSetupSourceInfo(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_S
else
{
Assert(!pAllocation);
+ fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_ALL;
}
+
+ vboxWddmAssignPrimary(pDevExt, pSource, pAllocation, srcId);
+
Assert(pSource->AllocData.SurfDesc.VidPnSourceId == srcId);
- pSource->bGhSynced = FALSE;
+ pSource->u8SyncState &= ~fChanges;
return STATUS_SUCCESS;
}
@@ -2155,7 +2192,6 @@ DECLCALLBACK(BOOLEAN) vboxVidPnCommitTargetModeEnum(PVBOXMP_DEVEXT pDevExt, D3DK
{
pTarget->HeightVisible = pPinnedVidPnTargetModeInfo->VideoSignalInfo.ActiveSize.cy;
pTarget->HeightTotal = pPinnedVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cy;
- pTarget->ScanLineState = 0;
}
pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pPinnedVidPnTargetModeInfo);
}
@@ -2169,6 +2205,10 @@ DECLCALLBACK(BOOLEAN) vboxVidPnCommitTargetModeEnum(PVBOXMP_DEVEXT pDevExt, D3DK
return Status == STATUS_SUCCESS;
}
+#ifdef DEBUG_misha
+DWORD g_VBoxDbgBreakModes = 0;
+#endif
+
NTSTATUS vboxVidPnCommitSourceModeForSrcId(PVBOXMP_DEVEXT pDevExt, const D3DKMDT_HVIDPN hDesiredVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId, PVBOXWDDM_ALLOCATION pAllocation)
{
D3DKMDT_HVIDPNSOURCEMODESET hCurVidPnSourceModeSet;
@@ -2222,29 +2262,33 @@ NTSTATUS vboxVidPnCommitSourceModeForSrcId(PVBOXMP_DEVEXT pDevExt, const D3DKMDT
Status = STATUS_SUCCESS;
}
else
- LOGREL(("vboxVidPnEnumTargetsForSource failed Status(0x%x)", Status));
+ WARN(("vboxVidPnEnumTargetsForSource failed Status(0x%x)", Status));
}
else
- LOGREL(("pfnGetTopology failed Status(0x%x)", Status));
+ WARN(("pfnGetTopology failed Status(0x%x)", Status));
}
else
- LOGREL(("vboxVidPnCommitSourceMode failed Status(0x%x)", Status));
+ WARN(("vboxVidPnCommitSourceMode failed Status(0x%x)", Status));
/* release */
pCurVidPnSourceModeSetInterface->pfnReleaseModeInfo(hCurVidPnSourceModeSet, pPinnedVidPnSourceModeInfo);
}
else if (Status == STATUS_GRAPHICS_MODE_NOT_PINNED)
{
+#ifdef DEBUG_misha
+ Assert(!g_VBoxDbgBreakModes);
+ ++g_VBoxDbgBreakModes;
+#endif
Status = vboxVidPnCommitSourceMode(pDevExt, srcId, NULL, pAllocation);
Assert(Status == STATUS_SUCCESS);
}
else
- LOGREL(("pfnAcquirePinnedModeInfo failed Status(0x%x)", Status));
+ WARN(("pfnAcquirePinnedModeInfo failed Status(0x%x)", Status));
pVidPnInterface->pfnReleaseSourceModeSet(hDesiredVidPn, hCurVidPnSourceModeSet);
}
else
{
- LOGREL(("pfnAcquireSourceModeSet failed Status(0x%x)", Status));
+ WARN(("pfnAcquireSourceModeSet failed Status(0x%x)", Status));
}
return Status;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.h
index f9a4d1e1..e51a0287 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.h
@@ -57,8 +57,8 @@ typedef struct VBOXVIDPNCOFUNCMODALITY
const DXGK_VIDPN_INTERFACE* pVidPnInterface;
CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* pEnumCofuncModalityArg;
PVBOXWDDM_VIDEOMODES_INFO pInfos;
- UINT cPathInfos;
- PVBOXVIDPNPATHITEM apPathInfos;
+// UINT cPathInfos;
+// PVBOXVIDPNPATHITEM apPathInfos;
} VBOXVIDPNCOFUNCMODALITY, *PVBOXVIDPNCOFUNCMODALITY;
typedef struct VBOXVIDPNCOMMIT
@@ -145,8 +145,7 @@ NTSTATUS vboxVidPnMatchMonitorModes(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT
NTSTATUS vboxVidPnCofuncModalityForPath(PVBOXVIDPNCOFUNCMODALITY pCbContext, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId);
-NTSTATUS vboxVidPnCheckTopology(D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
- BOOLEAN fBreakOnDisabled, UINT cItems, PVBOXVIDPNPATHITEM paItems, BOOLEAN *pfDisabledFound);
+NTSTATUS vboxVidPnCheckTopology(D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface, BOOLEAN *pfSupported);
NTSTATUS vboxVidPnPathAdd(D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
const D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, const D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId);
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp
index 446d048c..39b66cf1 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -30,6 +30,10 @@
#include <VBoxDisplay.h> /* this is from Additions/WINNT/include/ to include escape codes */
#include <VBox/Hardware/VBoxVideoVBE.h>
+#include <stdio.h>
+
+#define VBOXWDDM_DUMMY_DMABUFFER_SIZE sizeof (RECT)
+
DWORD g_VBoxLogUm = 0;
#ifdef VBOX_WDDM_WIN8
DWORD g_VBoxDisplayOnly = 0;
@@ -54,12 +58,31 @@ VOID vboxWddmMemFree(PVOID pvMem)
ExFreePool(pvMem);
}
+DECLINLINE(void) VBoxWddmOaHostIDReleaseLocked(PVBOXWDDM_OPENALLOCATION pOa)
+{
+ Assert(pOa->cHostIDRefs);
+ PVBOXWDDM_ALLOCATION pAllocation = pOa->pAllocation;
+ Assert(pAllocation->AllocData.cHostIDRefs >= pOa->cHostIDRefs);
+ Assert(pAllocation->AllocData.hostID);
+ --pOa->cHostIDRefs;
+ --pAllocation->AllocData.cHostIDRefs;
+ if (!pAllocation->AllocData.cHostIDRefs)
+ pAllocation->AllocData.hostID = 0;
+}
+
+DECLINLINE(void) VBoxWddmOaHostIDCheckReleaseLocked(PVBOXWDDM_OPENALLOCATION pOa)
+{
+ if (pOa->cHostIDRefs)
+ VBoxWddmOaHostIDReleaseLocked(pOa);
+}
+
DECLINLINE(void) VBoxWddmOaRelease(PVBOXWDDM_OPENALLOCATION pOa)
{
PVBOXWDDM_ALLOCATION pAllocation = pOa->pAllocation;
KIRQL OldIrql;
KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
Assert(pAllocation->cOpens);
+ VBoxWddmOaHostIDCheckReleaseLocked(pOa);
--pAllocation->cOpens;
uint32_t cOpens = --pOa->cOpens;
Assert(cOpens < UINT32_MAX/2);
@@ -96,6 +119,47 @@ DECLINLINE(PVBOXWDDM_OPENALLOCATION) VBoxWddmOaSearch(PVBOXWDDM_DEVICE pDevice,
return pOa;
}
+DECLINLINE(int) VBoxWddmOaSetHostID(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation, uint32_t hostID, uint32_t *pHostID)
+{
+ PVBOXWDDM_OPENALLOCATION pOa;
+ KIRQL OldIrql;
+ int rc = VINF_SUCCESS;
+ KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
+ pOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
+ if (!pOa)
+ {
+ KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);;
+ WARN(("no open allocation!"));
+ return VERR_INVALID_STATE;
+ }
+
+ if (hostID)
+ {
+ if (pAllocation->AllocData.hostID == 0)
+ {
+ pAllocation->AllocData.hostID = hostID;
+ }
+ else if (pAllocation->AllocData.hostID != hostID)
+ {
+ WARN(("hostID differ: alloc(%d), trying to assign(%d)", pAllocation->AllocData.hostID, hostID));
+ hostID = pAllocation->AllocData.hostID;
+ rc = VERR_NOT_EQUAL;
+ }
+
+ ++pAllocation->AllocData.cHostIDRefs;
+ ++pOa->cHostIDRefs;
+ }
+ else
+ VBoxWddmOaHostIDCheckReleaseLocked(pOa);
+
+ KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
+
+ if (pHostID)
+ *pHostID = hostID;
+
+ return rc;
+}
+
DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromHandle(PVBOXMP_DEVEXT pDevExt, D3DKMT_HANDLE hAllocation)
{
DXGKARGCB_GETHANDLEDATA GhData;
@@ -137,7 +201,7 @@ static void vboxWddmPopulateDmaAllocInfoWithOffset(PVBOXWDDM_DMA_ALLOCINFO pInfo
pInfo->srcId = pAlloc->AllocData.SurfDesc.VidPnSourceId;
}
-NTSTATUS vboxWddmGhDisplayPostInfoScreenBySDesc (PVBOXMP_DEVEXT pDevExt, const PVBOXWDDM_SURFACE_DESC pDesc, const POINT * pVScreenPos, uint16_t fFlags)
+NTSTATUS vboxWddmGhDisplayPostInfoScreenBySDesc (PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_SURFACE_DESC *pDesc, const POINT * pVScreenPos, uint16_t fFlags)
{
void *p = VBoxHGSMIBufferAlloc (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
sizeof (VBVAINFOSCREEN),
@@ -167,7 +231,7 @@ NTSTATUS vboxWddmGhDisplayPostInfoScreenBySDesc (PVBOXMP_DEVEXT pDevExt, const P
}
-NTSTATUS vboxWddmGhDisplayPostInfoScreen(PVBOXMP_DEVEXT pDevExt, const PVBOXWDDM_ALLOC_DATA pAllocData, const POINT * pVScreenPos)
+NTSTATUS vboxWddmGhDisplayPostInfoScreen(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos)
{
NTSTATUS Status = vboxWddmGhDisplayPostInfoScreenBySDesc(pDevExt, &pAllocData->SurfDesc, pVScreenPos, VBVA_SCREEN_F_ACTIVE);
if (!NT_SUCCESS(Status))
@@ -177,16 +241,26 @@ NTSTATUS vboxWddmGhDisplayPostInfoScreen(PVBOXMP_DEVEXT pDevExt, const PVBOXWDDM
NTSTATUS vboxWddmGhDisplayHideScreen(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
{
- VBOXWDDM_SURFACE_DESC SurfDesc = {0};
+ PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[VidPnTargetId];
+ /* this will force update on re-activation */
+ pSource->AllocData.SurfDesc.width = 0;
+ pSource->AllocData.SurfDesc.height = 0;
POINT VScreenPos = {0};
- SurfDesc.VidPnSourceId = VidPnTargetId;
- NTSTATUS Status = vboxWddmGhDisplayPostInfoScreenBySDesc(pDevExt, &SurfDesc, &VScreenPos, VBVA_SCREEN_F_ACTIVE | VBVA_SCREEN_F_DISABLED);
+
+ NTSTATUS Status = vboxWddmGhDisplayPostInfoScreenBySDesc(pDevExt, &pSource->AllocData.SurfDesc, &VScreenPos, VBVA_SCREEN_F_ACTIVE | VBVA_SCREEN_F_DISABLED);
if (!NT_SUCCESS(Status))
WARN(("vboxWddmGhDisplayPostInfoScreenBySDesc failed Status 0x%x", Status));
return Status;
}
-NTSTATUS vboxWddmGhDisplayPostInfoView(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOC_DATA pAllocData)
+BOOL vboxWddmGhDisplayCheckCompletePeningScreenInfo(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
+{
+ if (!ASMAtomicCmpXchgBool(&pDevExt->aTargets[VidPnTargetId].fStateSyncPening, false, true))
+ return FALSE;
+ return vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, &pDevExt->aSources[VidPnTargetId]);
+}
+
+NTSTATUS vboxWddmGhDisplayPostInfoView(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData)
{
VBOXVIDEOOFFSET offVram = pAllocData->Addr.offVram;
if (offVram == VBOXVIDEOOFFSET_VOID)
@@ -219,7 +293,7 @@ NTSTATUS vboxWddmGhDisplayPostInfoView(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOC_D
return STATUS_SUCCESS;
}
-NTSTATUS vboxWddmGhDisplaySetMode(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOC_DATA pAllocData)
+NTSTATUS vboxWddmGhDisplaySetMode(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData)
{
// PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
if (/*pPrimaryInfo->*/pAllocData->SurfDesc.VidPnSourceId)
@@ -269,38 +343,77 @@ NTSTATUS vboxWddmGhDisplayUpdateScreenPos(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOUR
return Status;
}
-NTSTATUS vboxWddmGhDisplaySetInfo(PVBOXMP_DEVEXT pDevExt, const PVBOXWDDM_ALLOC_DATA pAllocData, const POINT * pVScreenPos)
+NTSTATUS vboxWddmGhDisplaySetInfo(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pRealFbAlloc, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos, uint8_t u8CurCyncState)
{
- NTSTATUS Status = vboxWddmGhDisplaySetMode(pDevExt, pAllocData);
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
+ NTSTATUS Status;
+
+ if ((u8CurCyncState & VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY) == VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY
+ && pRealFbAlloc->AllocData.hostID)
+ {
+ Status = vboxVdmaTexPresentSetAlloc(pDevExt, pRealFbAlloc);
+ if (!NT_SUCCESS(Status))
+ WARN(("vboxVdmaTexPresentSetAlloc failed, Status 0x%x", Status));
+ return Status;
+ }
+
+ Status = vboxWddmGhDisplaySetMode(pDevExt, pAllocData);
+ if (NT_SUCCESS(Status))
{
Status = vboxWddmGhDisplayPostInfoView(pDevExt, pAllocData);
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
+ if (NT_SUCCESS(Status))
{
Status = vboxWddmGhDisplayPostInfoScreen(pDevExt, pAllocData, pVScreenPos);
- Assert(Status == STATUS_SUCCESS);
- if (!NT_SUCCESS(Status))
- WARN(("vboxWddmGhDisplayPostInfoScreen failed"));
+ if (NT_SUCCESS(Status))
+ {
+ if (pDevExt->f3DEnabled)
+ {
+ Status = vboxVdmaTexPresentSetAlloc(pDevExt, pRealFbAlloc);
+ if (NT_SUCCESS(Status))
+ return STATUS_SUCCESS;
+ else
+ WARN(("vboxVdmaTexPresentSetAlloc failed, Status 0x%x", Status));
+ }
+ }
+ else
+ WARN(("vboxWddmGhDisplayPostInfoScreen failed, Status 0x%x", Status));
}
else
- WARN(("vboxWddmGhDisplayPostInfoView failed"));
+ WARN(("vboxWddmGhDisplayPostInfoView failed, Status 0x%x", Status));
}
else
- WARN(("vboxWddmGhDisplaySetMode failed"));
+ WARN(("vboxWddmGhDisplaySetMode failed, Status 0x%x", Status));
return Status;
}
-bool vboxWddmGhDisplayCheckSetInfoFromSource(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource)
+bool vboxWddmGhDisplaySetInfoFromSourceTarget(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, PVBOXWDDM_TARGET pTarget)
{
- Assert(VBOXVIDEOOFFSET_VOID != pSource->AllocData.Addr.offVram);
-
- if (pSource->bGhSynced)
- return false;
+ if (!pTarget->HeightVisible)
+ {
+ vboxWddmGhDisplayHideScreen(pDevExt, pSource->AllocData.SurfDesc.VidPnSourceId);
+ pSource->u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
+ return true;
+ }
PVBOXWDDM_ALLOCATION pFbAlloc = VBOXWDDM_FB_ALLOCATION(pDevExt, pSource);
+ PVBOXWDDM_ALLOCATION pRealFbAlloc = pSource->pPrimaryAllocation;
+#ifdef VBOXWDDM_RENDER_FROM_SHADOW
+# ifdef VBOX_WDDM_WIN8
+ if (!g_VBoxDisplayOnly)
+# endif
+ {
+ if (!pRealFbAlloc)
+ return false;
+
+ if (!pFbAlloc)
+ pFbAlloc = pRealFbAlloc;
+
+ if (!pFbAlloc || pFbAlloc->AllocData.Addr.offVram == VBOXVIDEOOFFSET_VOID)
+ {
+ return false;
+ }
+ }
+#endif
#ifdef VBOX_WDDM_WIN8
Assert(!g_VBoxDisplayOnly == !!pFbAlloc);
@@ -312,15 +425,32 @@ bool vboxWddmGhDisplayCheckSetInfoFromSource(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_S
#endif
Assert(!pFbAlloc || pFbAlloc->AllocData.Addr.SegmentId == pSource->AllocData.Addr.SegmentId);
- NTSTATUS Status = vboxWddmGhDisplaySetInfo(pDevExt, pFbAlloc ? &pFbAlloc->AllocData : &pSource->AllocData, &pSource->VScreenPos);
+ NTSTATUS Status = vboxWddmGhDisplaySetInfo(pDevExt, pRealFbAlloc, pFbAlloc ? &pFbAlloc->AllocData : &pSource->AllocData, &pSource->VScreenPos, pSource->u8SyncState);
if (NT_SUCCESS(Status))
- pSource->bGhSynced = TRUE;
+ pSource->u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
else
WARN(("vboxWddmGhDisplaySetInfo failed, Status (0x%x)", Status));
+ vboxVideoCmSignalEvents(&pDevExt->SeamlessCtxMgr);
+
return true;
}
+bool vboxWddmGhDisplayCheckSetInfoFromSource(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource)
+{
+ Assert(VBOXVIDEOOFFSET_VOID != pSource->AllocData.Addr.offVram
+ || !pDevExt->aTargets[pSource->AllocData.SurfDesc.VidPnSourceId].HeightVisible);
+
+ if (pSource->u8SyncState == VBOXWDDM_HGSYNC_F_SYNCED_ALL)
+ return false;
+
+ PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[pSource->AllocData.SurfDesc.VidPnSourceId];
+ if (ASMAtomicUoReadBool(&pTarget->fStateSyncPening))
+ return false;
+
+ return vboxWddmGhDisplaySetInfoFromSourceTarget(pDevExt, pSource, pTarget);
+}
+
static VOID vboxWddmModeRenderFromShadowDisableOnSubmitCommand(PVBOXMP_DEVEXT pDevExt, BOOLEAN fDisable)
{
for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
@@ -354,7 +484,7 @@ static VOID vboxWddmModeRenderFromShadowDisableOnSubmitCommand(PVBOXMP_DEVEXT pD
}
/* ensure we issue resize command on next update */
- pSource->bGhSynced = FALSE;
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
}
}
@@ -397,19 +527,6 @@ static VOID vboxWddmModeRenderFromShadowDisableUnregister(PVBOXMP_DEVEXT pDevExt
pContext->fRenderFromShadowDisabled = FALSE;
}
-#ifdef VBOXWDDM_RENDER_FROM_SHADOW
-bool vboxWddmCheckUpdateFramebufferAddress(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource)
-{
- if (pSource->pPrimaryAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
- {
- Assert(pSource->bGhSynced == FALSE);
- return false;
- }
-
- return vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
-}
-#endif
-
PVBOXSHGSMI vboxWddmHgsmiGetHeapFromCmdOffset(PVBOXMP_DEVEXT pDevExt, HGSMIOFFSET offCmd)
{
#ifdef VBOX_WITH_VDMA
@@ -441,322 +558,6 @@ VBOXWDDM_HGSMICMD_TYPE vboxWddmHgsmiGetCmdTypeFromOffset(PVBOXMP_DEVEXT pDevExt,
return VBOXWDDM_HGSMICMD_TYPE_UNDEFINED;
}
-static NTSTATUS vboxWddmChildStatusReportPerform(PVBOXMP_DEVEXT pDevExt, PVBOXVDMA_CHILD_STATUS pChildStatus, D3DDDI_VIDEO_PRESENT_TARGET_ID iChild)
-{
- DXGK_CHILD_STATUS DdiChildStatus;
- if (pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_DISCONNECTED)
- {
- /* report disconnected */
- memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
- DdiChildStatus.Type = StatusConnection;
- if (iChild != D3DDDI_ID_UNINITIALIZED)
- {
- Assert(iChild < UINT32_MAX/2);
- Assert(iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
- DdiChildStatus.ChildUid = iChild;
- }
- else
- {
- Assert(pChildStatus->iChild < UINT32_MAX/2);
- Assert(pChildStatus->iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
- DdiChildStatus.ChildUid = pChildStatus->iChild;
- }
- DdiChildStatus.HotPlug.Connected = FALSE;
- NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
- if (!NT_SUCCESS(Status))
- {
- WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
- return Status;
- }
- }
-
- if (pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_CONNECTED)
- {
- /* report disconnected */
- memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
- DdiChildStatus.Type = StatusConnection;
- if (iChild != D3DDDI_ID_UNINITIALIZED)
- {
- Assert(iChild < UINT32_MAX/2);
- Assert(iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
- DdiChildStatus.ChildUid = iChild;
- }
- else
- {
- Assert(pChildStatus->iChild < UINT32_MAX/2);
- Assert(pChildStatus->iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
- DdiChildStatus.ChildUid = pChildStatus->iChild;
- }
- DdiChildStatus.HotPlug.Connected = TRUE;
- NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
- if (!NT_SUCCESS(Status))
- {
- WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
- return Status;
- }
- }
-
- if (pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_ROTATED)
- {
- /* report disconnected */
- memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
- DdiChildStatus.Type = StatusRotation;
- if (iChild != D3DDDI_ID_UNINITIALIZED)
- {
- Assert(iChild < UINT32_MAX/2);
- Assert(iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
- DdiChildStatus.ChildUid = iChild;
- }
- else
- {
- Assert(pChildStatus->iChild < UINT32_MAX/2);
- Assert(pChildStatus->iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
- DdiChildStatus.ChildUid = pChildStatus->iChild;
- }
- DdiChildStatus.Rotation.Angle = pChildStatus->u8RotationAngle;
- NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
- if (!NT_SUCCESS(Status))
- {
- WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
- return Status;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static NTSTATUS vboxWddmChildStatusDoReportReconnected(PVBOXMP_DEVEXT pDevExt, VBOXVDMACMD_CHILD_STATUS_IRQ *pBody)
-{
- NTSTATUS Status = STATUS_SUCCESS;
-
- for (UINT i = 0; i < pBody->cInfos; ++i)
- {
- PVBOXVDMA_CHILD_STATUS pInfo = &pBody->aInfos[i];
- if (pBody->fFlags & VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL)
- {
- for (D3DDDI_VIDEO_PRESENT_TARGET_ID iChild = 0; iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++iChild)
- {
- Status = vboxWddmChildStatusReportPerform(pDevExt, pInfo, iChild);
- if (!NT_SUCCESS(Status))
- {
- WARN(("vboxWddmChildStatusReportPerform failed with Status (0x%x)", Status));
- break;
- }
- }
- }
- else
- {
- Status = vboxWddmChildStatusReportPerform(pDevExt, pInfo, D3DDDI_ID_UNINITIALIZED);
- if (!NT_SUCCESS(Status))
- {
- WARN(("vboxWddmChildStatusReportPerform failed with Status (0x%x)", Status));
- break;
- }
- }
- }
-
- return Status;
-}
-
-typedef struct VBOXWDDMCHILDSTATUSCB
-{
- PVBOXVDMACBUF_DR pDr;
- PKEVENT pEvent;
-} VBOXWDDMCHILDSTATUSCB, *PVBOXWDDMCHILDSTATUSCB;
-
-static DECLCALLBACK(VOID) vboxWddmChildStatusReportCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
-{
- /* we should be called from our DPC routine */
- Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
-
- PVBOXWDDMCHILDSTATUSCB pCtx = (PVBOXWDDMCHILDSTATUSCB)pvContext;
- PVBOXVDMACBUF_DR pDr = pCtx->pDr;
- PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
- VBOXVDMACMD_CHILD_STATUS_IRQ *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHILD_STATUS_IRQ);
-
- vboxWddmChildStatusDoReportReconnected(pDevExt, pBody);
-
- vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
-
- if (pCtx->pEvent)
- {
- KeSetEvent(pCtx->pEvent, 0, FALSE);
- }
-}
-
-static NTSTATUS vboxWddmChildStatusReportReconnected(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID idTarget)
-{
-#ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
- UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(sizeof (VBOXVDMACMD_CHILD_STATUS_IRQ));
-
- PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
- if (pDr)
- {
- // vboxVdmaCBufDrCreate zero initializes the pDr
- /* the command data follows the descriptor */
- pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
- pDr->cbBuf = cbCmd;
- pDr->rc = VERR_NOT_IMPLEMENTED;
-
- PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
- pHdr->enmType = VBOXVDMACMD_TYPE_CHILD_STATUS_IRQ;
- pHdr->u32CmdSpecific = 0;
- PVBOXVDMACMD_CHILD_STATUS_IRQ pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHILD_STATUS_IRQ);
- pBody->cInfos = 1;
- if (idTarget == D3DDDI_ID_ALL)
- {
- pBody->fFlags |= VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL;
- }
- pBody->aInfos[0].iChild = idTarget;
- pBody->aInfos[0].fFlags = VBOXVDMA_CHILD_STATUS_F_DISCONNECTED | VBOXVDMA_CHILD_STATUS_F_CONNECTED;
- /* we're going to KeWaitForSingleObject */
- Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
-
- PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
- VBOXWDDMCHILDSTATUSCB Ctx;
- KEVENT Event;
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Ctx.pDr = pDr;
- Ctx.pEvent = &Event;
- vboxVdmaDdiCmdInit(pDdiCmd, 0, 0, vboxWddmChildStatusReportCompletion, &Ctx);
- /* mark command as submitted & invisible for the dx runtime since dx did not originate it */
- vboxVdmaDdiCmdSubmittedNotDx(pDdiCmd);
- int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
- Assert(rc == VINF_SUCCESS);
- if (RT_SUCCESS(rc))
- {
- Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
- Assert(Status == STATUS_SUCCESS);
- return STATUS_SUCCESS;
- }
-
- Status = STATUS_UNSUCCESSFUL;
-
- vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
- }
- else
- {
- Assert(0);
- /* @todo: try flushing.. */
- LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
-
- return Status;
-#else
- VBOXVDMACMD_CHILD_STATUS_IRQ Body = {0};
- Body.cInfos = 1;
- if (idTarget == D3DDDI_ID_ALL)
- {
- Body.fFlags |= VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL;
- }
- Body.aInfos[0].iChild = idTarget;
- Body.aInfos[0].fFlags = VBOXVDMA_CHILD_STATUS_F_DISCONNECTED | VBOXVDMA_CHILD_STATUS_F_CONNECTED;
- Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
- return vboxWddmChildStatusDoReportReconnected(pDevExt, &Body);
-#endif
-}
-
-static NTSTATUS vboxWddmChildStatusCheckByMask(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_VIDEOMODES_INFO paInfos, uint8_t *pMask)
-{
- NTSTATUS Status = STATUS_SUCCESS;
- bool bChanged[VBOX_VIDEO_MAX_SCREENS] = {0};
- int i;
-
- for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
- {
- if (pMask && !ASMBitTest(pMask, i))
- continue;
-
- /* @todo: check that we actually need the current source->target */
- PVBOXWDDM_VIDEOMODES_INFO pInfo = &paInfos[i];
- VIDEO_MODE_INFORMATION *pModeInfo = &pInfo->aModes[pInfo->iPreferredMode];
- BOOLEAN fMatch = FALSE;
- Status = vboxVidPnMatchMonitorModes(pDevExt, i, pInfo->aResolutions, pInfo->cResolutions, &fMatch);
- if (!NT_SUCCESS(Status))
- {
- WARN(("vboxVidPnMatchMonitorModes failed Status(0x%x)", Status));
- /* ignore the failures here, although we probably should not?? */
- break;
- }
-
- bChanged[i] = !fMatch;
- }
-
- if (!NT_SUCCESS(Status))
- {
- WARN(("updating monitor modes failed, Status(0x%x)", Status));
- return Status;
- }
-
- for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
- {
- if (bChanged[i])
- {
- NTSTATUS tmpStatus = vboxWddmChildStatusReportReconnected(pDevExt, i);
- if (!NT_SUCCESS(tmpStatus))
- {
- WARN(("vboxWddmChildStatusReportReconnected failed Status(0x%x)", Status));
- /* ignore the failures here, although we probably should not?? */
- break;
- }
- }
- }
-
- /* wait for the reconnected monitor data to be picked up */
- CONST DXGK_MONITOR_INTERFACE *pMonitorInterface;
- Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryMonitorInterface(pDevExt->u.primary.DxgkInterface.DeviceHandle, DXGK_MONITOR_INTERFACE_VERSION_V1, &pMonitorInterface);
- if (!NT_SUCCESS(Status))
- {
- WARN(("DxgkCbQueryMonitorInterface failed, Status()0x%x", Status));
- return Status;
- }
-
- for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
- {
- D3DKMDT_HMONITORSOURCEMODESET hMonitorSMS;
- CONST DXGK_MONITORSOURCEMODESET_INTERFACE *pMonitorSMSIf;
- if (!bChanged[i])
- continue;
-
- while (1)
- {
- Status = pMonitorInterface->pfnAcquireMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle,
- i,
- &hMonitorSMS,
- &pMonitorSMSIf);
- if (NT_SUCCESS(Status))
- {
- NTSTATUS tmpStatus = pMonitorInterface->pfnReleaseMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle, hMonitorSMS);
- if (!NT_SUCCESS(tmpStatus))
- {
- WARN(("pfnReleaseMonitorSourceModeSet failed tmpStatus(0x%x)", tmpStatus));
- }
- break;
- }
-
- if (Status != STATUS_GRAPHICS_MONITOR_NOT_CONNECTED)
- {
- WARN(("DxgkCbQueryMonitorInterface failed, Status()0x%x", Status));
- break;
- }
-
- Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
-
- LARGE_INTEGER Interval;
- Interval.QuadPart = -(int64_t) 2 /* ms */ * 10000;
- NTSTATUS tmpStatus = KeDelayExecutionThread(KernelMode, FALSE, &Interval);
- if (!NT_SUCCESS(tmpStatus))
- {
- WARN(("KeDelayExecutionThread failed tmpStatus(0x%x)", tmpStatus));
- }
- }
- }
-
- return STATUS_SUCCESS;
-}
-
typedef struct VBOXWDDM_HWRESOURCES
{
PHYSICAL_ADDRESS phVRAM;
@@ -856,7 +657,7 @@ static void vboxWddmDevExtZeroinit(PVBOXMP_DEVEXT pDevExt, CONST PDEVICE_OBJECT
#endif
}
-static void vboxWddmSetupDisplays(PVBOXMP_DEVEXT pDevExt)
+static void vboxWddmSetupDisplaysLegacy(PVBOXMP_DEVEXT pDevExt)
{
/* For WDDM, we simply store the number of monitors as we will deal with
* VidPN stuff later */
@@ -968,6 +769,74 @@ static void vboxWddmSetupDisplays(PVBOXMP_DEVEXT pDevExt)
}
}
+static NTSTATUS vboxWddmSetupDisplaysNew(PVBOXMP_DEVEXT pDevExt)
+{
+ if (!VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
+ return STATUS_UNSUCCESSFUL;
+
+ ULONG cbAvailable = VBoxCommonFromDeviceExt(pDevExt)->cbVRAM
+ - VBoxCommonFromDeviceExt(pDevExt)->cbMiniportHeap
+ - VBVA_ADAPTER_INFORMATION_SIZE;
+
+ ULONG cbCmdVbva = cbAvailable / 2;
+ ULONG cbCmdVbvaApprox = VBOXCMDVBVA_BUFFERSIZE(4096);
+ if (cbCmdVbvaApprox > cbCmdVbva)
+ {
+ WARN(("too few VRAM memory %d, cmdVbva %d, while approximately needed %d, trying to adjust", cbAvailable, cbCmdVbva, cbCmdVbvaApprox));
+ cbCmdVbva = cbCmdVbvaApprox;
+ }
+
+ cbCmdVbva = VBOXWDDM_ROUNDBOUND(cbCmdVbva, 0x1000);
+ if (cbCmdVbva > cbAvailable - 0x1000)
+ {
+ WARN(("too few VRAM memory fatal, %d, requested for CmdVbva %d", cbAvailable, cbCmdVbva));
+ return STATUS_UNSUCCESSFUL;
+ }
+
+
+ ULONG offCmdVbva = cbAvailable - cbCmdVbva;
+
+ int rc = VBoxCmdVbvaCreate(pDevExt, &pDevExt->CmdVbva, offCmdVbva, cbCmdVbva);
+ if (RT_SUCCESS(rc))
+ {
+ rc = VBoxCmdVbvaEnable(pDevExt, &pDevExt->CmdVbva);
+ if (RT_SUCCESS(rc))
+ {
+ rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pDevExt->pvVisibleVram,
+ 0, vboxWddmVramCpuVisibleSize(pDevExt));
+ if (RT_SUCCESS(rc))
+ return STATUS_SUCCESS;
+ else
+ WARN(("VBoxMPCmnMapAdapterMemory failed, rc %d", rc));
+
+ VBoxCmdVbvaDisable(pDevExt, &pDevExt->CmdVbva);
+ }
+ else
+ WARN(("VBoxCmdVbvaEnable failed, rc %d", rc));
+
+ VBoxCmdVbvaDestroy(pDevExt, &pDevExt->CmdVbva);
+ }
+ else
+ WARN(("VBoxCmdVbvaCreate failed, rc %d", rc));
+
+ return STATUS_UNSUCCESSFUL;
+}
+
+static NTSTATUS vboxWddmSetupDisplays(PVBOXMP_DEVEXT pDevExt)
+{
+ if (pDevExt->fCmdVbvaEnabled)
+ {
+ NTSTATUS Status = vboxWddmSetupDisplaysNew(pDevExt);
+ if (!NT_SUCCESS(Status))
+ VBoxCommonFromDeviceExt(pDevExt)->bHGSMI = FALSE;
+ return Status;
+ }
+
+ vboxWddmSetupDisplaysLegacy(pDevExt);
+ return VBoxCommonFromDeviceExt(pDevExt)->bHGSMI ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
+ return STATUS_UNSUCCESSFUL;
+}
+
static int vboxWddmFreeDisplays(PVBOXMP_DEVEXT pDevExt)
{
int rc = VINF_SUCCESS;
@@ -1095,6 +964,19 @@ NTSTATUS DxgkDdiStartDevice(
Status = vboxWddmPickResources(pDevExt, &DeviceInfo, &HwRc);
if (Status == STATUS_SUCCESS)
{
+ pDevExt->f3DEnabled = VBoxMpCrCtlConIs3DSupported();
+
+ if (pDevExt->f3DEnabled)
+ {
+ pDevExt->fTexPresentEnabled = !!(VBoxMpCrGetHostCaps() & CR_VBOX_CAP_TEX_PRESENT);
+ pDevExt->fCmdVbvaEnabled = !!(VBoxMpCrGetHostCaps() & CR_VBOX_CAP_CMDVBVA);
+ }
+ else
+ {
+ pDevExt->fTexPresentEnabled = FALSE;
+ pDevExt->fCmdVbvaEnabled = FALSE;
+ }
+
/* Guest supports only HGSMI, the old VBVA via VMMDev is not supported.
* The host will however support both old and new interface to keep compatibility
* with old guest additions.
@@ -1117,17 +999,18 @@ NTSTATUS DxgkDdiStartDevice(
vboxVdmaDdiNodesInit(pDevExt);
vboxVideoCmInit(&pDevExt->CmMgr);
+ vboxVideoCmInit(&pDevExt->SeamlessCtxMgr);
InitializeListHead(&pDevExt->SwapchainList3D);
pDevExt->cContexts3D = 0;
pDevExt->cContexts2D = 0;
+ pDevExt->cContextsDispIfResize = 0;
pDevExt->cUnlockedVBVADisabled = 0;
- ExInitializeFastMutex(&pDevExt->ContextMutex);
+ VBOXWDDM_CTXLOCK_INIT(pDevExt);
KeInitializeSpinLock(&pDevExt->SynchLock);
VBoxMPCmnInitCustomVideoModes(pDevExt);
- VBoxWddmInvalidateAllVideoModesInfos(pDevExt);
- pDevExt->fAnyX = VBoxVideoAnyWidthAllowed();
+ VBoxCommonFromDeviceExt(pDevExt)->fAnyX = VBoxVideoAnyWidthAllowed();
#if 0
vboxShRcTreeInit(pDevExt);
#endif
@@ -1137,12 +1020,73 @@ NTSTATUS DxgkDdiStartDevice(
#endif
VBoxWddmSlInit(pDevExt);
+ VBoxMpCrShgsmiTransportCreate(&pDevExt->CrHgsmiTransport, pDevExt);
+
+
for (UINT i = 0; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
{
PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
KeInitializeSpinLock(&pSource->AllocationLock);
+ VBoxVrListInit(&pSource->VrList);
+ }
+
+ DWORD dwVal = VBOXWDDM_CFG_DRV_DEFAULT;
+ HANDLE hKey = NULL;
+ WCHAR aNameBuf[100];
+
+ Status = IoOpenDeviceRegistryKey(pDevExt->pPDO, PLUGPLAY_REGKEY_DRIVER, GENERIC_READ, &hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("IoOpenDeviceRegistryKey failed, Status = 0x%x", Status));
+ hKey = NULL;
+ }
+
+
+ if (hKey)
+ {
+ Status = vboxWddmRegQueryValueDword(hKey, VBOXWDDM_REG_DRV_FLAGS_NAME, &dwVal);
+ if (!NT_SUCCESS(Status))
+ {
+ LOG(("vboxWddmRegQueryValueDword failed, Status = 0x%x", Status));
+ dwVal = VBOXWDDM_CFG_DRV_DEFAULT;
+ }
+ }
+
+ pDevExt->dwDrvCfgFlags = dwVal;
+
+ for (UINT i = 0; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
+ {
+ PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
+ if (i == 0 || (pDevExt->dwDrvCfgFlags & VBOXWDDM_CFG_DRV_SECONDARY_TARGETS_CONNECTED) || !hKey)
+ {
+ pTarget->fConnected = true;
+ pTarget->fConfigured = true;
+ }
+ else if (hKey)
+ {
+ swprintf(aNameBuf, L"%s%d", VBOXWDDM_REG_DRV_DISPFLAGS_PREFIX, i);
+ Status = vboxWddmRegQueryValueDword(hKey, aNameBuf, &dwVal);
+ if (NT_SUCCESS(Status))
+ {
+ pTarget->fConnected = !!(dwVal & VBOXWDDM_CFG_DRVTARGET_CONNECTED);
+ pTarget->fConfigured = true;
+ }
+ else
+ {
+ WARN(("vboxWddmRegQueryValueDword failed, Status = 0x%x", Status));
+ pTarget->fConnected = false;
+ pTarget->fConfigured = false;
+ }
+ }
+ }
+
+ if (hKey)
+ {
+ NTSTATUS tmpStatus = ZwClose(hKey);
+ Assert(tmpStatus == STATUS_SUCCESS);
}
+ Status = STATUS_SUCCESS;
#ifdef VBOX_WDDM_WIN8
DXGK_DISPLAY_INFORMATION DisplayInfo;
Status = pDevExt->u.primary.DxgkInterface.DxgkCbAcquirePostDisplayOwnership(pDevExt->u.primary.DxgkInterface.DeviceHandle,
@@ -1181,6 +1125,8 @@ NTSTATUS DxgkDdiStartDevice(
WARN(("DxgkCbAcquirePostDisplayOwnership failed, Status 0x%x", Status));
}
#endif
+
+ VBoxWddmInitVideoModes(pDevExt);
}
else
{
@@ -1226,10 +1172,14 @@ NTSTATUS DxgkDdiStopDevice(
PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
NTSTATUS Status = STATUS_SUCCESS;
+ VBoxMpCrShgsmiTransportTerm(&pDevExt->CrHgsmiTransport);
+
VBoxWddmSlTerm(pDevExt);
vboxVideoCmTerm(&pDevExt->CmMgr);
+ vboxVideoCmTerm(&pDevExt->SeamlessCtxMgr);
+
/* do everything we did on DxgkDdiStartDevice in the reverse order */
#ifdef VBOX_WITH_VIDEOHWACCEL
vboxVhwaFree(pDevExt);
@@ -1347,7 +1297,148 @@ NTSTATUS DxgkDdiDispatchIoRequest(
return STATUS_SUCCESS;
}
-BOOLEAN DxgkDdiInterruptRoutine(
+
+BOOLEAN DxgkDdiInterruptRoutineNew(
+ IN CONST PVOID MiniportDeviceContext,
+ IN ULONG MessageNumber
+ )
+{
+// LOGF(("ENTER, context(0x%p), msg(0x%x)", MiniportDeviceContext, MessageNumber));
+
+ vboxVDbgBreakFv();
+
+ PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
+ BOOLEAN bOur = FALSE;
+ bool bNeedDpc = FALSE;
+ if (!VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags) /* If HGSMI is enabled at all. */
+ {
+ WARN(("ISR called with hgsmi disabled!"));
+ return FALSE;
+ }
+
+ VBOXVTLIST CtlList;
+ vboxVtListInit(&CtlList);
+#ifdef VBOX_WITH_VIDEOHWACCEL
+ VBOXVTLIST VhwaCmdList;
+ vboxVtListInit(&VhwaCmdList);
+#endif
+
+ uint32_t flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
+ bOur = (flags & HGSMIHOSTFLAGS_IRQ);
+
+ if (bOur)
+ VBoxHGSMIClearIrq(&VBoxCommonFromDeviceExt(pDevExt)->hostCtx);
+
+ bNeedDpc |= VBoxCmdVbvaCheckCompletedIrq(pDevExt, &pDevExt->CmdVbva);
+
+ do {
+ if (flags & HGSMIHOSTFLAGS_GCOMMAND_COMPLETED)
+ {
+ /* read the command offset */
+ HGSMIOFFSET offCmd = VBoxVideoCmnPortReadUlong(VBoxCommonFromDeviceExt(pDevExt)->guestCtx.port);
+ if (offCmd == HGSMIOFFSET_VOID)
+ {
+ WARN(("void command offset!"));
+ continue;
+ }
+
+ uint16_t chInfo;
+ uint8_t *pvCmd = HGSMIBufferDataAndChInfoFromOffset (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, offCmd, &chInfo);
+ if (!pvCmd)
+ {
+ WARN(("zero cmd"));
+ continue;
+ }
+
+ switch (chInfo)
+ {
+ case VBVA_CMDVBVA_CTL:
+ {
+ int rc = VBoxSHGSMICommandProcessCompletion (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, (VBOXSHGSMIHEADER*)pvCmd, TRUE /*bool bIrq*/ , &CtlList);
+ AssertRC(rc);
+ break;
+ }
+#ifdef VBOX_WITH_VIDEOHWACCEL
+ case VBVA_VHWA_CMD:
+ {
+ vboxVhwaPutList(&VhwaCmdList, (VBOXVHWACMD*)pvCmd);
+ break;
+ }
+#endif /* # ifdef VBOX_WITH_VIDEOHWACCEL */
+ default:
+ AssertBreakpoint();
+ }
+ }
+ else if (flags & HGSMIHOSTFLAGS_COMMANDS_PENDING)
+ {
+ AssertBreakpoint();
+ /* @todo: FIXME: implement !!! */
+ }
+ else
+ break;
+
+ flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
+
+ } while (1);
+
+ if (!vboxVtListIsEmpty(&CtlList))
+ {
+ vboxVtListCat(&pDevExt->CtlList, &CtlList);
+ bNeedDpc = TRUE;
+ ASMAtomicWriteU32(&pDevExt->fCompletingCommands, 1);
+ }
+
+ if (!vboxVtListIsEmpty(&VhwaCmdList))
+ {
+ vboxVtListCat(&pDevExt->VhwaCmdList, &VhwaCmdList);
+ bNeedDpc = TRUE;
+ ASMAtomicWriteU32(&pDevExt->fCompletingCommands, 1);
+ }
+
+ bNeedDpc |= !vboxVdmaDdiCmdIsCompletedListEmptyIsr(pDevExt);
+
+ if (bOur)
+ {
+#ifdef VBOX_VDMA_WITH_WATCHDOG
+ if (flags & HGSMIHOSTFLAGS_WATCHDOG)
+ {
+ Assert(0);
+ }
+#endif
+ if (flags & HGSMIHOSTFLAGS_VSYNC)
+ {
+ Assert(0);
+ DXGKARGCB_NOTIFY_INTERRUPT_DATA notify;
+ for (UINT i = 0; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
+ {
+ PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
+ PVBOXWDDM_ALLOCATION pPrimary = pSource->pPrimaryAllocation;
+ if (pPrimary && pPrimary->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID)
+ {
+ memset(&notify, 0, sizeof(DXGKARGCB_NOTIFY_INTERRUPT_DATA));
+ notify.InterruptType = DXGK_INTERRUPT_CRTC_VSYNC;
+ /* @todo: !!!this is not correct in case we want source[i]->target[i!=j] mapping */
+ notify.CrtcVsync.VidPnTargetId = i;
+ notify.CrtcVsync.PhysicalAddress.QuadPart = pPrimary->AllocData.Addr.offVram;
+ pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, &notify);
+
+ bNeedDpc = TRUE;
+ }
+ }
+ }
+ }
+
+ if (pDevExt->bNotifyDxDpc)
+ bNeedDpc = TRUE;
+
+ if (bNeedDpc)
+ pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
+
+ return bOur;
+}
+
+
+static BOOLEAN DxgkDdiInterruptRoutineLegacy(
IN CONST PVOID MiniportDeviceContext,
IN ULONG MessageNumber
)
@@ -1377,6 +1468,10 @@ BOOLEAN DxgkDdiInterruptRoutine(
uint32_t flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
bOur = (flags & HGSMIHOSTFLAGS_IRQ);
+
+ if (bOur)
+ VBoxHGSMIClearIrq(&VBoxCommonFromDeviceExt(pDevExt)->hostCtx);
+
do
{
if (flags & HGSMIHOSTFLAGS_GCOMMAND_COMPLETED)
@@ -1508,7 +1603,6 @@ BOOLEAN DxgkDdiInterruptRoutine(
bNeedDpc = TRUE;
}
- VBoxHGSMIClearIrq(&VBoxCommonFromDeviceExt(pDevExt)->hostCtx);
#if 0 //def DEBUG_misha
/* this is not entirely correct since host may concurrently complete some commands and raise a new IRQ while we are here,
* still this allows to check that the host flags are correctly cleared after the ISR */
@@ -1552,22 +1646,73 @@ typedef struct VBOXWDDM_GETDPCDATA_CONTEXT
BOOLEAN vboxWddmGetDPCDataCallback(PVOID Context)
{
PVBOXWDDM_GETDPCDATA_CONTEXT pdc = (PVBOXWDDM_GETDPCDATA_CONTEXT)Context;
-
- vboxVtListDetach2List(&pdc->pDevExt->CtlList, &pdc->data.CtlList);
+ PVBOXMP_DEVEXT pDevExt = pdc->pDevExt;
+ vboxVtListDetach2List(&pDevExt->CtlList, &pdc->data.CtlList);
#ifdef VBOX_WITH_VDMA
- vboxVtListDetach2List(&pdc->pDevExt->DmaCmdList, &pdc->data.DmaCmdList);
+ vboxVtListDetach2List(&pDevExt->DmaCmdList, &pdc->data.DmaCmdList);
#endif
#ifdef VBOX_WITH_VIDEOHWACCEL
- vboxVtListDetach2List(&pdc->pDevExt->VhwaCmdList, &pdc->data.VhwaCmdList);
+ vboxVtListDetach2List(&pDevExt->VhwaCmdList, &pdc->data.VhwaCmdList);
#endif
- vboxVdmaDdiCmdGetCompletedListIsr(pdc->pDevExt, &pdc->data.CompletedDdiCmdQueue);
+ if (!pDevExt->fCmdVbvaEnabled)
+ vboxVdmaDdiCmdGetCompletedListIsr(pDevExt, &pdc->data.CompletedDdiCmdQueue);
+
+ pdc->data.bNotifyDpc = pDevExt->bNotifyDxDpc;
+ pDevExt->bNotifyDxDpc = FALSE;
+
+ ASMAtomicWriteU32(&pDevExt->fCompletingCommands, 0);
- pdc->data.bNotifyDpc = pdc->pDevExt->bNotifyDxDpc;
- pdc->pDevExt->bNotifyDxDpc = FALSE;
return TRUE;
}
-VOID DxgkDdiDpcRoutine(
+static VOID DxgkDdiDpcRoutineNew(
+ IN CONST PVOID MiniportDeviceContext
+ )
+{
+// LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
+
+ vboxVDbgBreakFv();
+
+ PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
+
+ pDevExt->u.primary.DxgkInterface.DxgkCbNotifyDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
+
+ if (ASMAtomicReadU32(&pDevExt->fCompletingCommands))
+ {
+ VBOXWDDM_GETDPCDATA_CONTEXT context = {0};
+ BOOLEAN bRet;
+
+ context.pDevExt = pDevExt;
+
+ /* get DPC data at IRQL */
+ NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
+ pDevExt->u.primary.DxgkInterface.DeviceHandle,
+ vboxWddmGetDPCDataCallback,
+ &context,
+ 0, /* IN ULONG MessageNumber */
+ &bRet);
+ Assert(Status == STATUS_SUCCESS);
+
+ // if (context.data.bNotifyDpc)
+ pDevExt->u.primary.DxgkInterface.DxgkCbNotifyDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
+
+ if (!vboxVtListIsEmpty(&context.data.CtlList))
+ {
+ int rc = VBoxSHGSMICommandPostprocessCompletion (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, &context.data.CtlList);
+ AssertRC(rc);
+ }
+#ifdef VBOX_WITH_VIDEOHWACCEL
+ if (!vboxVtListIsEmpty(&context.data.VhwaCmdList))
+ {
+ vboxVhwaCompletionListProcess(pDevExt, &context.data.VhwaCmdList);
+ }
+#endif
+ }
+// LOGF(("LEAVE, context(0x%p)", MiniportDeviceContext));
+}
+
+
+static VOID DxgkDdiDpcRoutineLegacy(
IN CONST PVOID MiniportDeviceContext
)
{
@@ -1637,7 +1782,7 @@ NTSTATUS DxgkDdiQueryChildRelations(
{
ChildRelations[i].ChildDeviceType = TypeVideoOutput;
ChildRelations[i].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = D3DKMDT_VOT_HD15; /* VGA */
- ChildRelations[i].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_INTERRUPTIBLE; /* ?? D3DKMDT_MOA_NONE*/
+ ChildRelations[i].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_NONE; //D3DKMDT_MOA_INTERRUPTIBLE; /* ?? D3DKMDT_MOA_NONE*/
ChildRelations[i].ChildCapabilities.Type.VideoOutput.SupportsSdtvModes = FALSE;
ChildRelations[i].ChildCapabilities.HpdAwareness = HpdAwarenessInterruptible; /* ?? HpdAwarenessAlwaysConnected; */
ChildRelations[i].AcpiUid = 0; /* */
@@ -1660,20 +1805,24 @@ NTSTATUS DxgkDdiQueryChildStatus(
LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
+ PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
+
NTSTATUS Status = STATUS_SUCCESS;
switch (ChildStatus->Type)
{
case StatusConnection:
- ChildStatus->HotPlug.Connected = TRUE;
+ {
LOGF(("StatusConnection"));
+ VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[ChildStatus->ChildUid];
+ ChildStatus->HotPlug.Connected = !!pTarget->fConnected;
break;
+ }
case StatusRotation:
- ChildStatus->Rotation.Angle = 0;
LOGF(("StatusRotation"));
+ ChildStatus->Rotation.Angle = 0;
break;
default:
- LOGREL(("ERROR: status type: %d", ChildStatus->Type));
- AssertBreakpoint();
+ WARN(("ERROR: status type: %d", ChildStatus->Type));
Status = STATUS_INVALID_PARAMETER;
break;
}
@@ -1763,7 +1912,7 @@ VOID DxgkDdiUnload(
VbglTerminate();
- VBoxWddmVrTerm();
+ VBoxVrTerm();
PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
if (pLogger)
@@ -1953,12 +2102,12 @@ NTSTATUS APIENTRY DxgkDdiQueryAdapterInfo(
if (!g_VBoxDisplayOnly)
#endif
{
- Assert (pQueryAdapterInfo->OutputDataSize >= sizeof (VBOXWDDM_QI));
- if (pQueryAdapterInfo->OutputDataSize >= sizeof (VBOXWDDM_QI))
+ if (pQueryAdapterInfo->OutputDataSize == sizeof (VBOXWDDM_QI))
{
VBOXWDDM_QI * pQi = (VBOXWDDM_QI*)pQueryAdapterInfo->pOutputData;
memset (pQi, 0, sizeof (VBOXWDDM_QI));
pQi->u32Version = VBOXVIDEOIF_VERSION;
+ pQi->u32VBox3DCaps = VBoxMpCrGetHostCaps();
pQi->cInfos = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
#ifdef VBOX_WITH_VIDEOHWACCEL
for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
@@ -1969,7 +2118,7 @@ NTSTATUS APIENTRY DxgkDdiQueryAdapterInfo(
}
else
{
- LOGREL(("buffer too small"));
+ WARN(("incorrect buffer size %d, expected %d", pQueryAdapterInfo->OutputDataSize, sizeof (VBOXWDDM_QI)));
Status = STATUS_BUFFER_TOO_SMALL;
}
}
@@ -2133,8 +2282,6 @@ VOID vboxWddmAllocationCleanup(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAll
}
case VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER:
{
- if (pAllocation->pSynchEvent)
- ObDereferenceObject(pAllocation->pSynchEvent);
break;
}
default:
@@ -2237,6 +2384,7 @@ NTSTATUS vboxWddmAllocationCreate(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_RESOURCE pRe
{
pAllocation->fRcFlags = pAllocInfo->fFlags;
pAllocation->AllocData.SurfDesc = pAllocInfo->SurfDesc;
+ pAllocation->AllocData.hostID = pAllocInfo->hostID;
pAllocationInfo->Size = pAllocInfo->SurfDesc.cbSize;
@@ -2327,13 +2475,6 @@ NTSTATUS vboxWddmAllocationCreate(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_RESOURCE pRe
pAllocationInfo->Flags.CpuVisible = 1;
// pAllocationInfo->Flags.SynchronousPaging = 1;
pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_MAXIMUM;
- if (pAllocInfo->hSynch)
- {
- Status = ObReferenceObjectByHandle((HANDLE)pAllocInfo->hSynch, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode,
- (PVOID*)&pAllocation->pSynchEvent,
- NULL);
- Assert(Status == STATUS_SUCCESS);
- }
break;
}
@@ -2673,9 +2814,59 @@ DxgkDdiReleaseSwizzlingRange(
return STATUS_SUCCESS;
}
-NTSTATUS
+static NTSTATUS
+APIENTRY
+DxgkDdiPatchNew(
+ CONST HANDLE hAdapter,
+ CONST DXGKARG_PATCH* pPatch)
+{
+ /* DxgkDdiPatch should be made pageable. */
+ PAGED_CODE();
+
+ LOGF(("ENTER, context(0x%x)", hAdapter));
+
+ vboxVDbgBreakFv();
+
+ uint8_t * pPrivateBuf = (uint8_t*)((uint8_t*)pPatch->pDmaBufferPrivateData + pPatch->DmaBufferPrivateDataSubmissionStartOffset);
+ UINT cbPatchBuff = pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset;
+
+ for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
+ {
+ const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[i];
+ Assert(pPatchList->AllocationIndex < pPatch->AllocationListSize);
+ const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
+ if (!pAllocationList->SegmentId)
+ {
+ WARN(("no segment id specified"));
+ continue;
+ }
+
+ if (pPatchList->PatchOffset == ~0UL)
+ {
+ /* this is a dummy patch request, ignore */
+ continue;
+ }
+
+ if (pPatchList->PatchOffset >= cbPatchBuff)
+ {
+ WARN(("pPatchList->PatchOffset(%d) >= cbPatchBuff(%d)", pPatchList->PatchOffset, cbPatchBuff));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ VBOXCMDVBVAOFFSET *poffVram = (VBOXCMDVBVAOFFSET*)(pPrivateBuf + pPatchList->PatchOffset);
+ Assert(pAllocationList->SegmentId);
+ Assert(!pAllocationList->PhysicalAddress.HighPart);
+ Assert(!(pAllocationList->PhysicalAddress.QuadPart & 0xfffUL)); /* <- just a check to ensure allocation offset does not go here */
+ *poffVram = pAllocationList->PhysicalAddress.LowPart + pPatchList->AllocationOffset;;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
APIENTRY
-DxgkDdiPatch(
+DxgkDdiPatchLegacy(
CONST HANDLE hAdapter,
CONST DXGKARG_PATCH* pPatch)
{
@@ -2815,7 +3006,7 @@ DxgkDdiPatch(
else if (pPatch->DmaBufferPrivateDataSubmissionEndOffset == pPatch->DmaBufferPrivateDataSubmissionStartOffset)
{
/* this is a NOP, just return success */
- WARN(("null data size, treating as NOP"));
+// LOG(("null data size, treating as NOP"));
return STATUS_SUCCESS;
}
else
@@ -2841,7 +3032,10 @@ typedef struct VBOXWDDM_CALL_ISR
static BOOLEAN vboxWddmCallIsrCb(PVOID Context)
{
PVBOXWDDM_CALL_ISR pdc = (PVBOXWDDM_CALL_ISR)Context;
- return DxgkDdiInterruptRoutine(pdc->pDevExt, pdc->MessageNumber);
+ PVBOXMP_DEVEXT pDevExt = pdc->pDevExt;
+ if (pDevExt->fCmdVbvaEnabled)
+ return DxgkDdiInterruptRoutineNew(pDevExt, pdc->MessageNumber);
+ return DxgkDdiInterruptRoutineLegacy(pDevExt, pdc->MessageNumber);
}
NTSTATUS vboxWddmCallIsr(PVBOXMP_DEVEXT pDevExt)
@@ -2860,54 +3054,6 @@ NTSTATUS vboxWddmCallIsr(PVBOXMP_DEVEXT pDevExt)
return Status;
}
-static NTSTATUS vboxWddmSubmitCmd(PVBOXMP_DEVEXT pDevExt, VBOXVDMAPIPE_CMD_DMACMD *pCmd)
-{
- NTSTATUS Status = vboxVdmaGgCmdDmaNotifySubmitted(pDevExt, pCmd);
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
- {
- NTSTATUS submStatus = vboxVdmaGgCmdSubmit(pDevExt, &pCmd->Hdr);
- Assert(submStatus == STATUS_SUCCESS);
- if (submStatus != STATUS_SUCCESS)
- {
- vboxVdmaGgCmdDmaNotifyCompleted(pDevExt, pCmd, DXGK_INTERRUPT_DMA_FAULTED);
- }
- }
- else
- {
- vboxVdmaGgCmdRelease(pDevExt, &pCmd->Hdr);
- }
- return Status;
-}
-
-static NTSTATUS vboxWddmSubmitBltCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, UINT u32FenceId, PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt, VBOXVDMAPIPE_FLAGS_DMACMD fBltFlags)
-{
- NTSTATUS Status = STATUS_SUCCESS;
- PVBOXVDMAPIPE_CMD_DMACMD_BLT pBltCmd = (PVBOXVDMAPIPE_CMD_DMACMD_BLT)vboxVdmaGgCmdCreate(pDevExt, VBOXVDMAPIPE_CMD_TYPE_DMACMD, RT_OFFSETOF(VBOXVDMAPIPE_CMD_DMACMD_BLT, Blt.DstRects.UpdateRects.aRects[pBlt->Blt.DstRects.UpdateRects.cRects]));
- Assert(pBltCmd);
- if (pBltCmd)
- {
- VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pBlt->Blt.DstAlloc.srcId];
- vboxVdmaGgCmdDmaNotifyInit(&pBltCmd->Hdr, pContext->NodeOrdinal, u32FenceId, vboxVdmaGgDdiCmdRelease, pBltCmd);
- pBltCmd->Hdr.fFlags = fBltFlags;
- pBltCmd->Hdr.pContext = pContext;
- pBltCmd->Hdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
- memcpy(&pBltCmd->Blt, &pBlt->Blt, RT_OFFSETOF(VBOXVDMA_BLT, DstRects.UpdateRects.aRects[pBlt->Blt.DstRects.UpdateRects.cRects]));
- Status = vboxWddmSubmitCmd(pDevExt, &pBltCmd->Hdr);
- if (Status != STATUS_SUCCESS)
- {
- WARN(("vboxWddmSubmitCmd failed, Status 0x%x", Status));
- Status = STATUS_SUCCESS;
- }
- vboxVdmaGgCmdRelease(pDevExt, &pBltCmd->Hdr.Hdr);
- }
- else
- {
- Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, u32FenceId, DXGK_INTERRUPT_DMA_FAULTED);
- }
- return Status;
-}
-
#ifdef VBOX_WITH_CRHGSMI
DECLCALLBACK(VOID) vboxWddmDmaCompleteChromiumCmd(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
{
@@ -2915,25 +3061,56 @@ DECLCALLBACK(VOID) vboxWddmDmaCompleteChromiumCmd(PVBOXMP_DEVEXT pDevExt, PVBOXV
PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHROMIUM_CMD);
UINT cBufs = pBody->cBuffers;
- for (UINT i = 0; i < cBufs; ++i)
+ vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
+}
+#endif
+
+static NTSTATUS
+APIENTRY
+DxgkDdiSubmitCommandNew(
+ CONST HANDLE hAdapter,
+ CONST DXGKARG_SUBMITCOMMAND* pSubmitCommand)
+{
+ /* DxgkDdiSubmitCommand runs at dispatch, should not be pageable. */
+
+// LOGF(("ENTER, context(0x%x)", hAdapter));
+
+ vboxVDbgBreakFv();
+
+ PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
+#ifdef DEBUG
+ PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pSubmitCommand->hContext;
+ Assert(pContext);
+ Assert(pContext->pDevice);
+ Assert(pContext->pDevice->pAdapter == pDevExt);
+ Assert(!pSubmitCommand->DmaBufferSegmentId);
+#endif
+
+ /* the DMA command buffer is located in system RAM, the host will need to pick it from there */
+ //BufInfo.fFlags = 0; /* see VBOXVDMACBUF_FLAG_xx */
+ uint32_t cbCmd = pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset;
+ if (cbCmd < sizeof (VBOXCMDVBVA_HDR))
{
- VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[i];
- if (!pBufCmd->u32GuestData)
- {
- /* signal completion */
- PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBufCmd->u64GuestData;
- if (pAlloc->pSynchEvent)
- KeSetEvent(pAlloc->pSynchEvent, 3, FALSE);
- }
+ WARN(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXCMDVBVA_HDR) (%d)",
+ pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset,
+ pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset,
+ sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
+ return STATUS_INVALID_PARAMETER;
}
- vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
+ VBOXCMDVBVA_HDR *pHdr = (VBOXCMDVBVA_HDR*)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
+ pHdr->u32FenceID = pSubmitCommand->SubmissionFenceId;
+ int rc = VBoxCmdVbvaSubmit(pDevExt, &pDevExt->CmdVbva, pHdr, cbCmd);
+ if (RT_SUCCESS(rc))
+ return STATUS_SUCCESS;
+
+ WARN(("VBoxCmdVbvaSubmit failed rc %d", rc));
+ return STATUS_UNSUCCESSFUL;
}
-#endif
-NTSTATUS
+static NTSTATUS
APIENTRY
-DxgkDdiSubmitCommand(
+DxgkDdiSubmitCommandLegacy(
CONST HANDLE hAdapter,
CONST DXGKARG_SUBMITCOMMAND* pSubmitCommand)
{
@@ -2963,7 +3140,6 @@ DxgkDdiSubmitCommand(
}
else if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset == pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset)
{
- WARN(("null data size, treating as NOP"));
enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
}
else
@@ -2978,8 +3154,6 @@ DxgkDdiSubmitCommand(
if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D)
vboxWddmModeRenderFromShadowDisableRegister(pDevExt, pContext);
- BOOLEAN fRenderFromSharedDisabled = pDevExt->fRenderToShadowDisabled;
-
switch (enmCmd)
{
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
@@ -2988,10 +3162,12 @@ DxgkDdiSubmitCommand(
PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateDataBase;
VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pS2P->Shadow2Primary.VidPnSourceId];
PVBOXWDDM_ALLOCATION pSrcAlloc = pS2P->Shadow2Primary.ShadowAlloc.pAlloc;
- vboxWddmAddrSetVram(&pSrcAlloc->AllocData.Addr, pS2P->Shadow2Primary.ShadowAlloc.segmentIdAlloc, pS2P->Shadow2Primary.ShadowAlloc.offAlloc);
+ BOOLEAN fShadowChanged = vboxWddmAddrSetVram(&pSrcAlloc->AllocData.Addr, pS2P->Shadow2Primary.ShadowAlloc.segmentIdAlloc, pS2P->Shadow2Primary.ShadowAlloc.offAlloc);
+ if (fShadowChanged)
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pS2P->Shadow2Primary.VidPnSourceId);
- fRenderFromSharedDisabled = vboxWddmModeRenderFromShadowCheckOnSubmitCommand(pDevExt, NULL);
- vboxWddmCheckUpdateFramebufferAddress(pDevExt, pSource);
+ vboxWddmModeRenderFromShadowCheckOnSubmitCommand(pDevExt, NULL);
+ vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
if (pSrcAlloc->bVisible)
{
uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
@@ -3014,253 +3190,77 @@ DxgkDdiSubmitCommand(
PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
PVBOXWDDM_ALLOCATION pDstAlloc = pBlt->Blt.DstAlloc.pAlloc;
PVBOXWDDM_ALLOCATION pSrcAlloc = pBlt->Blt.SrcAlloc.pAlloc;
+ BOOLEAN fSrcChanged;
+ BOOLEAN fDstChanged;
- vboxWddmAddrSetVram(&pDstAlloc->AllocData.Addr, pBlt->Blt.DstAlloc.segmentIdAlloc, pBlt->Blt.DstAlloc.offAlloc);
- vboxWddmAddrSetVram(&pSrcAlloc->AllocData.Addr, pBlt->Blt.SrcAlloc.segmentIdAlloc, pBlt->Blt.SrcAlloc.offAlloc);
+ fDstChanged = vboxWddmAddrSetVram(&pDstAlloc->AllocData.Addr, pBlt->Blt.DstAlloc.segmentIdAlloc, pBlt->Blt.DstAlloc.offAlloc);
+ fSrcChanged = vboxWddmAddrSetVram(&pSrcAlloc->AllocData.Addr, pBlt->Blt.SrcAlloc.segmentIdAlloc, pBlt->Blt.SrcAlloc.offAlloc);
- uint32_t cContexts3D = ASMAtomicReadU32(&pDevExt->cContexts3D);
+ vboxWddmModeRenderFromShadowCheckOnSubmitCommand(pDevExt, NULL);
- VBOXVDMAPIPE_FLAGS_DMACMD fBltFlags;
- fBltFlags.Value = 0;
-
- if (pDstAlloc->bAssigned &&
- (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
- || pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
- )
+ if (VBOXWDDM_IS_REAL_FB_ALLOCATION(pDevExt, pDstAlloc))
{
VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->AllocData.SurfDesc.VidPnSourceId];
- Assert(pDstAlloc->AllocData.SurfDesc.VidPnSourceId < VBOX_VIDEO_MAX_SCREENS);
- if (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
- vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pDstAlloc->AllocData.SurfDesc.VidPnSourceId);
- fRenderFromSharedDisabled = vboxWddmModeRenderFromShadowCheckOnSubmitCommand(pDevExt, NULL);
- if(pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D
- || pDstAlloc->enmType !=VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
- vboxWddmCheckUpdateFramebufferAddress(pDevExt, pSource);
- }
- else if (pSrcAlloc->bAssigned &&
- (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
- || pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
- )
- {
- VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->AllocData.SurfDesc.VidPnSourceId];
Assert(pDstAlloc->AllocData.SurfDesc.VidPnSourceId < VBOX_VIDEO_MAX_SCREENS);
-
- if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
- vboxWddmAssignShadow(pDevExt, pSource, pDstAlloc, pSrcAlloc->AllocData.SurfDesc.VidPnSourceId);
- fRenderFromSharedDisabled = vboxWddmModeRenderFromShadowCheckOnSubmitCommand(pDevExt, NULL);
- if(pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D
- || pSrcAlloc->enmType !=VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
- vboxWddmCheckUpdateFramebufferAddress(pDevExt, pSource);
- }
-
- if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D && fRenderFromSharedDisabled)
- fBltFlags.fRealOp = 1;
-
- switch (pDstAlloc->enmType)
- {
- case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
- case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
+#if 0
+ if (VBOXWDDM_IS_FB_ALLOCATION(pDevExt, pDstAlloc) && pDstAlloc->AllocData.hostID)
{
- if (pDstAlloc->bAssigned)
+ if (pSource->AllocData.hostID != pDstAlloc->AllocData.hostID)
{
-// Assert(pSource->pPrimaryAllocation == pDstAlloc);
-
- switch (pSrcAlloc->enmType)
- {
- case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
- {
- fBltFlags.fVisibleRegions = !!cContexts3D;
- Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
- VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->AllocData.SurfDesc.VidPnSourceId];
- Assert(pDstAlloc->AllocData.SurfDesc.VidPnSourceId < VBOX_VIDEO_MAX_SCREENS);
-
- if (!fRenderFromSharedDisabled && pSource->bVisible)
- {
- RECT rect;
- if (pBlt->Blt.DstRects.UpdateRects.cRects)
- {
- rect = pBlt->Blt.DstRects.UpdateRects.aRects[0];
- for (UINT i = 1; i < pBlt->Blt.DstRects.UpdateRects.cRects; ++i)
- {
- vboxWddmRectUnited(&rect, &rect, &pBlt->Blt.DstRects.UpdateRects.aRects[i]);
- }
- }
- else
- rect = pBlt->Blt.DstRects.ContextRect;
-
- uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
- if (!cUnlockedVBVADisabled)
- {
- VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &rect);
- }
- else
- {
- VBOXVBVA_OP_WITHLOCK_ATDPC(ReportDirtyRect, pDevExt, pSource, &rect);
- }
- }
-
- break;
- }
- case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
- {
- if(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D)
- {
- Assert(pSrcAlloc->fRcFlags.RenderTarget);
- if (pSrcAlloc->fRcFlags.RenderTarget)
- fBltFlags.fVisibleRegions = 1;
- }
- break;
- }
- default:
- {
- AssertBreakpoint();
- break;
- }
- }
+ pSource->AllocData.hostID = pDstAlloc->AllocData.hostID;
+ fDstChanged = TRUE;
}
- break;
- }
- case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
- {
-// Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
- Assert(pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
- Assert(pSrcAlloc->fRcFlags.RenderTarget);
- Assert(vboxWddmRectIsEqual(&pBlt->Blt.SrcRect, &pBlt->Blt.DstRects.ContextRect));
- Assert(pBlt->Blt.DstRects.UpdateRects.cRects == 1);
- Assert(vboxWddmRectIsEqual(&pBlt->Blt.SrcRect, pBlt->Blt.DstRects.UpdateRects.aRects));
- break;
+ if (fDstChanged)
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
}
- case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
+ else
+#endif
+ if (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
{
- Assert(pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
- Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
- break;
+ if (fSrcChanged)
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
+
+ vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pDstAlloc->AllocData.SurfDesc.VidPnSourceId);
+ vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
}
- default:
- AssertBreakpoint();
- break;
- }
- if (fBltFlags.Value)
- {
- Status = vboxWddmSubmitBltCmd(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, pBlt, fBltFlags);
- }
- else
- {
- Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
+ Assert(pSource->u8SyncState == VBOXWDDM_HGSYNC_F_SYNCED_ALL || pDevExt->aTargets[pDstAlloc->AllocData.SurfDesc.VidPnSourceId].fStateSyncPening);
}
- break;
- }
- case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
- {
-#ifdef VBOX_WITH_CRHGSMI
- VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD *pChromiumCmd = (VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD*)pPrivateDataBase;
- UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[pChromiumCmd->Base.u32CmdReserved]));
- PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, cbCmd);
- if (!pDr)
- {
- /* @todo: try flushing.. */
- LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- // vboxVdmaCBufDrCreate zero initializes the pDr
- pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
- pDr->cbBuf = cbCmd;
- pDr->rc = VERR_NOT_IMPLEMENTED;
-
- PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
- pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
- pHdr->u32CmdSpecific = 0;
- VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHROMIUM_CMD);
- pBody->cBuffers = pChromiumCmd->Base.u32CmdReserved;
- for (UINT i = 0; i < pChromiumCmd->Base.u32CmdReserved; ++i)
- {
- VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[i];
- VBOXWDDM_UHGSMI_BUFFER_SUBMIT_INFO *pBufInfo = &pChromiumCmd->aBufInfos[i];
-
- pBufCmd->offBuffer = pBufInfo->Alloc.offAlloc;
- pBufCmd->cbBuffer = pBufInfo->cbData;
- pBufCmd->u32GuestData = pBufInfo->bDoNotSignalCompletion;
- pBufCmd->u64GuestData = (uint64_t)pBufInfo->Alloc.pAlloc;
- }
+ Status = vboxVdmaProcessBltCmd(pDevExt, pContext, pBlt);
+ if (!NT_SUCCESS(Status))
+ WARN(("vboxVdmaProcessBltCmd failed, Status 0x%x", Status));
- PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
- vboxVdmaDdiCmdInit(pDdiCmd, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, vboxWddmDmaCompleteChromiumCmd, pDr);
- NTSTATUS Status = vboxVdmaDdiCmdSubmitted(pDevExt, pDdiCmd);
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
- {
- int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
- Assert(rc == VINF_SUCCESS);
- }
- else
- {
- vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
- }
-#else
- Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
- Assert(Status == STATUS_SUCCESS);
-#endif
+ Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId,
+ NT_SUCCESS(Status) ? DXGK_INTERRUPT_DMA_COMPLETED : DXGK_INTERRUPT_DMA_FAULTED);
break;
}
case VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP:
{
VBOXWDDM_DMA_PRIVATEDATA_FLIP *pFlip = (VBOXWDDM_DMA_PRIVATEDATA_FLIP*)pPrivateDataBase;
- vboxWddmAddrSetVram(&pFlip->Flip.Alloc.pAlloc->AllocData.Addr, pFlip->Flip.Alloc.segmentIdAlloc, pFlip->Flip.Alloc.offAlloc);
- PVBOXVDMAPIPE_CMD_DMACMD_FLIP pFlipCmd = (PVBOXVDMAPIPE_CMD_DMACMD_FLIP)vboxVdmaGgCmdCreate(pDevExt,
- VBOXVDMAPIPE_CMD_TYPE_DMACMD, sizeof (VBOXVDMAPIPE_CMD_DMACMD_FLIP));
- Assert(pFlipCmd);
- if (pFlipCmd)
- {
- VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pFlip->Flip.Alloc.srcId];
- vboxVdmaGgCmdDmaNotifyInit(&pFlipCmd->Hdr, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, vboxVdmaGgDdiCmdRelease, pFlipCmd);
- pFlipCmd->Hdr.fFlags.Value = 0;
- pFlipCmd->Hdr.fFlags.fVisibleRegions = 1;
- pFlipCmd->Hdr.pContext = pContext;
- pFlipCmd->Hdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP;
- memcpy(&pFlipCmd->Flip, &pFlip->Flip, sizeof (pFlipCmd->Flip));
- Status = vboxWddmSubmitCmd(pDevExt, &pFlipCmd->Hdr);
- if (Status != STATUS_SUCCESS)
- WARN(("vboxWddmSubmitCmd failed, Status 0x%x", Status));
- vboxVdmaGgCmdRelease(pDevExt, &pFlipCmd->Hdr.Hdr);
- }
- else
- {
- Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_FAULTED);
- Assert(Status == STATUS_SUCCESS);
- }
+ PVBOXWDDM_ALLOCATION pAlloc = pFlip->Flip.Alloc.pAlloc;
+ VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pAlloc->AllocData.SurfDesc.VidPnSourceId];
+ vboxWddmAddrSetVram(&pAlloc->AllocData.Addr, pFlip->Flip.Alloc.segmentIdAlloc, pFlip->Flip.Alloc.offAlloc);
+ vboxWddmAssignPrimary(pDevExt, pSource, pAlloc, pAlloc->AllocData.SurfDesc.VidPnSourceId);
+ vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
+
+ Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId,
+ NT_SUCCESS(Status) ? DXGK_INTERRUPT_DMA_COMPLETED : DXGK_INTERRUPT_DMA_FAULTED);
break;
}
case VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL:
{
PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateDataBase;
vboxWddmAddrSetVram(&pCF->ClrFill.Alloc.pAlloc->AllocData.Addr, pCF->ClrFill.Alloc.segmentIdAlloc, pCF->ClrFill.Alloc.offAlloc);
- PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL pCFCmd = (PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL)vboxVdmaGgCmdCreate(pDevExt,
- VBOXVDMAPIPE_CMD_TYPE_DMACMD, RT_OFFSETOF(VBOXVDMAPIPE_CMD_DMACMD_CLRFILL, ClrFill.Rects.aRects[pCF->ClrFill.Rects.cRects]));
- Assert(pCFCmd);
- if (pCFCmd)
- {
- vboxVdmaGgCmdDmaNotifyInit(&pCFCmd->Hdr, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, vboxVdmaGgDdiCmdRelease, pCFCmd);
- pCFCmd->Hdr.fFlags.Value = 0;
- pCFCmd->Hdr.fFlags.fRealOp = 1;
- pCFCmd->Hdr.pContext = pContext;
- pCFCmd->Hdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL;
- memcpy(&pCFCmd->ClrFill, &pCF->ClrFill, RT_OFFSETOF(VBOXVDMA_CLRFILL, Rects.aRects[pCF->ClrFill.Rects.cRects]));
- Status = vboxWddmSubmitCmd(pDevExt, &pCFCmd->Hdr);
- if (Status != STATUS_SUCCESS)
- WARN(("vboxWddmSubmitCmd failed, Status 0x%x", Status));
- vboxVdmaGgCmdRelease(pDevExt, &pCFCmd->Hdr.Hdr);
- }
- else
- {
- Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_FAULTED);
- Assert(Status == STATUS_SUCCESS);
- }
+ Status = vboxVdmaProcessClrFillCmd(pDevExt, pContext, pCF);
+ if (!NT_SUCCESS(Status))
+ WARN(("vboxVdmaProcessClrFillCmd failed, Status 0x%x", Status));
+ Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId,
+ NT_SUCCESS(Status) ? DXGK_INTERRUPT_DMA_COMPLETED : DXGK_INTERRUPT_DMA_FAULTED);
break;
}
case VBOXVDMACMD_TYPE_DMA_NOP:
@@ -3302,9 +3302,27 @@ DxgkDdiSubmitCommand(
return Status;
}
-NTSTATUS
+static NTSTATUS
APIENTRY
-DxgkDdiPreemptCommand(
+DxgkDdiPreemptCommandNew(
+ CONST HANDLE hAdapter,
+ CONST DXGKARG_PREEMPTCOMMAND* pPreemptCommand)
+{
+ LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
+
+ PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
+
+ VBoxCmdVbvaPreempt(pDevExt, &pDevExt->CmdVbva, pPreemptCommand->PreemptionFenceId);
+
+ LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
+
+ return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+APIENTRY
+DxgkDdiPreemptCommandLegacy(
CONST HANDLE hAdapter,
CONST DXGKARG_PREEMPTCOMMAND* pPreemptCommand)
{
@@ -3318,103 +3336,159 @@ DxgkDdiPreemptCommand(
return STATUS_SUCCESS;
}
-#if 0
-static uint32_t vboxWddmSysMemElBuild(PVBOXVDMACMD_SYSMEMEL pEl, PMDL pMdl, uint32_t iPfn, uint32_t cPages, uint32_t cbBuffer, uint32_t *pcPagesRemaining)
-{
- uint32_t cbInitialBuffer = cbBuffer;
- if (cbBuf >= sizeof (*pEl))
- {
- PFN_NUMBER cur = MmGetMdlPfnArray(pMdl)[iPfn];
- uint32_t cbEl = sizeof (*pEl);
- uint32_t cBufs = 1;
- pEl->phBuf[0] = (cur << 12);
- --cPages;
- cbBuffer -= sizeof (*pEl);
- bool bArrayMode = false;
- while (cPages)
- {
- PFN_NUMBER next = MmGetMdlPfnArray(pMdl)[iPfn+cBufs];
- if (!bArrayMode)
+/*
+ * DxgkDdiBuildPagingBuffer
+ */
+static NTSTATUS
+APIENTRY
+DxgkDdiBuildPagingBufferNew(
+ CONST HANDLE hAdapter,
+ DXGKARG_BUILDPAGINGBUFFER* pBuildPagingBuffer)
+{
+ /* DxgkDdiBuildPagingBuffer should be made pageable. */
+ PAGED_CODE();
+
+ vboxVDbgBreakFv();
+
+ PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
+ uint32_t cbBuffer = 0, cbPrivateData = 0;
+
+ LOGF(("ENTER, context(0x%x)", hAdapter));
+
+ /* paging buffer transfer is nop for hostID allocations */
+ if (pBuildPagingBuffer->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_HDR))
+ {
+ WARN(("pBuildPagingBuffer->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_HDR (%d)", pBuildPagingBuffer->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_HDR)));
+ /* @todo: can this actually happen? what status to return? */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ switch (pBuildPagingBuffer->Operation)
+ {
+ case DXGK_OPERATION_TRANSFER:
+ {
+ VBOXCMDVBVA_HDR *pHdr = (VBOXCMDVBVA_HDR*)pBuildPagingBuffer->pDmaBuffer;
+ pHdr->u8Flags = 0;
+ pHdr->u8State = VBOXCMDVBVA_STATE_SUBMITTED;
+ /* sanity */
+ pHdr->u32FenceID = 0;
+
+ if ((!pBuildPagingBuffer->Transfer.Source.SegmentId) == (!pBuildPagingBuffer->Transfer.Destination.SegmentId))
{
- if (next == cur+1)
- {
- cur = next;
- ++cBufs;
- --cPages;
- }
- else if (cBufs > 1)
- {
- break;
- }
- else
- {
- bArrayMode = true;
- }
+ WARN(("we only support RAM <-> VRAM moves, Src Seg(%d), Dst Seg(%d)", pBuildPagingBuffer->Transfer.Source.SegmentId, pBuildPagingBuffer->Transfer.Destination.SegmentId));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Transfer.hAllocation;
+ if (!pAlloc)
+ {
+ WARN(("allocation is null"));
+ return STATUS_INVALID_PARAMETER;
}
- /* array mode */
- if (cbBuffer < sizeof (pEl->phBuf[0]))
+ if (pAlloc->AllocData.hostID)
{
+ pHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_NOPCMD;
+ cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
+ cbPrivateData = sizeof (*pHdr);
break;
}
- pEl->phBuf[cBufs] = (next << 12);
- cbBuffer -= sizeof (pEl->phBuf[0]);
- ++cBufs;
- --cPages;
- }
+ if (pBuildPagingBuffer->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_PAGING_TRANSFER))
+ {
+ WARN(("pBuildPagingBuffer->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_PAGING_TRANSFER (%d)", pBuildPagingBuffer->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_PAGING_TRANSFER)));
+ /* @todo: can this actually happen? what status to return? */
+ return STATUS_INVALID_PARAMETER;
+ }
- pEl->cPages = cPages;
- if (bArrayMode)
- pEl->fFlags = VBOXVDMACMD_SYSMEMEL_F_PAGELIST;
- else
- pEl->fFlags = 0;
- }
- else
- {
- Assert(0);
- }
+ VBOXCMDVBVA_PAGING_TRANSFER *pPaging = (VBOXCMDVBVA_PAGING_TRANSFER*)pBuildPagingBuffer->pDmaBuffer;
+ pPaging->Hdr.u8OpCode = VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER;
- *pcPagesRemaining = cPages;
- return cbInitialBuffer - cbBuffer;
-}
+ PMDL pMdl;
+ uint32_t offVRAM;
+ BOOLEAN fIn;
-static uint32_t vboxWddmBpbTransferVRamSysBuildEls(PVBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS pCmd, PMDL pMdl, uint32_t iPfn, uint32_t cPages, uint32_t cbBuffer, uint32_t *pcPagesRemaining)
-{
- uint32_t cInitPages = cPages;
- uint32_t cbBufferUsed = vboxWddmSysMemElBuild(&pCmd->FirstEl, pMdl, iPfn, cPages, cbBuffer, &cPages);
- if (cbBufferUsed)
- {
- uint32_t cEls = 1;
- PVBOXVDMACMD_SYSMEMEL pEl = &pCmd->FirstEl;
- while (cPages)
- {
- PVBOXVDMACMD_SYSMEMEL pEl = VBOXVDMACMD_SYSMEMEL_NEXT(pEl);
- cbBufferUsed = vboxWddmSysMemElBuild(pEl, pMdl, iPfn + cInitPages - cPages, cPages, cbBuffer - cbBufferUsed, &cPages);
- if (cbBufferUsed)
+ if (pBuildPagingBuffer->Transfer.Source.SegmentId)
{
- ++cEls;
+ Assert(!pBuildPagingBuffer->Transfer.Destination.SegmentId);
+ Assert(!pBuildPagingBuffer->Transfer.Source.SegmentAddress.HighPart);
+ offVRAM = pBuildPagingBuffer->Transfer.Source.SegmentAddress.LowPart;
+ pMdl = pBuildPagingBuffer->Transfer.Destination.pMdl;
+ fIn = FALSE;
}
else
- break;
+ {
+ Assert(pBuildPagingBuffer->Transfer.Destination.SegmentId);
+ Assert(!pBuildPagingBuffer->Transfer.Source.SegmentId);
+ Assert(!pBuildPagingBuffer->Transfer.Destination.SegmentAddress.HighPart);
+ offVRAM = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.LowPart;
+ pMdl = pBuildPagingBuffer->Transfer.Source.pMdl;
+ fIn = TRUE;
+ }
+
+ uint32_t cPages = (uint32_t)((pBuildPagingBuffer->Transfer.TransferSize + 0xfff) >> PAGE_SHIFT);
+ uint32_t cTotalPages = cPages;
+ cPages -= pBuildPagingBuffer->MultipassOffset;
+ uint32_t iFirstPage = pBuildPagingBuffer->Transfer.MdlOffset + pBuildPagingBuffer->MultipassOffset;
+ uint32_t cPagesWritten;
+ offVRAM += pBuildPagingBuffer->Transfer.TransferOffset + pBuildPagingBuffer->MultipassOffset;
+
+ pPaging->Alloc.u.offVRAM = offVRAM;
+ if (fIn)
+ pPaging->Hdr.u8Flags |= VBOXCMDVBVA_OPF_PAGING_TRANSFER_IN;
+ cbPrivateData = VBoxCVDdiPTransferVRamSysBuildEls(pPaging, pMdl, iFirstPage, cPages, pBuildPagingBuffer->DmaBufferPrivateDataSize, &cPagesWritten);
+ if (cPagesWritten != cPages)
+ pBuildPagingBuffer->MultipassOffset += cPagesWritten;
+ else
+ pBuildPagingBuffer->MultipassOffset = 0;
+
+ cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
+ break;
+ }
+ case DXGK_OPERATION_FILL:
+ {
+ Assert(pBuildPagingBuffer->Fill.FillPattern == 0);
+ PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Fill.hAllocation;
+ if (!pAlloc)
+ {
+ WARN(("allocation is null"));
+ return STATUS_INVALID_PARAMETER;
+ }
+ /** @todo: add necessary bits */
+ WARN(("Impl!"));
+ break;
+ }
+ case DXGK_OPERATION_DISCARD_CONTENT:
+ {
+ PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->DiscardContent.hAllocation;
+ if (!pAlloc)
+ {
+ WARN(("allocation is null"));
+ return STATUS_INVALID_PARAMETER;
+ }
+ break;
+ }
+ default:
+ {
+ WARN(("unsupported op (%d)", pBuildPagingBuffer->Operation));
+ break;
}
}
- else
- {
- Assert(0);
- }
- pCmd->cTransferPages = (cInitPages - cPages);
- *pcPagesRemaining = cPages;
- return cbBufferUsed;
+ pBuildPagingBuffer->pDmaBuffer = ((uint8_t*)pBuildPagingBuffer->pDmaBuffer) + cbBuffer;
+ pBuildPagingBuffer->pDmaBufferPrivateData = ((uint8_t*)pBuildPagingBuffer->pDmaBufferPrivateData) + cbPrivateData;
+
+ LOGF(("LEAVE, context(0x%x)", hAdapter));
+
+ if (pBuildPagingBuffer->MultipassOffset)
+ return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
+ return STATUS_SUCCESS;
}
-#endif
-/*
- * DxgkDdiBuildPagingBuffer
- */
-NTSTATUS
+
+
+static NTSTATUS
APIENTRY
-DxgkDdiBuildPagingBuffer(
+DxgkDdiBuildPagingBufferLegacy(
CONST HANDLE hAdapter,
DXGKARG_BUILDPAGINGBUFFER* pBuildPagingBuffer)
{
@@ -3428,11 +3502,14 @@ DxgkDdiBuildPagingBuffer(
LOGF(("ENTER, context(0x%x)", hAdapter));
+ uint32_t cbCmdDma = 0;
+
/* @todo: */
switch (pBuildPagingBuffer->Operation)
{
case DXGK_OPERATION_TRANSFER:
{
+ cbCmdDma = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
#ifdef VBOX_WITH_VDMA
#if 0
if ((!pBuildPagingBuffer->Transfer.Source.SegmentId) != (!pBuildPagingBuffer->Transfer.Destination.SegmentId))
@@ -3583,6 +3660,7 @@ DxgkDdiBuildPagingBuffer(
}
case DXGK_OPERATION_FILL:
{
+ cbCmdDma = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
Assert(pBuildPagingBuffer->Fill.FillPattern == 0);
PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Fill.hAllocation;
// pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_FILL);
@@ -3595,12 +3673,16 @@ DxgkDdiBuildPagingBuffer(
}
default:
{
- LOGREL(("unsupported op (%d)", pBuildPagingBuffer->Operation));
- AssertBreakpoint();
+ WARN(("unsupported op (%d)", pBuildPagingBuffer->Operation));
break;
}
}
+ if (cbCmdDma)
+ {
+ pBuildPagingBuffer->pDmaBuffer = ((uint8_t*)pBuildPagingBuffer->pDmaBuffer) + cbCmdDma;
+ }
+
LOGF(("LEAVE, context(0x%x)", hAdapter));
return Status;
@@ -3929,6 +4011,12 @@ DxgkDdiEscape(
#ifdef VBOX_WITH_CRHGSMI
case VBOXESC_UHGSMI_SUBMIT:
{
+ if (pDevExt->fCmdVbvaEnabled)
+ {
+ WARN(("VBOXESC_UHGSMI_SUBMIT not supported for CmdVbva mode"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
/* submit VBOXUHGSMI command */
PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
PVBOXDISPIFESCAPE_UHGSMI_SUBMIT pSubmit = (PVBOXDISPIFESCAPE_UHGSMI_SUBMIT)pEscapeHdr;
@@ -3949,6 +4037,13 @@ DxgkDdiEscape(
case VBOXESC_UHGSMI_ALLOCATE:
{
/* allocate VBOXUHGSMI buffer */
+ if (pDevExt->fCmdVbvaEnabled)
+ {
+ WARN(("VBOXESC_UHGSMI_ALLOCATE not supported for CmdVbva mode"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
PVBOXDISPIFESCAPE_UHGSMI_ALLOCATE pAlocate = (PVBOXDISPIFESCAPE_UHGSMI_ALLOCATE)pEscapeHdr;
Assert(pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_ALLOCATE));
@@ -3965,6 +4060,12 @@ DxgkDdiEscape(
case VBOXESC_UHGSMI_DEALLOCATE:
{
+ if (pDevExt->fCmdVbvaEnabled)
+ {
+ WARN(("VBOXESC_UHGSMI_DEALLOCATE not supported for CmdVbva mode"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
/* deallocate VBOXUHGSMI buffer */
PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
PVBOXDISPIFESCAPE_UHGSMI_DEALLOCATE pDealocate = (PVBOXDISPIFESCAPE_UHGSMI_DEALLOCATE)pEscapeHdr;
@@ -3982,14 +4083,29 @@ DxgkDdiEscape(
case VBOXESC_GETVBOXVIDEOCMCMD:
{
+ if (pDevExt->fCmdVbvaEnabled || pDevExt->fTexPresentEnabled)
+ {
+ WARN(("VBOXESC_GETVBOXVIDEOCMCMD not supported for CmdVbva or TexPresent mode"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
/* get the list of r0->r3 commands (d3d window visible regions reporting )*/
PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pRegions = (PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)pEscapeHdr;
Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD));
if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD))
{
- Status = vboxVideoCmEscape(&pContext->CmContext, pRegions, pEscape->PrivateDriverDataSize);
- Assert(Status == STATUS_SUCCESS);
+ if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D)
+ {
+ Status = vboxVideoCmEscape(&pContext->CmContext, pRegions, pEscape->PrivateDriverDataSize);
+ Assert(Status == STATUS_SUCCESS);
+ }
+ else
+ {
+ WARN(("VBOXESC_GETVBOXVIDEOCMCMD recieved invalid context type %d", pContext->enmType));
+ Status = STATUS_INVALID_PARAMETER;
+ }
}
else
Status = STATUS_BUFFER_TOO_SMALL;
@@ -3999,6 +4115,13 @@ DxgkDdiEscape(
case VBOXESC_CRHGSMICTLCON_CALL:
{
+ if (pDevExt->fCmdVbvaEnabled)
+ {
+ WARN(("VBOXESC_CRHGSMICTLCON_CALL not supported for CmdVbva mode"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
PVBOXDISPIFESCAPE_CRHGSMICTLCON_CALL pCall = (PVBOXDISPIFESCAPE_CRHGSMICTLCON_CALL)pEscapeHdr;
if (pEscape->PrivateDriverDataSize >= sizeof (*pCall))
@@ -4006,13 +4129,11 @@ DxgkDdiEscape(
/* this is true due to the above condition */
Assert(pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL, CallInfo));
int rc = VBoxMpCrCtlConCallUserData(&pDevExt->CrCtlCon, &pCall->CallInfo, pEscape->PrivateDriverDataSize - RT_OFFSETOF(VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL, CallInfo));
- if (RT_SUCCESS(rc))
- Status = STATUS_SUCCESS;
- else
- {
+ pEscapeHdr->u32CmdSpecific = (uint32_t)rc;
+ Status = STATUS_SUCCESS; /* <- always return success here, otherwise the private data buffer modifications
+ * i.e. rc status stored in u32CmdSpecific will not be copied to user mode */
+ if (!RT_SUCCESS(rc))
WARN(("VBoxMpCrUmCtlConCall failed, rc(%d)", rc));
- Status = STATUS_UNSUCCESSFUL;
- }
}
else
{
@@ -4042,6 +4163,22 @@ DxgkDdiEscape(
case VBOXESC_SETVISIBLEREGION:
{
+ PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
+#ifdef VBOX_DISPIF_WITH_OPCONTEXT
+ if (!pContext)
+ {
+ WARN(("VBOXESC_SETVISIBLEREGION no context supplied!"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS)
+ {
+ WARN(("VBOXESC_SETVISIBLEREGION invalid context supplied %d!", pContext->enmType));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+#endif
/* visible regions for seamless */
LPRGNDATA lpRgnData = VBOXDISPIFESCAPE_DATA(pEscapeHdr, RGNDATA);
uint32_t cbData = VBOXDISPIFESCAPE_DATA_SIZE(pEscape->PrivateDriverDataSize);
@@ -4080,22 +4217,23 @@ DxgkDdiEscape(
rc = VbglGRPerform (&req->header);
AssertRC(rc);
- if (!RT_SUCCESS(rc))
+ if (RT_SUCCESS(rc))
+ Status = STATUS_SUCCESS;
+ else
{
- LOGREL(("VbglGRPerform failed rc (%d)", rc));
+ WARN(("VbglGRPerform failed rc (%d)", rc));
Status = STATUS_UNSUCCESSFUL;
}
}
else
{
- LOGREL(("VbglGRAlloc failed rc (%d)", rc));
+ WARN(("VbglGRAlloc failed rc (%d)", rc));
Status = STATUS_UNSUCCESSFUL;
}
}
else
{
- LOGREL(("VBOXESC_SETVISIBLEREGION: incorrect buffer size (%d), reported count (%d)", cbRects, lpRgnData->rdh.nCount));
- AssertBreakpoint();
+ WARN(("VBOXESC_SETVISIBLEREGION: incorrect buffer size (%d), reported count (%d)", cbRects, lpRgnData->rdh.nCount));
Status = STATUS_INVALID_PARAMETER;
}
break;
@@ -4139,6 +4277,43 @@ DxgkDdiEscape(
Status = STATUS_SUCCESS;
break;
}
+ case VBOXESC_SETCTXHOSTID:
+ {
+ /* set swapchain information */
+ PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
+ if (!pContext)
+ {
+ WARN(("VBOXESC_SETCTXHOSTID: no context specified"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE))
+ {
+ WARN(("VBOXESC_SETCTXHOSTID: invalid data size %d", pEscape->PrivateDriverDataSize));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ int32_t hostID = (int32_t)pEscapeHdr->u32CmdSpecific;
+ if (hostID <= 0)
+ {
+ WARN(("VBOXESC_SETCTXHOSTID: invalid hostID %d", hostID));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ if (pContext->hostID)
+ {
+ WARN(("VBOXESC_SETCTXHOSTID: context already has hostID specified"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ pContext->hostID = hostID;
+ Status = STATUS_SUCCESS;
+ break;
+ }
case VBOXESC_SWAPCHAININFO:
{
/* set swapchain information */
@@ -4149,46 +4324,171 @@ DxgkDdiEscape(
}
case VBOXESC_REINITVIDEOMODES:
{
- if (pEscape->Flags.HardwareAccess)
+ if (!pEscape->Flags.HardwareAccess)
{
- WARN(("VBOXESC_REINITVIDEOMODES called with HardwareAccess flag set, failing"));
+ WARN(("VBOXESC_REINITVIDEOMODESBYMASK called without HardwareAccess flag set, failing"));
Status = STATUS_INVALID_PARAMETER;
break;
}
- WARN(("VBOXESC_REINITVIDEOMODESBYMASK should be called instead"));
- PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateAllVideoModesInfos(pDevExt);
- Status = vboxWddmChildStatusCheckByMask(pDevExt, pInfos, NULL);
- if (!NT_SUCCESS(Status))
+
+#ifdef VBOX_DISPIF_WITH_OPCONTEXT
+ /* win8.1 does not allow context-based escapes for display-only mode */
+ PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
+ if (!pContext)
+ {
+ WARN(("VBOXESC_REINITVIDEOMODES no context supplied!"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE)
{
- WARN(("vboxWddmChildStatusCheckByMask failed, Status 0x%x", Status));
+ WARN(("VBOXESC_REINITVIDEOMODES invalid context supplied %d!", pContext->enmType));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
}
+#endif
+
+ WARN(("VBOXESC_REINITVIDEOMODESBYMASK should be called instead"));
+ VBoxWddmUpdateVideoModesInfoByMask(pDevExt, NULL);
+ Status = STATUS_SUCCESS;
break;
}
case VBOXESC_REINITVIDEOMODESBYMASK:
{
- BOOLEAN fCheckDisplayRecconect = (pEscapeHdr->u32CmdSpecific & VBOXWDDM_REINITVIDEOMODESBYMASK_F_RECONNECT_DISPLAYS_ON_CHANGE);
- if (fCheckDisplayRecconect && pEscape->Flags.HardwareAccess)
+ if (!pEscape->Flags.HardwareAccess)
+ {
+ WARN(("VBOXESC_REINITVIDEOMODESBYMASK called without HardwareAccess flag set, failing"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+#ifdef VBOX_DISPIF_WITH_OPCONTEXT
+ /* win8.1 does not allow context-based escapes for display-only mode */
+ PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
+ if (!pContext)
+ {
+ WARN(("VBOXESC_REINITVIDEOMODESBYMASK no context supplied!"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE)
{
- WARN(("VBOXESC_REINITVIDEOMODESBYMASK called with HardwareAccess flag set, failing"));
+ WARN(("VBOXESC_REINITVIDEOMODESBYMASK invalid context supplied %d!", pContext->enmType));
Status = STATUS_INVALID_PARAMETER;
break;
}
+#endif
+
if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK))
{
WARN(("invalid private driver size %d", pEscape->PrivateDriverDataSize));
Status = STATUS_INVALID_PARAMETER;
break;
}
+ LOG(("=> VBOXESC_REINITVIDEOMODESBYMASK"));
PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK pData = (PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK)pEscapeHdr;
- PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateVideoModesInfoByMask(pDevExt, pData->ScreenMask);
- if (fCheckDisplayRecconect)
+ VBoxWddmUpdateVideoModesInfoByMask(pDevExt, pData->ScreenMask);
+ Status = STATUS_SUCCESS;
+ LOG(("<= VBOXESC_REINITVIDEOMODESBYMASK"));
+ break;
+ }
+ case VBOXESC_CONFIGURETARGETS:
+ {
+ LOG(("=> VBOXESC_CONFIGURETARGETS"));
+
+ if (!pEscape->Flags.HardwareAccess)
{
- Status = vboxWddmChildStatusCheckByMask(pDevExt, pInfos, pData->ScreenMask);
- if (!NT_SUCCESS(Status))
+ WARN(("VBOXESC_CONFIGURETARGETS called without HardwareAccess flag set, failing"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+#ifdef VBOX_DISPIF_WITH_OPCONTEXT
+ /* win8.1 does not allow context-based escapes for display-only mode */
+ PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
+ if (!pContext)
+ {
+ WARN(("VBOXESC_CONFIGURETARGETS no context supplied!"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE)
+ {
+ WARN(("VBOXESC_CONFIGURETARGETS invalid context supplied %d!", pContext->enmType));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+#endif
+
+ if (pEscape->PrivateDriverDataSize != sizeof (*pEscapeHdr))
+ {
+ WARN(("VBOXESC_CONFIGURETARGETS invalid private driver size %d", pEscape->PrivateDriverDataSize));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ if (pEscapeHdr->u32CmdSpecific)
+ {
+ WARN(("VBOXESC_CONFIGURETARGETS invalid command %d", pEscapeHdr->u32CmdSpecific));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ HANDLE hKey = NULL;
+ WCHAR aNameBuf[100];
+ uint32_t cAdjusted = 0;
+
+ for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
+ {
+ VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[i];
+ if (pTarget->fConfigured)
+ continue;
+
+ pTarget->fConfigured = true;
+
+ if (!pTarget->fConnected)
{
- WARN(("vboxWddmChildStatusCheckByMask failed, Status 0x%x", Status));
+ Status = vboxWddmChildStatusConnect(pDevExt, (uint32_t)i, TRUE);
+ if (NT_SUCCESS(Status))
+ ++cAdjusted;
+ else
+ WARN(("VBOXESC_CONFIGURETARGETS vboxWddmChildStatusConnectSecondaries failed Status 0x%x\n", Status));
}
+
+ if (!hKey)
+ {
+ Status = IoOpenDeviceRegistryKey(pDevExt->pPDO, PLUGPLAY_REGKEY_DRIVER, GENERIC_WRITE, &hKey);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("VBOXESC_CONFIGURETARGETS IoOpenDeviceRegistryKey failed, Status = 0x%x", Status));
+ hKey = NULL;
+ continue;
+ }
+ }
+
+ Assert(hKey);
+
+ swprintf(aNameBuf, L"%s%d", VBOXWDDM_REG_DRV_DISPFLAGS_PREFIX, i);
+ Status = vboxWddmRegSetValueDword(hKey, aNameBuf, VBOXWDDM_CFG_DRVTARGET_CONNECTED);
+ if (!NT_SUCCESS(Status))
+ WARN(("VBOXESC_CONFIGURETARGETS vboxWddmRegSetValueDword (%d) failed Status 0x%x\n", aNameBuf, Status));
+
+ }
+
+ if (hKey)
+ {
+ NTSTATUS tmpStatus = ZwClose(hKey);
+ Assert(tmpStatus == STATUS_SUCCESS);
}
+
+ pEscapeHdr->u32CmdSpecific = cAdjusted;
+
+ Status = STATUS_SUCCESS;
+
+ LOG(("<= VBOXESC_CONFIGURETARGETS"));
break;
}
case VBOXESC_ADJUSTVIDEOMODES:
@@ -4212,11 +4512,57 @@ DxgkDdiEscape(
PVBOXDISPIFESCAPE_ADJUSTVIDEOMODES pPodesInfo = (PVBOXDISPIFESCAPE_ADJUSTVIDEOMODES)pEscapeHdr;
VBoxWddmAdjustModes(pDevExt, cModes, pPodesInfo->aScreenInfos);
Status = STATUS_SUCCESS;
+ break;
+ }
+ case VBOXESC_SETALLOCHOSTID:
+ {
+ PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)pEscape->hDevice;
+ if (!pDevice)
+ {
+ WARN(("VBOXESC_SETALLOCHOSTID called without no device specified, failing"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_SETALLOCHOSTID))
+ {
+ WARN(("invalid buffer size for VBOXDISPIFESCAPE_SHRC_REF, was(%d), but expected (%d)",
+ pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE_SHRC_REF)));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ PVBOXDISPIFESCAPE_SETALLOCHOSTID pSetHostID = (PVBOXDISPIFESCAPE_SETALLOCHOSTID)pEscapeHdr;
+ PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromHandle(pDevExt, (D3DKMT_HANDLE)pSetHostID->hAlloc);
+ if (!pAlloc)
+ {
+ WARN(("failed to get allocation from handle"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ if (pAlloc->enmType != VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
+ {
+ WARN(("setHostID: invalid allocation type: %d", pAlloc->enmType));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ pSetHostID->rc = VBoxWddmOaSetHostID(pDevice, pAlloc, pSetHostID->hostID, &pSetHostID->EscapeHdr.u32CmdSpecific);
+ Status = STATUS_SUCCESS;
+ break;
}
case VBOXESC_SHRC_ADDREF:
case VBOXESC_SHRC_RELEASE:
{
PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)pEscape->hDevice;
+ if (!pDevice)
+ {
+ WARN(("VBOXESC_SHRC_ADDREF|VBOXESC_SHRC_RELEASE called without no device specified, failing"));
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
/* query whether the allocation represanted by the given [wine-generated] shared resource handle still exists */
if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_SHRC_REF))
{
@@ -4282,7 +4628,7 @@ DxgkDdiEscape(
}
PVBOXDISPIFESCAPE_ISANYX pIsAnyX = (PVBOXDISPIFESCAPE_ISANYX)pEscapeHdr;
- pIsAnyX->u32IsAnyX = pDevExt->fAnyX;
+ pIsAnyX->u32IsAnyX = VBoxCommonFromDeviceExt(pDevExt)->fAnyX;
Status = STATUS_SUCCESS;
break;
}
@@ -4313,15 +4659,13 @@ DxgkDdiEscape(
break;
}
default:
- Assert(0);
- LOGREL(("unsupported escape code (0x%x)", pEscapeHdr->escapeCode));
+ WARN(("unsupported escape code (0x%x)", pEscapeHdr->escapeCode));
break;
}
}
else
{
- LOGREL(("pEscape->PrivateDriverDataSize(%d) < (%d)", pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE)));
- AssertBreakpoint();
+ WARN(("pEscape->PrivateDriverDataSize(%d) < (%d)", pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE)));
Status = STATUS_BUFFER_TOO_SMALL;
}
@@ -4356,14 +4700,34 @@ typedef struct VBOXWDDM_QUERYCURFENCE_CB
static BOOLEAN vboxWddmQueryCurrentFenceCb(PVOID Context)
{
PVBOXWDDM_QUERYCURFENCE_CB pdc = (PVBOXWDDM_QUERYCURFENCE_CB)Context;
- BOOL bRc = DxgkDdiInterruptRoutine(pdc->pDevExt, pdc->MessageNumber);
- pdc->uLastCompletedCmdFenceId = pdc->pDevExt->u.primary.Vdma.uLastCompletedPagingBufferCmdFenceId;
+ PVBOXMP_DEVEXT pDevExt = pdc->pDevExt;
+ BOOL bRc = DxgkDdiInterruptRoutineLegacy(pDevExt, pdc->MessageNumber);
+ pdc->uLastCompletedCmdFenceId = pDevExt->u.primary.Vdma.uLastCompletedPagingBufferCmdFenceId;
return bRc;
}
-NTSTATUS
+static NTSTATUS
+APIENTRY
+DxgkDdiQueryCurrentFenceNew(
+ CONST HANDLE hAdapter,
+ DXGKARG_QUERYCURRENTFENCE* pCurrentFence)
+{
+ LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
+
+ vboxVDbgBreakF();
+
+ PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
+ pCurrentFence->CurrentFence = VBoxCmdVbvaCheckCompleted(pDevExt, &pDevExt->CmdVbva, false);
+
+ LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
+
+ return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
APIENTRY
-DxgkDdiQueryCurrentFence(
+DxgkDdiQueryCurrentFenceLegacy(
CONST HANDLE hAdapter,
DXGKARG_QUERYCURRENTFENCE* pCurrentFence)
{
@@ -4407,7 +4771,6 @@ DxgkDdiIsSupportedVidPn(
vboxVDbgBreakFv();
NTSTATUS Status = STATUS_SUCCESS;
- BOOLEAN bSupported = TRUE;
PVBOXMP_DEVEXT pContext = (PVBOXMP_DEVEXT)hAdapter;
const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
@@ -4431,23 +4794,18 @@ DxgkDdiIsSupportedVidPn(
return Status;
}
- VBOXVIDPNPATHITEM aItems[VBOX_VIDEO_MAX_SCREENS];
- BOOLEAN fDisabledFound = FALSE;
- Status = vboxVidPnCheckTopology(hVidPnTopology, pVidPnTopologyInterface, TRUE /* fBreakOnDisabled */, RT_ELEMENTS(aItems), aItems, &fDisabledFound);
- Assert(Status == STATUS_SUCCESS);
+ BOOLEAN fSupported = FALSE;
+ Status = vboxVidPnCheckTopology(hVidPnTopology, pVidPnTopologyInterface, &fSupported);
if (!NT_SUCCESS(Status))
{
WARN(("vboxVidPnCheckTopology failed Status()0x%x\n", Status));
return Status;
}
- if (fDisabledFound)
- {
+ if (!fSupported)
LOG(("found unsupported path"));
- bSupported = FALSE;
- }
- pIsSupportedVidPnArg->IsVidPnSupported = bSupported;
+ pIsSupportedVidPnArg->IsVidPnSupported = fSupported;
#ifdef VBOXWDDM_DEBUG_VIDPN
LOGREL(("The Given VidPn is %ssupported\n", pIsSupportedVidPnArg->IsVidPnSupported ? "" : "!!NOT!! "));
@@ -4472,11 +4830,15 @@ DxgkDdiRecommendFunctionalVidPn(
vboxVDbgBreakFv();
+#ifdef DEBUG_misha
+ Assert(0);
+#endif
+
PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
NTSTATUS Status;
PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo = pRecommendFunctionalVidPnArg->PrivateDriverDataSize >= sizeof (VBOXWDDM_RECOMMENDVIDPN) ?
(PVBOXWDDM_RECOMMENDVIDPN)pRecommendFunctionalVidPnArg->pPrivateDriverData : NULL;
- PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateAllVideoModesInfos(pDevExt);
+ PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmGetAllVideoModesInfos(pDevExt);
int i;
for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
@@ -4621,26 +4983,25 @@ DxgkDdiEnumVidPnCofuncModality(
return Status;
}
- VBOXVIDPNPATHITEM aItems[VBOX_VIDEO_MAX_SCREENS];
- Status = vboxVidPnCheckTopology(hVidPnTopology, pVidPnTopologyInterface, FALSE /* fBreakOnDisabled */, RT_ELEMENTS(aItems), aItems, NULL /* *pfDisabledFound */);
- Assert(Status == STATUS_SUCCESS);
+#ifdef DEBUG_misha
+ BOOLEAN fSupported = FALSE;
+ Status = vboxVidPnCheckTopology(hVidPnTopology, pVidPnTopologyInterface, &fSupported);
if (!NT_SUCCESS(Status))
{
WARN(("vboxVidPnCheckTopology failed Status()0x%x\n", Status));
return Status;
}
+ Assert(fSupported);
+#endif
VBOXVIDPNCOFUNCMODALITY CbContext = {0};
CbContext.pDevExt = pDevExt;
CbContext.pVidPnInterface = pVidPnInterface;
CbContext.pEnumCofuncModalityArg = pEnumCofuncModalityArg;
CbContext.pInfos = VBoxWddmGetAllVideoModesInfos(pDevExt);
- CbContext.cPathInfos = RT_ELEMENTS(aItems);
- CbContext.apPathInfos = aItems;
Status = vboxVidPnEnumPaths(hVidPnTopology, pVidPnTopologyInterface,
vboxVidPnCofuncModalityPathEnum, &CbContext);
- Assert(Status == STATUS_SUCCESS);
if (!NT_SUCCESS(Status))
{
WARN(("vboxVidPnEnumPaths failed Status()0x%x\n", Status));
@@ -4682,8 +5043,18 @@ DxgkDdiSetVidPnSourceAddress(
Assert((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceAddress->VidPnSourceId);
PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceAddress->VidPnSourceId];
- Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceAddress->VidPnSourceId, &pSource->VScreenPos);
+ POINT Pos;
+ Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceAddress->VidPnSourceId, &Pos);
Assert(Status == STATUS_SUCCESS);
+ if (NT_SUCCESS(Status))
+ {
+ if (memcmp(&pSource->VScreenPos, &Pos, sizeof (Pos)))
+ {
+ pSource->VScreenPos = Pos;
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
+ }
+ }
+
Status = STATUS_SUCCESS;
if ((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays <= pSetVidPnSourceAddress->VidPnSourceId)
@@ -4728,26 +5099,9 @@ DxgkDdiSetVidPnSourceAddress(
pSetVidPnSourceAddress->PrimaryAddress.QuadPart);
}
- pSource->bGhSynced = FALSE; /* force guest->host notification */
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
- if (pSource->bVisible
-#if defined(VBOXWDDM_RENDER_FROM_SHADOW)
- && (
-# if defined(VBOX_WDDM_WIN8)
- g_VBoxDisplayOnly
- ||
-# endif
- pDevExt->fRenderToShadowDisabled
- /* only update for UMD_RC_GENERIC when resolution changes to inform host about it
- * otherwise keep host using the same VRAM, containing a valid data before the switch (i.e. SHADOW) */
- || (pAllocation
- && pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC
- && (pAllocation->AllocData.SurfDesc.width != pSource->AllocData.SurfDesc.width
- || pAllocation->AllocData.SurfDesc.height != pSource->AllocData.SurfDesc.height)
- )
- )
-#endif
- )
+ if (pSource->bVisible)
{
vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
}
@@ -4776,8 +5130,17 @@ DxgkDdiSetVidPnSourceVisibility(
Assert((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceVisibility->VidPnSourceId);
PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceVisibility->VidPnSourceId];
- Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceVisibility->VidPnSourceId, &pSource->VScreenPos);
+ POINT Pos;
+ Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceVisibility->VidPnSourceId, &Pos);
Assert(Status == STATUS_SUCCESS);
+ if (NT_SUCCESS(Status))
+ {
+ if (memcmp(&pSource->VScreenPos, &Pos, sizeof (Pos)))
+ {
+ pSource->VScreenPos = Pos;
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
+ }
+ }
Status = STATUS_SUCCESS;
if ((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays <= pSetVidPnSourceVisibility->VidPnSourceId)
@@ -4793,24 +5156,7 @@ DxgkDdiSetVidPnSourceVisibility(
if (pSource->bVisible != pSetVidPnSourceVisibility->Visible)
{
pSource->bVisible = pSetVidPnSourceVisibility->Visible;
- if (pSource->bVisible
-#if defined(VBOXWDDM_RENDER_FROM_SHADOW)
- && (
-# if defined(VBOX_WDDM_WIN8)
- g_VBoxDisplayOnly
- ||
-# endif
- pDevExt->fRenderToShadowDisabled
- /* only update for UMD_RC_GENERIC when resolution changes to inform host about it
- * otherwise keep host using the same VRAM, containing a valid data before the switch (i.e. SHADOW) */
- || (pAllocation
- && pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC
- && (pAllocation->AllocData.SurfDesc.width != pSource->AllocData.SurfDesc.width
- || pAllocation->AllocData.SurfDesc.height != pSource->AllocData.SurfDesc.height)
- )
- )
-#endif
- )
+ if (pSource->bVisible)
{
vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
}
@@ -4831,7 +5177,6 @@ static DECLCALLBACK(BOOLEAN) vboxWddmVidPnCleanupTargetsForSrcEnum(PVBOXMP_DEVEX
return TRUE;
}
-
NTSTATUS
APIENTRY
DxgkDdiCommitVidPn(
@@ -4842,24 +5187,10 @@ DxgkDdiCommitVidPn(
LOGF(("ENTER, context(0x%x)", hAdapter));
PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
- uint32_t au32OldHeightVisible[VBOX_VIDEO_MAX_SCREENS];
NTSTATUS Status;
vboxVDbgBreakFv();
- /* we first store the current visible height for each target (monitor)
- * and then we will zero up it for targets either for the given source
- * (in case pCommitVidPnArg->AffectedVidPnSourceId != D3DDDI_ID_ALL)
- * or all targets otherwize.
- * In the end we will match the old and new visible height for all targets to see if
- * some of them become inactivated and hide them accordingly,
- * or we will restore the old height values on failure */
- for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
- {
- PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
- au32OldHeightVisible[i] = pTarget->HeightVisible;
- }
-
do {
const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPnArg->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
@@ -4895,7 +5226,7 @@ DxgkDdiCommitVidPn(
break;
}
- /* this will zero up visible height for all targets of the fiven source, see above comment */
+ /* this will zero up visible height for all targets of the given source, see above comment */
Status = vboxVidPnEnumTargetsForSource(pDevExt, hVidPnTopology, pVidPnTopologyInterface,
pCommitVidPnArg->AffectedVidPnSourceId,
vboxWddmVidPnCleanupTargetsForSrcEnum, NULL);
@@ -4966,43 +5297,26 @@ DxgkDdiCommitVidPn(
Assert(NT_SUCCESS(Status));
pDevExt->u.primary.hCommittedVidPn = pCommitVidPnArg->hFunctionalVidPn;
- for (int i = 1; /* <- never try to hide a primary monitor */
- i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
+ for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
{
PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
- if (!pTarget->HeightVisible && !!au32OldHeightVisible[i])
- {
- /* the target was previously visible */
- vboxWddmGhDisplayHideScreen(pDevExt, i);
- }
- }
-
-#ifdef VBOX_WDDM_WIN8
- if (g_VBoxDisplayOnly)
- {
- for (int i = 0; /* <- never try to hide a primary monitor */
- i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
+ PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
+ uint32_t cAutoresizes = pDevExt->cContextsDispIfResize;
+ if (!cAutoresizes)
{
- PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
- if (pSource->bVisible && !pSource->bGhSynced)
- {
+ if (pSource->bVisible || !pTarget->HeightVisible)
vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
- }
}
+ else
+ pTarget->fStateSyncPening = true;
}
-#endif
+
LOGF(("LEAVE, SUCCESS status(0x%x), context(0x%x)", Status, hAdapter));
return Status;
} while (0);
AssertRelease(!NT_SUCCESS(Status));
- /* failure branch restore original visible height values, see comments above */
- for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
- {
- PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
- pTarget->HeightVisible = au32OldHeightVisible[i];
- }
LOGF(("LEAVE, !!FAILURE!! status(0x%x), context(0x%x)", Status, hAdapter));
return Status;
@@ -5139,7 +5453,7 @@ DxgkDdiControlInterrupt(
{
LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
switch (InterruptType)
@@ -5147,7 +5461,9 @@ DxgkDdiControlInterrupt(
case DXGK_INTERRUPT_CRTC_VSYNC:
{
Status = VBoxWddmSlEnableVSyncNotification(pDevExt, Enable);
- if (!NT_SUCCESS(Status))
+ if (NT_SUCCESS(Status))
+ Status = STATUS_SUCCESS; /* <- sanity */
+ else
WARN(("VSYNC Interrupt control failed Enable(%d), Status(0x%x)", Enable, Status));
break;
}
@@ -5243,15 +5559,17 @@ DxgkDdiOpenAllocation(
PVBOXWDDM_RCINFO pRcInfo = NULL;
if (pOpenAllocation->PrivateDriverSize)
{
- Assert(pOpenAllocation->PrivateDriverSize == sizeof (VBOXWDDM_RCINFO));
Assert(pOpenAllocation->pPrivateDriverData);
- if (pOpenAllocation->PrivateDriverSize >= sizeof (VBOXWDDM_RCINFO))
+ if (pOpenAllocation->PrivateDriverSize == sizeof (VBOXWDDM_RCINFO))
{
pRcInfo = (PVBOXWDDM_RCINFO)pOpenAllocation->pPrivateDriverData;
Assert(pRcInfo->cAllocInfos == pOpenAllocation->NumAllocations);
}
else
+ {
+ WARN(("Invalid PrivateDriverSize %d", pOpenAllocation->PrivateDriverSize));
Status = STATUS_INVALID_PARAMETER;
+ }
}
if (Status == STATUS_SUCCESS)
@@ -5387,26 +5705,24 @@ DxgkDdiCloseAllocation(
return STATUS_SUCCESS;
}
-NTSTATUS
+static NTSTATUS
APIENTRY
-DxgkDdiRender(
+DxgkDdiRenderNew(
CONST HANDLE hContext,
DXGKARG_RENDER *pRender)
{
// LOGF(("ENTER, hContext(0x%x)", hContext));
- Assert(pRender->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
- if (pRender->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
+ if (pRender->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_HDR))
{
- LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
- pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
+ WARN(("pRender->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_HDR (%d)",
+ pRender->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_HDR)));
/* @todo: can this actually happen? what status to return? */
return STATUS_INVALID_PARAMETER;
}
if (pRender->CommandLength < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
{
- Assert(0);
- LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
+ WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
/* @todo: can this actually happen? what status to return? */
return STATUS_INVALID_PARAMETER;
@@ -5414,87 +5730,249 @@ DxgkDdiRender(
PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pInputHdr = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pCommand;
NTSTATUS Status = STATUS_SUCCESS;
+
+ uint32_t cbBuffer = 0;
+ uint32_t cbCmdDma = 0;
+ VBOXCMDVBVA_HDR* pCmd = (VBOXCMDVBVA_HDR*)pRender->pDmaBufferPrivateData;
+
switch (pInputHdr->enmCmd)
{
case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
{
- if (pRender->CommandLength != RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pInputHdr->u32CmdReserved]))
+ if (pRender->AllocationListSize >= (UINT32_MAX - RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos))/ RT_SIZEOFMEMB(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[0]))
{
- Assert(0);
+ WARN(("Invalid AllocationListSize %d", pRender->AllocationListSize));
return STATUS_INVALID_PARAMETER;
}
- PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD pUmCmd = (PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD)pInputHdr;
- PVBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD pChromiumCmd = (PVBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD)pRender->pDmaBufferPrivateData;
- const uint32_t cbDma = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD, aBufInfos[pInputHdr->u32CmdReserved]);
- if (pRender->DmaBufferPrivateDataSize < cbDma)
+
+ if (pRender->CommandLength != RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pRender->AllocationListSize]))
{
- Assert(0);
+ WARN(("pRender->CommandLength (%d) != RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pRender->AllocationListSize](%d)",
+ pRender->CommandLength, RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pRender->AllocationListSize])));
return STATUS_INVALID_PARAMETER;
}
- if (pRender->DmaSize < cbDma)
+
+ if (pRender->AllocationListSize >= (UINT32_MAX - RT_OFFSETOF(VBOXCMDVBVA_CRCMD, Cmd.aBuffers))/ RT_SIZEOFMEMB(VBOXCMDVBVA_CRCMD, Cmd.aBuffers[0]))
{
- Assert(0);
+ WARN(("Invalid AllocationListSize %d", pRender->AllocationListSize));
return STATUS_INVALID_PARAMETER;
}
- if (pRender->PatchLocationListOutSize < pInputHdr->u32CmdReserved)
+ cbBuffer = RT_OFFSETOF(VBOXCMDVBVA_CRCMD, Cmd.aBuffers[pRender->AllocationListSize]);
+ if (cbBuffer > 4096)
{
- Assert(0);
+ /* this should not be bigger actually */
+ WARN(("too big command buffer %d", cbBuffer));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ cbCmdDma = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
+
+ if (pRender->DmaBufferPrivateDataSize < cbBuffer)
+ {
+ WARN(("pRender->DmaBufferPrivateDataSize too small %d, requested %d", pRender->DmaBufferPrivateDataSize, cbBuffer));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (pRender->DmaSize < cbCmdDma)
+ {
+ WARN(("dma buffer %d too small", pRender->DmaSize));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Assert(pRender->PatchLocationListOutSize == pRender->AllocationListSize);
+
+ if (pRender->PatchLocationListOutSize < pRender->AllocationListSize)
+ {
+ WARN(("pRender->PatchLocationListOutSize too small %d, requested %d", pRender->PatchLocationListOutSize, pRender->AllocationListSize));
return STATUS_INVALID_PARAMETER;
}
+ PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD pUmCmd = (PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD)pInputHdr;
+ VBOXCMDVBVA_CRCMD* pChromiumCmd = (VBOXCMDVBVA_CRCMD*)pRender->pDmaBufferPrivateData;
+
PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
- pChromiumCmd->Base.enmCmd = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
- pChromiumCmd->Base.u32CmdReserved = pInputHdr->u32CmdReserved;
- pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + cbDma;
- pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + cbDma;
- D3DDDI_PATCHLOCATIONLIST* pPLL = pRender->pPatchLocationListOut;
- memset(pPLL, 0, sizeof (*pPLL) * pChromiumCmd->Base.u32CmdReserved);
- pRender->pPatchLocationListOut += pInputHdr->u32CmdReserved;
- PVBOXWDDM_UHGSMI_BUFFER_SUBMIT_INFO pSubmInfo = pChromiumCmd->aBufInfos;
- PVBOXWDDM_UHGSMI_BUFFER_UI_SUBMIT_INFO pSubmUmInfo = pUmCmd->aBufInfos;
+ pChromiumCmd->Hdr.u8OpCode = VBOXCMDVBVA_OPTYPE_CRCMD;
+ pChromiumCmd->Hdr.u8Flags = 0;
+ pChromiumCmd->Cmd.cBuffers = pRender->AllocationListSize;
+
DXGK_ALLOCATIONLIST *pAllocationList = pRender->pAllocationList;
- for (UINT i = 0; i < pChromiumCmd->Base.u32CmdReserved; ++i)
+ VBOXCMDVBVA_CRCMD_BUFFER *pSubmInfo = pChromiumCmd->Cmd.aBuffers;
+ PVBOXWDDM_UHGSMI_BUFFER_UI_SUBMIT_INFO pSubmUmInfo = pUmCmd->aBufInfos;
+
+ for (UINT i = 0; i < pRender->AllocationListSize; ++i, ++pRender->pPatchLocationListOut, ++pAllocationList, ++pSubmInfo, ++pSubmUmInfo)
{
+ D3DDDI_PATCHLOCATIONLIST* pPLL = pRender->pPatchLocationListOut;
PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pAllocationList);
- vboxWddmPopulateDmaAllocInfoWithOffset(&pSubmInfo->Alloc, pAlloc, pAllocationList, pSubmUmInfo->offData);
+ if (pSubmUmInfo->offData >= pAlloc->AllocData.SurfDesc.cbSize
+ || pSubmUmInfo->cbData > pAlloc->AllocData.SurfDesc.cbSize
+ || pSubmUmInfo->offData + pSubmUmInfo->cbData > pAlloc->AllocData.SurfDesc.cbSize)
+ {
+ WARN(("invalid data"));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ memset(pPLL, 0, sizeof (*pPLL));
+
+ if (pAllocationList->SegmentId)
+ pSubmInfo->offBuffer = pAllocationList->PhysicalAddress.LowPart + pSubmUmInfo->offData;
- pSubmInfo->cbData = pSubmUmInfo->cbData;
- pSubmInfo->bDoNotSignalCompletion = pSubmUmInfo->bDoNotSignalCompletion;
+ pSubmInfo->cbBuffer = pSubmUmInfo->cbData;
pPLL->AllocationIndex = i;
- pPLL->PatchOffset = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD, aBufInfos[i].Alloc);
+ pPLL->PatchOffset = RT_OFFSETOF(VBOXCMDVBVA_CRCMD, Cmd.aBuffers[i].offBuffer);
pPLL->AllocationOffset = pSubmUmInfo->offData;
-
- ++pPLL;
- ++pSubmInfo;
- ++pSubmUmInfo;
- ++pAllocationList;
}
break;
}
case VBOXVDMACMD_TYPE_DMA_NOP:
{
- PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pDmaBufferPrivateData;
- pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
+ cbBuffer = sizeof (VBOXCMDVBVA_HDR);
+ cbCmdDma = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
+
+ if (pRender->DmaBufferPrivateDataSize < cbBuffer)
+ {
+ WARN(("pRender->DmaBufferPrivateDataSize too small %d, requested %d", pRender->DmaBufferPrivateDataSize, cbBuffer));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (pRender->DmaSize < cbCmdDma)
+ {
+ WARN(("dma buffer %d too small", pRender->DmaSize));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ pCmd->u8OpCode = VBOXCMDVBVA_OPTYPE_NOPCMD;
+ pCmd->u8Flags = 0;
+
+ for (UINT i = 0; i < pRender->AllocationListSize; ++i, ++pRender->pPatchLocationListOut)
+ {
+ D3DDDI_PATCHLOCATIONLIST* pPLL = pRender->pPatchLocationListOut;
+ memset(pPLL, 0, sizeof (*pPLL));
+ pPLL->AllocationIndex = i;
+ pPLL->PatchOffset = ~0UL;
+ pPLL->AllocationOffset = 0;
+ }
- pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR);
- pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + pRender->CommandLength;
- Assert(pRender->DmaSize >= pRender->CommandLength);
- Assert(pRender->PatchLocationListOutSize >= pRender->PatchLocationListInSize);
- UINT cbPLL = pRender->PatchLocationListInSize * sizeof (pRender->pPatchLocationListOut[0]);
- memcpy(pRender->pPatchLocationListOut, pRender->pPatchLocationListIn, cbPLL);
- pRender->pPatchLocationListOut += pRender->PatchLocationListInSize;
break;
}
default:
+ {
+ WARN(("unsupported render command %d", pInputHdr->enmCmd));
return STATUS_INVALID_PARAMETER;
+ }
}
+ pRender->pDmaBufferPrivateData = ((uint8_t*)pRender->pDmaBufferPrivateData) + cbBuffer;
+ pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + cbCmdDma;
+
+ pCmd->u8State = VBOXCMDVBVA_STATE_SUBMITTED;
+ /* sanity */
+ pCmd->u32FenceID = 0;
+
+// LOGF(("LEAVE, hContext(0x%x)", hContext));
+
+ return STATUS_SUCCESS;
+}
+
+static void vboxWddmPatchLocationInit(D3DDDI_PATCHLOCATIONLIST *pPatchLocationListOut, UINT idx, UINT offPatch)
+{
+ memset(pPatchLocationListOut, 0, sizeof (*pPatchLocationListOut));
+ pPatchLocationListOut->AllocationIndex = idx;
+ pPatchLocationListOut->PatchOffset = offPatch;
+}
+
+static NTSTATUS
+APIENTRY
+DxgkDdiRenderLegacy(
+ CONST HANDLE hContext,
+ DXGKARG_RENDER *pRender)
+{
+// LOGF(("ENTER, hContext(0x%x)", hContext));
+
+ Assert(pRender->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
+ if (pRender->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
+ {
+ WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
+ pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
+ return STATUS_INVALID_PARAMETER;
+ }
+ if (pRender->CommandLength < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
+ {
+ WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
+ pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
+ return STATUS_INVALID_PARAMETER;
+ }
+ if (pRender->DmaSize < pRender->CommandLength)
+ {
+ WARN(("pRender->DmaSize(%d) < pRender->CommandLength(%d)",
+ pRender->DmaSize, pRender->CommandLength));
+ return STATUS_INVALID_PARAMETER;
+ }
+ if (pRender->PatchLocationListOutSize < pRender->PatchLocationListInSize)
+ {
+ WARN(("pRender->PatchLocationListOutSize(%d) < pRender->PatchLocationListInSize(%d)",
+ pRender->PatchLocationListOutSize, pRender->PatchLocationListInSize));
+ return STATUS_INVALID_PARAMETER;
+ }
+ if (pRender->AllocationListSize != pRender->PatchLocationListInSize)
+ {
+ WARN(("pRender->AllocationListSize(%d) != pRender->PatchLocationListInSize(%d)",
+ pRender->AllocationListSize, pRender->PatchLocationListInSize));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ __try
+ {
+ PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pInputHdr = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pCommand;
+ switch (pInputHdr->enmCmd)
+ {
+ case VBOXVDMACMD_TYPE_DMA_NOP:
+ {
+ PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pDmaBufferPrivateData;
+ pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
+ pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR);
+ pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + pRender->CommandLength;
+ for (UINT i = 0; i < pRender->PatchLocationListInSize; ++i)
+ {
+ UINT offPatch = i * 4;
+ if (offPatch + 4 > pRender->CommandLength)
+ {
+ WARN(("wrong offPatch"));
+ return STATUS_INVALID_PARAMETER;
+ }
+ if (offPatch != pRender->pPatchLocationListIn[i].PatchOffset)
+ {
+ WARN(("wrong PatchOffset"));
+ return STATUS_INVALID_PARAMETER;
+ }
+ if (i != pRender->pPatchLocationListIn[i].AllocationIndex)
+ {
+ WARN(("wrong AllocationIndex"));
+ return STATUS_INVALID_PARAMETER;
+ }
+ vboxWddmPatchLocationInit(&pRender->pPatchLocationListOut[i], i, offPatch);
+ }
+ break;
+ }
+ default:
+ {
+ WARN(("unsupported command %d", pInputHdr->enmCmd));
+ return STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ WARN(("invalid parameter"));
+ }
// LOGF(("LEAVE, hContext(0x%x)", hContext));
return Status;
@@ -5536,12 +6014,27 @@ DECLINLINE(BOOLEAN) vboxWddmPixFormatConversionSupported(D3DDDIFORMAT From, D3DD
return From == To;
}
+DECLINLINE(bool) VBoxCVDdiFillAllocInfo(VBOXCMDVBVA_HDR* pHdr,
+ VBOXCMDVBVA_ALLOCINFO *pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pList, bool fDst)
+{
+ if (pAlloc->AllocData.hostID)
+ {
+ pHdr->u8Flags |= (fDst ? VBOXCMDVBVA_OPF_ALLOC_DSTID : VBOXCMDVBVA_OPF_ALLOC_SRCID);
+ pInfo->u.id = pAlloc->AllocData.hostID;
+ return false;
+ }
+
+ Assert(!pList->PhysicalAddress.HighPart);
+ pInfo->u.offVRAM = pList->PhysicalAddress.LowPart;
+ return true;
+}
+
/**
* DxgkDdiPresent
*/
-NTSTATUS
+static NTSTATUS
APIENTRY
-DxgkDdiPresent(
+DxgkDdiPresentNew(
CONST HANDLE hContext,
DXGKARG_PRESENT *pPresent)
{
@@ -5551,24 +6044,32 @@ DxgkDdiPresent(
vboxVDbgBreakFv();
- NTSTATUS Status = STATUS_SUCCESS;
PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
- Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR));
- if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR))
+ if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_HDR))
{
- LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)));
- /* @todo: can this actually happen? what status tu return? */
+ WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_HDR (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_HDR)));
+ /* @todo: can this actually happen? what status to return? */
return STATUS_INVALID_PARAMETER;
}
- PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)pPresent->pDmaBufferPrivateData;
- pPrivateData->BaseHdr.fFlags.Value = 0;
- uint32_t cContexts3D = ASMAtomicReadU32(&pDevExt->cContexts3D);
- uint32_t cContexts2D = ASMAtomicReadU32(&pDevExt->cContexts2D);
-#define VBOXWDDM_DUMMY_DMABUFFER_SIZE sizeof(RECT)
+ VBOXCMDVBVA_HDR* pHdr = (VBOXCMDVBVA_HDR*)pPresent->pDmaBufferPrivateData;
+
+ UINT u32SrcPatch = ~0UL;
+ UINT u32DstPatch = ~0UL;
+ BOOLEAN fPatchSrc = false;
+ BOOLEAN fPatchDst = false;
+ VBOXCMDVBVA_RECT *paRects = NULL;
+ uint32_t cbMaxRects;
+
+ if (pPresent->DmaSize < VBOXWDDM_DUMMY_DMABUFFER_SIZE)
+ {
+ WARN(("Present->DmaSize(%d) < VBOXWDDM_DUMMY_DMABUFFER_SIZE (%d)", pPresent->DmaSize , VBOXWDDM_DUMMY_DMABUFFER_SIZE));
+ /* @todo: can this actually happen? what status to return? */
+ return STATUS_INVALID_PARAMETER;
+ }
if (pPresent->Flags.Blt)
{
@@ -5576,348 +6077,348 @@ DxgkDdiPresent(
DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
- Assert(pSrcAlloc);
- if (pSrcAlloc)
+ if (!pSrcAlloc)
{
- PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
- Assert(pDstAlloc);
- if (pDstAlloc)
- {
- do
- {
-#ifdef VBOXWDDM_RENDER_FROM_SHADOW
-#if 0
- Assert (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE);
- Assert (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
-#else
- if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM)
- {
- Assert ((pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE
- && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
- || (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
- && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE));
- }
-#endif
- /* issue VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE ONLY in case there are no 3D contexts currently
- * otherwise we would need info about all rects being updated on primary for visible rect reporting */
- if (!cContexts3D && !cContexts2D)
- {
- if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
- && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
- {
- Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
- Assert(pDstAlloc->bAssigned);
- if (pDstAlloc->bAssigned)
- {
-#ifdef VBOX_WITH_VIDEOHWACCEL
-// if (vboxVhwaHlpOverlayListIsEmpty(pDevExt, pDstAlloc->AllocData.SurfDesc.VidPnSourceId))
-#endif
- {
- Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY));
- if (pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY))
- {
- Assert(pPresent->SrcRect.left == pPresent->DstRect.left);
- Assert(pPresent->SrcRect.right == pPresent->DstRect.right);
- Assert(pPresent->SrcRect.top == pPresent->DstRect.top);
- Assert(pPresent->SrcRect.bottom == pPresent->DstRect.bottom);
- RECT rect;
- if (pPresent->SubRectCnt)
- {
- rect = pPresent->pDstSubRects[0];
- for (UINT i = 1; i < pPresent->SubRectCnt; ++i)
- {
- vboxWddmRectUnited(&rect, &rect, &pPresent->pDstSubRects[i]);
- }
- }
- else
- rect = pPresent->SrcRect;
-
-
- pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY);
- pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
- Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
- memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
- pPresent->pPatchLocationListOut->PatchOffset = 0;
- pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
- ++pPresent->pPatchLocationListOut;
- pPresent->pPatchLocationListOut->PatchOffset = 4;
- pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
- ++pPresent->pPatchLocationListOut;
-
- pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY;
- PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateData;
- /* we do not know the shadow address yet, perform dummy DMA cycle */
- vboxWddmPopulateDmaAllocInfo(&pS2P->Shadow2Primary.ShadowAlloc, pSrcAlloc, pSrc);
-// vboxWddmPopulateDmaAllocInfo(&pPrivateData->DstAllocInfo, pDstAlloc, pDst);
- pS2P->Shadow2Primary.SrcRect = rect;
- pS2P->Shadow2Primary.VidPnSourceId = pDstAlloc->AllocData.SurfDesc.VidPnSourceId;
- break;
- }
- else
- {
- Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
- break;
- }
- }
- }
- }
- }
+ /* this should not happen actually */
+ WARN(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
+ return STATUS_INVALID_HANDLE;
+ }
- /* we're here because this is NOT a shadow->primary update
- * or because there are d3d contexts and we need to report visible rects
- * or because we have overlays active and we need a special handling for primary */
-#endif
- UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
- pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
-
- PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
-
- vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.SrcAlloc, pSrcAlloc, pSrc);
- vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.DstAlloc, pDstAlloc, pDst);
-
- ASSERT_WARN(!pSrcAlloc->fRcFlags.SharedResource, ("Shared Allocatoin used in Present!"));
-
- pBlt->Blt.SrcRect = pPresent->SrcRect;
- pBlt->Blt.DstRects.ContextRect = pPresent->DstRect;
- pBlt->Blt.DstRects.UpdateRects.cRects = 0;
- UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_BLT, Blt.DstRects.UpdateRects.aRects[0]);
- Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
- UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
- pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
- pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
- Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
- cbCmd -= cbHead;
- Assert(cbCmd < UINT32_MAX/2);
- Assert(cbCmd > sizeof (RECT));
- if (cbCmd >= cbRects)
- {
- cbCmd -= cbRects;
- memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
- pBlt->Blt.DstRects.UpdateRects.cRects += cbRects/sizeof (RECT);
- }
- else
- {
- UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
- Assert(cbFitingRects);
- memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
- cbCmd -= cbFitingRects;
- pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
- pBlt->Blt.DstRects.UpdateRects.cRects += cbFitingRects/sizeof (RECT);
- Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
- Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
- }
+ PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
+ if (!pDstAlloc)
+ {
+ /* this should not happen actually */
+ WARN(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
+ return STATUS_INVALID_HANDLE;
+ }
- memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
- pPresent->pPatchLocationListOut->PatchOffset = 0;
- pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
- ++pPresent->pPatchLocationListOut;
- pPresent->pPatchLocationListOut->PatchOffset = 4;
- pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
- ++pPresent->pPatchLocationListOut;
+ fPatchSrc = TRUE;
+ fPatchDst = TRUE;
- break;
-#ifdef VBOX_WITH_VDMA
- cbCmd = pPresent->DmaSize;
-
- Assert(pPresent->SubRectCnt);
- UINT cmdSize = VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(pPresent->SubRectCnt - pPresent->MultipassOffset);
- PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pPresent->pDmaBuffer;
- pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cmdSize;
- Assert(cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE());
- if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
- {
- if (vboxWddmPixFormatConversionSupported(pSrcAlloc->AllocData.SurfDesc.format, pDstAlloc->AllocData.SurfDesc.format))
- {
- memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
- // pPresent->pPatchLocationListOut->PatchOffset = 0;
- // ++pPresent->pPatchLocationListOut;
- pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
- pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
- ++pPresent->pPatchLocationListOut;
- pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
- pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
- ++pPresent->pPatchLocationListOut;
-
- pCmd->enmType = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
- pCmd->u32CmdSpecific = 0;
- PVBOXVDMACMD_DMA_PRESENT_BLT pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
- pTransfer->offSrc = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
- pTransfer->offDst = (VBOXVIDEOOFFSET)pDst->PhysicalAddress.QuadPart;
- vboxWddmSurfDescFromAllocation(pSrcAlloc, &pTransfer->srcDesc);
- vboxWddmSurfDescFromAllocation(pDstAlloc, &pTransfer->dstDesc);
- vboxWddmRectlFromRect(&pPresent->SrcRect, &pTransfer->srcRectl);
- vboxWddmRectlFromRect(&pPresent->DstRect, &pTransfer->dstRectl);
- UINT i = 0;
- cbCmd -= VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects);
- Assert(cbCmd >= sizeof (VBOXVDMA_RECTL));
- Assert(cbCmd < pPresent->DmaSize);
- for (; i < pPresent->SubRectCnt; ++i)
- {
- if (cbCmd < sizeof (VBOXVDMA_RECTL))
- {
- Assert(i);
- pPresent->MultipassOffset += i;
- Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
- break;
- }
- vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
- cbCmd -= sizeof (VBOXVDMA_RECTL);
- }
- Assert(i);
- pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
- pTransfer->cDstSubRects = i;
- pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR);
- }
- else
- {
- AssertBreakpoint();
- LOGREL(("unsupported format conversion from(%d) to (%d)",pSrcAlloc->AllocData.SurfDesc.format, pDstAlloc->AllocData.SurfDesc.format));
- Status = STATUS_GRAPHICS_CANNOTCOLORCONVERT;
- }
- }
- else
- {
- /* this should not happen actually */
- LOGREL(("cbCmd too small!! (%d)", cbCmd));
- Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
- }
-#endif
- } while(0);
- }
- else
+ BOOLEAN fDstPrimary = (!pDstAlloc->AllocData.hostID
+ && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
+ && pDstAlloc->bAssigned);
+ BOOLEAN fSrcPrimary = (!pSrcAlloc->AllocData.hostID
+ && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
+ && pSrcAlloc->bAssigned);
+
+ pHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_BLT_OFFPRIMSZFMT_OR_ID;
+ pHdr->u8Flags = 0;
+
+ if (fDstPrimary || fSrcPrimary)
+ {
+ if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_BLT_PRIMARY))
{
- /* this should not happen actually */
- LOGREL(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
- Status = STATUS_INVALID_HANDLE;
+ WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_BLT_PRIMARY (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_BLT_PRIMARY)));
+ /* @todo: can this actually happen? what status to return? */
+ return STATUS_INVALID_PARAMETER;
}
- }
- else
- {
- /* this should not happen actually */
- LOGREL(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
- Status = STATUS_INVALID_HANDLE;
- }
-#if 0
- UINT cbCmd = pPresent->DmaSize;
-
- Assert(pPresent->SubRectCnt);
- UINT cmdSize = VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(pPresent->SubRectCnt - pPresent->MultipassOffset);
- PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pPresent->pDmaBuffer;
- pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cmdSize;
- Assert(cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE());
- if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
- {
- DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
- DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
- PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
- Assert(pSrcAlloc);
- if (pSrcAlloc)
+
+ VBOXCMDVBVA_BLT_PRIMARY *pBlt = (VBOXCMDVBVA_BLT_PRIMARY*)pHdr;
+
+ /* this is the most common case, so we optimize it a bit with VBOXCMDVBVA_BLT_PRIMARY */
+
+ if (fSrcPrimary)
{
- PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
- Assert(pDstAlloc);
- if (pDstAlloc)
- {
- if (vboxWddmPixFormatConversionSupported(pSrcAlloc->AllocData.SurfDesc.format, pDstAlloc->AllocData.SurfDesc.format))
- {
- memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
-// pPresent->pPatchLocationListOut->PatchOffset = 0;
-// ++pPresent->pPatchLocationListOut;
- pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
- pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
- ++pPresent->pPatchLocationListOut;
- pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
- pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
- ++pPresent->pPatchLocationListOut;
-
- pCmd->enmType = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
- pCmd->u32CmdSpecific = 0;
- PVBOXVDMACMD_DMA_PRESENT_BLT pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
- pTransfer->offSrc = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
- pTransfer->offDst = (VBOXVIDEOOFFSET)pDst->PhysicalAddress.QuadPart;
- vboxWddmSurfDescFromAllocation(pSrcAlloc, &pTransfer->srcDesc);
- vboxWddmSurfDescFromAllocation(pDstAlloc, &pTransfer->dstDesc);
- vboxWddmRectlFromRect(&pPresent->SrcRect, &pTransfer->srcRectl);
- vboxWddmRectlFromRect(&pPresent->DstRect, &pTransfer->dstRectl);
- UINT i = 0;
- cbCmd -= VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects);
- Assert(cbCmd >= sizeof (VBOXVDMA_RECTL));
- Assert(cbCmd < pPresent->DmaSize);
- for (; i < pPresent->SubRectCnt; ++i)
- {
- if (cbCmd < sizeof (VBOXVDMA_RECTL))
- {
- Assert(i);
- pPresent->MultipassOffset += i;
- Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
- break;
- }
- vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
- cbCmd -= sizeof (VBOXVDMA_RECTL);
- }
- Assert(i);
- pTransfer->cDstSubRects = i;
- pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_HDR);
- }
- else
- {
- AssertBreakpoint();
- LOGREL(("unsupported format conversion from(%d) to (%d)",pSrcAlloc->AllocData.SurfDesc.format, pDstAlloc->AllocData.SurfDesc.format));
- Status = STATUS_GRAPHICS_CANNOTCOLORCONVERT;
- }
- }
- else
+ pBlt->Hdr.u8Flags |= VBOXCMDVBVA_OPF_ALLOC_SRCPRIMARY;
+ pBlt->Hdr.u.u8PrimaryID = pSrcAlloc->AllocData.SurfDesc.VidPnSourceId;
+
+ if (fDstPrimary)
{
- /* this should not happen actually */
- LOGREL(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
- Status = STATUS_INVALID_HANDLE;
+ pBlt->Hdr.u8Flags |= VBOXCMDVBVA_OPF_ALLOC_DSTPRIMARY;
+ pBlt->alloc.u.id = pDstAlloc->AllocData.SurfDesc.VidPnSourceId;
}
+ else if (VBoxCVDdiFillAllocInfo(pHdr, &pBlt->alloc, pDstAlloc, pDst, true))
+ u32DstPatch = RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, alloc.u.offVRAM);
}
else
{
- /* this should not happen actually */
- LOGREL(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
- Status = STATUS_INVALID_HANDLE;
+ Assert(fDstPrimary);
+ pBlt->Hdr.u8Flags |= VBOXCMDVBVA_OPF_ALLOC_DSTPRIMARY;
+ pBlt->Hdr.u.u8PrimaryID = pDstAlloc->AllocData.SurfDesc.VidPnSourceId;
+
+ if (VBoxCVDdiFillAllocInfo(pHdr, &pBlt->alloc, pSrcAlloc, pSrc, false))
+ u32SrcPatch = RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, alloc.u.offVRAM);
}
+
+ pBlt->Pos.x = (int16_t)(pPresent->DstRect.left - pPresent->SrcRect.left);
+ pBlt->Pos.y = (int16_t)(pPresent->DstRect.top - pPresent->SrcRect.top);
+
+ paRects = pBlt->aRects;
+ cbMaxRects = pPresent->DmaBufferPrivateDataSize - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects);
}
else
{
- /* this should not happen actually */
- LOGREL(("cbCmd too small!! (%d)", cbCmd));
- Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
+ if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
+ {
+ WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID)));
+ /* @todo: can this actually happen? what status to return? */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pBlt = (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID*)pHdr;
+
+ if (VBoxCVDdiFillAllocInfo(pHdr, &pBlt->src, pSrcAlloc, pSrc, false))
+ u32SrcPatch = RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, src.u.offVRAM);
+
+ if (VBoxCVDdiFillAllocInfo(pHdr, &pBlt->dst, pDstAlloc, pDst, true))
+ u32DstPatch = RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, dst.u.offVRAM);
+
+ pBlt->Pos.x = (int16_t)(pPresent->DstRect.left - pPresent->SrcRect.left);
+ pBlt->Pos.y = (int16_t)(pPresent->DstRect.top - pPresent->SrcRect.top);
+
+ paRects = pBlt->aRects;
+ cbMaxRects = pPresent->DmaBufferPrivateDataSize - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects);
}
-#endif
}
else if (pPresent->Flags.Flip)
{
+ if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_FLIP))
+ {
+ WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_FLIP (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_FLIP)));
+ /* @todo: can this actually happen? what status to return? */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ fPatchSrc = TRUE;
+
Assert(pPresent->Flags.Value == 4); /* only Blt is set, we do not support anything else for now */
Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
- Assert(pSrcAlloc);
- if (pSrcAlloc)
+
+ if (!pSrcAlloc)
{
- Assert(cContexts3D);
- pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP;
- PVBOXWDDM_DMA_PRIVATEDATA_FLIP pFlip = (PVBOXWDDM_DMA_PRIVATEDATA_FLIP)pPrivateData;
+ /* this should not happen actually */
+ WARN(("failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
+ return STATUS_INVALID_HANDLE;
+ }
- vboxWddmPopulateDmaAllocInfo(&pFlip->Flip.Alloc, pSrcAlloc, pSrc);
+ Assert(pDevExt->cContexts3D);
+ pHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_FLIP;
+ pHdr->u8Flags = 0;
+ VBOXCMDVBVA_FLIP *pFlip = (VBOXCMDVBVA_FLIP*)pHdr;
- UINT cbCmd = sizeof (VBOXWDDM_DMA_PRIVATEDATA_FLIP);
- pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbCmd;
- pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
- Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
+ if (VBoxCVDdiFillAllocInfo(pHdr, &pFlip->src, pSrcAlloc, pSrc, false))
+ u32SrcPatch = RT_OFFSETOF(VBOXCMDVBVA_FLIP, src.u.offVRAM);
+ }
+ else if (pPresent->Flags.ColorFill)
+ {
+ if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_CLRFILL))
+ {
+ WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_CLRFILL (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_CLRFILL)));
+ /* @todo: can this actually happen? what status to return? */
+ return STATUS_INVALID_PARAMETER;
+ }
- memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
- pPresent->pPatchLocationListOut->PatchOffset = 0;
- pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
- ++pPresent->pPatchLocationListOut;
+ fPatchDst = TRUE;
+
+ Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D);
+ Assert(pPresent->Flags.Value == 2); /* only ColorFill is set, we do not support anything else for now */
+ DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
+ PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
+ if (!pDstAlloc)
+ {
+ /* this should not happen actually */
+ WARN(("failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
+ return STATUS_INVALID_HANDLE;
+ }
+
+ pHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_CLRFILL;
+ pHdr->u8Flags = 0;
+ VBOXCMDVBVA_CLRFILL *pCFill = (VBOXCMDVBVA_CLRFILL*)pHdr;
+
+ if (VBoxCVDdiFillAllocInfo(pHdr, &pCFill->dst, pDstAlloc, pDst, true))
+ u32DstPatch = RT_OFFSETOF(VBOXCMDVBVA_CLRFILL, dst.u.offVRAM);
+
+ paRects = pCFill->aRects;
+ cbMaxRects = pPresent->DmaBufferPrivateDataSize - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL, aRects);
+ }
+ else
+ {
+ WARN(("cmd NOT IMPLEMENTED!! Flags(0x%x)", pPresent->Flags.Value));
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ if (paRects)
+ {
+ UINT iStartRect = pPresent->MultipassOffset;
+ UINT cMaxRects = cbMaxRects / sizeof (VBOXCMDVBVA_RECT);
+ Assert(pPresent->SubRectCnt > iStartRect);
+ UINT cRects = pPresent->SubRectCnt - iStartRect;
+ if (cRects > cMaxRects)
+ {
+ pPresent->MultipassOffset += cMaxRects;
+ cRects = cMaxRects;
}
else
+ pPresent->MultipassOffset = 0;
+
+ const RECT *paDstSubRects = &pPresent->pDstSubRects[iStartRect];
+ VBoxCVDdiPackRects(paRects, paDstSubRects, cRects);
+ }
+
+ if (fPatchSrc)
+ {
+ memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
+ pPresent->pPatchLocationListOut->PatchOffset = u32SrcPatch;
+ pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
+ ++pPresent->pPatchLocationListOut;
+ }
+
+ if (fPatchDst)
+ {
+ memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
+ pPresent->pPatchLocationListOut->PatchOffset = u32DstPatch;
+ pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
+ ++pPresent->pPatchLocationListOut;
+ }
+
+ pHdr->u8State = VBOXCMDVBVA_STATE_SUBMITTED;
+ /* sanity */
+ pHdr->u32FenceID = 0;
+
+ pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
+
+ if (pPresent->MultipassOffset)
+ return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
+ return STATUS_SUCCESS;
+}
+
+/**
+ * DxgkDdiPresent
+ */
+static NTSTATUS
+APIENTRY
+DxgkDdiPresentLegacy(
+ CONST HANDLE hContext,
+ DXGKARG_PRESENT *pPresent)
+{
+ PAGED_CODE();
+
+// LOGF(("ENTER, hContext(0x%x)", hContext));
+
+ vboxVDbgBreakFv();
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
+ PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
+ PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
+
+ Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR));
+ if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR))
+ {
+ LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)));
+ /* @todo: can this actually happen? what status tu return? */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)pPresent->pDmaBufferPrivateData;
+ pPrivateData->BaseHdr.fFlags.Value = 0;
+ uint32_t cContexts2D = ASMAtomicReadU32(&pDevExt->cContexts2D);
+
+ if (pPresent->Flags.Blt)
+ {
+ Assert(pPresent->Flags.Value == 1); /* only Blt is set, we do not support anything else for now */
+ DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
+ DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
+ PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
+ if (!pSrcAlloc)
{
/* this should not happen actually */
- LOGREL(("failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
+ WARN(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
Status = STATUS_INVALID_HANDLE;
+ goto done;
}
+
+ PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
+ if (!pDstAlloc)
+ {
+ /* this should not happen actually */
+ WARN(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
+ Status = STATUS_INVALID_HANDLE;
+ goto done;
+ }
+
+
+ UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
+ pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
+
+ PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
+
+ vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.SrcAlloc, pSrcAlloc, pSrc);
+ vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.DstAlloc, pDstAlloc, pDst);
+
+ ASSERT_WARN(!pSrcAlloc->fRcFlags.SharedResource, ("Shared Allocatoin used in Present!"));
+
+ pBlt->Blt.SrcRect = pPresent->SrcRect;
+ pBlt->Blt.DstRects.ContextRect = pPresent->DstRect;
+ pBlt->Blt.DstRects.UpdateRects.cRects = 0;
+ UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_BLT, Blt.DstRects.UpdateRects.aRects[0]);
+ Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
+ UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
+ pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
+ pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
+ Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
+ cbCmd -= cbHead;
+ Assert(cbCmd < UINT32_MAX/2);
+ Assert(cbCmd > sizeof (RECT));
+ if (cbCmd >= cbRects)
+ {
+ cbCmd -= cbRects;
+ memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], &pPresent->pDstSubRects[pPresent->MultipassOffset], cbRects);
+ pBlt->Blt.DstRects.UpdateRects.cRects += cbRects/sizeof (RECT);
+ }
+ else
+ {
+ UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
+ Assert(cbFitingRects);
+ memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], &pPresent->pDstSubRects[pPresent->MultipassOffset], cbFitingRects);
+ cbCmd -= cbFitingRects;
+ pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
+ pBlt->Blt.DstRects.UpdateRects.cRects += cbFitingRects/sizeof (RECT);
+ Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
+ Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
+ }
+
+ memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
+ pPresent->pPatchLocationListOut->PatchOffset = 0;
+ pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
+ ++pPresent->pPatchLocationListOut;
+ pPresent->pPatchLocationListOut->PatchOffset = 4;
+ pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
+ ++pPresent->pPatchLocationListOut;
+ }
+ else if (pPresent->Flags.Flip)
+ {
+ Assert(pPresent->Flags.Value == 4); /* only Blt is set, we do not support anything else for now */
+ Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
+ DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
+ PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
+
+ if (!pSrcAlloc)
+ {
+ /* this should not happen actually */
+ WARN(("failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
+ Status = STATUS_INVALID_HANDLE;
+ goto done;
+ }
+
+ Assert(pDevExt->cContexts3D);
+ pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP;
+ PVBOXWDDM_DMA_PRIVATEDATA_FLIP pFlip = (PVBOXWDDM_DMA_PRIVATEDATA_FLIP)pPrivateData;
+
+ vboxWddmPopulateDmaAllocInfo(&pFlip->Flip.Alloc, pSrcAlloc, pSrc);
+
+ UINT cbCmd = sizeof (VBOXWDDM_DMA_PRIVATEDATA_FLIP);
+ pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbCmd;
+ pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
+ Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
+
+ memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
+ pPresent->pPatchLocationListOut->PatchOffset = 0;
+ pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
+ ++pPresent->pPatchLocationListOut;
}
else if (pPresent->Flags.ColorFill)
{
@@ -5925,63 +6426,62 @@ DxgkDdiPresent(
Assert(pPresent->Flags.Value == 2); /* only ColorFill is set, we do not support anything else for now */
DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
- Assert(pDstAlloc);
- if (pDstAlloc)
+ if (!pDstAlloc)
{
- UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
- pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL;
- PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateData;
-
- vboxWddmPopulateDmaAllocInfo(&pCF->ClrFill.Alloc, pDstAlloc, pDst);
- pCF->ClrFill.Color = pPresent->Color;
- pCF->ClrFill.Rects.cRects = 0;
- UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CLRFILL, ClrFill.Rects.aRects[0]);
- Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
- UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
- pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
- pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
- Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
- cbCmd -= cbHead;
- Assert(cbCmd < UINT32_MAX/2);
- Assert(cbCmd > sizeof (RECT));
- if (cbCmd >= cbRects)
- {
- cbCmd -= cbRects;
- memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
- pCF->ClrFill.Rects.cRects += cbRects/sizeof (RECT);
- }
- else
- {
- UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
- Assert(cbFitingRects);
- memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
- cbCmd -= cbFitingRects;
- pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
- pCF->ClrFill.Rects.cRects += cbFitingRects/sizeof (RECT);
- Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
- Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
- }
+ /* this should not happen actually */
+ WARN(("failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
+ Status = STATUS_INVALID_HANDLE;
+ goto done;
+ }
- memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
- pPresent->pPatchLocationListOut->PatchOffset = 0;
- pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
- ++pPresent->pPatchLocationListOut;
+ UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
+ pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL;
+ PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateData;
+
+ vboxWddmPopulateDmaAllocInfo(&pCF->ClrFill.Alloc, pDstAlloc, pDst);
+
+ pCF->ClrFill.Color = pPresent->Color;
+ pCF->ClrFill.Rects.cRects = 0;
+ UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CLRFILL, ClrFill.Rects.aRects[0]);
+ Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
+ UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
+ pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
+ pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
+ Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
+ cbCmd -= cbHead;
+ Assert(cbCmd < UINT32_MAX/2);
+ Assert(cbCmd > sizeof (RECT));
+ if (cbCmd >= cbRects)
+ {
+ cbCmd -= cbRects;
+ memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
+ pCF->ClrFill.Rects.cRects += cbRects/sizeof (RECT);
}
else
{
- /* this should not happen actually */
- LOGREL(("failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
- Status = STATUS_INVALID_HANDLE;
+ UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
+ Assert(cbFitingRects);
+ memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
+ cbCmd -= cbFitingRects;
+ pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
+ pCF->ClrFill.Rects.cRects += cbFitingRects/sizeof (RECT);
+ Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
+ Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
}
+ memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
+ pPresent->pPatchLocationListOut->PatchOffset = 0;
+ pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
+ ++pPresent->pPatchLocationListOut;
}
else
{
- LOGREL(("cmd NOT IMPLEMENTED!! Flags(0x%x)", pPresent->Flags.Value));
- AssertBreakpoint();
+ WARN(("cmd NOT IMPLEMENTED!! Flags(0x%x)", pPresent->Flags.Value));
+ Status = STATUS_NOT_SUPPORTED;
}
+done:
// LOGF(("LEAVE, hContext(0x%x), Status(0x%x)", hContext, Status));
return Status;
@@ -6100,10 +6600,20 @@ DxgkDdiCreateContext(
pContext->enmType = VBOXWDDM_CONTEXT_TYPE_SYSTEM;
for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
{
- pDevExt->aSources[i].bGhSynced = FALSE;
+ pDevExt->aSources[i].u8SyncState = 0;
NTSTATUS tmpStatus= vboxWddmDisplaySettingsQueryPos(pDevExt, i, &pDevExt->aSources[i].VScreenPos);
Assert(tmpStatus == STATUS_SUCCESS);
}
+
+ if (!VBOXWDDM_IS_DISPLAYONLY() && pDevExt->f3DEnabled)
+ {
+ VBoxMpCrPackerInit(&pContext->CrPacker);
+ int rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &pContext->u32CrConClientID);
+ if (!RT_SUCCESS(rc))
+ WARN(("VBoxMpCrCtlConConnect failed rc (%d), ignoring for system context", rc));
+ }
+
+ Status = STATUS_SUCCESS;
}
else
{
@@ -6130,20 +6640,31 @@ DxgkDdiCreateContext(
Assert(Status == STATUS_SUCCESS);
if (Status == STATUS_SUCCESS)
{
- int rc = VINF_SUCCESS;
if (pInfo->crVersionMajor || pInfo->crVersionMinor)
{
- rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon,
- pInfo->crVersionMajor, pInfo->crVersionMinor,
- &pContext->u32CrConClientID);
- if (!RT_SUCCESS(rc))
+ if (pDevExt->f3DEnabled)
+ {
+ int rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon,
+ pInfo->crVersionMajor, pInfo->crVersionMinor,
+ &pContext->u32CrConClientID);
+ if (RT_SUCCESS(rc))
+ {
+ VBoxMpCrPackerInit(&pContext->CrPacker);
+ }
+ else
+ {
+ WARN(("VBoxMpCrCtlConConnect failed rc (%d)", rc));
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ }
+ else
{
- WARN(("VBoxMpCrCtlConConnect failed rc (%d)", rc));
+ LOG(("3D Not Enabled, failing 3D context creation"));
Status = STATUS_UNSUCCESSFUL;
}
}
- if (RT_SUCCESS(rc))
+ if (NT_SUCCESS(Status))
{
ASMAtomicIncU32(&pDevExt->cContexts3D);
break;
@@ -6164,20 +6685,27 @@ DxgkDdiCreateContext(
Assert(Status == STATUS_SUCCESS);
if (Status == STATUS_SUCCESS)
{
- int rc = VINF_SUCCESS;
if (pInfo->crVersionMajor || pInfo->crVersionMinor)
{
- rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon,
- pInfo->crVersionMajor, pInfo->crVersionMinor,
- &pContext->u32CrConClientID);
- if (!RT_SUCCESS(rc))
+ if (pDevExt->f3DEnabled)
{
- WARN(("VBoxMpCrCtlConConnect failed rc (%d)", rc));
+ int rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon,
+ pInfo->crVersionMajor, pInfo->crVersionMinor,
+ &pContext->u32CrConClientID);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("VBoxMpCrCtlConConnect failed rc (%d)", rc));
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ }
+ else
+ {
+ LOG(("3D Not Enabled, failing 3D (hgsmi) context creation"));
Status = STATUS_UNSUCCESSFUL;
}
}
- if (RT_SUCCESS(rc))
+ if (NT_SUCCESS(Status))
{
ASMAtomicIncU32(&pDevExt->cContexts3D);
break;
@@ -6192,9 +6720,25 @@ DxgkDdiCreateContext(
ASMAtomicIncU32(&pDevExt->cContexts2D);
break;
}
+ case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE:
+ {
+ pContext->enmType = pInfo->enmType;
+ ASMAtomicIncU32(&pDevExt->cContextsDispIfResize);
+ break;
+ }
+ case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS:
+ {
+ pContext->enmType = pInfo->enmType;
+ Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->SeamlessCtxMgr, &pContext->CmContext, (HANDLE)pInfo->hUmEvent, pInfo->u64UmInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxVideoCmCtxAdd failed, Status 0x%x", Status));
+ }
+ break;
+ }
default:
{
- Assert(0);
+ WARN(("unsupported context type %d", pInfo->enmType));
Status = STATUS_INVALID_PARAMETER;
break;
}
@@ -6235,6 +6779,8 @@ DxgkDdiDestroyContext(
vboxVDbgBreakFv();
PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
PVBOXMP_DEVEXT pDevExt = pContext->pDevice->pAdapter;
+ NTSTATUS Status = STATUS_SUCCESS;
+
switch(pContext->enmType)
{
case VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D:
@@ -6243,10 +6789,6 @@ DxgkDdiDestroyContext(
{
uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContexts3D);
Assert(cContexts < UINT32_MAX/2);
- if (pContext->u32CrConClientID)
- {
- VBoxMpCrCtlConDisconnect(&pDevExt->CrCtlCon, pContext->u32CrConClientID);
- }
break;
}
case VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D:
@@ -6255,10 +6797,37 @@ DxgkDdiDestroyContext(
Assert(cContexts < UINT32_MAX/2);
break;
}
+ case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE:
+ {
+ uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContextsDispIfResize);
+ Assert(cContexts < UINT32_MAX/2);
+ if (!cContexts)
+ {
+ for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
+ {
+ vboxWddmGhDisplayCheckCompletePeningScreenInfo(pDevExt, i);
+ }
+ }
+ break;
+ }
+ case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS:
+ {
+ Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->SeamlessCtxMgr, &pContext->CmContext);
+ if (!NT_SUCCESS(Status))
+ WARN(("vboxVideoCmCtxRemove failed, Status 0x%x", Status));
+
+ Assert(pContext->CmContext.pSession == NULL);
+ break;
+ }
default:
break;
}
+ if (pContext->u32CrConClientID)
+ {
+ VBoxMpCrCtlConDisconnect(&pDevExt->CrCtlCon, pContext->u32CrConClientID);
+ }
+
vboxWddmModeRenderFromShadowDisableUnregister(pDevExt, pContext);
/* first terminate the swapchain, this will also ensure
@@ -6266,17 +6835,17 @@ DxgkDdiDestroyContext(
* (i.e. visible regions commands) are completed */
vboxWddmSwapchainCtxTerm(pDevExt, pContext);
- NTSTATUS Status = vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
+ Status = vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
+ if (NT_SUCCESS(Status))
{
Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->CmMgr, &pContext->CmContext);
- Assert(Status == STATUS_SUCCESS);
- if (Status == STATUS_SUCCESS)
- {
+ if (NT_SUCCESS(Status))
vboxWddmMemFree(pContext);
- }
+ else
+ WARN(("vboxVideoCmCtxRemove failed, Status 0x%x", Status));
}
+ else
+ WARN(("vboxVideoAMgrCtxDestroy failed, Status 0x%x", Status));
LOGF(("LEAVE, hContext(0x%x)", hContext));
@@ -6380,6 +6949,8 @@ static NTSTATUS APIENTRY DxgkDdiPresentDisplayOnly(
SrcAllocData.SurfDesc.cbSize = ~0UL;
SrcAllocData.Addr.SegmentId = 0;
SrcAllocData.Addr.pvMem = pPresentDisplayOnly->pSource;
+ SrcAllocData.hostID = 0;
+ SrcAllocData.pSwapchain = NULL;
RECT UpdateRect;
BOOLEAN bUpdateRectInited = FALSE;
@@ -6528,8 +7099,8 @@ static NTSTATUS vboxWddmInitDisplayOnlyDriver(IN PDRIVER_OBJECT pDriverObject, I
DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
- DriverInitializationData.DxgkDdiInterruptRoutine = DxgkDdiInterruptRoutine;
- DriverInitializationData.DxgkDdiDpcRoutine = DxgkDdiDpcRoutine;
+ DriverInitializationData.DxgkDdiInterruptRoutine = DxgkDdiInterruptRoutineLegacy;
+ DriverInitializationData.DxgkDdiDpcRoutine = DxgkDdiDpcRoutineLegacy;
DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
@@ -6575,8 +7146,10 @@ static NTSTATUS vboxWddmInitDisplayOnlyDriver(IN PDRIVER_OBJECT pDriverObject, I
}
#endif
-static NTSTATUS vboxWddmInitFullGraphicsDriver(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
+static NTSTATUS vboxWddmInitFullGraphicsDriver(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath, BOOLEAN fCmdVbva)
{
+#define VBOXWDDM_CALLBACK_NAME(_base, _fCmdVbva) ((_fCmdVbva) ? _base##New : _base##Legacy)
+
DRIVER_INITIALIZATION_DATA DriverInitializationData = {'\0'};
// Fill in the DriverInitializationData structure and call DxgkInitialize()
@@ -6587,8 +7160,8 @@ static NTSTATUS vboxWddmInitFullGraphicsDriver(IN PDRIVER_OBJECT pDriverObject,
DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
- DriverInitializationData.DxgkDdiInterruptRoutine = DxgkDdiInterruptRoutine;
- DriverInitializationData.DxgkDdiDpcRoutine = DxgkDdiDpcRoutine;
+ DriverInitializationData.DxgkDdiInterruptRoutine = VBOXWDDM_CALLBACK_NAME(DxgkDdiInterruptRoutine, fCmdVbva);
+ DriverInitializationData.DxgkDdiDpcRoutine = VBOXWDDM_CALLBACK_NAME(DxgkDdiDpcRoutine, fCmdVbva);
DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
@@ -6607,10 +7180,10 @@ static NTSTATUS vboxWddmInitFullGraphicsDriver(IN PDRIVER_OBJECT pDriverObject,
DriverInitializationData.DxgkDdiGetStandardAllocationDriverData = DxgkDdiGetStandardAllocationDriverData;
DriverInitializationData.DxgkDdiAcquireSwizzlingRange = DxgkDdiAcquireSwizzlingRange;
DriverInitializationData.DxgkDdiReleaseSwizzlingRange = DxgkDdiReleaseSwizzlingRange;
- DriverInitializationData.DxgkDdiPatch = DxgkDdiPatch;
- DriverInitializationData.DxgkDdiSubmitCommand = DxgkDdiSubmitCommand;
- DriverInitializationData.DxgkDdiPreemptCommand = DxgkDdiPreemptCommand;
- DriverInitializationData.DxgkDdiBuildPagingBuffer = DxgkDdiBuildPagingBuffer;
+ DriverInitializationData.DxgkDdiPatch = VBOXWDDM_CALLBACK_NAME(DxgkDdiPatch, fCmdVbva);
+ DriverInitializationData.DxgkDdiSubmitCommand = VBOXWDDM_CALLBACK_NAME(DxgkDdiSubmitCommand, fCmdVbva);
+ DriverInitializationData.DxgkDdiPreemptCommand = VBOXWDDM_CALLBACK_NAME(DxgkDdiPreemptCommand, fCmdVbva);
+ DriverInitializationData.DxgkDdiBuildPagingBuffer = VBOXWDDM_CALLBACK_NAME(DxgkDdiBuildPagingBuffer, fCmdVbva);
DriverInitializationData.DxgkDdiSetPalette = DxgkDdiSetPalette;
DriverInitializationData.DxgkDdiSetPointerPosition = DxgkDdiSetPointerPosition;
DriverInitializationData.DxgkDdiSetPointerShape = DxgkDdiSetPointerShape;
@@ -6618,7 +7191,7 @@ static NTSTATUS vboxWddmInitFullGraphicsDriver(IN PDRIVER_OBJECT pDriverObject,
DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
DriverInitializationData.DxgkDdiEscape = DxgkDdiEscape;
DriverInitializationData.DxgkDdiCollectDbgInfo = DxgkDdiCollectDbgInfo;
- DriverInitializationData.DxgkDdiQueryCurrentFence = DxgkDdiQueryCurrentFence;
+ DriverInitializationData.DxgkDdiQueryCurrentFence = VBOXWDDM_CALLBACK_NAME(DxgkDdiQueryCurrentFence, fCmdVbva);
DriverInitializationData.DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
DriverInitializationData.DxgkDdiRecommendFunctionalVidPn = DxgkDdiRecommendFunctionalVidPn;
DriverInitializationData.DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality;
@@ -6636,8 +7209,8 @@ static NTSTATUS vboxWddmInitFullGraphicsDriver(IN PDRIVER_OBJECT pDriverObject,
DriverInitializationData.DxgkDdiDestroyDevice = DxgkDdiDestroyDevice;
DriverInitializationData.DxgkDdiOpenAllocation = DxgkDdiOpenAllocation;
DriverInitializationData.DxgkDdiCloseAllocation = DxgkDdiCloseAllocation;
- DriverInitializationData.DxgkDdiRender = DxgkDdiRender;
- DriverInitializationData.DxgkDdiPresent = DxgkDdiPresent;
+ DriverInitializationData.DxgkDdiRender = VBOXWDDM_CALLBACK_NAME(DxgkDdiRender, fCmdVbva);
+ DriverInitializationData.DxgkDdiPresent = VBOXWDDM_CALLBACK_NAME(DxgkDdiPresent, fCmdVbva);
DriverInitializationData.DxgkDdiUpdateOverlay = DxgkDdiUpdateOverlay;
DriverInitializationData.DxgkDdiFlipOverlay = DxgkDdiFlipOverlay;
@@ -6677,14 +7250,14 @@ DriverEntry(
vboxVDbgBreakFv();
-#ifdef DEBUG_misha
+#if 0//def DEBUG_misha
RTLogGroupSettings(0, "+default.e.l.f.l2.l3");
#endif
#ifdef VBOX_WDDM_WIN8
- LOGREL(("VBox WDDM Driver for Windows 8; Built %s %s", __DATE__, __TIME__));
+ LOGREL(("VBox WDDM Driver for Windows 8, %d bit; Built %s %s", (sizeof (void*) << 3), __DATE__, __TIME__));
#else
- LOGREL(("VBox WDDM Driver for Windows Vista and 7; Built %s %s", __DATE__, __TIME__));
+ LOGREL(("VBox WDDM Driver for Windows Vista and 7, %d bit; Built %s %s", (sizeof (void*) << 3), __DATE__, __TIME__));
#endif
if (! ARGUMENT_PRESENT(DriverObject) ||
@@ -6697,7 +7270,7 @@ DriverEntry(
ULONG major, minor, build;
BOOLEAN checkedBuild = PsGetVersion(&major, &minor, &build, NULL);
- BOOLEAN f3DCheckRequired = FALSE;
+ BOOLEAN f3DRequired = FALSE;
LOGREL(("OsVersion( %d, %d, %d )", major, minor, build));
@@ -6709,47 +7282,53 @@ DriverEntry(
if (major > 6)
{
WARN(("Unknow win version, newer major release, assuming 3D check is required"));
- f3DCheckRequired = TRUE;
+ f3DRequired = TRUE;
}
else if (major == 6)
{
- if (minor > 2)
+ if (minor > 3)
{
WARN(("Unknow win version, newer minor release, assuming 3D check is required"));
- f3DCheckRequired = TRUE;
+ f3DRequired = TRUE;
}
- else if (minor == 2)
+ else if (minor >= 2)
{
LOG(("3D check is required!"));
- f3DCheckRequired = TRUE;
+ f3DRequired = TRUE;
}
else
{
LOG(("3D is NOT required!"));
- f3DCheckRequired = FALSE;
+ f3DRequired = FALSE;
}
}
else
{
WARN(("Unsupported OLDER win version, ignore and assume 3D is NOT required"));
- f3DCheckRequired = FALSE;
+ f3DRequired = FALSE;
}
Status = STATUS_SUCCESS;
- if (f3DCheckRequired)
+ VBoxMpCrCtlConInit();
+
+ /* always need to do the check to request host caps */
+ LOG(("Doing the 3D check.."));
+ if (!VBoxMpCrCtlConIs3DSupported())
{
- LOG(("3D check is required, doing the 3D check.."));
- if (!VBoxMpCrCtlConIs3DSupported())
- {
#ifdef VBOX_WDDM_WIN8
- LOGREL(("3D is NOT supported by the host, falling back to display-only mode.."));
- g_VBoxDisplayOnly = 1;
+ Assert(f3DRequired);
+ LOGREL(("3D is NOT supported by the host, falling back to display-only mode.."));
+ g_VBoxDisplayOnly = 1;
#else
+ if (f3DRequired)
+ {
LOGREL(("3D is NOT supported by the host, but is required for the current guest version using this driver.."));
Status = STATUS_UNSUCCESSFUL;
-#endif
}
+ else
+ LOGREL(("3D is NOT supported by the host, but is NOT required for the current guest version using this driver, continuing with Disabled 3D.."));
+#endif
}
#if 0 //defined(DEBUG_misha) && defined(VBOX_WDDM_WIN8)
@@ -6760,8 +7339,8 @@ DriverEntry(
if (NT_SUCCESS(Status))
{
- Status = VBoxWddmVrInit();
- if (NT_SUCCESS(Status))
+ rc = VBoxVrInit();
+ if (RT_SUCCESS(rc))
{
#ifdef VBOX_WDDM_WIN8
if (g_VBoxDisplayOnly)
@@ -6771,16 +7350,19 @@ DriverEntry(
else
#endif
{
- Status = vboxWddmInitFullGraphicsDriver(DriverObject, RegistryPath);
+ Status = vboxWddmInitFullGraphicsDriver(DriverObject, RegistryPath, !!(VBoxMpCrGetHostCaps() & CR_VBOX_CAP_CMDVBVA));
}
if (NT_SUCCESS(Status))
return Status;
- VBoxWddmVrTerm();
+ VBoxVrTerm();
}
else
- WARN(("VBoxWddmVrInit failed, Status(0x%x)", Status));
+ {
+ WARN(("VBoxVrInit failed, rc(%d)", rc));
+ Status = STATUS_UNSUCCESSFUL;
+ }
}
else
LOGREL(("Aborting the video driver load due to 3D support missing"));
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.h
index bed17c57..ab50708e 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -36,13 +36,32 @@
//#define VBOXWDDM_DEBUG_VIDPN
+#define VBOXWDDM_CFG_DRV_DEFAULT 0
+#define VBOXWDDM_CFG_DRV_SECONDARY_TARGETS_CONNECTED 1
+
+#define VBOXWDDM_CFG_DRVTARGET_CONNECTED 1
+
#define VBOXWDDM_CFG_LOG_UM_BACKDOOR 0x00000001
#define VBOXWDDM_CFG_LOG_UM_DBGPRINT 0x00000002
#define VBOXWDDM_CFG_STR_LOG_UM L"VBoxLogUm"
+
+#define VBOXWDDM_REG_DRV_FLAGS_NAME L"VBoxFlags"
+#define VBOXWDDM_REG_DRV_DISPFLAGS_PREFIX L"VBoxDispFlags"
+
+#define VBOXWDDM_REG_DRVKEY_PREFIX L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\"
+
+#define VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\"
+#define VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY L"\\Video"
+
+
+#define VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_VISTA L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Control\\VIDEO\\"
+#define VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7 L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\UnitedVideo\\CONTROL\\VIDEO\\"
+
+#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELX L"Attach.RelativeX"
+#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELY L"Attach.RelativeY"
+#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_DESKTOP L"Attach.ToDesktop"
+
extern DWORD g_VBoxLogUm;
-#ifdef VBOX_WDDM_WIN8
-extern DWORD g_VBoxDisplayOnly;
-#endif
RT_C_DECLS_BEGIN
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
@@ -83,10 +102,14 @@ DECLINLINE(VOID) vboxWddmAllocationRetain(PVBOXWDDM_ALLOCATION pAllocation)
ASMAtomicIncU32(&pAllocation->cRefs);
}
-DECLINLINE(VOID) vboxWddmAddrSetVram(PVBOXWDDM_ADDR pAddr, UINT SegmentId, VBOXVIDEOOFFSET offVram)
+DECLINLINE(BOOLEAN) vboxWddmAddrSetVram(PVBOXWDDM_ADDR pAddr, UINT SegmentId, VBOXVIDEOOFFSET offVram)
{
+ if (pAddr->SegmentId == SegmentId && pAddr->offVram == offVram)
+ return FALSE;
+
pAddr->SegmentId = SegmentId;
pAddr->offVram = offVram;
+ return TRUE;
}
DECLINLINE(bool) vboxWddmAddrVramEqual(PVBOXWDDM_ADDR pAddr1, PVBOXWDDM_ADDR pAddr2)
@@ -104,6 +127,12 @@ DECLINLINE(VBOXVIDEOOFFSET) vboxWddmVramAddrToOffset(PVBOXMP_DEVEXT pDevExt, PHY
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
DECLINLINE(void) vboxWddmAssignShadow(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, PVBOXWDDM_ALLOCATION pAllocation, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
{
+ if (pDevExt->fCmdVbvaEnabled)
+ {
+ WARN(("Trying to assign shadow surface for CmdVbva enabled mode!"));
+ return;
+ }
+
if (pSource->pShadowAllocation == pAllocation)
{
Assert(pAllocation->bAssigned);
@@ -132,9 +161,18 @@ DECLINLINE(void) vboxWddmAssignShadow(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE p
pAllocation->bVisible = pSource->bVisible;
if(!vboxWddmAddrVramEqual(&pSource->AllocData.Addr, &pAllocation->AllocData.Addr))
- pSource->bGhSynced = FALSE; /* force guest->host notification */
- pSource->AllocData.Addr = pAllocation->AllocData.Addr;
+ {
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION; /* force guest->host notification */
+ pSource->AllocData.Addr = pAllocation->AllocData.Addr;
+ }
+ if (pSource->AllocData.hostID != pAllocation->AllocData.hostID)
+ {
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION; /* force guest->host notification */
+ pSource->AllocData.hostID = pAllocation->AllocData.hostID;
+ }
}
+ else
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION; /* force guest->host notification */
pSource->pShadowAllocation = pAllocation;
}
@@ -164,11 +202,20 @@ DECLINLINE(VOID) vboxWddmAssignPrimary(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE
pAllocation->bVisible = pSource->bVisible;
if(!vboxWddmAddrVramEqual(&pSource->AllocData.Addr, &pAllocation->AllocData.Addr))
- pSource->bGhSynced = FALSE; /* force guest->host notification */
- pSource->AllocData.Addr = pAllocation->AllocData.Addr;
+ {
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION; /* force guest->host notification */
+ pSource->AllocData.Addr = pAllocation->AllocData.Addr;
+ }
+ if (pSource->AllocData.hostID != pAllocation->AllocData.hostID)
+ {
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION; /* force guest->host notification */
+ pSource->AllocData.hostID = pAllocation->AllocData.hostID;
+ }
vboxWddmAllocationRetain(pAllocation);
}
+ else
+ pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION; /* force guest->host notification */
KIRQL OldIrql;
KeAcquireSpinLock(&pSource->AllocationLock, &OldIrql);
@@ -188,31 +235,60 @@ DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmAquirePrimary(PVBOXMP_DEVEXT pDevExt, P
return pPrimary;
}
+bool vboxWddmGhDisplayCheckSetInfoFromSource(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource);
+
#define VBOXWDDMENTRY_2_SWAPCHAIN(_pE) ((PVBOXWDDM_SWAPCHAIN)((uint8_t*)(_pE) - RT_OFFSETOF(VBOXWDDM_SWAPCHAIN, DevExtListEntry)))
+BOOLEAN DxgkDdiInterruptRoutineNew(
+ IN CONST PVOID MiniportDeviceContext,
+ IN ULONG MessageNumber
+ );
+
+#ifdef VBOX_WDDM_WIN8
+# define VBOXWDDM_IS_DISPLAYONLY() (g_VBoxDisplayOnly)
+#else
+# define VBOXWDDM_IS_DISPLAYONLY() (FALSE)
+#endif
+
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
-# ifdef VBOX_WDDM_WIN8
-# define VBOXWDDM_IS_FB_ALLOCATION(_pDevExt, _pAlloc) ( (_pAlloc)->bAssigned \
- && ( (_pAlloc)->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC \
+
+# define VBOXWDDM_IS_FB_ALLOCATION(_pDevExt, _pAlloc) ( (_pAlloc)->bAssigned \
+ && ( (_pAlloc)->AllocData.hostID \
|| (_pAlloc)->enmType == \
- ((g_VBoxDisplayOnly || (_pDevExt)->fRenderToShadowDisabled) ? VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE : VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE) \
+ ((VBOXWDDM_IS_DISPLAYONLY() || (_pDevExt)->fRenderToShadowDisabled) ? VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE : VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE) \
))
-# else
-# define VBOXWDDM_IS_FB_ALLOCATION(_pDevExt, _pAlloc) ( (_pAlloc)->bAssigned \
- && ( (_pAlloc)->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC \
- || (_pAlloc)->enmType == \
- (((_pDevExt)->fRenderToShadowDisabled) ? VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE : VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE) \
+
+# define VBOXWDDM_IS_REAL_FB_ALLOCATION(_pDevExt, _pAlloc) ( (_pAlloc)->bAssigned \
+ && ( (_pAlloc)->AllocData.hostID \
+ || (_pAlloc)->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE \
))
-# endif
+
# define VBOXWDDM_FB_ALLOCATION(_pDevExt, _pSrc) ( ((_pSrc)->pPrimaryAllocation && VBOXWDDM_IS_FB_ALLOCATION(_pDevExt, (_pSrc)->pPrimaryAllocation)) ? \
(_pSrc)->pPrimaryAllocation : ( \
((_pSrc)->pShadowAllocation && VBOXWDDM_IS_FB_ALLOCATION(_pDevExt, (_pSrc)->pShadowAllocation)) ? \
(_pSrc)->pShadowAllocation : NULL \
) \
)
+# define VBOXWDDM_NONFB_ALLOCATION(_pDevExt, _pSrc) ( !((_pSrc)->pPrimaryAllocation && VBOXWDDM_IS_FB_ALLOCATION(_pDevExt, (_pSrc)->pPrimaryAllocation)) ? \
+ (_pSrc)->pPrimaryAllocation : ( \
+ ((_pSrc)->pShadowAllocation && VBOXWDDM_IS_FB_ALLOCATION(_pDevExt, (_pSrc)->pShadowAllocation)) ? \
+ (_pSrc)->pShadowAllocation : NULL \
+ ) \
+ )
#else
# define VBOXWDDM_FB_ALLOCATION(_pDevExt, _pSrc) ((_pSrc)->pPrimaryAllocation)
#endif
+#define VBOXWDDM_CTXLOCK_INIT(_p) do { \
+ KeInitializeSpinLock(&(_p)->ContextLock); \
+ } while (0)
+#define VBOXWDDM_CTXLOCK_DATA KIRQL _ctxLockOldIrql;
+#define VBOXWDDM_CTXLOCK_LOCK(_p) do { \
+ KeAcquireSpinLock(&(_p)->ContextLock, &_ctxLockOldIrql); \
+ } while (0)
+#define VBOXWDDM_CTXLOCK_UNLOCK(_p) do { \
+ KeReleaseSpinLock(&(_p)->ContextLock, _ctxLockOldIrql); \
+ } while (0)
+
#endif /* #ifndef ___VBoxMPWddm_h___ */
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.rc b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.rc
index 435a9a5a..e4d271d9 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.rc
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.rc
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxVideoWddm.inf b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxVideoWddm.inf
index 6cfda59e..9a2e7c87 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxVideoWddm.inf
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxVideoWddm.inf
@@ -1,7 +1,7 @@
;
; VirtualBox Video Wddm driver
;
-; Copyright (C) 2011 Oracle Corporation
+; Copyright (C) 2011-2012 Oracle Corporation
;
; This file is part of VirtualBox Open Source Edition (OSE), as
; available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPDriver.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPDriver.cpp
index 6bb3d7d0..e448468e 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPDriver.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPDriver.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -147,6 +147,18 @@ VBoxDrvFindAdapter(IN PVOID HwDeviceExtension, IN PVOID HwContext, IN PWSTR Argu
*/
VBoxSetupDisplaysHGSMI(&pExt->u.primary.commonInfo, phVRAM, ulApertureSize, cbVRAM, 0);
+ /* Check if the chip restricts horizontal resolution or not.
+ * Must be done after VBoxSetupDisplaysHGSMI, because it initializes the common structure.
+ */
+ VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
+ VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX);
+ DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA);
+
+ if (DispiId == VBE_DISPI_ID_ANYX)
+ VBoxCommonFromDeviceExt(pExt)->fAnyX = TRUE;
+ else
+ VBoxCommonFromDeviceExt(pExt)->fAnyX = FALSE;
+
if (pExt->u.primary.commonInfo.bHGSMI)
{
LOGREL(("using HGSMI"));
@@ -166,7 +178,6 @@ static BOOLEAN
VBoxDrvInitialize(PVOID HwDeviceExtension)
{
PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension;
- USHORT DispiId;
PAGED_CODE();
LOGF_ENTER();
@@ -174,16 +185,6 @@ VBoxDrvInitialize(PVOID HwDeviceExtension)
/* Initialize the request pointer. */
pExt->u.primary.pvReqFlush = NULL;
- /* Check if the chip restricts horizontal resolution or not. */
- VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
- VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX);
- DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA);
-
- if (DispiId == VBE_DISPI_ID_ANYX)
- pExt->fAnyX = TRUE;
- else
- pExt->fAnyX = FALSE;
-
VBoxMPCmnInitCustomVideoModes(pExt);
LOGF_LEAVE();
@@ -308,7 +309,7 @@ VBoxDrvStartIO(PVOID HwDeviceExtension, PVIDEO_REQUEST_PACKET RequestPacket)
{
PVIDEO_MODE_INFORMATION pModes = (PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer;
- if (RequestPacket->OutputBufferLength < VBoxMPXpdmGetVideoModesCount()*sizeof(VIDEO_MODE_INFORMATION))
+ if (RequestPacket->OutputBufferLength < VBoxMPXpdmGetVideoModesCount(pExt)*sizeof(VIDEO_MODE_INFORMATION))
{
pStatus->Status = ERROR_INSUFFICIENT_BUFFER;
break;
@@ -538,12 +539,29 @@ VBoxDrvStartIO(PVOID HwDeviceExtension, PVIDEO_REQUEST_PACKET RequestPacket)
case IOCTL_VIDEO_VBOX_ISANYX:
{
STARTIO_OUT(uint32_t, pu32AnyX);
- *pu32AnyX = pExt->fAnyX;
+ *pu32AnyX = VBoxCommonFromDeviceExt(pExt)->fAnyX;
pStatus->Information = sizeof (uint32_t);
bResult = TRUE;
break;
}
+ case IOCTL_VIDEO_QUERY_VBOXVIDEO_INFO:
+ {
+ STARTIO_IN(ULONG, pulInfoLevel);
+ if (*pulInfoLevel == VBOXVIDEO_INFO_LEVEL_REGISTRY_FLAGS)
+ {
+ STARTIO_OUT(ULONG, pulFlags);
+ bResult = VBoxMPQueryRegistryFlags(pExt, pulFlags, pStatus);
+ }
+ else
+ {
+ pStatus->Status = ERROR_INVALID_PARAMETER;
+ bResult = FALSE;
+ }
+
+ break;
+ }
+
default:
{
WARN(("unsupported IOCTL %p, fn(%#x)",
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPIOCTL.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPIOCTL.cpp
index 3769fbe1..772f6c92 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPIOCTL.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPIOCTL.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -192,15 +192,15 @@ BOOLEAN VBoxMPSetCurrentMode(PVBOXMP_DEVEXT pExt, PVIDEO_MODE pMode, PSTATUS_BLO
WARN(("ignoring set VIDEO_MODE_NO_ZERO_MEMORY or VIDEO_MODE_MAP_MEM_LINEAR"));
}
- pModeInfo = VBoxMPCmnGetVideoModeInfo(RequestedMode-1);
+ pModeInfo = VBoxMPCmnGetVideoModeInfo(pExt, RequestedMode-1);
if (!pModeInfo)
{
pStatus->Status = ERROR_INVALID_PARAMETER;
return FALSE;
}
- LOG(("width %d, height %d, bpp %d",
- pModeInfo->VisScreenWidth, pModeInfo->VisScreenHeight, pModeInfo->BitsPerPlane));
+ LOG(("screen [%d] mode %d width %d, height %d, bpp %d",
+ pExt->iDevice, pModeInfo->ModeIndex, pModeInfo->VisScreenWidth, pModeInfo->VisScreenHeight, pModeInfo->BitsPerPlane));
/* Update device info */
pExt->CurrentMode = RequestedMode;
@@ -249,7 +249,7 @@ BOOLEAN VBoxMPQueryNumAvailModes(PVBOXMP_DEVEXT pExt, PVIDEO_NUM_MODES pNumModes
VBoxMPXpdmBuildVideoModesTable(pExt);
- pNumModes->NumModes = VBoxMPXpdmGetVideoModesCount();
+ pNumModes->NumModes = VBoxMPXpdmGetVideoModesCount(pExt);
pNumModes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION);
pStatus->Information = sizeof(VIDEO_NUM_MODES);
@@ -264,9 +264,9 @@ BOOLEAN VBoxMPQueryAvailModes(PVBOXMP_DEVEXT pExt, PVIDEO_MODE_INFORMATION pMode
{
LOGF_ENTER();
- ULONG ulSize = VBoxMPXpdmGetVideoModesCount()*sizeof(VIDEO_MODE_INFORMATION);
+ ULONG ulSize = VBoxMPXpdmGetVideoModesCount(pExt)*sizeof(VIDEO_MODE_INFORMATION);
pStatus->Information = ulSize;
- VideoPortMoveMemory(pModes, VBoxMPCmnGetVideoModeInfo(0), ulSize);
+ VideoPortMoveMemory(pModes, VBoxMPCmnGetVideoModeInfo(pExt, 0), ulSize);
LOGF_LEAVE();
return TRUE;
@@ -616,3 +616,35 @@ BOOLEAN VBoxMPVhwaQueryInfo(PVBOXMP_DEVEXT pExt, VHWAQUERYINFO *pInfo, PSTATUS_B
return bRC;
}
#endif
+
+BOOLEAN VBoxMPQueryRegistryFlags(PVBOXMP_DEVEXT pExt, ULONG *pulFlags, PSTATUS_BLOCK pStatus)
+{
+ BOOLEAN bRC = TRUE;
+ LOGF_ENTER();
+
+ VBOXMPCMNREGISTRY Registry;
+
+ int rc = VBoxMPCmnRegInit(pExt, &Registry);
+ VBOXMP_WARN_VPS_NOBP(rc);
+
+ if (rc == NO_ERROR)
+ {
+ uint32_t u32Flags = 0;
+ rc = VBoxMPCmnRegQueryDword(Registry, L"VBoxVideoFlags", &u32Flags);
+ VBOXMP_WARN_VPS_NOBP(rc);
+ if (rc != NO_ERROR)
+ {
+ u32Flags = 0;
+ }
+
+ LOG(("Registry flags 0x%08X", u32Flags));
+ *pulFlags = u32Flags;
+ pStatus->Information = sizeof(ULONG);
+ }
+
+ rc = VBoxMPCmnRegFini(Registry);
+ VBOXMP_WARN_VPS_NOBP(rc);
+
+ LOGF_LEAVE();
+ return bRC;
+}
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPInternal.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPInternal.cpp
index 97dd0d50..e7841d42 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPInternal.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPInternal.cpp
@@ -130,7 +130,10 @@ void VBoxCreateDisplays(PVBOXMP_DEVEXT pExt, PVIDEO_PORT_CONFIG_INFO pConfigInfo
PVBOXMP_DEVEXT pSExt = NULL;
VP_STATUS rc;
- rc = pAPI->pfnCreateSecondaryDisplay(pExt, (PVOID*)&pSExt, VIDEO_DUALVIEW_REMOVABLE);
+ /* If VIDEO_DUALVIEW_REMOVABLE is passed as the 3rd parameter, then
+ * the guest does not allow to choose the primary screen.
+ */
+ rc = pAPI->pfnCreateSecondaryDisplay(pExt, (PVOID*)&pSExt, 0);
VBOXMP_WARN_VPS(rc);
if (rc != NO_ERROR)
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPInternal.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPInternal.h
index fd9628b8..14ed1571 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPInternal.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/xpdm/VBoxMPInternal.h
@@ -61,5 +61,6 @@ BOOLEAN VBoxMPHGSMIQueryCallbacks(PVBOXMP_DEVEXT pExt, HGSMIQUERYCALLBACKS *pCal
BOOLEAN VBoxMPQueryHgsmiInfo(PVBOXMP_DEVEXT pExt, QUERYHGSMIRESULT *pResult, PSTATUS_BLOCK pStatus);
BOOLEAN VBoxMPHgsmiHandlerEnable(PVBOXMP_DEVEXT pExt, HGSMIHANDLERENABLE *pChannel, PSTATUS_BLOCK pStatus);
BOOLEAN VBoxMPVhwaQueryInfo(PVBOXMP_DEVEXT pExt, VHWAQUERYINFO *pInfo, PSTATUS_BLOCK pStatus);
+BOOLEAN VBoxMPQueryRegistryFlags(PVBOXMP_DEVEXT pExt, ULONG *pulFlags, PSTATUS_BLOCK pStatus);
#endif /*VBOXMPINTERNAL_H*/