Index: /trunk/include/VBox/VBoxVideoHost3D.h
===================================================================
--- /trunk/include/VBox/VBoxVideoHost3D.h	(revision 50847)
+++ /trunk/include/VBox/VBoxVideoHost3D.h	(revision 50848)
@@ -28,4 +28,5 @@
 #include <iprt/cdefs.h>
 #include <VBox/VBoxVideo.h>
+#include <VBox/hgcmsvc.h>
 
 /* screen update instance */
@@ -112,6 +113,12 @@
         void(*pfnInternal)();
         void* pvInternal;
-    };
+    } u;
 } VBOXCRCMDCTL;
+
+typedef struct VBOXCRCMDCTL_HGCM
+{
+    VBOXCRCMDCTL Hdr;
+    VBOXHGCMSVCPARM aParms[1];
+} VBOXCRCMDCTL_HGCM;
 
 typedef struct VBOXVDMAHOST * HVBOXCRCMDCTL_REMAINING_HOST_COMMAND;
Index: /trunk/include/VBox/vmm/pdmifs.h
===================================================================
--- /trunk/include/VBox/vmm/pdmifs.h	(revision 50847)
+++ /trunk/include/VBox/vmm/pdmifs.h	(revision 50848)
@@ -3076,7 +3076,10 @@
                                                                    PFNCRCTLCOMPLETION pfnCompletion,
                                                                    void *pvCompletion));
+
+    DECLR3CALLBACKMEMBER(int, pfnCrCtlSubmitSync, (PPDMIDISPLAYVBVACALLBACKS pInterface,
+                                                                   struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd));
 } PDMIDISPLAYVBVACALLBACKS;
 /** PDMIDISPLAYVBVACALLBACKS  */
-#define PDMIDISPLAYVBVACALLBACKS_IID            "b78b81d2-c821-4e66-96ff-dbafa76343a5"
+#define PDMIDISPLAYVBVACALLBACKS_IID            "193b2975-215f-480a-abef-42f029ae890f"
 
 /** Pointer to a PCI raw connector interface. */
Index: /trunk/src/VBox/Devices/Graphics/DevVGA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA.cpp	(revision 50847)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA.cpp	(revision 50848)
@@ -5955,4 +5955,5 @@
 #endif
     pThis->IVBVACallbacks.pfnCrCtlSubmit = vboxCmdVBVACmdHostCtl;
+    pThis->IVBVACallbacks.pfnCrCtlSubmitSync = vboxCmdVBVACmdHostCtlSync;
 
     /*
Index: /trunk/src/VBox/Devices/Graphics/DevVGA.h
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA.h	(revision 50847)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA.h	(revision 50848)
@@ -630,4 +630,6 @@
                                                                PFNCRCTLCOMPLETION pfnCompletion,
                                                                void *pvCompletion);
+int vboxCmdVBVACmdHostCtlSync(PPDMIDISPLAYVBVACALLBACKS pInterface,
+                                                               struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd);
 
 int vboxVBVASaveStateExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
Index: /trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp	(revision 50847)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp	(revision 50848)
@@ -605,5 +605,5 @@
     if ((enmSource == VBVAEXHOSTCTL_SOURCE_HOST_ENABLED) && !VBoxVBVAExHSIsEnabled(pCmdVbva))
     {
-        WARN(("cmd vbva not enabled\n"));
+        Log(("cmd vbva not enabled\n"));
         return VERR_INVALID_STATE;
     }
@@ -619,5 +619,5 @@
             if ((enmSource == VBVAEXHOSTCTL_SOURCE_HOST_ENABLED) && !VBoxVBVAExHSIsEnabled(pCmdVbva))
             {
-                WARN(("cmd vbva not enabled\n"));
+                Log(("cmd vbva not enabled\n"));
                 RTCritSectLeave(&pCmdVbva->CltCritSect);
                 return VERR_INVALID_STATE;
@@ -669,4 +669,6 @@
     VBOXCRCMD_SVRINFO CrSrvInfo;
     VBVAEXHOSTCTL* pCurRemainingHostCtl;
+    RTSEMEVENTMULTI HostCrCtlCompleteEvent;
+    int32_t volatile i32cHostCrCtlCompleted;
 #ifdef VBOX_VDMA_WITH_WATCHDOG
     PTMTIMERR3 WatchDogTimer;
@@ -2157,29 +2159,38 @@
         pVdma->pVGAState = pVGAState;
 
+        rc = RTSemEventMultiCreate(&pVdma->HostCrCtlCompleteEvent);
+        if (RT_SUCCESS(rc))
+        {
 #ifdef VBOX_VDMA_WITH_WATCHDOG
-        rc = PDMDevHlpTMTimerCreate(pVGAState->pDevInsR3, TMCLOCK_REAL, vboxVDMAWatchDogTimer,
-                                    pVdma, TMTIMER_FLAGS_NO_CRIT_SECT,
-                                    "VDMA WatchDog Timer", &pVdma->WatchDogTimer);
-        AssertRC(rc);
+            rc = PDMDevHlpTMTimerCreate(pVGAState->pDevInsR3, TMCLOCK_REAL, vboxVDMAWatchDogTimer,
+                                        pVdma, TMTIMER_FLAGS_NO_CRIT_SECT,
+                                        "VDMA WatchDog Timer", &pVdma->WatchDogTimer);
+            AssertRC(rc);
 #endif
-        rc = VBoxVBVAExHSInit(&pVdma->CmdVbva);
-        if (RT_SUCCESS(rc))
-        {
-            rc = VBoxVDMAThreadCreate(&pVdma->Thread, vboxVDMAWorkerThread, pVdma);
+            rc = VBoxVBVAExHSInit(&pVdma->CmdVbva);
             if (RT_SUCCESS(rc))
             {
-                pVGAState->pVdma = pVdma;
+                rc = VBoxVDMAThreadCreate(&pVdma->Thread, vboxVDMAWorkerThread, pVdma);
+                if (RT_SUCCESS(rc))
+                {
+                    pVGAState->pVdma = pVdma;
 #ifdef VBOX_WITH_CRHGSMI
-                int rcIgnored = vboxVDMACrCtlHgsmiSetup(pVdma); NOREF(rcIgnored); /** @todo is this ignoring intentional? */
+                    int rcIgnored = vboxVDMACrCtlHgsmiSetup(pVdma); NOREF(rcIgnored); /** @todo is this ignoring intentional? */
 #endif
-                return VINF_SUCCESS;
+                    return VINF_SUCCESS;
+                }
+                else
+                    WARN(("VBoxVDMAThreadCreate faile %d\n", rc));
+
+                VBoxVBVAExHSTerm(&pVdma->CmdVbva);
             }
             else
-                WARN(("VBoxVDMAThreadCreate faile %d\n", rc));
-
-            VBoxVBVAExHSTerm(&pVdma->CmdVbva);
+                WARN(("VBoxVBVAExHSInit failed %d\n", rc));
+
+            RTSemEventMultiDestroy(pVdma->HostCrCtlCompleteEvent);
         }
         else
-            WARN(("VBoxVBVAExHSInit faile %d\n", rc));
+            WARN(("RTSemEventMultiCreate failed %d\n", rc));
+
 
         RTMemFree(pVdma);
@@ -2216,4 +2227,5 @@
     VBoxVDMAThreadTerm(&pVdma->Thread);
     VBoxVBVAExHSTerm(&pVdma->CmdVbva);
+    RTSemEventMultiDestroy(pVdma->HostCrCtlCompleteEvent);
     RTMemFree(pVdma);
     return VINF_SUCCESS;
@@ -2393,5 +2405,5 @@
     }
     else
-        WARN(("VBoxVBVAExHCtlSubmit failed %d\n", rc));
+        Log(("VBoxVBVAExHCtlSubmit failed %d\n", rc));
 
     return rc;
@@ -2426,5 +2438,5 @@
     if (!RT_SUCCESS(rc))
     {
-        WARN(("vdmaVBVACtlSubmit failed rc %d\n", rc));
+        Log(("vdmaVBVACtlSubmit failed rc %d\n", rc));
         return rc;;
     }
@@ -2450,6 +2462,6 @@
 {
     VBOXCRCMDCTL* pVboxCtl = (VBOXCRCMDCTL*)pCtl->u.cmd.pu8Cmd;
-    if (pVboxCtl->pfnInternal)
-        ((PFNCRCTLCOMPLETION)pVboxCtl->pfnInternal)(pVboxCtl, pCtl->u.cmd.cbCmd, rc, pvCompletion);
+    if (pVboxCtl->u.pfnInternal)
+        ((PFNCRCTLCOMPLETION)pVboxCtl->u.pfnInternal)(pVboxCtl, pCtl->u.cmd.cbCmd, rc, pvCompletion);
     VBoxVBVAExHCtlFree(pVbva, pCtl);
 }
@@ -2459,5 +2471,5 @@
         void *pvCompletion)
 {
-    pCmd->pfnInternal = (void(*)())pfnCompletion;
+    pCmd->u.pfnInternal = (void(*)())pfnCompletion;
     int rc = vdmaVBVACtlOpaqueSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_HOST_ENABLED, (uint8_t*)pCmd, cbCmd, vboxCmdVBVACmdCtlHostCompletion, pvCompletion);
     if (!RT_SUCCESS(rc))
@@ -2465,5 +2477,5 @@
         if (rc == VERR_INVALID_STATE)
         {
-            pCmd->pfnInternal = NULL;
+            pCmd->u.pfnInternal = NULL;
             PVGASTATE pVGAState = pVdma->pVGAState;
             rc = pVGAState->pDrv->pfnCrHgcmCtlSubmit(pVGAState->pDrv, pCmd, cbCmd, pfnCompletion, pvCompletion);
@@ -2597,4 +2609,67 @@
 }
 
+typedef struct VBOXCMDVBVA_CMDHOSTCTL_SYNC
+{
+    struct VBOXVDMAHOST *pVdma;
+    uint32_t fProcessing;
+    int rc;
+} VBOXCMDVBVA_CMDHOSTCTL_SYNC;
+
+static DECLCALLBACK(void) vboxCmdVBVACmdHostCtlSyncCb(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion)
+{
+    VBOXCMDVBVA_CMDHOSTCTL_SYNC *pData = (VBOXCMDVBVA_CMDHOSTCTL_SYNC*)pvCompletion;
+
+    pData->rc = rc;
+    pData->fProcessing = 0;
+
+    struct VBOXVDMAHOST *pVdma = pData->pVdma;
+
+    ASMAtomicIncS32(&pVdma->i32cHostCrCtlCompleted);
+
+    RTSemEventMultiSignal(pVdma->HostCrCtlCompleteEvent);
+}
+
+int vboxCmdVBVACmdHostCtlSync(PPDMIDISPLAYVBVACALLBACKS pInterface,
+                                                               struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd)
+{
+    PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
+    struct VBOXVDMAHOST *pVdma = pVGAState->pVdma;
+    VBOXCMDVBVA_CMDHOSTCTL_SYNC Data;
+    Data.pVdma = pVdma;
+    Data.fProcessing = 1;
+    Data.rc = VERR_INTERNAL_ERROR;
+    int rc = vdmaVBVACtlOpaqueHostSubmit(pVdma, pCmd, cbCmd, vboxCmdVBVACmdHostCtlSyncCb, &Data);
+    if (!RT_SUCCESS(rc))
+    {
+        WARN(("vdmaVBVACtlOpaqueHostSubmit failed %d", rc));
+        return rc;
+    }
+
+    while (Data.fProcessing)
+    {
+        /* Poll infrequently to make sure no completed message has been missed. */
+        RTSemEventMultiWait(pVdma->HostCrCtlCompleteEvent, 500);
+
+        if (Data.fProcessing)
+            RTThreadYield();
+    }
+
+    /* 'Our' message has been processed, so should reset the semaphore.
+     * There is still possible that another message has been processed
+     * and the semaphore has been signalled again.
+     * Reset only if there are no other messages completed.
+     */
+    int32_t c = ASMAtomicDecS32(&pVdma->i32cHostCrCtlCompleted);
+    Assert(c >= 0);
+    if (!c)
+        RTSemEventMultiReset(pVdma->HostCrCtlCompleteEvent);
+
+    rc = Data.rc;
+    if (!RT_SUCCESS(rc))
+        WARN(("host call failed %d", rc));
+
+    return rc;
+}
+
 int vboxCmdVBVACmdCtl(PVGASTATE pVGAState, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl)
 {
Index: /trunk/src/VBox/Main/include/DisplayImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/DisplayImpl.h	(revision 50847)
+++ /trunk/src/VBox/Main/include/DisplayImpl.h	(revision 50848)
@@ -26,4 +26,5 @@
 #include <VBox/VMMDev.h>
 #include <VBox/VBoxVideo.h>
+#include <VBox/vmm/pdmifs.h>
 
 #ifdef VBOX_WITH_CROGL
@@ -168,9 +169,8 @@
 #endif
 #ifdef VBOX_WITH_CRHGSMI
+    void handleCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
+    void handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
     void handleCrHgsmiCommandProcess(PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd);
     void handleCrHgsmiControlProcess(PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl);
-
-    void handleCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
-    void handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
 #endif
     int  handleCrHgcmCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
@@ -178,5 +178,4 @@
                                         void *pvCompletion);
 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
-    void  handleCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
     void  handleCrVRecScreenshotPerform(uint32_t uScreen,
                                         uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBitsPerPixel,
@@ -298,6 +297,6 @@
 
     static DECLCALLBACK(void)  displayVRecCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext);
-    static DECLCALLBACK(void)  displayCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext);
-#endif
+#endif
+    static DECLCALLBACK(void) displayCrCmdFree(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion);
 
     static DECLCALLBACK(void)  displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser);
@@ -350,4 +349,5 @@
     volatile uint32_t mfCrOglVideoRecState;
     CRVBOXHGCMTAKESCREENSHOT mCrOglScreenshotData;
+    VBOXCRCMDCTL_HGCM mCrOglScreenshotCtl;
 #endif
 
@@ -374,4 +374,7 @@
 #endif
 
+    int crCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, PFNCRCTLCOMPLETION pfnCompletion, void *pvCompletion);
+    int crCtlSubmitSync(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd);
+
 private:
     static void InvalidateAndUpdateEMT(Display *pDisplay, unsigned uId, bool fUpdateAll);
Index: /trunk/src/VBox/Main/src-client/ConsoleVRDPServer.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleVRDPServer.cpp	(revision 50847)
+++ /trunk/src/VBox/Main/src-client/ConsoleVRDPServer.cpp	(revision 50848)
@@ -2131,23 +2131,13 @@
     }
 
-    VBOXHGCMSVCPARM parm;
-
-    parm.type = VBOX_HGCM_SVC_PARM_PTR;
-    parm.u.pointer.addr = &outputRedirect;
-    parm.u.pointer.size = sizeof(outputRedirect);
-
-    VMMDev *pVMMDev = mConsole->getVMMDev();
-
-    if (!pVMMDev)
-    {
-        AssertMsgFailed(("remote3DRedirect no vmmdev\n"));
-        return;
-    }
-
-    int rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL",
-                                   SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT,
-                                   SHCRGL_CPARMS_SET_OUTPUT_REDIRECT,
-                                   &parm);
-
+    VBOXCRCMDCTL_HGCM data;
+    data.Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
+    data.Hdr.u32Function = SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT;
+
+    data.aParms[0].type = VBOX_HGCM_SVC_PARM_PTR;
+    data.aParms[0].u.pointer.addr = &outputRedirect;
+    data.aParms[0].u.pointer.size = sizeof(outputRedirect);
+
+    int rc = mConsole->getDisplay()->crCtlSubmitSync(&data.Hdr, sizeof (data));
     if (!RT_SUCCESS(rc))
     {
@@ -2157,4 +2147,7 @@
 
     LogRel(("VRDE: %s 3D redirect.\n", fEnable? "Enabled": "Disabled"));
+#ifdef DEBUG_misha
+    AssertFailed();
+#endif
 
     return;
Index: /trunk/src/VBox/Main/src-client/DisplayImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/DisplayImpl.cpp	(revision 50847)
+++ /trunk/src/VBox/Main/src-client/DisplayImpl.cpp	(revision 50848)
@@ -338,11 +338,13 @@
                     pScreenshot->Base.pfnScreenshotEnd = NULL;
 
-                    VBOXHGCMSVCPARM parm;
-
-                    parm.type = VBOX_HGCM_SVC_PARM_PTR;
-                    parm.u.pointer.addr = &pScreenshot->Base;
-                    parm.u.pointer.size = sizeof (pScreenshot->Base);
-
-                    int rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_TAKE_SCREENSHOT, 1, &parm);
+                    VBOXCRCMDCTL_HGCM data;
+                    data.Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
+                    data.Hdr.u32Function = SHCRGL_HOST_FN_TAKE_SCREENSHOT;
+
+                    data.aParms[0].type = VBOX_HGCM_SVC_PARM_PTR;
+                    data.aParms[0].u.pointer.addr = &pScreenshot->Base;
+                    data.aParms[0].u.pointer.size = sizeof (pScreenshot->Base);
+
+                    int rc = that->crCtlSubmitSync(&data.Hdr, sizeof (data));
                     if (RT_SUCCESS(rc))
                     {
@@ -723,4 +725,10 @@
 }
 
+DECLCALLBACK(void) Display::displayCrCmdFree(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion)
+{
+    Assert(pvCompletion);
+    RTMemFree(pvCompletion);
+}
+
 #ifdef VBOX_WITH_CROGL
 int Display::crOglWindowsShow(bool fShow)
@@ -747,14 +755,25 @@
     }
 
-    VBOXHGCMSVCPARM parm;
-
-    parm.type = VBOX_HGCM_SVC_PARM_32BIT;
-    parm.u.uint32 = (uint32_t)fShow;
-
-    int rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_WINDOWS_SHOW, &parm, NULL, NULL);
+    VBOXCRCMDCTL_HGCM *pData = (VBOXCRCMDCTL_HGCM*)RTMemAlloc(sizeof (VBOXCRCMDCTL_HGCM));
+    if (!pData)
+    {
+        AssertMsgFailed(("RTMemAlloc failed\n"));
+        return VERR_NO_MEMORY;
+    }
+
+    pData->Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
+    pData->Hdr.u32Function = SHCRGL_HOST_FN_WINDOWS_SHOW;
+
+    pData->aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
+    pData->aParms[0].u.uint32 = (uint32_t)fShow;
+
+    int rc = crCtlSubmit(&pData->Hdr, sizeof (*pData), displayCrCmdFree, pData);
     if (RT_SUCCESS(rc))
         mfCrOglDataHidden = !fShow;
     else
-        AssertMsgFailed(("hgcmHostFastCallAsync failed rc %n", rc));
+    {
+        AssertMsgFailed(("crCtlSubmit failed rc %n", rc));
+        RTMemFree(pData);
+    }
 
     return rc;
@@ -850,18 +869,23 @@
             if (pVMMDev)
             {
-                CRVBOXHGCMDEVRESIZE *pData = (CRVBOXHGCMDEVRESIZE*)RTMemAlloc(sizeof (*pData));
-                if (pData)
+                VBOXCRCMDCTL_HGCM *pCtl = (VBOXCRCMDCTL_HGCM*)RTMemAlloc(sizeof (CRVBOXHGCMDEVRESIZE) + sizeof (VBOXCRCMDCTL_HGCM));
+                if (pCtl)
                 {
+                    CRVBOXHGCMDEVRESIZE *pData = (CRVBOXHGCMDEVRESIZE*)(pCtl+1);
                     pData->Screen = *pScreen;
                     pData->pvVRAM = pvVRAM;
 
-                    VBOXHGCMSVCPARM parm;
-
-                    parm.type = VBOX_HGCM_SVC_PARM_PTR;
-                    parm.u.pointer.addr = pData;
-                    parm.u.pointer.size = sizeof (*pData);
-
-                    rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_DEV_RESIZE, &parm, displayCrAsyncCmdCompletion, this);
-                    AssertRC(rc);
+                    pCtl->Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
+                    pCtl->Hdr.u32Function = SHCRGL_HOST_FN_DEV_RESIZE;
+                    pCtl->aParms[0].type = VBOX_HGCM_SVC_PARM_PTR;
+                    pCtl->aParms[0].u.pointer.addr = pData;
+                    pCtl->aParms[0].u.pointer.size = sizeof (*pData);
+
+                    rc = crCtlSubmit(&pCtl->Hdr, sizeof (*pCtl), displayCrCmdFree, pCtl);
+                    if (!RT_SUCCESS(rc))
+                    {
+                        AssertMsgFailed(("crCtlSubmit failed rc %n", rc));
+                        RTMemFree(pCtl);
+                    }
                 }
                 else
@@ -1113,21 +1137,12 @@
             if (is3denabled)
             {
-                VBOXHGCMSVCPARM parm;
-
-                parm.type = VBOX_HGCM_SVC_PARM_32BIT;
-                parm.u.uint32 = uScreenId;
-
-                VMMDev *pVMMDev = mParent->getVMMDev();
-                if (pVMMDev)
-                {
-#if 0
-                    if (mhCrOglSvc)
-                        pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_SCREEN_CHANGED, &parm, NULL, NULL);
-                    else
-                        AssertMsgFailed(("mhCrOglSvc is NULL\n"));
-#else
-                    pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
-#endif
-                }
+                VBOXCRCMDCTL_HGCM data;
+                data.Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
+                data.Hdr.u32Function = SHCRGL_HOST_FN_SCREEN_CHANGED;
+
+                data.aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
+                data.aParms[0].u.uint32 = uScreenId;
+
+                crCtlSubmitSync(&data.Hdr, sizeof (data));
             }
         }
@@ -1447,17 +1462,24 @@
         if (mhCrOglSvc)
         {
-            RTRECT *pRectsCopy = (RTRECT *)RTMemAlloc(  RT_MAX(cRect, 1)
-                                                             * sizeof (RTRECT));
-            if (pRectsCopy)
+            VBOXCRCMDCTL_HGCM *pCtl = (VBOXCRCMDCTL_HGCM*)RTMemAlloc(RT_MAX(cRect, 1) * sizeof (RTRECT)
+                    + sizeof (VBOXCRCMDCTL_HGCM));
+            if (pCtl)
             {
+                RTRECT *pRectsCopy = (RTRECT*)(pCtl+1);
                 memcpy(pRectsCopy, pRect, cRect * sizeof (RTRECT));
 
-                VBOXHGCMSVCPARM parm;
-
-                parm.type = VBOX_HGCM_SVC_PARM_PTR;
-                parm.u.pointer.addr = pRectsCopy;
-                parm.u.pointer.size = cRect * sizeof (RTRECT);
-
-                vmmDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_SET_VISIBLE_REGION, &parm, displayCrAsyncCmdCompletion, this);
+                pCtl->Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
+                pCtl->Hdr.u32Function = SHCRGL_HOST_FN_SET_VISIBLE_REGION;
+
+                pCtl->aParms[0].type = VBOX_HGCM_SVC_PARM_PTR;
+                pCtl->aParms[0].u.pointer.addr = pRectsCopy;
+                pCtl->aParms[0].u.pointer.size = cRect * sizeof (RTRECT);
+
+                int rc = crCtlSubmit(&pCtl->Hdr, sizeof (*pCtl), displayCrCmdFree, pCtl);
+                if (!RT_SUCCESS(rc))
+                {
+                    AssertMsgFailed(("crCtlSubmit failed rc %n", rc));
+                    RTMemFree(pCtl);
+                }
             }
             else
@@ -2410,25 +2432,14 @@
             if (is3denabled)
             {
-                VBOXHGCMSVCPARM parm;
-
-                parm.type = VBOX_HGCM_SVC_PARM_32BIT;
-                parm.u.uint32 = aScreenId;
-
-                VMMDev *pVMMDev = mParent->getVMMDev();
+                VBOXCRCMDCTL_HGCM data;
+                data.Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
+                data.Hdr.u32Function = SHCRGL_HOST_FN_SCREEN_CHANGED;
+
+                data.aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
+                data.aParms[0].u.uint32 = aScreenId;
 
                 alock.release();
 
-                if (pVMMDev)
-                {
-#if 0
-                    if (mhCrOglSvc)
-                        pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_SCREEN_CHANGED, &parm, NULL, NULL);
-                    else
-                        AssertMsgFailed(("mhCrOglSvc is NULL\n"));
-#else
-                    pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
-#endif
-                }
-                /*ComAssertRCRet (vrc, E_FAIL);*/
+                crCtlSubmitSync(&data.Hdr, sizeof (data));
 
                 alock.acquire();
@@ -2560,16 +2571,24 @@
         if (is3denabled && vmmDev)
         {
-            VBOXHGCMSVCPARM parm;
-
-            parm.type = VBOX_HGCM_SVC_PARM_PTR;
-            /* NULL means disable */
-            parm.u.pointer.addr = NULL;
-            parm.u.pointer.size = 0;  /* <- means null rects, NULL pRects address and 0 rects means "disable" */
-
-            if (mhCrOglSvc)
-                vmmDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_SET_VISIBLE_REGION, &parm, NULL, NULL);
-            else
-                AssertMsgFailed(("mhCrOglSvc is NULL\n"));
-
+            VBOXCRCMDCTL_HGCM *pData = (VBOXCRCMDCTL_HGCM*)RTMemAlloc(sizeof (VBOXCRCMDCTL_HGCM));
+            if (!pData)
+            {
+                AssertMsgFailed(("RTMemAlloc failed\n"));
+                return VERR_NO_MEMORY;
+            }
+
+            pData->Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
+            pData->Hdr.u32Function = SHCRGL_HOST_FN_SET_VISIBLE_REGION;
+
+            pData->aParms[0].type = VBOX_HGCM_SVC_PARM_PTR;
+            pData->aParms[0].u.pointer.addr = NULL;
+            pData->aParms[0].u.pointer.size = 0; /* <- means null rects, NULL pRects address and 0 rects means "disable" */
+
+            int rc = crCtlSubmit(&pData->Hdr, sizeof (*pData), displayCrCmdFree, pData);
+            if (!RT_SUCCESS(rc))
+            {
+                AssertMsgFailed(("crCtlSubmit failed rc %n", rc));
+                RTMemFree(pData);
+            }
         }
     }
@@ -2602,11 +2621,13 @@
                 pScreenshot->pfnScreenshotEnd = NULL;
 
-                VBOXHGCMSVCPARM parm;
-
-                parm.type = VBOX_HGCM_SVC_PARM_PTR;
-                parm.u.pointer.addr = pScreenshot;
-                parm.u.pointer.size = sizeof (*pScreenshot);
-
-                int rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_TAKE_SCREENSHOT, 1, &parm);
+                VBOXCRCMDCTL_HGCM data;
+                data.Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
+                data.Hdr.u32Function = SHCRGL_HOST_FN_TAKE_SCREENSHOT;
+
+                data.aParms[0].type = VBOX_HGCM_SVC_PARM_PTR;
+                data.aParms[0].u.pointer.addr = pScreenshot;
+                data.aParms[0].u.pointer.size = sizeof (*pScreenshot);
+
+                int rc = pDisplay->crCtlSubmitSync(&data.Hdr, sizeof (data));
 
                 RTMemFree(pScreenshot);
@@ -3590,46 +3611,28 @@
 void Display::crViewportNotify(VMMDev *pVMMDev, ULONG aScreenId, ULONG x, ULONG y, ULONG width, ULONG height)
 {
-#if 0
-    VBOXHGCMSVCPARM parm;
-
-    CRVBOXHGCMVIEWPORT *pViewportInfo = (CRVBOXHGCMVIEWPORT*)RTMemAlloc(sizeof (*pViewportInfo));
-    if(!pViewportInfo)
-    {
-        AssertMsgFailed(("RTMemAlloc failed!\n"));
-        return;
-    }
-
-    pViewportInfo->u32Screen = aScreenId;
-    pViewportInfo->x = x;
-    pViewportInfo->y = y;
-    pViewportInfo->width = width;
-    pViewportInfo->height = height;
-
-    parm.type = VBOX_HGCM_SVC_PARM_PTR;
-    parm.u.pointer.addr = pViewportInfo;
-    parm.u.pointer.size = sizeof (*pViewportInfo);
-
-    pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_VIEWPORT_CHANGED2, &parm, displayCrAsyncCmdCompletion, this);
-#else
-    VBOXHGCMSVCPARM aParms[5];
-
-    aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
-    aParms[0].u.uint32 = aScreenId;
-
-    aParms[1].type = VBOX_HGCM_SVC_PARM_32BIT;
-    aParms[1].u.uint32 = x;
-
-    aParms[2].type = VBOX_HGCM_SVC_PARM_32BIT;
-    aParms[2].u.uint32 = y;
-
-
-    aParms[3].type = VBOX_HGCM_SVC_PARM_32BIT;
-    aParms[3].u.uint32 = width;
-
-    aParms[4].type = VBOX_HGCM_SVC_PARM_32BIT;
-    aParms[4].u.uint32 = height;
-
-    pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_VIEWPORT_CHANGED, SHCRGL_CPARMS_VIEWPORT_CHANGED, aParms);
-#endif
+    struct {
+        VBOXCRCMDCTL_HGCM data;
+        VBOXHGCMSVCPARM aParms[4];
+    } s;
+
+    s.data.Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
+    s.data.Hdr.u32Function = SHCRGL_HOST_FN_VIEWPORT_CHANGED;
+
+    s.data.aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
+    s.data.aParms[0].u.uint32 = aScreenId;
+
+    s.data.aParms[1].type = VBOX_HGCM_SVC_PARM_32BIT;
+    s.data.aParms[1].u.uint32 = x;
+
+    s.data.aParms[2].type = VBOX_HGCM_SVC_PARM_32BIT;
+    s.data.aParms[2].u.uint32 = y;
+
+    s.data.aParms[3].type = VBOX_HGCM_SVC_PARM_32BIT;
+    s.data.aParms[3].u.uint32 = width;
+
+    s.data.aParms[4].type = VBOX_HGCM_SVC_PARM_32BIT;
+    s.data.aParms[4].u.uint32 = height;
+
+    crCtlSubmitSync(&s.data.Hdr, RT_OFFSETOF(VBOXCRCMDCTL_HGCM, aParms[5]));
 }
 #endif
@@ -3662,16 +3665,4 @@
         if (RT_SUCCESS(rc))
         {
-            ULONG ul;
-
-            for (ul = 0; ul < mcMonitors; ul++)
-            {
-                DISPLAYFBINFO *pFb = &maFramebuffers[ul];
-                if (!pFb->pendingViewportInfo.fPending)
-                    continue;
-
-                crViewportNotify(pVMMDev, ul, pFb->pendingViewportInfo.x, pFb->pendingViewportInfo.y, pFb->pendingViewportInfo.width, pFb->pendingViewportInfo.height);
-                pFb->pendingViewportInfo.fPending = false;
-            }
-
             mCrOglCallbacks = Completion.MainInterface;
 
@@ -3913,22 +3904,15 @@
                     {
                         /* submit */
-
-                        VBOXHGCMSVCPARM parm;
-
-                        parm.type = VBOX_HGCM_SVC_PARM_PTR;
-                        parm.u.pointer.addr = &pDisplay->mCrOglScreenshotData;
-                        parm.u.pointer.size = sizeof (pDisplay->mCrOglScreenshotData);
-
-                        VMMDev *pVMMDev = pDisplay->mParent->getVMMDev();
-                        if (pVMMDev)
-                        {
-                            int rc = pVMMDev->hgcmHostFastCallAsync(pDisplay->mhCrOglSvc, SHCRGL_HOST_FN_TAKE_SCREENSHOT, &parm, displayVRecCompletion, pDisplay);
-                            if (RT_SUCCESS(rc))
-                                break;
-                            else
-                                AssertMsgFailed(("hgcmHostFastCallAsync failed %f\n", rc));
-                        }
-                        else
-                            AssertMsgFailed(("no VMMDev\n"));
+                        VBOXCRCMDCTL_HGCM *pData = &pDisplay->mCrOglScreenshotCtl;
+
+                        pData->Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
+                        pData->Hdr.u32Function = SHCRGL_HOST_FN_TAKE_SCREENSHOT;
+
+                        pData->aParms[0].type = VBOX_HGCM_SVC_PARM_PTR;
+                        pData->aParms[0].u.pointer.addr = &pDisplay->mCrOglScreenshotData;
+                        pData->aParms[0].u.pointer.size = sizeof (pDisplay->mCrOglScreenshotData);
+                        int rc = pDisplay->crCtlSubmit(&pData->Hdr, sizeof (*pData), displayCrCmdFree, pData);
+                        if (!RT_SUCCESS(rc))
+                            AssertMsgFailed(("crCtlSubmit failed rc %n", rc));
                     }
 
@@ -4305,5 +4289,6 @@
 void Display::handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam)
 {
-    mpDrv->pVBVACallbacks->pfnCrHgsmiControlCompleteAsync(mpDrv->pVBVACallbacks, (PVBOXVDMACMD_CHROMIUM_CTL)pParam->u.pointer.addr, result);
+    PVBOXVDMACMD_CHROMIUM_CTL pCtl = (PVBOXVDMACMD_CHROMIUM_CTL)pParam->u.pointer.addr;
+    mpDrv->pVBVACallbacks->pfnCrHgsmiControlCompleteAsync(mpDrv->pVBVACallbacks, pCtl, result);
 }
 
@@ -4349,8 +4334,24 @@
         if (pVMMDev)
         {
+            bool fCheckPendingViewport = (pCtl->enmType == VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP);
             rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_CRHGSMI_CTL, &parm, Display::displayCrHgsmiControlCompletion, this);
             AssertRC(rc);
             if (RT_SUCCESS(rc))
+            {
+                if (fCheckPendingViewport)
+                {
+                    ULONG ul;
+                    for (ul = 0; ul < mcMonitors; ul++)
+                    {
+                        DISPLAYFBINFO *pFb = &maFramebuffers[ul];
+                        if (!pFb->pendingViewportInfo.fPending)
+                            continue;
+
+                        crViewportNotify(pVMMDev, ul, pFb->pendingViewportInfo.x, pFb->pendingViewportInfo.y, pFb->pendingViewportInfo.width, pFb->pendingViewportInfo.height);
+                        pFb->pendingViewportInfo.fPending = false;
+                    }
+                }
                 return;
+            }
         }
         else
@@ -4387,4 +4388,5 @@
     Display *pDisplay = (Display *)pvContext;
     pDisplay->handleCrHgsmiControlCompletion(result, u32Function, pParam);
+
 }
 #endif
@@ -4393,6 +4395,6 @@
 {
     VBOXCRCMDCTL *pCmd = (VBOXCRCMDCTL*)pParam->u.pointer.addr;
-    if (pCmd->pfnInternal)
-        ((PFNCRCTLCOMPLETION)pCmd->pfnInternal)(pCmd, pParam->u.pointer.size, result, pvContext);
+    if (pCmd->u.pfnInternal)
+        ((PFNCRCTLCOMPLETION)pCmd->u.pfnInternal)(pCmd, pParam->u.pointer.size, result, pvContext);
 }
 
@@ -4414,5 +4416,5 @@
     parm.u.pointer.size = cbCmd;
 
-    pCmd->pfnInternal = (void(*)())pfnCompletion;
+    pCmd->u.pfnInternal = (void(*)())pfnCompletion;
     int rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_CTL, &parm, displayCrHgcmCtlSubmitCompletion, pvCompletion);
     if (!RT_SUCCESS(rc))
@@ -4432,18 +4434,15 @@
 }
 
+int Display::crCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, PFNCRCTLCOMPLETION pfnCompletion, void *pvCompletion)
+{
+    return mpDrv->pVBVACallbacks->pfnCrCtlSubmit(mpDrv->pVBVACallbacks, pCmd, cbCmd, pfnCompletion, pvCompletion);
+}
+
+int Display::crCtlSubmitSync(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd)
+{
+    return mpDrv->pVBVACallbacks->pfnCrCtlSubmitSync(mpDrv->pVBVACallbacks, pCmd, cbCmd);
+}
+
 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
-DECLCALLBACK(void)  Display::displayCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
-{
-    Display *pDisplay = (Display *)pvContext;
-    pDisplay->handleCrAsyncCmdCompletion(result, u32Function, pParam);
-}
-
-
-void  Display::handleCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam)
-{
-    if (pParam->type == VBOX_HGCM_SVC_PARM_PTR && pParam->u.pointer.addr)
-        RTMemFree(pParam->u.pointer.addr);
-}
-
 bool  Display::handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t u64TimeStamp)
 {
