VirtualBox

Changeset 50754 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 12, 2014 5:43:09 PM (11 years ago)
Author:
vboxsync
Message:

Dev/VGA/crOpenGL/wddm: command thread, more command processing

Location:
trunk/src/VBox
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.cpp

    r49591 r50754  
    114114}
    115115
    116 static bool vboxVBVAExInformHost(PVBVAEXBUFFERCONTEXT pCtx,
    117                                PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, bool bEnable)
    118 {
    119     bool bRc = false;
    120 
    121 #if 0  /* All callers check this */
    122     if (ppdev->bHGSMISupported)
    123 #endif
    124     {
    125         void *p = VBoxHGSMIBufferAlloc(pHGSMICtx,
    126                                        sizeof (VBVAENABLE_EX),
    127                                        HGSMI_CH_VBVA,
    128                                        pCtx->u16EnableOp);
    129         if (!p)
    130         {
    131             LogFunc(("HGSMIHeapAlloc failed\n"));
     116static int vboxCmdVbvaSubmitHgsmi(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, HGSMIOFFSET offDr)
     117{
     118    VBoxVideoCmnPortWriteUlong(pHGSMICtx->port, offDr);
     119    return VINF_SUCCESS;
     120}
     121#define vboxCmdVbvaSubmit vboxCmdVbvaSubmitHgsmi
     122
     123static VBOXCMDVBVA_CTL * vboxCmdVbvaCtlCreate(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, uint32_t cbCtl)
     124{
     125    Assert(cbCtl >= sizeof (VBOXCMDVBVA_CTL));
     126    return (VBOXCMDVBVA_CTL*)VBoxSHGSMICommandAlloc(&pHGSMICtx->heapCtx, cbCtl, HGSMI_CH_VBVA, VBVA_CMDVBVA_CTL);
     127}
     128
     129static void vboxCmdVbvaCtlFree(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, VBOXCMDVBVA_CTL * pCtl)
     130{
     131    VBoxSHGSMICommandFree(&pHGSMICtx->heapCtx, pCtl);
     132}
     133
     134static int vboxCmdVbvaCtlSubmitSync(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, VBOXCMDVBVA_CTL * pCtl)
     135{
     136    const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepSynch(&pHGSMICtx->heapCtx, pCtl);
     137    if (!pHdr)
     138    {
     139        WARN(("VBoxSHGSMICommandPrepSynch returnd NULL"));
     140        return VERR_INVALID_PARAMETER;
     141    }
     142
     143    HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pHGSMICtx->heapCtx, pHdr);
     144    if (offCmd == HGSMIOFFSET_VOID)
     145    {
     146        WARN(("VBoxSHGSMICommandOffset returnd NULL"));
     147        VBoxSHGSMICommandCancelSynch(&pHGSMICtx->heapCtx, pHdr);
     148        return VERR_INVALID_PARAMETER;
     149    }
     150
     151    int rc = vboxCmdVbvaSubmit(pHGSMICtx, offCmd);
     152    if (RT_SUCCESS(rc))
     153    {
     154        rc = VBoxSHGSMICommandDoneSynch(&pHGSMICtx->heapCtx, pHdr);
     155        if (RT_SUCCESS(rc))
     156        {
     157            rc = pCtl->i32Result;
     158            if (!RT_SUCCESS(rc))
     159                WARN(("pCtl->i32Result %d", pCtl->i32Result));
     160
     161            return rc;
    132162        }
    133163        else
    134         {
    135             VBVAENABLE_EX *pEnable = (VBVAENABLE_EX *)p;
    136 
    137             pEnable->Base.u32Flags  = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
    138             pEnable->Base.u32Offset = pCtx->offVRAMBuffer;
    139             pEnable->Base.i32Result = VERR_NOT_SUPPORTED;
    140             pEnable->Base.u32Flags |= VBVA_F_ABSOFFSET;
    141 
    142             VBoxHGSMIBufferSubmit(pHGSMICtx, p);
    143 
    144             if (bEnable)
    145             {
    146                 bRc = RT_SUCCESS(pEnable->Base.i32Result);
    147             }
    148             else
    149             {
    150                 bRc = true;
    151             }
    152 
    153             VBoxHGSMIBufferFree(pHGSMICtx, p);
    154         }
    155     }
    156 
    157     return bRc;
     164            WARN(("VBoxSHGSMICommandDoneSynch returnd %d", rc));
     165    }
     166    else
     167        WARN(("vboxCmdVbvaSubmit returnd %d", rc));
     168
     169    VBoxSHGSMICommandCancelSynch(&pHGSMICtx->heapCtx, pHdr);
     170
     171    return rc;
     172}
     173
     174static int vboxCmdVbvaCtlSubmitAsync(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, VBOXCMDVBVA_CTL * pCtl, PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCompletionIrq, void *pvCompletionIrq)
     175{
     176    const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepAsynchIrq(&pHGSMICtx->heapCtx, pCtl, pfnCompletionIrq, pvCompletionIrq, VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE);
     177    if (!pHdr)
     178    {
     179        WARN(("VBoxSHGSMICommandPrepAsynchIrq returnd NULL"));
     180        return VERR_INVALID_PARAMETER;
     181    }
     182
     183    HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pHGSMICtx->heapCtx, pHdr);
     184    if (offCmd == HGSMIOFFSET_VOID)
     185    {
     186        WARN(("VBoxSHGSMICommandOffset returnd NULL"));
     187        VBoxSHGSMICommandCancelAsynch(&pHGSMICtx->heapCtx, pHdr);
     188        return VERR_INVALID_PARAMETER;
     189    }
     190
     191    int rc = vboxCmdVbvaSubmit(pHGSMICtx, offCmd);
     192    if (RT_SUCCESS(rc))
     193    {
     194        VBoxSHGSMICommandDoneAsynch(&pHGSMICtx->heapCtx, pHdr);
     195        return rc;
     196    }
     197    else
     198        WARN(("vboxCmdVbvaSubmit returnd %d", rc));
     199
     200    VBoxSHGSMICommandCancelAsynch(&pHGSMICtx->heapCtx, pHdr);
     201
     202    return rc;
     203}
     204
     205static int vboxVBVAExCtlSubmitEnableDisable(PVBVAEXBUFFERCONTEXT pCtx, PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, bool fEnable)
     206{
     207    VBOXCMDVBVA_CTL_ENABLE *pCtl = (VBOXCMDVBVA_CTL_ENABLE*)vboxCmdVbvaCtlCreate(pHGSMICtx, sizeof (*pCtl));
     208    if (!pCtl)
     209    {
     210        WARN(("vboxCmdVbvaCtlCreate failed"));
     211        return VERR_NO_MEMORY;
     212    }
     213
     214    pCtl->Hdr.u32Type = VBOXCMDVBVACTL_TYPE_ENABLE;
     215    pCtl->Hdr.i32Result = VERR_NOT_IMPLEMENTED;
     216    memset(&pCtl->Enable, 0, sizeof (pCtl->Enable));
     217    pCtl->Enable.u32Flags  = fEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
     218    pCtl->Enable.u32Offset = pCtx->offVRAMBuffer;
     219    pCtl->Enable.i32Result = VERR_NOT_SUPPORTED;
     220    pCtl->Enable.u32Flags |= VBVA_F_ABSOFFSET;
     221
     222    int rc = vboxCmdVbvaCtlSubmitSync(pHGSMICtx, &pCtl->Hdr);
     223    if (RT_SUCCESS(rc))
     224    {
     225        rc = pCtl->Hdr.i32Result;
     226        if (!RT_SUCCESS(rc))
     227            WARN(("vboxCmdVbvaCtlSubmitSync Disable failed %d", rc));
     228    }
     229    else
     230        WARN(("vboxCmdVbvaCtlSubmitSync returnd %d", rc));
     231
     232    vboxCmdVbvaCtlFree(pHGSMICtx, &pCtl->Hdr);
     233
     234    return rc;
    158235}
    159236
     
    189266        pCtx->pVBVA      = pVBVA;
    190267
    191         bRc = vboxVBVAExInformHost(pCtx, pHGSMICtx, true);
     268        bRc = vboxVBVAExCtlSubmitEnableDisable(pCtx, pHGSMICtx, true);
    192269    }
    193270
     
    209286    pCtx->pVBVA             = NULL;
    210287
    211     vboxVBVAExInformHost(pCtx, pHGSMICtx, false);
     288    vboxVBVAExCtlSubmitEnableDisable(pCtx, pHGSMICtx, false);
    212289
    213290    return;
     
    539616                                        uint32_t cbBuffer,
    540617                                        PFNVBVAEXBUFFERFLUSH pfnFlush,
    541                                         void *pvFlush,
    542                                         uint16_t u16EnableOp)
     618                                        void *pvFlush)
    543619{
    544620    memset(pCtx, 0, RT_OFFSETOF(VBVAEXBUFFERCONTEXT, pVBVA));
    545621    pCtx->offVRAMBuffer = offVRAMBuffer;
    546622    pCtx->cbBuffer      = cbBuffer;
    547     pCtx->u16EnableOp   = u16EnableOp;
    548623    pCtx->pfnFlush = pfnFlush;
    549624    pCtx->pvFlush = pvFlush;
     
    824899    {
    825900        Assert(pVbva->Vbva.pVBVA);
    826         VBoxVBVAExSetupBufferContext(&pVbva->Vbva, offBuffer, cbBuffer, voxCmdVbvaFlushCb, pDevExt, VBVA_CMDVBVA_ENABLE);
     901        VBoxVBVAExSetupBufferContext(&pVbva->Vbva, offBuffer, cbBuffer, voxCmdVbvaFlushCb, pDevExt);
    827902    }
    828903    else
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.h

    r49591 r50754  
    7777     * read it. */
    7878    bool        fHwBufferOverflow;
    79     /* VBVA operation used to enable/disable VBVA */
    80     uint16_t    u16EnableOp;
    8179    /* the window between indexRecordFirstUncompleted and pVBVA->::indexRecordFirst represents
    8280     * command records processed by the host, but not completed by the guest yet */
     
    150148                                        uint32_t cbBuffer,
    151149                                        PFNVBVAEXBUFFERFLUSH pfnFlush,
    152                                         void *pvFlush,
    153                                         uint16_t u16EnableOp);
     150                                        void *pvFlush);
    154151
    155152DECLINLINE(uint32_t) VBoxVBVAExGetSize(PVBVAEXBUFFERCONTEXT pCtx)
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp

    r50678 r50754  
    13531353            switch (chInfo)
    13541354            {
    1355                 case VBVA_VBVACMD_CTL:
     1355                case VBVA_CMDVBVA_CTL:
    13561356                {
    13571357                    int rc = VBoxSHGSMICommandProcessCompletion (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, (VBOXSHGSMIHEADER*)pvCmd, TRUE /*bool bIrq*/ , &CtlList);
  • trunk/src/VBox/Devices/Graphics/DevVGA.cpp

    r50552 r50754  
    54995499    LogFlow(("vgaReset\n"));
    55005500
     5501    if (pThis->pVdma)
     5502        vboxVDMAReset(pThis->pVdma);
     5503
    55015504#ifdef VBOX_WITH_HGSMI
    55025505    VBVAReset(pThis);
     
    59495952# endif
    59505953#endif
     5954    pThis->IVBVACallbacks.pfnCrCtlSubmit = vboxCmdVBVACmdHostCtl;
    59515955
    59525956    /*
  • trunk/src/VBox/Devices/Graphics/DevVGA.h

    r50259 r50754  
    625625int vboxVDMACrHgsmiControlCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCmd, int rc);
    626626# endif
     627int vboxCmdVBVACmdHostCtl(PPDMIDISPLAYVBVACALLBACKS pInterface,
     628                                                               struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
     629                                                               PFNCRCTLCOMPLETION pfnCompletion,
     630                                                               void *pvCompletion);
    627631
    628632int vboxVBVASaveStateExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
     
    634638int vboxVDMAConstruct(PVGASTATE pVGAState, uint32_t cPipeElements);
    635639int vboxVDMADestruct(PVBOXVDMAHOST pVdma);
     640int vboxVDMAReset(PVBOXVDMAHOST pVdma);
    636641void vboxVDMAControl(PVBOXVDMAHOST pVdma, PVBOXVDMA_CTL pCmd, uint32_t cbCmd);
    637642void vboxVDMACommand(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t cbCmd);
     
    640645# endif /* VBOX_WITH_VDMA */
    641646
    642 int vboxCmdVBVAEnable(PVGASTATE pVGAState, VBVABUFFER *pVBVA);
    643 int vboxCmdVBVADisable(PVGASTATE pVGAState);
    644647int vboxCmdVBVACmdSubmit(PVGASTATE pVGAState);
    645648int vboxCmdVBVACmdFlush(PVGASTATE pVGAState);
    646649void vboxCmdVBVACmdTimer(PVGASTATE pVGAState);
     650int vboxCmdVBVACmdCtl(PVGASTATE pVGAState, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl);
    647651
    648652#endif /* VBOX_WITH_HGSMI */
  • trunk/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp

    r50259 r50754  
    19401940    switch (u16ChannelInfo)
    19411941    {
     1942        case VBVA_CMDVBVA_SUBMIT:
     1943        {
     1944            rc = vboxCmdVBVACmdSubmit(pVGAState);
     1945            break;
     1946        }
     1947        case VBVA_CMDVBVA_FLUSH:
     1948        {
     1949            rc =vboxCmdVBVACmdFlush(pVGAState);
     1950            break;
     1951        }
     1952        case VBVA_CMDVBVA_CTL:
     1953        {
     1954            if (cbBuffer < VBoxSHGSMIBufferHeaderSize() + sizeof (VBOXCMDVBVA_CTL))
     1955            {
     1956                Log(("buffer too small\n"));
     1957#ifdef DEBUG_misha
     1958                AssertMsgFailed(("buffer too small\n"));
     1959#endif
     1960                rc = VERR_INVALID_PARAMETER;
     1961                break;
     1962            }
     1963
     1964            VBOXCMDVBVA_CTL *pCtl = (VBOXCMDVBVA_CTL*)VBoxSHGSMIBufferData((PVBOXSHGSMIHEADER)pvBuffer);
     1965            rc = vboxCmdVBVACmdCtl(pVGAState, pCtl, cbBuffer - VBoxSHGSMIBufferHeaderSize());
     1966            break;
     1967        }
    19421968#ifdef VBOX_WITH_VDMA
    19431969        case VBVA_VDMA_CMD:
     
    22532279        } break;
    22542280#endif
    2255 
    2256         case VBVA_CMDVBVA_ENABLE:
    2257         {
    2258             if (cbBuffer < sizeof (VBVAENABLE))
    2259             {
    2260                 rc = VERR_INVALID_PARAMETER;
    2261                 break;
    2262             }
    2263 
    2264             VBVAENABLE *pEnable = (VBVAENABLE *)pvBuffer;
    2265 
    2266             if ((pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_ENABLE)
    2267             {
    2268                 uint32_t u32Offset = pEnable->u32Offset;
    2269                 VBVABUFFER *pVBVA = (VBVABUFFER *)HGSMIOffsetToPointerHost (pIns, u32Offset);
    2270 
    2271                 if (pVBVA)
    2272                     rc = vboxCmdVBVAEnable(pVGAState, pVBVA);
    2273                 else
    2274                 {
    2275                     LogRel(("Invalid VBVABUFFER offset 0x%x!!!\n",
    2276                          pEnable->u32Offset));
    2277                     rc = VERR_INVALID_PARAMETER;
    2278                 }
    2279             }
    2280             else if ((pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_DISABLE)
    2281             {
    2282                 rc = vboxCmdVBVADisable(pVGAState);
    2283             }
    2284             else
    2285             {
    2286                 LogRel(("Invalid VBVA_ENABLE flags 0x%x!!!\n", pEnable->u32Flags));
    2287                 rc = VERR_INVALID_PARAMETER;
    2288             }
    2289 
    2290             pEnable->i32Result = rc;
    2291             break;
    2292         }
    2293         case VBVA_CMDVBVA_SUBMIT:
    2294         {
    2295             rc = vboxCmdVBVACmdSubmit(pVGAState);
    2296             break;
    2297         }
    2298         case VBVA_CMDVBVA_FLUSH:
    2299         {
    2300             rc =vboxCmdVBVACmdFlush(pVGAState);
    2301             break;
    2302         }
    23032281        case VBVA_SCANLINE_CFG:
    23042282        {
  • trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp

    r50550 r50754  
    2121#include <iprt/mem.h>
    2222#include <iprt/asm.h>
     23#include <iprt/list.h>
    2324
    2425#include "DevVGA.h"
     
    2627
    2728#include <VBox/VBoxVideo3D.h>
     29#include <VBox/VBoxVideoHost3D.h>
     30
     31#ifdef DEBUG_misha
     32# define VBOXVDBG_MEMCACHE_DISABLE
     33#endif
     34
     35#ifndef VBOXVDBG_MEMCACHE_DISABLE
     36# include <iprt/memcache.h>
     37#endif
    2838
    2939#ifdef DEBUG_misha
     
    3747    } while (0)
    3848
    39 #ifdef VBOX_VDMA_WITH_WORKERTHREAD
    40 typedef enum
    41 {
    42     VBOXVDMAPIPE_STATE_CLOSED    = 0,
    43     VBOXVDMAPIPE_STATE_CREATED   = 1,
    44     VBOXVDMAPIPE_STATE_OPENNED   = 2,
    45     VBOXVDMAPIPE_STATE_CLOSING   = 3
    46 } VBOXVDMAPIPE_STATE;
    47 
    48 typedef struct VBOXVDMAPIPE
    49 {
     49#define VBOXVDMATHREAD_STATE_TERMINATED     0
     50#define VBOXVDMATHREAD_STATE_CREATED        1
     51#define VBOXVDMATHREAD_STATE_TERMINATING    2
     52
     53typedef struct VBOXVDMATHREAD
     54{
     55    RTTHREAD hWorkerThread;
    5056    RTSEMEVENT hEvent;
    51     /* critical section for accessing pipe properties */
    52     RTCRITSECT hCritSect;
    53     VBOXVDMAPIPE_STATE enmState;
    54     /* true iff the other end needs Event notification */
    55     bool bNeedNotify;
    56 } VBOXVDMAPIPE, *PVBOXVDMAPIPE;
    57 
    58 typedef enum
    59 {
    60     VBOXVDMAPIPE_CMD_TYPE_UNDEFINED = 0,
    61     VBOXVDMAPIPE_CMD_TYPE_DMACMD    = 1,
    62     VBOXVDMAPIPE_CMD_TYPE_DMACTL    = 2
    63 } VBOXVDMAPIPE_CMD_TYPE;
    64 
    65 typedef struct VBOXVDMAPIPE_CMD_BODY
    66 {
    67     VBOXVDMAPIPE_CMD_TYPE enmType;
    68     union
    69     {
    70         PVBOXVDMACBUF_DR pDr;
    71         PVBOXVDMA_CTL    pCtl;
    72         void            *pvCmd;
    73     } u;
    74 }VBOXVDMAPIPE_CMD_BODY, *PVBOXVDMAPIPE_CMD_BODY;
    75 
    76 typedef struct VBOXVDMAPIPE_CMD
    77 {
    78     HGSMILISTENTRY Entry;
    79     VBOXVDMAPIPE_CMD_BODY Cmd;
    80 } VBOXVDMAPIPE_CMD, *PVBOXVDMAPIPE_CMD;
    81 
    82 #define VBOXVDMAPIPE_CMD_FROM_ENTRY(_pE)  ( (PVBOXVDMAPIPE_CMD)((uint8_t *)(_pE) - RT_OFFSETOF(VBOXVDMAPIPE_CMD, Entry)) )
    83 
    84 typedef struct VBOXVDMAPIPE_CMD_POOL
    85 {
    86     HGSMILIST List;
    87     uint32_t cCmds;
    88     VBOXVDMAPIPE_CMD aCmds[1];
    89 } VBOXVDMAPIPE_CMD_POOL, *PVBOXVDMAPIPE_CMD_POOL;
    90 #endif
     57    RTSEMEVENT hClientEvent;
     58    volatile uint32_t u32State;
     59} VBOXVDMATHREAD, *PVBOXVDMATHREAD;
    9160
    9261
     
    9463 *
    9564 *   submitter   |    processor
    96  *   STOPPED
    97  *      |
    98  *      |
    99  *      >
     65 *
    10066 *  LISTENING   --->  PROCESSING
    101  *      ^               _/
    102  *      |             _/
    103  *      |           _/
    104  *      |         _/
    105  *      |       _/
    106  *      |     _/
    107  *      |    /
    108  *      <   >
    109  *     PAUSED
    11067 *
    11168 *  */
    112 #define VBVAEXHOSTCONTEXT_STATE_STOPPED        0
    113 #define VBVAEXHOSTCONTEXT_STATE_LISTENING      1
    114 #define VBVAEXHOSTCONTEXT_STATE_PROCESSING     2
    115 #define VBVAEXHOSTCONTEXT_STATE_PAUSED         3
     69#define VBVAEXHOSTCONTEXT_STATE_LISTENING      0
     70#define VBVAEXHOSTCONTEXT_STATE_PROCESSING     1
     71
     72#define VBVAEXHOSTCONTEXT_ESTATE_DISABLED     -1
     73#define VBVAEXHOSTCONTEXT_ESTATE_PAUSED        0
     74#define VBVAEXHOSTCONTEXT_ESTATE_ENABLED       1
    11675
    11776typedef struct VBVAEXHOSTCONTEXT
    11877{
    11978    VBVABUFFER *pVBVA;
    120     uint32_t cbCurData;
    121     volatile uint32_t u32State;
    122     volatile uint32_t u32Pause;
    123     volatile uint32_t u32cOtherCommands;
     79    volatile int32_t i32State;
     80    volatile int32_t i32EnableState;
     81    volatile uint32_t u32cCtls;
     82    /* critical section for accessing ctl lists */
     83    RTCRITSECT CltCritSect;
     84    RTLISTNODE GuestCtlList;
     85    RTLISTNODE HostCtlList;
     86#ifndef VBOXVDBG_MEMCACHE_DISABLE
     87    RTMEMCACHE CtlCache;
     88#endif
    12489} VBVAEXHOSTCONTEXT;
     90
     91typedef enum
     92{
     93    VBVAEXHOSTCTL_TYPE_UNDEFINED = 0,
     94    VBVAEXHOSTCTL_TYPE_HH_INTERNAL_PAUSE,
     95    VBVAEXHOSTCTL_TYPE_HH_INTERNAL_RESUME,
     96    VBVAEXHOSTCTL_TYPE_HH_ENABLE,
     97    VBVAEXHOSTCTL_TYPE_HH_TERM,
     98    VBVAEXHOSTCTL_TYPE_HH_RESET,
     99    VBVAEXHOSTCTL_TYPE_HH_SAVESTATE,
     100    VBVAEXHOSTCTL_TYPE_HH_LOADSTATE,
     101    VBVAEXHOSTCTL_TYPE_HH_BE_OPAQUE,
     102    VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE,
     103    VBVAEXHOSTCTL_TYPE_GH_ENABLE_DISABLE
     104} VBVAEXHOSTCTL_TYPE;
     105
     106struct VBVAEXHOSTCTL;
     107
     108typedef DECLCALLBACKPTR(void, PFNVBVAEXHOSTCTL_COMPLETE)(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvComplete);
     109
     110typedef struct VBVAEXHOSTCTL
     111{
     112    RTLISTNODE Node;
     113    VBVAEXHOSTCTL_TYPE enmType;
     114    union
     115    {
     116        struct
     117        {
     118            uint8_t * pu8Cmd;
     119            uint32_t cbCmd;
     120        } cmd;
     121
     122        struct
     123        {
     124            PSSMHANDLE pSSM;
     125            uint32_t u32Version;
     126        } state;
     127    } u;
     128    PFNVBVAEXHOSTCTL_COMPLETE pfnComplete;
     129    void *pvComplete;
     130} VBVAEXHOSTCTL;
    125131
    126132/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other,
     
    128134 * Can only be called be the processor, i.e. the entity that acquired the processor state by direct or indirect call to the VBoxVBVAExHSCheckCommands
    129135 * see mor edetailed comments in headers for function definitions */
    130 static bool VBoxVBVAExHPCmdCheckRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva);
    131 static int VBoxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd);
     136typedef enum
     137{
     138    VBVAEXHOST_DATA_TYPE_NO_DATA = 0,
     139    VBVAEXHOST_DATA_TYPE_CMD,
     140    VBVAEXHOST_DATA_TYPE_HOSTCTL,
     141    VBVAEXHOST_DATA_TYPE_GUESTCTL,
     142} VBVAEXHOST_DATA_TYPE;
     143static VBVAEXHOST_DATA_TYPE VBoxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd);
     144
     145static void VBoxVBVAExHPDataCompleteCmd(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint32_t cbCmd);
     146static void VBoxVBVAExHPDataCompleteCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl, int rc);
    132147
    133148/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other,
     
    135150static int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva);
    136151
    137 static void VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva);
     152static int VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva);
    138153static int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA);
    139154static int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva);
     
    142157static int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version);
    143158
     159static VBVAEXHOSTCTL* VBoxVBVAExHCtlAlloc(VBVAEXHOSTCONTEXT *pCmdVbva)
     160{
     161#ifndef VBOXVDBG_MEMCACHE_DISABLE
     162    return (VBVAEXHOSTCONTEXT*)RTMemCacheAlloc(pCmdVbva->CtlCache);
     163#else
     164    return (VBVAEXHOSTCTL*)RTMemAlloc(sizeof (VBVAEXHOSTCTL));
     165#endif
     166}
     167
     168static void VBoxVBVAExHCtlFree(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl)
     169{
     170#ifndef VBOXVDBG_MEMCACHE_DISABLE
     171    RTMemCacheFree(pCmdVbva->CtlCache, pCtl);
     172#else
     173    RTMemFree(pCtl);
     174#endif
     175}
     176
     177static VBVAEXHOSTCTL* VBoxVBVAExHCtlCreate(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL_TYPE enmType)
     178{
     179    VBVAEXHOSTCTL* pCtl = VBoxVBVAExHCtlAlloc(pCmdVbva);
     180    if (!pCtl)
     181    {
     182        WARN(("VBoxVBVAExHCtlAlloc failed\n"));
     183        return NULL;
     184    }
     185
     186    pCtl->enmType = enmType;
     187    return pCtl;
     188}
     189
     190static int vboxVBVAExHSProcessorAcquire(struct VBVAEXHOSTCONTEXT *pCmdVbva)
     191{
     192    Assert(pCmdVbva->i32State >= VBVAEXHOSTCONTEXT_STATE_LISTENING);
     193
     194    if (ASMAtomicCmpXchgS32(&pCmdVbva->i32State, VBVAEXHOSTCONTEXT_STATE_PROCESSING, VBVAEXHOSTCONTEXT_STATE_LISTENING))
     195            return VINF_SUCCESS;
     196    return VERR_SEM_BUSY;
     197}
     198
     199static VBVAEXHOSTCTL* vboxVBVAExHPCheckCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, bool *pfHostCtl, bool fHostOnlyMode)
     200{
     201    Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
     202
     203    if(!fHostOnlyMode && !ASMAtomicUoReadU32(&pCmdVbva->u32cCtls))
     204        return NULL;
     205
     206    int rc = RTCritSectEnter(&pCmdVbva->CltCritSect);
     207    if (RT_SUCCESS(rc))
     208    {
     209        VBVAEXHOSTCTL* pCtl = RTListGetFirst(&pCmdVbva->HostCtlList, VBVAEXHOSTCTL, Node);
     210        if (pCtl)
     211            *pfHostCtl = true;
     212        else if (!fHostOnlyMode)
     213        {
     214            if (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) > VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
     215            {
     216                pCtl = RTListGetFirst(&pCmdVbva->GuestCtlList, VBVAEXHOSTCTL, Node);
     217                /* pCtl can not be null here since pCmdVbva->u32cCtls is not null,
     218                 * and there are no HostCtl commands*/
     219                Assert(pCtl);
     220                *pfHostCtl = false;
     221            }
     222        }
     223
     224        if (pCtl)
     225        {
     226            RTListNodeRemove(&pCtl->Node);
     227            ASMAtomicDecU32(&pCmdVbva->u32cCtls);
     228        }
     229
     230        RTCritSectLeave(&pCmdVbva->CltCritSect);
     231
     232        return pCtl;
     233    }
     234    else
     235        WARN(("RTCritSectEnter failed %d\n", rc));
     236
     237    return NULL;
     238}
     239
     240static VBVAEXHOSTCTL* VBoxVBVAExHPCheckHostCtlOnDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva)
     241{
     242    bool fHostCtl;
     243    return vboxVBVAExHPCheckCtl(pCmdVbva, &fHostCtl, true);
     244}
     245
     246
     247static bool vboxVBVAExHPCheckProcessCtlInternal(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl)
     248{
     249    switch (pCtl->enmType)
     250    {
     251        case VBVAEXHOSTCTL_TYPE_HH_INTERNAL_PAUSE:
     252            if (pCmdVbva->i32EnableState > VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
     253                ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_PAUSED);
     254            return true;
     255        case VBVAEXHOSTCTL_TYPE_HH_INTERNAL_RESUME:
     256            if (pCmdVbva->i32EnableState == VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
     257                ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_ENABLED);
     258            return true;
     259        default:
     260            return false;
     261    }
     262}
     263
     264static void vboxVBVAExHPProcessorRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva)
     265{
     266    Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
     267
     268    ASMAtomicWriteS32(&pCmdVbva->i32State, VBVAEXHOSTCONTEXT_STATE_LISTENING);
     269}
     270
     271static void vboxVBVAExHPHgEventSet(struct VBVAEXHOSTCONTEXT *pCmdVbva)
     272{
     273    Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
     274    if (pCmdVbva->pVBVA)
     275        ASMAtomicOrU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, VBVA_F_STATE_PROCESSING);
     276}
     277
     278static void vboxVBVAExHPHgEventClear(struct VBVAEXHOSTCONTEXT *pCmdVbva)
     279{
     280    Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
     281    if (pCmdVbva->pVBVA)
     282        ASMAtomicAndU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, ~VBVA_F_STATE_PROCESSING);
     283}
     284
     285static int vboxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
     286{
     287    Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
     288    Assert(pCmdVbva->i32EnableState > VBVAEXHOSTCONTEXT_ESTATE_PAUSED);
     289
     290    VBVABUFFER *pVBVA = pCmdVbva->pVBVA;
     291
     292    uint32_t indexRecordFirst = pVBVA->indexRecordFirst;
     293    uint32_t indexRecordFree = pVBVA->indexRecordFree;
     294
     295    Log(("first = %d, free = %d\n",
     296                   indexRecordFirst, indexRecordFree));
     297
     298    if (indexRecordFirst == indexRecordFree)
     299    {
     300        /* No records to process. Return without assigning output variables. */
     301        return VINF_EOF;
     302    }
     303
     304    uint32_t cbRecordCurrent = ASMAtomicReadU32(&pVBVA->aRecords[indexRecordFirst].cbRecord);
     305
     306    /* A new record need to be processed. */
     307    if (cbRecordCurrent & VBVA_F_RECORD_PARTIAL)
     308    {
     309        /* the record is being recorded, try again */
     310        return VINF_TRY_AGAIN;
     311    }
     312
     313    uint32_t cbRecord = cbRecordCurrent & ~VBVA_F_RECORD_PARTIAL;
     314
     315    if (!cbRecord)
     316    {
     317        /* the record is being recorded, try again */
     318        return VINF_TRY_AGAIN;
     319    }
     320
     321    /* we should not get partial commands here actually */
     322    Assert(cbRecord);
     323
     324    /* The size of largest contiguous chunk in the ring biffer. */
     325    uint32_t u32BytesTillBoundary = pVBVA->cbData - pVBVA->off32Data;
     326
     327    /* The pointer to data in the ring buffer. */
     328    uint8_t *pSrc = &pVBVA->au8Data[pVBVA->off32Data];
     329
     330    /* Fetch or point the data. */
     331    if (u32BytesTillBoundary >= cbRecord)
     332    {
     333        /* The command does not cross buffer boundary. Return address in the buffer. */
     334        *ppCmd = pSrc;
     335        *pcbCmd = cbRecord;
     336        return VINF_SUCCESS;
     337    }
     338
     339    LogRel(("CmdVbva: cross-bound writes unsupported\n"));
     340    return VERR_INVALID_STATE;
     341}
     342
     343static void VBoxVBVAExHPDataCompleteCmd(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint32_t cbCmd)
     344{
     345    VBVABUFFER *pVBVA = pCmdVbva->pVBVA;
     346    pVBVA->off32Data = (pVBVA->off32Data + cbCmd) % pVBVA->cbData;
     347
     348    pVBVA->indexRecordFirst = (pVBVA->indexRecordFirst + 1) % RT_ELEMENTS(pVBVA->aRecords);
     349}
     350
     351static void VBoxVBVAExHPDataCompleteCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl, int rc)
     352{
     353    if (pCtl->pfnComplete)
     354        pCtl->pfnComplete(pCmdVbva, pCtl, rc, pCtl->pvComplete);
     355    else
     356        VBoxVBVAExHCtlFree(pCmdVbva, pCtl);
     357}
     358
     359static VBVAEXHOST_DATA_TYPE vboxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
     360{
     361    Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
     362    VBVAEXHOSTCTL*pCtl;
     363    bool fHostClt;
     364
     365    for(;;)
     366    {
     367        pCtl = vboxVBVAExHPCheckCtl(pCmdVbva, &fHostClt, false);
     368        if (pCtl)
     369        {
     370            if (fHostClt)
     371            {
     372                if (!vboxVBVAExHPCheckProcessCtlInternal(pCmdVbva, pCtl))
     373                {
     374                    *ppCmd = (uint8_t*)pCtl;
     375                    *pcbCmd = sizeof (*pCtl);
     376                    return VBVAEXHOST_DATA_TYPE_HOSTCTL;
     377                }
     378            }
     379            else
     380            {
     381                *ppCmd = (uint8_t*)pCtl;
     382                *pcbCmd = sizeof (*pCtl);
     383                return VBVAEXHOST_DATA_TYPE_GUESTCTL;
     384            }
     385        }
     386
     387        if (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) <= VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
     388            return VBVAEXHOST_DATA_TYPE_NO_DATA;
     389
     390        int rc = vboxVBVAExHPCmdGet(pCmdVbva, ppCmd, pcbCmd);
     391        switch (rc)
     392        {
     393            case VINF_SUCCESS:
     394                return VBVAEXHOST_DATA_TYPE_CMD;
     395            case VINF_EOF:
     396                return VBVAEXHOST_DATA_TYPE_NO_DATA;
     397            case VINF_TRY_AGAIN:
     398                RTThreadSleep(1);
     399                continue;
     400            default:
     401                /* this is something really unexpected, i.e. most likely guest has written something incorrect to the VBVA buffer */
     402                WARN(("Warning: vboxVBVAExHCmdGet returned unexpected status %d\n", rc));
     403                return VBVAEXHOST_DATA_TYPE_NO_DATA;
     404        }
     405    }
     406
     407    WARN(("Warning: VBoxVBVAExHCmdGet unexpected state\n"));
     408    return VBVAEXHOST_DATA_TYPE_NO_DATA;
     409}
     410
     411static VBVAEXHOST_DATA_TYPE VBoxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
     412{
     413    VBVAEXHOST_DATA_TYPE enmType = vboxVBVAExHPDataGet(pCmdVbva, ppCmd, pcbCmd);
     414    if (enmType == VBVAEXHOST_DATA_TYPE_NO_DATA)
     415    {
     416        vboxVBVAExHPHgEventClear(pCmdVbva);
     417        vboxVBVAExHPProcessorRelease(pCmdVbva);
     418        /* we need to prevent racing between us clearing the flag and command check/submission thread, i.e.
     419         * 1. we check the queue -> and it is empty
     420         * 2. submitter adds command to the queue
     421         * 3. submitter checks the "processing" -> and it is true , thus it does not submit a notification
     422         * 4. we clear the "processing" state
     423         * 5. ->here we need to re-check the queue state to ensure we do not leak the notification of the above command
     424         * 6. if the queue appears to be not-empty set the "processing" state back to "true"
     425         **/
     426        int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva);
     427        if (RT_SUCCESS(rc))
     428        {
     429            /* we are the processor now */
     430            enmType = vboxVBVAExHPDataGet(pCmdVbva, ppCmd, pcbCmd);
     431            if (enmType == VBVAEXHOST_DATA_TYPE_NO_DATA)
     432            {
     433                vboxVBVAExHPProcessorRelease(pCmdVbva);
     434                return VBVAEXHOST_DATA_TYPE_NO_DATA;
     435            }
     436
     437            vboxVBVAExHPHgEventSet(pCmdVbva);
     438        }
     439    }
     440
     441    return enmType;
     442}
     443
     444DECLINLINE(bool) vboxVBVAExHSHasCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva)
     445{
     446    VBVABUFFER *pVBVA = pCmdVbva->pVBVA;
     447
     448    if (pVBVA)
     449    {
     450        uint32_t indexRecordFirst = pVBVA->indexRecordFirst;
     451        uint32_t indexRecordFree = pVBVA->indexRecordFree;
     452
     453        if (indexRecordFirst != indexRecordFree)
     454            return true;
     455    }
     456
     457    return !!ASMAtomicReadU32(&pCmdVbva->u32cCtls);
     458}
     459
     460/* Checks whether the new commands are ready for processing
     461 * @returns
     462 *   VINF_SUCCESS - there are commands are in a queue, and the given thread is now the processor (i.e. typically it would delegate processing to a worker thread)
     463 *   VINF_EOF - no commands in a queue
     464 *   VINF_ALREADY_INITIALIZED - another thread already processing the commands
     465 *   VERR_INVALID_STATE - the VBVA is paused or pausing */
     466static int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva)
     467{
     468    int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva);
     469    if (RT_SUCCESS(rc))
     470    {
     471        /* we are the processor now */
     472        if (vboxVBVAExHSHasCommands(pCmdVbva))
     473        {
     474            vboxVBVAExHPHgEventSet(pCmdVbva);
     475            return VINF_SUCCESS;
     476        }
     477
     478        vboxVBVAExHPProcessorRelease(pCmdVbva);
     479        return VINF_EOF;
     480    }
     481    if (rc == VERR_SEM_BUSY)
     482        return VINF_ALREADY_INITIALIZED;
     483    return VERR_INVALID_STATE;
     484}
     485
     486static int VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva)
     487{
     488    memset(pCmdVbva, 0, sizeof (*pCmdVbva));
     489    int rc = RTCritSectInit(&pCmdVbva->CltCritSect);
     490    if (RT_SUCCESS(rc))
     491    {
     492#ifndef VBOXVDBG_MEMCACHE_DISABLE
     493        rc = RTMemCacheCreate(&pCmdVbva->CtlCache, sizeof (VBVAEXHOSTCTL),
     494                                0, /* size_t cbAlignment */
     495                                UINT32_MAX, /* uint32_t cMaxObjects */
     496                                NULL, /* PFNMEMCACHECTOR pfnCtor*/
     497                                NULL, /* PFNMEMCACHEDTOR pfnDtor*/
     498                                NULL, /* void *pvUser*/
     499                                0 /* uint32_t fFlags*/
     500                                );
     501        if (RT_SUCCESS(rc))
     502#endif
     503        {
     504            RTListInit(&pCmdVbva->GuestCtlList);
     505            RTListInit(&pCmdVbva->HostCtlList);
     506            pCmdVbva->i32State = VBVAEXHOSTCONTEXT_STATE_PROCESSING;
     507            pCmdVbva->i32EnableState = VBVAEXHOSTCONTEXT_ESTATE_DISABLED;
     508            return VINF_SUCCESS;
     509        }
     510#ifndef VBOXVDBG_MEMCACHE_DISABLE
     511        else
     512            WARN(("RTMemCacheCreate failed %d\n", rc));
     513#endif
     514    }
     515    else
     516        WARN(("RTCritSectInit failed %d\n", rc));
     517
     518    return rc;
     519}
     520
     521DECLINLINE(bool) VBoxVBVAExHSIsEnabled(struct VBVAEXHOSTCONTEXT *pCmdVbva)
     522{
     523    return (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) >= VBVAEXHOSTCONTEXT_ESTATE_PAUSED);
     524}
     525
     526static int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA)
     527{
     528    if (VBoxVBVAExHSIsEnabled(pCmdVbva))
     529        return VINF_ALREADY_INITIALIZED;
     530
     531    pCmdVbva->pVBVA = pVBVA;
     532    pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0;
     533    ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_ENABLED);
     534    return VINF_SUCCESS;
     535}
     536
     537static int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva)
     538{
     539    if (!VBoxVBVAExHSIsEnabled(pCmdVbva))
     540        return VINF_SUCCESS;
     541
     542    ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_DISABLED);
     543    return VINF_SUCCESS;
     544}
     545
     546static void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva)
     547{
     548    /* ensure the processor is stopped */
     549    Assert(pCmdVbva->i32State >= VBVAEXHOSTCONTEXT_STATE_LISTENING);
     550
     551    /* ensure no one tries to submit the command */
     552    if (pCmdVbva->pVBVA)
     553        pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0;
     554
     555    Assert(RTListIsEmpty(&pCmdVbva->GuestCtlList));
     556    Assert(RTListIsEmpty(&pCmdVbva->HostCtlList));
     557
     558    RTCritSectDelete(&pCmdVbva->CltCritSect);
     559
     560#ifndef VBOXVDBG_MEMCACHE_DISABLE
     561    RTMemCacheDestroy(pCmdVbva->CtlCache);
     562#endif
     563
     564    memset(pCmdVbva, 0, sizeof (*pCmdVbva));
     565}
     566
     567/* Saves state
     568 * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail
     569 */
     570static int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM)
     571{
     572    int rc;
     573
     574    int32_t i32EnableState = ASMAtomicUoReadS32(&pCmdVbva->i32EnableState);
     575    if (i32EnableState >= VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
     576    {
     577        if (i32EnableState != VBVAEXHOSTCONTEXT_ESTATE_PAUSED)
     578        {
     579            WARN(("vbva not paused\n"));
     580            return VERR_INVALID_STATE;
     581        }
     582
     583        rc = SSMR3PutU32(pSSM, (uint32_t)(((uint8_t*)pCmdVbva->pVBVA) - pu8VramBase));
     584        AssertRCReturn(rc, rc);
     585        return VINF_SUCCESS;
     586    }
     587
     588    rc = SSMR3PutU32(pSSM, 0xffffffff);
     589    AssertRCReturn(rc, rc);
     590
     591    return VINF_SUCCESS;
     592}
     593
     594typedef enum
     595{
     596    VBVAEXHOSTCTL_SOURCE_GUEST = 0,
     597    VBVAEXHOSTCTL_SOURCE_HOST_ANY,
     598    VBVAEXHOSTCTL_SOURCE_HOST_ENABLED
     599} VBVAEXHOSTCTL_SOURCE;
     600
     601
     602static int VBoxVBVAExHCtlSubmit(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
     603{
     604    if ((enmSource == VBVAEXHOSTCTL_SOURCE_HOST_ENABLED) && !VBoxVBVAExHSIsEnabled(pCmdVbva))
     605    {
     606        WARN(("cmd vbva not enabled\n"));
     607        return VERR_INVALID_STATE;
     608    }
     609
     610    pCtl->pfnComplete = pfnComplete;
     611    pCtl->pvComplete = pvComplete;
     612
     613    int rc = RTCritSectEnter(&pCmdVbva->CltCritSect);
     614    if (RT_SUCCESS(rc))
     615    {
     616        if (enmSource > VBVAEXHOSTCTL_SOURCE_GUEST)
     617        {
     618            if ((enmSource == VBVAEXHOSTCTL_SOURCE_HOST_ENABLED) && !VBoxVBVAExHSIsEnabled(pCmdVbva))
     619            {
     620                WARN(("cmd vbva not enabled\n"));
     621                RTCritSectLeave(&pCmdVbva->CltCritSect);
     622                return VERR_INVALID_STATE;
     623            }
     624            RTListAppend(&pCmdVbva->HostCtlList, &pCtl->Node);
     625        }
     626        else
     627            RTListAppend(&pCmdVbva->GuestCtlList, &pCtl->Node);
     628
     629        ASMAtomicIncU32(&pCmdVbva->u32cCtls);
     630
     631        RTCritSectLeave(&pCmdVbva->CltCritSect);
     632
     633        rc = VBoxVBVAExHSCheckCommands(pCmdVbva);
     634    }
     635    else
     636        WARN(("RTCritSectEnter failed %d\n", rc));
     637
     638    return rc;
     639}
     640
     641
     642/* Loads state
     643 * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail
     644 */
     645static int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version)
     646{
     647    AssertMsgFailed(("implement!\n"));
     648    uint32_t u32;
     649    int rc = SSMR3GetU32(pSSM, &u32);
     650    AssertRCReturn(rc, rc);
     651    if (u32 != 0xffffffff)
     652    {
     653        VBVABUFFER *pVBVA = (VBVABUFFER*)pu8VramBase + u32;
     654        rc = VBoxVBVAExHSEnable(pCmdVbva, pVBVA);
     655        AssertRCReturn(rc, rc);
     656        return VBoxVBVAExHSCheckCommands(pCmdVbva);
     657    }
     658
     659    return VINF_SUCCESS;
     660}
     661
    144662typedef struct VBOXVDMAHOST
    145663{
     
    147665    PVGASTATE pVGAState;
    148666    VBVAEXHOSTCONTEXT CmdVbva;
     667    VBOXVDMATHREAD Thread;
     668    VBOXCRCMD_SVRINFO CrSrvInfo;
     669    VBVAEXHOSTCTL* pCurRemainingHostCtl;
    149670#ifdef VBOX_VDMA_WITH_WATCHDOG
    150671    PTMTIMERR3 WatchDogTimer;
    151672#endif
    152 #ifdef VBOX_VDMA_WITH_WORKERTHREAD
    153     VBOXVDMAPIPE Pipe;
    154     HGSMILIST PendingList;
    155     RTTHREAD hWorkerThread;
    156     VBOXVDMAPIPE_CMD_POOL CmdPool;
    157 #endif
    158673} VBOXVDMAHOST, *PVBOXVDMAHOST;
    159674
     675int VBoxVDMAThreadNotifyConstructSucceeded(PVBOXVDMATHREAD pThread)
     676{
     677    Assert(pThread->u32State == VBOXVDMATHREAD_STATE_TERMINATED);
     678    int rc = RTSemEventSignal(pThread->hClientEvent);
     679    AssertRC(rc);
     680    if (RT_SUCCESS(rc))
     681    {
     682        pThread->u32State = VBOXVDMATHREAD_STATE_CREATED;
     683        return VINF_SUCCESS;
     684    }
     685    return rc;
     686}
     687
     688int VBoxVDMAThreadNotifyConstructFailed(PVBOXVDMATHREAD pThread)
     689{
     690    Assert(pThread->u32State == VBOXVDMATHREAD_STATE_TERMINATED);
     691    int rc = RTSemEventSignal(pThread->hClientEvent);
     692    AssertRC(rc);
     693    if (RT_SUCCESS(rc))
     694        return VINF_SUCCESS;
     695    return rc;
     696}
     697
     698DECLINLINE(bool) VBoxVDMAThreadIsTerminating(PVBOXVDMATHREAD pThread)
     699{
     700    return ASMAtomicUoReadU32(&pThread->u32State) == VBOXVDMATHREAD_STATE_TERMINATING;
     701}
     702
     703int VBoxVDMAThreadCreate(PVBOXVDMATHREAD pThread, PFNRTTHREAD pfnThread, void *pvThread)
     704{
     705    int rc = RTSemEventCreate(&pThread->hEvent);
     706    if (RT_SUCCESS(rc))
     707    {
     708        rc = RTSemEventCreate(&pThread->hClientEvent);
     709        if (RT_SUCCESS(rc))
     710        {
     711            pThread->u32State = VBOXVDMATHREAD_STATE_TERMINATED;
     712            rc = RTThreadCreate(&pThread->hWorkerThread, pfnThread, pvThread, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "VDMA");
     713            if (RT_SUCCESS(rc))
     714            {
     715                rc = RTSemEventWait(pThread->hClientEvent, RT_INDEFINITE_WAIT);
     716                if (RT_SUCCESS(rc))
     717                {
     718                    if (pThread->u32State == VBOXVDMATHREAD_STATE_CREATED)
     719                        return VINF_SUCCESS;
     720                    WARN(("thread routine failed the initialization\n"));
     721                    rc = VERR_INVALID_STATE;
     722                }
     723                else
     724                    WARN(("RTSemEventWait failed %d\n", rc));
     725
     726                RTThreadWait(pThread->hWorkerThread, RT_INDEFINITE_WAIT, NULL);
     727            }
     728            else
     729                WARN(("RTThreadCreate failed %d\n", rc));
     730
     731            RTSemEventDestroy(pThread->hClientEvent);
     732        }
     733        else
     734            WARN(("RTSemEventCreate failed %d\n", rc));
     735
     736        RTSemEventDestroy(pThread->hEvent);
     737    }
     738    else
     739        WARN(("RTSemEventCreate failed %d\n", rc));
     740
     741    return rc;
     742}
     743
     744DECLINLINE(int) VBoxVDMAThreadEventNotify(PVBOXVDMATHREAD pThread)
     745{
     746    int rc = RTSemEventSignal(pThread->hEvent);
     747    AssertRC(rc);
     748    return rc;
     749}
     750
     751DECLINLINE(int) VBoxVDMAThreadEventWait(PVBOXVDMATHREAD pThread, RTMSINTERVAL cMillies)
     752{
     753    int rc = RTSemEventWait(pThread->hEvent, cMillies);
     754    AssertRC(rc);
     755    return rc;
     756}
     757
     758void VBoxVDMAThreadMarkTerminating(PVBOXVDMATHREAD pThread)
     759{
     760    Assert(pThread->u32State == VBOXVDMATHREAD_STATE_CREATED);
     761    ASMAtomicWriteU32(&pThread->u32State, VBOXVDMATHREAD_STATE_TERMINATING);
     762}
     763
     764void VBoxVDMAThreadTerm(PVBOXVDMATHREAD pThread)
     765{
     766    int rc;
     767    if (ASMAtomicReadU32(&pThread->u32State) != VBOXVDMATHREAD_STATE_TERMINATING)
     768    {
     769        VBoxVDMAThreadMarkTerminating(pThread);
     770        rc = VBoxVDMAThreadEventNotify(pThread);
     771        AssertRC(rc);
     772    }
     773    rc = RTThreadWait(pThread->hWorkerThread, RT_INDEFINITE_WAIT, NULL);
     774    AssertRC(rc);
     775    RTSemEventDestroy(pThread->hClientEvent);
     776    RTSemEventDestroy(pThread->hEvent);
     777}
     778
     779static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource);
    160780
    161781#ifdef VBOX_WITH_CRHGSMI
     
    248868    if(RT_SUCCESS(rc))
    249869    {
    250         rc = vboxVDMACrCtlPostAsync (pVGAState, pCmd, cbCmd, vboxVDMACrCtlCbSetEvent, (void*)hComplEvent);
     870        rc = vboxVDMACrCtlPostAsync(pVGAState, pCmd, cbCmd, vboxVDMACrCtlCbSetEvent, (void*)hComplEvent);
    251871#ifdef DEBUG_misha
    252872        AssertRC(rc);
     
    270890}
    271891
    272 static void vboxVDMACrCmdNotifyPerform(struct VBOXVDMAHOST *pVdma)
    273 {
     892typedef struct VDMA_VBVA_CTL_CYNC_COMPLETION
     893{
     894    int rc;
     895    RTSEMEVENT hEvent;
     896} VDMA_VBVA_CTL_CYNC_COMPLETION;
     897
     898static DECLCALLBACK(void) vboxVDMACrHgcmSubmitSyncCompletion(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion)
     899{
     900    VDMA_VBVA_CTL_CYNC_COMPLETION *pData = (VDMA_VBVA_CTL_CYNC_COMPLETION*)pvCompletion;
     901    pData->rc = rc;
     902    rc = RTSemEventSignal(pData->hEvent);
     903    if (!RT_SUCCESS(rc))
     904        WARN(("RTSemEventSignal failed %d\n", rc));
     905}
     906
     907static int vboxVDMACrHgcmSubmitSync(struct VBOXVDMAHOST *pVdma, VBOXCRCMDCTL* pCtl, uint32_t cbCtl)
     908{
     909    VDMA_VBVA_CTL_CYNC_COMPLETION Data;
     910    Data.rc = VERR_NOT_IMPLEMENTED;
     911    int rc = RTSemEventCreate(&Data.hEvent);
     912    if (!RT_SUCCESS(rc))
     913    {
     914        WARN(("RTSemEventCreate failed %d\n", rc));
     915        return rc;
     916    }
     917
    274918    PVGASTATE pVGAState = pVdma->pVGAState;
    275     pVGAState->pDrv->pfnCrCmdNotifyCmds(pVGAState->pDrv);
    276 }
     919    rc = pVGAState->pDrv->pfnCrHgcmCtlSubmit(pVGAState->pDrv, pCtl, cbCtl, vboxVDMACrHgcmSubmitSyncCompletion, &Data);
     920    if (RT_SUCCESS(rc))
     921    {
     922        rc = RTSemEventWait(Data.hEvent, RT_INDEFINITE_WAIT);
     923        if (RT_SUCCESS(rc))
     924        {
     925            rc = Data.rc;
     926            if (!RT_SUCCESS(rc))
     927            {
     928                WARN(("pfnCrHgcmCtlSubmit command failed %d\n", rc));
     929            }
     930
     931        }
     932        else
     933            WARN(("RTSemEventWait failed %d\n", rc));
     934    }
     935    else
     936        WARN(("pfnCrHgcmCtlSubmit failed %d\n", rc));
     937
     938
     939    RTSemEventDestroy(Data.hEvent);
     940
     941    return rc;
     942}
     943
     944static DECLCALLBACK(VBOXCRCMDCTL*) vboxVDMACrHgcmHandleEnableRemainingHostCommand(HVBOXCRCMDCTL_REMAINING_HOST_COMMAND hClient, uint32_t *pcbCtl, int prevCmdRc)
     945{
     946    struct VBOXVDMAHOST *pVdma = hClient;
     947    if (!pVdma->pCurRemainingHostCtl)
     948    {
     949        /* disable VBVA, all subsequent host commands will go HGCM way */
     950        VBoxVBVAExHSDisable(&pVdma->CmdVbva);
     951    }
     952    else
     953    {
     954        VBoxVBVAExHPDataCompleteCtl(&pVdma->CmdVbva, pVdma->pCurRemainingHostCtl, prevCmdRc);
     955    }
     956
     957    pVdma->pCurRemainingHostCtl = VBoxVBVAExHPCheckHostCtlOnDisable(&pVdma->CmdVbva);
     958    if (pVdma->pCurRemainingHostCtl)
     959    {
     960        *pcbCtl = pVdma->pCurRemainingHostCtl->u.cmd.cbCmd;
     961        return (VBOXCRCMDCTL*)pVdma->pCurRemainingHostCtl->u.cmd.pu8Cmd;
     962    }
     963
     964    *pcbCtl = 0;
     965    return NULL;
     966}
     967
     968static int vboxVDMACrHgcmHandleEnable(struct VBOXVDMAHOST *pVdma)
     969{
     970    VBOXCRCMDCTL_ENABLE Enable;
     971    Enable.Hdr.enmType = VBOXCRCMDCTL_TYPE_ENABLE;
     972    Enable.hRHCmd = pVdma;
     973    Enable.pfnRHCmd = vboxVDMACrHgcmHandleEnableRemainingHostCommand;
     974
     975    int rc = vboxVDMACrHgcmSubmitSync(pVdma, &Enable.Hdr, sizeof (Enable));
     976    Assert(!pVdma->pCurRemainingHostCtl);
     977    if (RT_SUCCESS(rc))
     978    {
     979        Assert(!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva));
     980        return VINF_SUCCESS;
     981    }
     982
     983    Assert(VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva));
     984    WARN(("vboxVDMACrHgcmSubmitSync failed %d\n", rc));
     985
     986    return rc;
     987}
     988
     989static int vdmaVBVAEnableProcess(struct VBOXVDMAHOST *pVdma, uint32_t u32Offset)
     990{
     991    if (VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva))
     992    {
     993        WARN(("vdma VBVA is already enabled\n"));
     994        return VERR_INVALID_STATE;
     995    }
     996
     997    VBVABUFFER *pVBVA = (VBVABUFFER *)HGSMIOffsetToPointerHost(pVdma->pHgsmi, u32Offset);
     998    if (!pVBVA)
     999    {
     1000        WARN(("invalid offset %d\n", u32Offset));
     1001        return VERR_INVALID_PARAMETER;
     1002    }
     1003
     1004    if (!pVdma->CrSrvInfo.pfnEnable)
     1005    {
     1006#ifdef DEBUG_misha
     1007        WARN(("pfnEnable is NULL\n"));
     1008        return VERR_NOT_SUPPORTED;
     1009#endif
     1010    }
     1011
     1012    int rc = VBoxVBVAExHSEnable(&pVdma->CmdVbva, pVBVA);
     1013    if (RT_SUCCESS(rc))
     1014    {
     1015        VBOXCRCMDCTL Ctl;
     1016        Ctl.enmType = VBOXCRCMDCTL_TYPE_DISABLE;
     1017        rc = vboxVDMACrHgcmSubmitSync(pVdma, &Ctl, sizeof (Ctl));
     1018        if (RT_SUCCESS(rc))
     1019        {
     1020            PVGASTATE pVGAState = pVdma->pVGAState;
     1021            VBOXCRCMD_SVRENABLE_INFO Info;
     1022            Info.hCltScr = pVGAState->pDrv;
     1023            Info.pfnCltScrUpdateBegin = pVGAState->pDrv->pfnVBVAUpdateBegin;
     1024            Info.pfnCltScrUpdateProcess = pVGAState->pDrv->pfnVBVAUpdateProcess;
     1025            Info.pfnCltScrUpdateEnd = pVGAState->pDrv->pfnVBVAUpdateEnd;
     1026            rc = pVdma->CrSrvInfo.pfnEnable(pVdma->CrSrvInfo.hSvr, &Info);
     1027            if (RT_SUCCESS(rc))
     1028                return VINF_SUCCESS;
     1029            else
     1030                WARN(("pfnEnable failed %d\n", rc));
     1031
     1032            vboxVDMACrHgcmHandleEnable(pVdma);
     1033        }
     1034        else
     1035            WARN(("vboxVDMACrHgcmSubmitSync failed %d\n", rc));
     1036
     1037        VBoxVBVAExHSDisable(&pVdma->CmdVbva);
     1038    }
     1039    else
     1040        WARN(("VBoxVBVAExHSEnable failed %d\n", rc));
     1041
     1042    return rc;
     1043}
     1044
     1045static int vdmaVBVADisableProcess(struct VBOXVDMAHOST *pVdma)
     1046{
     1047    if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva))
     1048    {
     1049        Log(("vdma VBVA is already disabled\n"));
     1050        return VINF_SUCCESS;
     1051    }
     1052
     1053    int rc = pVdma->CrSrvInfo.pfnDisable(pVdma->CrSrvInfo.hSvr);
     1054    if (RT_SUCCESS(rc))
     1055    {
     1056        /* disable is a bit tricky
     1057         * we need to ensure the host ctl commands do not come out of order
     1058         * and do not come over HGCM channel until after it is enabled */
     1059        rc = vboxVDMACrHgcmHandleEnable(pVdma);
     1060        if (RT_SUCCESS(rc))
     1061            return rc;
     1062
     1063        PVGASTATE pVGAState = pVdma->pVGAState;
     1064        VBOXCRCMD_SVRENABLE_INFO Info;
     1065        Info.hCltScr = pVGAState->pDrv;
     1066        Info.pfnCltScrUpdateBegin = pVGAState->pDrv->pfnVBVAUpdateBegin;
     1067        Info.pfnCltScrUpdateProcess = pVGAState->pDrv->pfnVBVAUpdateProcess;
     1068        Info.pfnCltScrUpdateEnd = pVGAState->pDrv->pfnVBVAUpdateEnd;
     1069        pVdma->CrSrvInfo.pfnEnable(pVdma->CrSrvInfo.hSvr, &Info);
     1070    }
     1071    else
     1072        WARN(("pfnDisable failed %d\n", rc));
     1073
     1074    return rc;
     1075}
     1076
     1077static int vboxVDMACrHostCtlProcess(struct VBOXVDMAHOST *pVdma, VBVAEXHOSTCTL *pCmd)
     1078{
     1079    switch (pCmd->enmType)
     1080    {
     1081        case VBVAEXHOSTCTL_TYPE_HH_SAVESTATE:
     1082            if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva))
     1083            {
     1084                WARN(("VBVAEXHOSTCTL_TYPE_HH_SAVESTATE for disabled vdma VBVA\n"));
     1085                return VERR_INVALID_STATE;
     1086            }
     1087            return pVdma->CrSrvInfo.pfnSaveState(pVdma->CrSrvInfo.hSvr, pCmd->u.state.pSSM);
     1088        case VBVAEXHOSTCTL_TYPE_HH_LOADSTATE:
     1089            if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva))
     1090            {
     1091                WARN(("VBVAEXHOSTCTL_TYPE_HH_LOADSTATE for disabled vdma VBVA\n"));
     1092                return VERR_INVALID_STATE;
     1093            }
     1094            return pVdma->CrSrvInfo.pfnLoadState(pVdma->CrSrvInfo.hSvr, pCmd->u.state.pSSM, pCmd->u.state.u32Version);
     1095        case VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE:
     1096            if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva))
     1097            {
     1098                WARN(("VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE for disabled vdma VBVA\n"));
     1099                return VERR_INVALID_STATE;
     1100            }
     1101            return pVdma->CrSrvInfo.pfnHostCtl(pVdma->CrSrvInfo.hSvr, pCmd->u.cmd.pu8Cmd, pCmd->u.cmd.cbCmd);
     1102        case VBVAEXHOSTCTL_TYPE_HH_TERM:
     1103        {
     1104            int rc = vdmaVBVADisableProcess(pVdma);
     1105            if (!RT_SUCCESS(rc))
     1106            {
     1107                WARN(("vdmaVBVADisableProcess failed %d\n", rc));
     1108                return rc;
     1109            }
     1110
     1111            VBoxVDMAThreadMarkTerminating(&pVdma->Thread);
     1112            return VINF_SUCCESS;
     1113        }
     1114        case VBVAEXHOSTCTL_TYPE_HH_RESET:
     1115        {
     1116            int rc = vdmaVBVADisableProcess(pVdma);
     1117            if (!RT_SUCCESS(rc))
     1118            {
     1119                WARN(("vdmaVBVADisableProcess failed %d\n", rc));
     1120                return rc;
     1121            }
     1122            return VINF_SUCCESS;
     1123        }
     1124        default:
     1125            WARN(("unexpected host ctl type %d\n", pCmd->enmType));
     1126            return VERR_INVALID_PARAMETER;
     1127    }
     1128}
     1129
     1130static int vboxVDMACrGuestCtlProcess(struct VBOXVDMAHOST *pVdma, VBVAEXHOSTCTL *pCmd)
     1131{
     1132    switch (pCmd->enmType)
     1133    {
     1134       case VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE:
     1135           if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva))
     1136           {
     1137               WARN(("VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE for disabled vdma VBVA\n"));
     1138               return VERR_INVALID_STATE;
     1139           }
     1140           return pVdma->CrSrvInfo.pfnGuestCtl(pVdma->CrSrvInfo.hSvr, pCmd->u.cmd.pu8Cmd, pCmd->u.cmd.cbCmd);
     1141        case VBVAEXHOSTCTL_TYPE_GH_ENABLE_DISABLE:
     1142        {
     1143            VBVAENABLE *pEnable = (VBVAENABLE *)pCmd->u.cmd.pu8Cmd;
     1144            Assert(pCmd->u.cmd.cbCmd == sizeof (VBVAENABLE));
     1145            if ((pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_ENABLE)
     1146            {
     1147                uint32_t u32Offset = pEnable->u32Offset;
     1148                return vdmaVBVAEnableProcess(pVdma, u32Offset);
     1149            }
     1150
     1151            return vdmaVBVADisableProcess(pVdma);
     1152        }
     1153        default:
     1154            WARN(("unexpected ctl type %d\n", pCmd->enmType));
     1155            return VERR_INVALID_PARAMETER;
     1156    }
     1157}
     1158
    2771159
    2781160/*
     
    2801162 *
    2811163 */
    282 static int vboxVDMACrCmdPreprocess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd)
     1164static int vboxVDMACrCmdProcess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd)
    2831165{
    2841166    if (*pu8Cmd == VBOXCMDVBVA_OPTYPE_NOP)
     
    3051187}
    3061188
    307 static DECLCALLBACK(int) vboxVDMACrCmdCltCmdGet(HVBOXCRCMDCLT hClt, PVBOXCMDVBVA_HDR *ppNextCmd, uint32_t *pcbNextCmd)
    308 {
    309     struct VBOXVDMAHOST *pVdma = hClt;
    310 
    311     VBoxVBVAExHPCmdCheckRelease(&pVdma->CmdVbva);
    312 
    313     uint32_t cbCmd;
    314     uint8_t *pu8Cmd;
    315 
    316     for(;;)
    317     {
    318         int rc = VBoxVBVAExHPCmdGet(&pVdma->CmdVbva, &pu8Cmd, &cbCmd);
    319         switch (rc)
    320         {
    321             case VINF_SUCCESS:
    322             {
    323                 rc = vboxVDMACrCmdPreprocess(pVdma, pu8Cmd, cbCmd);
    324                 switch (rc)
    325                 {
    326                     case VINF_SUCCESS:
    327                         *ppNextCmd = (PVBOXCMDVBVA_HDR)pu8Cmd;
    328                         *pcbNextCmd = cbCmd;
    329                         return VINF_SUCCESS;
    330                     case VINF_EOF:
    331                         continue;
    332                     default:
    333                         Assert(!RT_FAILURE(rc));
    334                         return RT_FAILURE(rc) ? rc : VERR_INTERNAL_ERROR;
    335                 }
    336                 break;
    337             }
    338             case VINF_EOF:
    339                 return VINF_EOF;
    340             case VINF_PERMISSION_DENIED:
    341                 /* processing was paused, processing state was released, only VBoxVBVAExHS*** calls are now allowed */
    342                 return VINF_EOF;
    343             case VINF_INTERRUPTED:
    344                 /* command processing was interrupted, processor state remains set. client can process any commands */
    345                 vboxVDMACrCmdNotifyPerform(pVdma);
    346                 return VINF_EOF;
    347             default:
    348                 Assert(!RT_FAILURE(rc));
    349                 return RT_FAILURE(rc) ? rc : VERR_INTERNAL_ERROR;
    350         }
    351     }
    352 
    353     WARN(("Warning: vboxVDMACrCmdCltCmdGet unexpected state\n"));
    354     return VERR_INTERNAL_ERROR;
    355 }
    356 
    357 static DECLCALLBACK(int) vboxVDMACrCmdCltDmGet(HVBOXCRCMDCLT hClt, uint32_t idScreen, struct VBVAINFOSCREEN *pScreen, void **ppvVram)
    358 {
    359     struct VBOXVDMAHOST *pVdma = hClt;
    360     PVGASTATE pVGAState = pVdma->pVGAState;
    361 
    362     return VBVAGetScreenInfo(pVGAState, idScreen, pScreen, ppvVram);
     1189static DECLCALLBACK(int) vboxVDMACrCmdEnable(HVBOXCRCMDSVR hSvr, VBOXCRCMD_SVRENABLE_INFO *pInfo)
     1190{
     1191    return VINF_SUCCESS;
     1192}
     1193
     1194static DECLCALLBACK(void) vboxVDMACrCmdDisable(HVBOXCRCMDSVR hSvr)
     1195{
     1196}
     1197
     1198static DECLCALLBACK(int) vboxVDMACrCmdCtl(HVBOXCRCMDSVR hSvr, uint8_t* pCmd, uint32_t cbCmd)
     1199{
     1200    return VERR_NOT_SUPPORTED;
     1201}
     1202
     1203static DECLCALLBACK(int) vboxVDMACrCmdCmd(HVBOXCRCMDSVR hSvr, PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd)
     1204{
     1205    switch (pCmd->u8OpCode)
     1206    {
     1207#if 0
     1208        case VBOXCMDVBVA_OPTYPE_BLT_OFFPRIMSZFMT_OR_ID:
     1209        {
     1210            crVBoxServerCrCmdBltProcess(pCmd, cbCmd);
     1211            break;
     1212        }
     1213#endif
     1214        default:
     1215            WARN(("unsupported command\n"));
     1216            pCmd->i8Result = -1;
     1217    }
     1218    return VINF_SUCCESS;
    3631219}
    3641220
    3651221static int vboxVDMACrCtlHgsmiSetup(struct VBOXVDMAHOST *pVdma)
    3661222{
    367     PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pCmd;
    368     pCmd = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP) vboxVDMACrCtlCreate (VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP,
    369                                                                           sizeof (*pCmd));
     1223    PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pCmd = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP)
     1224            vboxVDMACrCtlCreate (VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP, sizeof (*pCmd));
     1225    int rc = VERR_NO_MEMORY;
    3701226    if (pCmd)
    3711227    {
    372         VBOXCRCMD_CLTINFO CltInfo;
    373         CltInfo.hClient = pVdma;
    374         CltInfo.pfnCmdGet = vboxVDMACrCmdCltCmdGet;
    375         CltInfo.pfnDmGet = vboxVDMACrCmdCltDmGet;
    3761228        PVGASTATE pVGAState = pVdma->pVGAState;
    3771229        pCmd->pvVRamBase = pVGAState->vram_ptrR3;
    3781230        pCmd->cbVRam = pVGAState->vram_size;
    379         pCmd->pCrCmdClientInfo = &CltInfo;
    380         int rc = vboxVDMACrCtlPost(pVGAState, &pCmd->Hdr, sizeof (*pCmd));
    381         Assert(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED);
     1231        rc = vboxVDMACrCtlPost(pVGAState, &pCmd->Hdr, sizeof (*pCmd));
    3821232        if (RT_SUCCESS(rc))
    3831233        {
    3841234            rc = vboxVDMACrCtlGetRc(&pCmd->Hdr);
    385         }
     1235            if (RT_SUCCESS(rc))
     1236                pVdma->CrSrvInfo = pCmd->CrCmdServerInfo;
     1237            else if (rc != VERR_NOT_SUPPORTED)
     1238                WARN(("vboxVDMACrCtlGetRc returned %d\n", rc));
     1239        }
     1240        else
     1241            WARN(("vboxVDMACrCtlPost failed %d\n", rc));
     1242
    3861243        vboxVDMACrCtlRelease(&pCmd->Hdr);
    387         return rc;
    388     }
    389     return VERR_NO_MEMORY;
     1244    }
     1245
     1246    if (!RT_SUCCESS(rc))
     1247        memset(&pVdma->CrSrvInfo, 0, sizeof (pVdma->CrSrvInfo));
     1248
     1249    return rc;
    3901250}
    3911251
     
    8831743}
    8841744
    885 #ifdef VBOX_VDMA_WITH_WORKERTHREAD
    886 
    887 int vboxVDMAPipeConstruct(PVBOXVDMAPIPE pPipe)
    888 {
    889     int rc = RTSemEventCreate(&pPipe->hEvent);
    890     AssertRC(rc);
    891     if (RT_SUCCESS(rc))
    892     {
    893         rc = RTCritSectInit(&pPipe->hCritSect);
    894         AssertRC(rc);
    895         if (RT_SUCCESS(rc))
    896         {
    897             pPipe->enmState = VBOXVDMAPIPE_STATE_CREATED;
    898             pPipe->bNeedNotify = true;
    899             return VINF_SUCCESS;
    900 //            RTCritSectDelete(pPipe->hCritSect);
    901         }
    902         RTSemEventDestroy(pPipe->hEvent);
    903     }
    904     return rc;
    905 }
    906 
    907 int vboxVDMAPipeOpenServer(PVBOXVDMAPIPE pPipe)
    908 {
    909     int rc = RTCritSectEnter(&pPipe->hCritSect);
    910     AssertRC(rc);
    911     if (RT_SUCCESS(rc))
    912     {
    913         Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED);
    914         switch (pPipe->enmState)
    915         {
    916             case VBOXVDMAPIPE_STATE_CREATED:
    917                 pPipe->enmState = VBOXVDMAPIPE_STATE_OPENNED;
    918                 pPipe->bNeedNotify = false;
    919                 rc = VINF_SUCCESS;
     1745static DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD ThreadSelf, void *pvUser)
     1746{
     1747    PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvUser;
     1748    PVGASTATE pVGAState = pVdma->pVGAState;
     1749    VBVAEXHOSTCONTEXT *pCmdVbva = &pVdma->CmdVbva;
     1750    PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
     1751    uint8_t *pCmd;
     1752    uint32_t cbCmd;
     1753
     1754    int rc = VBoxVDMAThreadNotifyConstructSucceeded(&pVdma->Thread);
     1755    if (!RT_SUCCESS(rc))
     1756    {
     1757        WARN(("VBoxVDMAThreadNotifyConstructSucceeded failed %d\n", rc));
     1758        return rc;
     1759    }
     1760
     1761    while (!VBoxVDMAThreadIsTerminating(&pVdma->Thread))
     1762    {
     1763        VBVAEXHOST_DATA_TYPE enmType = VBoxVBVAExHPDataGet(pCmdVbva, &pCmd, &cbCmd);
     1764        switch (enmType)
     1765        {
     1766            case VBVAEXHOST_DATA_TYPE_CMD:
     1767                vboxVDMACrCmdProcess(pVdma, pCmd, cbCmd);
     1768                VBoxVBVAExHPDataCompleteCmd(pCmdVbva, cbCmd);
     1769                VBVARaiseIrqNoWait(pVGAState, 0);
    9201770                break;
    921             case VBOXVDMAPIPE_STATE_OPENNED:
    922                 pPipe->bNeedNotify = false;
    923                 rc = VINF_ALREADY_INITIALIZED;
     1771            case VBVAEXHOST_DATA_TYPE_HOSTCTL:
     1772                rc = vboxVDMACrHostCtlProcess(pVdma, (VBVAEXHOSTCTL*)pCmd);
     1773                VBoxVBVAExHPDataCompleteCtl(pCmdVbva, (VBVAEXHOSTCTL*)pCmd, rc);
     1774                break;
     1775            case VBVAEXHOST_DATA_TYPE_GUESTCTL:
     1776                rc = vboxVDMACrGuestCtlProcess(pVdma, (VBVAEXHOSTCTL*)pCmd);
     1777                VBoxVBVAExHPDataCompleteCtl(pCmdVbva, (VBVAEXHOSTCTL*)pCmd, rc);
     1778                break;
     1779            case VBVAEXHOST_DATA_TYPE_NO_DATA:
     1780                rc = VBoxVDMAThreadEventWait(&pVdma->Thread, RT_INDEFINITE_WAIT);
     1781                AssertRC(rc);
    9241782                break;
    9251783            default:
    926                 AssertBreakpoint();
    927                 rc = VERR_INVALID_STATE;
     1784                WARN(("unexpected type %d\n", enmType));
    9281785                break;
    9291786        }
    930 
    931         RTCritSectLeave(&pPipe->hCritSect);
    932     }
    933     return rc;
    934 }
    935 
    936 int vboxVDMAPipeCloseServer(PVBOXVDMAPIPE pPipe)
    937 {
    938     int rc = RTCritSectEnter(&pPipe->hCritSect);
    939     AssertRC(rc);
    940     if (RT_SUCCESS(rc))
    941     {
    942         Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
    943                 || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING);
    944         switch (pPipe->enmState)
    945         {
    946             case VBOXVDMAPIPE_STATE_CLOSING:
    947                 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED;
    948                 rc = VINF_SUCCESS;
    949                 break;
    950             case VBOXVDMAPIPE_STATE_CLOSED:
    951                 rc = VINF_ALREADY_INITIALIZED;
    952                 break;
    953             default:
    954                 AssertBreakpoint();
    955                 rc = VERR_INVALID_STATE;
    956                 break;
    957         }
    958 
    959         RTCritSectLeave(&pPipe->hCritSect);
    960     }
    961     return rc;
    962 }
    963 
    964 int vboxVDMAPipeCloseClient(PVBOXVDMAPIPE pPipe)
    965 {
    966     int rc = RTCritSectEnter(&pPipe->hCritSect);
    967     AssertRC(rc);
    968     if (RT_SUCCESS(rc))
    969     {
    970         bool bNeedNotify = false;
    971         Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
    972                 || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED
    973                 ||  pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED);
    974         switch (pPipe->enmState)
    975         {
    976             case VBOXVDMAPIPE_STATE_OPENNED:
    977                 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSING;
    978                 bNeedNotify = pPipe->bNeedNotify;
    979                 pPipe->bNeedNotify = false;
    980                 break;
    981             case VBOXVDMAPIPE_STATE_CREATED:
    982                 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED;
    983                 pPipe->bNeedNotify = false;
    984                 break;
    985             case VBOXVDMAPIPE_STATE_CLOSED:
    986                 rc = VINF_ALREADY_INITIALIZED;
    987                 break;
    988             default:
    989                 AssertBreakpoint();
    990                 rc = VERR_INVALID_STATE;
    991                 break;
    992         }
    993 
    994         RTCritSectLeave(&pPipe->hCritSect);
    995 
    996         if (bNeedNotify)
    997         {
    998             rc = RTSemEventSignal(pPipe->hEvent);
    999             AssertRC(rc);
    1000         }
    1001     }
    1002     return rc;
    1003 }
    1004 
    1005 
    1006 typedef DECLCALLBACK(bool) FNHVBOXVDMARWCB(PVBOXVDMAPIPE pPipe, void *pvCallback);
    1007 typedef FNHVBOXVDMARWCB *PFNHVBOXVDMARWCB;
    1008 
    1009 int vboxVDMAPipeModifyServer(PVBOXVDMAPIPE pPipe, PFNHVBOXVDMARWCB pfnCallback, void * pvCallback)
    1010 {
    1011     int rc = RTCritSectEnter(&pPipe->hCritSect);
    1012     AssertRC(rc);
    1013     if (RT_SUCCESS(rc))
    1014     {
    1015         do
    1016         {
    1017             Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
    1018                     || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING);
    1019 
    1020             if (pPipe->enmState >= VBOXVDMAPIPE_STATE_OPENNED)
    1021             {
    1022                 bool bProcessing = pfnCallback(pPipe, pvCallback);
    1023                 pPipe->bNeedNotify = !bProcessing;
    1024                 if (bProcessing)
    1025                 {
    1026                     RTCritSectLeave(&pPipe->hCritSect);
    1027                     rc = VINF_SUCCESS;
    1028                     break;
    1029                 }
    1030                 else if (pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING)
    1031                 {
    1032                     pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED;
    1033                     RTCritSectLeave(&pPipe->hCritSect);
    1034                     rc = VINF_EOF;
    1035                     break;
    1036                 }
    1037             }
    1038             else
    1039             {
    1040                 AssertBreakpoint();
    1041                 rc = VERR_INVALID_STATE;
    1042                 RTCritSectLeave(&pPipe->hCritSect);
    1043                 break;
    1044             }
    1045 
    1046             RTCritSectLeave(&pPipe->hCritSect);
    1047 
    1048             rc = RTSemEventWait(pPipe->hEvent, RT_INDEFINITE_WAIT);
    1049             AssertRC(rc);
    1050             if (!RT_SUCCESS(rc))
    1051                 break;
    1052 
    1053             rc = RTCritSectEnter(&pPipe->hCritSect);
    1054             AssertRC(rc);
    1055             if (!RT_SUCCESS(rc))
    1056                 break;
    1057         } while (1);
    1058     }
    1059 
    1060     return rc;
    1061 }
    1062 
    1063 int vboxVDMAPipeModifyClient(PVBOXVDMAPIPE pPipe, PFNHVBOXVDMARWCB pfnCallback, void * pvCallback)
    1064 {
    1065     int rc = RTCritSectEnter(&pPipe->hCritSect);
    1066     AssertRC(rc);
    1067     if (RT_SUCCESS(rc))
    1068     {
    1069         bool bNeedNotify = false;
    1070         Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED);
    1071         if (pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED)
    1072         {
    1073             bool bModified = pfnCallback(pPipe, pvCallback);
    1074             if (bModified)
    1075             {
    1076                 bNeedNotify = pPipe->bNeedNotify;
    1077                 pPipe->bNeedNotify = false;
    1078             }
    1079         }
    1080         else
    1081             rc = VERR_INVALID_STATE;
    1082 
    1083         RTCritSectLeave(&pPipe->hCritSect);
    1084 
    1085         if (bNeedNotify)
    1086         {
    1087             rc = RTSemEventSignal(pPipe->hEvent);
    1088             AssertRC(rc);
    1089         }
    1090     }
    1091     return rc;
    1092 }
    1093 
    1094 int vboxVDMAPipeDestruct(PVBOXVDMAPIPE pPipe)
    1095 {
    1096     Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
    1097             || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED);
    1098     /* ensure the pipe is closed */
    1099     vboxVDMAPipeCloseClient(pPipe);
    1100 
    1101     Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED);
    1102 
    1103     if (pPipe->enmState != VBOXVDMAPIPE_STATE_CLOSED)
    1104         return VERR_INVALID_STATE;
    1105 
    1106     int rc = RTCritSectDelete(&pPipe->hCritSect);
    1107     AssertRC(rc);
    1108 
    1109     rc = RTSemEventDestroy(pPipe->hEvent);
    1110     AssertRC(rc);
     1787    }
    11111788
    11121789    return VINF_SUCCESS;
    11131790}
    1114 #endif
    11151791
    11161792static void vboxVDMACommandProcess(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t cbCmd)
     
    11801856    AssertRC(rc);
    11811857}
    1182 
    1183 #ifdef VBOX_VDMA_WITH_WORKERTHREAD
    1184 typedef struct
    1185 {
    1186     struct VBOXVDMAHOST *pVdma;
    1187     VBOXVDMAPIPE_CMD_BODY Cmd;
    1188     bool bHasCmd;
    1189 } VBOXVDMACMD_PROCESS_CONTEXT, *PVBOXVDMACMD_PROCESS_CONTEXT;
    1190 
    1191 static DECLCALLBACK(bool) vboxVDMACommandProcessCb(PVBOXVDMAPIPE pPipe, void *pvCallback)
    1192 {
    1193     PVBOXVDMACMD_PROCESS_CONTEXT pContext = (PVBOXVDMACMD_PROCESS_CONTEXT)pvCallback;
    1194     struct VBOXVDMAHOST *pVdma = pContext->pVdma;
    1195     HGSMILISTENTRY *pEntry = hgsmiListRemoveHead(&pVdma->PendingList);
    1196     if (pEntry)
    1197     {
    1198         PVBOXVDMAPIPE_CMD pPipeCmd = VBOXVDMAPIPE_CMD_FROM_ENTRY(pEntry);
    1199         Assert(pPipeCmd);
    1200         pContext->Cmd = pPipeCmd->Cmd;
    1201         hgsmiListPrepend(&pVdma->CmdPool.List, pEntry);
    1202         pContext->bHasCmd = true;
    1203         return true;
    1204     }
    1205 
    1206     pContext->bHasCmd = false;
    1207     return false;
    1208 }
    1209 
    1210 static DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD ThreadSelf, void *pvUser)
    1211 {
    1212     PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvUser;
    1213     PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
    1214     VBOXVDMACMD_PROCESS_CONTEXT Context;
    1215     Context.pVdma = pVdma;
    1216 
    1217     int rc = vboxVDMAPipeOpenServer(&pVdma->Pipe);
    1218     AssertRC(rc);
    1219     if (RT_SUCCESS(rc))
    1220     {
    1221         do
    1222         {
    1223             rc = vboxVDMAPipeModifyServer(&pVdma->Pipe, vboxVDMACommandProcessCb, &Context);
    1224             AssertRC(rc);
    1225             if (RT_SUCCESS(rc))
    1226             {
    1227                 switch (Context.Cmd.enmType)
    1228                 {
    1229                     case VBOXVDMAPIPE_CMD_TYPE_DMACMD:
    1230                     {
    1231                         PVBOXVDMACBUF_DR pDr = Context.Cmd.u.pDr;
    1232                         vboxVDMACommandProcess(pVdma, pDr);
    1233                         break;
    1234                     }
    1235                     case VBOXVDMAPIPE_CMD_TYPE_DMACTL:
    1236                     {
    1237                         PVBOXVDMA_CTL pCtl = Context.Cmd.u.pCtl;
    1238                         vboxVDMAControlProcess(pVdma, pCtl);
    1239                         break;
    1240                     }
    1241                     default:
    1242                         AssertBreakpoint();
    1243                         break;
    1244                 }
    1245 
    1246                 if (rc == VINF_EOF)
    1247                 {
    1248                     rc = VINF_SUCCESS;
    1249                     break;
    1250                 }
    1251             }
    1252             else
    1253                 break;
    1254         } while (1);
    1255     }
    1256 
    1257     /* always try to close the pipe to make sure the client side is notified */
    1258     int tmpRc = vboxVDMAPipeCloseServer(&pVdma->Pipe);
    1259     AssertRC(tmpRc);
    1260     return rc;
    1261 }
    1262 #endif
    12631858
    12641859#ifdef VBOX_VDMA_WITH_WATCHDOG
     
    13011896        AssertRC(rc);
    13021897#endif
    1303 #ifdef VBOX_VDMA_WITH_WORKERTHREAD
    1304         hgsmiListInit(&pVdma->PendingList);
    1305         rc = vboxVDMAPipeConstruct(&pVdma->Pipe);
    1306         AssertRC(rc);
     1898        rc = VBoxVBVAExHSInit(&pVdma->CmdVbva);
    13071899        if (RT_SUCCESS(rc))
    13081900        {
    1309             rc = RTThreadCreate(&pVdma->hWorkerThread, vboxVDMAWorkerThread, pVdma, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "VDMA");
    1310             AssertRC(rc);
     1901            rc = VBoxVDMAThreadCreate(&pVdma->Thread, vboxVDMAWorkerThread, pVdma);
    13111902            if (RT_SUCCESS(rc))
    13121903            {
    1313                 hgsmiListInit(&pVdma->CmdPool.List);
    1314                 pVdma->CmdPool.cCmds = cPipeElements;
    1315                 for (uint32_t i = 0; i < cPipeElements; ++i)
    1316                 {
    1317                     hgsmiListAppend(&pVdma->CmdPool.List, &pVdma->CmdPool.aCmds[i].Entry);
    1318                 }
    1319 # if 0 //def VBOX_WITH_CRHGSMI
    1320                 int tmpRc = vboxVDMACrCtlHgsmiSetup(pVdma);
    1321 # endif
    1322 #endif
    13231904                pVGAState->pVdma = pVdma;
    1324                 VBoxVBVAExHSInit(&pVdma->CmdVbva);
    13251905#ifdef VBOX_WITH_CRHGSMI
    13261906                int rcIgnored = vboxVDMACrCtlHgsmiSetup(pVdma); NOREF(rcIgnored); /** @todo is this ignoring intentional? */
    13271907#endif
    13281908                return VINF_SUCCESS;
    1329 #ifdef VBOX_VDMA_WITH_WORKERTHREAD
    1330             }
    1331 
    1332             int tmpRc = vboxVDMAPipeDestruct(&pVdma->Pipe);
    1333             AssertRC(tmpRc);
    1334         }
     1909            }
     1910            else
     1911                WARN(("VBoxVDMAThreadCreate faile %d\n", rc));
     1912
     1913            VBoxVBVAExHSTerm(&pVdma->CmdVbva);
     1914        }
     1915        else
     1916            WARN(("VBoxVBVAExHSInit faile %d\n", rc));
    13351917
    13361918        RTMemFree(pVdma);
    1337 #endif
    13381919    }
    13391920    else
     
    13431924}
    13441925
     1926int vboxVDMAReset(struct VBOXVDMAHOST *pVdma)
     1927{
     1928    VBVAEXHOSTCTL Ctl;
     1929    Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_RESET;
     1930    int rc = vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY);
     1931    if (!RT_SUCCESS(rc))
     1932    {
     1933        WARN(("vdmaVBVACtlSubmitSync failed %d\n", rc));
     1934        return rc;
     1935    }
     1936    return VINF_SUCCESS;
     1937}
     1938
    13451939int vboxVDMADestruct(struct VBOXVDMAHOST *pVdma)
    13461940{
    1347 #ifdef VBOX_VDMA_WITH_WORKERTHREAD
    1348     /* @todo: implement*/
    1349     AssertBreakpoint();
    1350 #endif
     1941    VBVAEXHOSTCTL Ctl;
     1942    Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_TERM;
     1943    int rc = vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY);
     1944    if (!RT_SUCCESS(rc))
     1945    {
     1946        WARN(("vdmaVBVACtlSubmitSync failed %d\n", rc));
     1947        return rc;
     1948    }
     1949    VBoxVDMAThreadTerm(&pVdma->Thread);
    13511950    VBoxVBVAExHSTerm(&pVdma->CmdVbva);
    13521951    RTMemFree(pVdma);
    13531952    return VINF_SUCCESS;
    13541953}
    1355 
    1356 #ifdef VBOX_VDMA_WITH_WORKERTHREAD
    1357 typedef struct
    1358 {
    1359     struct VBOXVDMAHOST *pVdma;
    1360     VBOXVDMAPIPE_CMD_BODY Cmd;
    1361     bool bQueued;
    1362 } VBOXVDMACMD_SUBMIT_CONTEXT, *PVBOXVDMACMD_SUBMIT_CONTEXT;
    1363 
    1364 DECLCALLBACK(bool) vboxVDMACommandSubmitCb(PVBOXVDMAPIPE pPipe, void *pvCallback)
    1365 {
    1366     PVBOXVDMACMD_SUBMIT_CONTEXT pContext = (PVBOXVDMACMD_SUBMIT_CONTEXT)pvCallback;
    1367     struct VBOXVDMAHOST *pVdma = pContext->pVdma;
    1368     HGSMILISTENTRY *pEntry = hgsmiListRemoveHead(&pVdma->CmdPool.List);
    1369     Assert(pEntry);
    1370     if (pEntry)
    1371     {
    1372         PVBOXVDMAPIPE_CMD pPipeCmd = VBOXVDMAPIPE_CMD_FROM_ENTRY(pEntry);
    1373         pPipeCmd->Cmd = pContext->Cmd;
    1374         VBoxSHGSMICommandMarkAsynchCompletion(pContext->Cmd.u.pvCmd);
    1375         pContext->bQueued = true;
    1376         hgsmiListAppend(&pVdma->PendingList, pEntry);
    1377         return true;
    1378     }
    1379 
    1380     /* @todo: should we try to flush some commands here? */
    1381     pContext->bQueued = false;
    1382     return false;
    1383 }
    1384 #endif
    13851954
    13861955int vboxVDMASaveStateExecPrep(struct VBOXVDMAHOST *pVdma, PSSMHANDLE pSSM)
     
    15452114
    15462115/**/
    1547 static int vboxVBVAExHSProcessorAcquire(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1548 {
    1549     Assert(pCmdVbva->u32State != VBVAEXHOSTCONTEXT_STATE_STOPPED);
    1550 
    1551     uint32_t oldState;
    1552     if (!ASMAtomicReadU32(&pCmdVbva->u32Pause))
    1553     {
    1554         if (ASMAtomicCmpXchgExU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PROCESSING, VBVAEXHOSTCONTEXT_STATE_LISTENING, &oldState))
    1555             return VINF_SUCCESS;
    1556         return oldState == VBVAEXHOSTCONTEXT_STATE_PROCESSING ? VERR_SEM_BUSY : VERR_INVALID_STATE;
    1557     }
    1558     return VERR_INVALID_STATE;
    1559 }
    1560 
    1561 static bool vboxVBVAExHPCheckPause(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1562 {
    1563     Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
    1564 
    1565     if (!ASMAtomicReadU32(&pCmdVbva->u32Pause))
    1566         return false;
    1567 
    1568     ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PAUSED);
    1569     return true;
    1570 }
    1571 
    1572 static bool vboxVBVAExHPCheckOtherCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1573 {
    1574     Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
    1575 
    1576     return !!ASMAtomicUoReadU32(&pCmdVbva->u32cOtherCommands);
    1577 }
    1578 
    1579 static void vboxVBVAExHPProcessorRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1580 {
    1581     Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
    1582 
    1583     if (!vboxVBVAExHPCheckPause(pCmdVbva))
    1584         ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_LISTENING);
     2116
     2117static int vdmaVBVACtlSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
     2118{
     2119    int rc = VBoxVBVAExHCtlSubmit(&pVdma->CmdVbva, pCtl, enmSource, pfnComplete, pvComplete);
     2120    if (RT_SUCCESS(rc))
     2121    {
     2122        if (rc == VINF_SUCCESS)
     2123            return VBoxVDMAThreadEventNotify(&pVdma->Thread);
     2124        else
     2125            Assert(rc == VINF_ALREADY_INITIALIZED);
     2126    }
    15852127    else
    1586         ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PAUSED);
    1587 }
    1588 
    1589 static void vboxVBVAExHPHgEventSet(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1590 {
    1591     Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
    1592 
    1593     ASMAtomicOrU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, VBVA_F_STATE_PROCESSING);
    1594 }
    1595 
    1596 static void vboxVBVAExHPHgEventClear(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1597 {
    1598     Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
    1599 
    1600     ASMAtomicAndU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, ~VBVA_F_STATE_PROCESSING);
    1601 }
    1602 
    1603 static bool vboxVBVAExHPCmdCheckRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1604 {
    1605     if (!pCmdVbva->cbCurData)
    1606         return false;
    1607 
    1608     VBVABUFFER *pVBVA = pCmdVbva->pVBVA;
    1609     pVBVA->off32Data = (pVBVA->off32Data + pCmdVbva->cbCurData) % pVBVA->cbData;
    1610 
    1611     pVBVA->indexRecordFirst = (pVBVA->indexRecordFirst + 1) % RT_ELEMENTS(pVBVA->aRecords);
    1612 
    1613     pCmdVbva->cbCurData = 0;
    1614 
    1615     return true;
    1616 }
    1617 
    1618 static int vboxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
    1619 {
    1620     Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
    1621 
    1622     VBVABUFFER *pVBVA = pCmdVbva->pVBVA;
    1623 
    1624     uint32_t indexRecordFirst = pVBVA->indexRecordFirst;
    1625     uint32_t indexRecordFree = pVBVA->indexRecordFree;
    1626 
    1627     Log(("first = %d, free = %d\n",
    1628                    indexRecordFirst, indexRecordFree));
    1629 
    1630     if (indexRecordFirst == indexRecordFree)
    1631     {
    1632         /* No records to process. Return without assigning output variables. */
    1633         return VINF_EOF;
    1634     }
    1635 
    1636     uint32_t cbRecordCurrent = ASMAtomicReadU32(&pVBVA->aRecords[indexRecordFirst].cbRecord);
    1637 
    1638     /* A new record need to be processed. */
    1639     if (cbRecordCurrent & VBVA_F_RECORD_PARTIAL)
    1640     {
    1641         /* the record is being recorded, try again */
    1642         return VINF_TRY_AGAIN;
    1643     }
    1644 
    1645     uint32_t cbRecord = cbRecordCurrent & ~VBVA_F_RECORD_PARTIAL;
    1646 
    1647     if (!cbRecord)
    1648     {
    1649         /* the record is being recorded, try again */
    1650         return VINF_TRY_AGAIN;
    1651     }
    1652 
    1653     /* we should not get partial commands here actually */
    1654     Assert(cbRecord);
    1655 
    1656     /* The size of largest contiguous chunk in the ring biffer. */
    1657     uint32_t u32BytesTillBoundary = pVBVA->cbData - pVBVA->off32Data;
    1658 
    1659     /* The pointer to data in the ring buffer. */
    1660     uint8_t *pSrc = &pVBVA->au8Data[pVBVA->off32Data];
    1661 
    1662     /* Fetch or point the data. */
    1663     if (u32BytesTillBoundary >= cbRecord)
    1664     {
    1665         /* The command does not cross buffer boundary. Return address in the buffer. */
    1666         *ppCmd = pSrc;
    1667         *pcbCmd = cbRecord;
    1668         pCmdVbva->cbCurData = cbRecord;
     2128        WARN(("VBoxVBVAExHCtlSubmit failed %d\n", rc));
     2129
     2130    return rc;
     2131}
     2132
     2133static DECLCALLBACK(void) vboxCmdVBVACmdCtlGuestCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext)
     2134{
     2135    PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvContext;
     2136    VBOXCMDVBVA_CTL *pGCtl = (VBOXCMDVBVA_CTL*)(pCtl->u.cmd.pu8Cmd - sizeof (VBOXCMDVBVA_CTL));
     2137    AssertRC(rc);
     2138    pGCtl->i32Result = rc;
     2139
     2140    Assert(pVdma->pVGAState->fGuestCaps & VBVACAPS_COMPLETEGCMD_BY_IOREAD);
     2141    rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pGCtl);
     2142    AssertRC(rc);
     2143
     2144    VBoxVBVAExHCtlFree(pVbva, pCtl);
     2145}
     2146
     2147static int vdmaVBVACtlOpaqueSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL_SOURCE enmSource, uint8_t* pu8Cmd, uint32_t cbCmd, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
     2148{
     2149    VBVAEXHOSTCTL* pHCtl = VBoxVBVAExHCtlCreate(&pVdma->CmdVbva, VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE);
     2150    if (!pHCtl)
     2151    {
     2152        WARN(("VBoxVBVAExHCtlCreate failed\n"));
     2153        return VERR_NO_MEMORY;
     2154    }
     2155
     2156    pHCtl->u.cmd.pu8Cmd = pu8Cmd;
     2157    pHCtl->u.cmd.cbCmd = cbCmd;
     2158    int rc = vdmaVBVACtlSubmit(pVdma, pHCtl, enmSource, pfnComplete, pvComplete);
     2159    if (!RT_SUCCESS(rc))
     2160    {
     2161        WARN(("vdmaVBVACtlSubmit failed rc %d\n", rc));
     2162        return rc;;
     2163    }
     2164    return VINF_SUCCESS;
     2165}
     2166
     2167static int vdmaVBVACtlOpaqueGuestSubmit(PVBOXVDMAHOST pVdma, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl)
     2168{
     2169    Assert(cbCtl >= sizeof (VBOXCMDVBVA_CTL));
     2170    VBoxSHGSMICommandMarkAsynchCompletion(pCtl);
     2171    int rc = vdmaVBVACtlOpaqueSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_GUEST, (uint8_t*)(pCtl+1), cbCtl - sizeof (VBOXCMDVBVA_CTL), vboxCmdVBVACmdCtlGuestCompletion, pVdma);
     2172    if (RT_SUCCESS(rc))
    16692173        return VINF_SUCCESS;
    1670     }
    1671 
    1672     LogRel(("CmdVbva: cross-bound writes unsupported\n"));
    1673     return VERR_INVALID_STATE;
    1674 }
    1675 
    1676 /* Resumes command processing
    1677  * @returns - same as VBoxVBVAExHSCheckCommands
    1678  */
    1679 static int vboxVBVAExHSResume(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1680 {
    1681     Assert(pCmdVbva->u32State != VBVAEXHOSTCONTEXT_STATE_STOPPED);
    1682 
    1683     ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_LISTENING);
    1684 
    1685     return VBoxVBVAExHSCheckCommands(pCmdVbva);
    1686 }
    1687 
    1688 /* pause the command processing. this will make the processor stop the command processing and release the processing state
    1689  * to resume the command processing the vboxVBVAExHSResume must be called */
    1690 static void vboxVBVAExHSPause(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1691 {
    1692     Assert(pCmdVbva->u32State != VBVAEXHOSTCONTEXT_STATE_STOPPED);
    1693 
    1694     Assert(!pCmdVbva->u32Pause);
    1695 
    1696     ASMAtomicWriteU32(&pCmdVbva->u32Pause, 1);
    1697 
    1698     for(;;)
    1699     {
    1700         if (ASMAtomicCmpXchgU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PAUSED, VBVAEXHOSTCONTEXT_STATE_LISTENING))
    1701             break;
    1702 
    1703         if (ASMAtomicReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_PAUSED)
    1704             break;
    1705 
    1706         RTThreadSleep(2);
    1707     }
    1708 
    1709     pCmdVbva->u32Pause = 0;
    1710 }
    1711 
    1712 /* releases (completed) the command previously acquired by VBoxVBVAExHCmdGet
    1713  * for convenience can be called if no command is currently acquired
    1714  * in that case it will do nothing and return false.
    1715  * if the completion notification is needed returns true. */
    1716 static bool VBoxVBVAExHPCmdCheckRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1717 {
    1718     Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
    1719 
    1720     return vboxVBVAExHPCmdCheckRelease(pCmdVbva);
    1721 }
    1722 
    1723 /*
    1724  * @returns
    1725  *  VINF_SUCCESS - new command is obtained
    1726  *  VINF_EOF - processor has completed all commands and release the processing state, only VBoxVBVAExHS*** calls are now allowed
    1727  *  VINF_PERMISSION_DENIED - processing was paused, processing state was released, only VBoxVBVAExHS*** calls are now allowed
    1728  *  VINF_INTERRUPTED - command processing was interrupted, processor state remains set. client can process any commands,
    1729  *                     and call VBoxVBVAExHPCmdGet again for further processing
    1730  *  VERR_** - error happened, most likely guest corrupted VBVA data
    1731  *
    1732  */
    1733 static int VBoxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
    1734 {
    1735     Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING);
    1736 
    1737     for(;;)
    1738     {
    1739         if (vboxVBVAExHPCheckPause(pCmdVbva))
    1740             return VINF_PERMISSION_DENIED;
    1741         if (vboxVBVAExHPCheckOtherCommands(pCmdVbva))
    1742             return VINF_INTERRUPTED;
    1743 
    1744         int rc = vboxVBVAExHPCmdGet(pCmdVbva, ppCmd, pcbCmd);
    1745         switch (rc)
    1746         {
    1747             case VINF_SUCCESS:
    1748                 return VINF_SUCCESS;
    1749             case VINF_EOF:
    1750                 vboxVBVAExHPHgEventClear(pCmdVbva);
    1751                 vboxVBVAExHPProcessorRelease(pCmdVbva);
    1752                 /* we need to prevent racing between us clearing the flag and command check/submission thread, i.e.
    1753                  * 1. we check the queue -> and it is empty
    1754                  * 2. submitter adds command to the queue
    1755                  * 3. submitter checks the "processing" -> and it is true , thus it does not submit a notification
    1756                  * 4. we clear the "processing" state
    1757                  * 5. ->here we need to re-check the queue state to ensure we do not leak the notification of the above command
    1758                  * 6. if the queue appears to be not-empty set the "processing" state back to "true"
    1759                  **/
    1760                 if (VBoxVBVAExHSCheckCommands(pCmdVbva) == VINF_SUCCESS)
    1761                     continue;
    1762                 return VINF_EOF;
    1763             case VINF_TRY_AGAIN:
    1764                 RTThreadSleep(1);
    1765                 continue;
    1766             default:
    1767                 /* this is something really unexpected, i.e. most likely guest has written something incorrect to the VBVA buffer */
    1768                 if (RT_FAILURE(rc))
    1769                     return rc;
    1770 
    1771                 WARN(("Warning: vboxVBVAExHCmdGet returned unexpected success status %d\n", rc));
    1772                 return VERR_INTERNAL_ERROR;
    1773         }
    1774     }
    1775 
    1776     WARN(("Warning: VBoxVBVAExHCmdGet unexpected state\n"));
    1777     return VERR_INTERNAL_ERROR;
    1778 }
    1779 
    1780 /* Checks whether the new commands are ready for processing
    1781  * @returns
    1782  *   VINF_SUCCESS - there are commands are in a queue, and the given thread is now the processor (i.e. typically it would delegate processing to a worker thread)
    1783  *   VINF_EOF - no commands in a queue
    1784  *   VINF_ALREADY_INITIALIZED - another thread already processing the commands
    1785  *   VERR_INVALID_STATE - the VBVA is paused or pausing */
    1786 static int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1787 {
    1788     if (ASMAtomicUoReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_STOPPED)
    1789         return VINF_EOF;
    1790 
    1791     int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva);
     2174
     2175    WARN(("vdmaVBVACtlOpaqueSubmit failed %d\n", rc));
     2176    pCtl->i32Result = rc;
     2177    rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCtl);
     2178    AssertRC(rc);
     2179    return VINF_SUCCESS;
     2180}
     2181
     2182static DECLCALLBACK(void) vboxCmdVBVACmdCtlHostCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvCompletion)
     2183{
     2184    VBOXCRCMDCTL* pVboxCtl = (VBOXCRCMDCTL*)pCtl->u.cmd.pu8Cmd;
     2185    if (pVboxCtl->pfnInternal)
     2186        ((PFNCRCTLCOMPLETION)pVboxCtl->pfnInternal)(pVboxCtl, pCtl->u.cmd.cbCmd, rc, pvCompletion);
     2187    VBoxVBVAExHCtlFree(pVbva, pCtl);
     2188}
     2189
     2190static int vdmaVBVACtlOpaqueHostSubmit(PVBOXVDMAHOST pVdma, struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
     2191        PFNCRCTLCOMPLETION pfnCompletion,
     2192        void *pvCompletion)
     2193{
     2194    pCmd->pfnInternal = (void(*)())pfnCompletion;
     2195    int rc = vdmaVBVACtlOpaqueSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_HOST_ENABLED, (uint8_t*)pCmd, cbCmd, vboxCmdVBVACmdCtlHostCompletion, pvCompletion);
     2196    if (!RT_SUCCESS(rc))
     2197    {
     2198        if (rc == VERR_INVALID_STATE)
     2199        {
     2200            pCmd->pfnInternal = NULL;
     2201            PVGASTATE pVGAState = pVdma->pVGAState;
     2202            rc = pVGAState->pDrv->pfnCrHgcmCtlSubmit(pVGAState->pDrv, pCmd, cbCmd, pfnCompletion, pvCompletion);
     2203            if (!RT_SUCCESS(rc))
     2204                WARN(("pfnCrHgsmiControlProcess failed %d\n", rc));
     2205
     2206            return rc;
     2207        }
     2208        WARN(("vdmaVBVACtlOpaqueSubmit failed %d\n", rc));
     2209        return rc;
     2210    }
     2211
     2212    return VINF_SUCCESS;
     2213}
     2214
     2215static int vdmaVBVACtlEnableDisableSubmitInternal(PVBOXVDMAHOST pVdma, VBOXCMDVBVA_CTL_ENABLE *pEnable, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
     2216{
     2217    VBVAEXHOSTCTL* pHCtl = VBoxVBVAExHCtlCreate(&pVdma->CmdVbva, VBVAEXHOSTCTL_TYPE_GH_ENABLE_DISABLE);
     2218    if (!pHCtl)
     2219    {
     2220        WARN(("VBoxVBVAExHCtlCreate failed\n"));
     2221        return VERR_NO_MEMORY;
     2222    }
     2223
     2224    pHCtl->u.cmd.pu8Cmd = (uint8_t*)&pEnable->Enable;
     2225    pHCtl->u.cmd.cbCmd = sizeof (pEnable->Enable);
     2226    int rc = vdmaVBVACtlSubmit(pVdma, pHCtl, VBVAEXHOSTCTL_SOURCE_GUEST, pfnComplete, pvComplete);
     2227    if (!RT_SUCCESS(rc))
     2228    {
     2229        WARN(("vdmaVBVACtlSubmit failed rc %d\n", rc));
     2230        return rc;;
     2231    }
     2232    return VINF_SUCCESS;
     2233}
     2234
     2235static int vdmaVBVACtlEnableDisableSubmit(PVBOXVDMAHOST pVdma, VBOXCMDVBVA_CTL_ENABLE *pEnable)
     2236{
     2237    VBoxSHGSMICommandMarkAsynchCompletion(&pEnable->Hdr);
     2238    int rc = vdmaVBVACtlEnableDisableSubmitInternal(pVdma, pEnable, vboxCmdVBVACmdCtlGuestCompletion, pVdma);
    17922239    if (RT_SUCCESS(rc))
    1793     {
    1794         /* we are the processor now */
    1795         VBVABUFFER *pVBVA = pCmdVbva->pVBVA;
    1796 
    1797         uint32_t indexRecordFirst = pVBVA->indexRecordFirst;
    1798         uint32_t indexRecordFree = pVBVA->indexRecordFree;
    1799 
    1800         if (indexRecordFirst != indexRecordFree)
    1801         {
    1802             vboxVBVAExHPHgEventSet(pCmdVbva);
    1803             return VINF_SUCCESS;
    1804         }
    1805 
    1806         vboxVBVAExHPProcessorRelease(pCmdVbva);
    1807         return VINF_EOF;
    1808     }
    1809     if (rc == VERR_SEM_BUSY)
    1810         return VINF_ALREADY_INITIALIZED;
    1811     Assert(rc == VERR_INVALID_STATE);
    1812     return VERR_INVALID_STATE;
    1813 }
    1814 
    1815 static void VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1816 {
    1817     memset(pCmdVbva, 0, sizeof (*pCmdVbva));
    1818 }
    1819 
    1820 static int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA)
    1821 {
    1822     if (ASMAtomicUoReadU32(&pCmdVbva->u32State) != VBVAEXHOSTCONTEXT_STATE_STOPPED)
    1823         return VINF_ALREADY_INITIALIZED;
    1824 
    1825     pCmdVbva->pVBVA = pVBVA;
    1826     pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0;
    1827     ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_LISTENING);
     2240        return VINF_SUCCESS;
     2241
     2242    WARN(("vdmaVBVACtlEnableDisableSubmitInternal failed %d\n", rc));
     2243    pEnable->Hdr.i32Result = rc;
     2244    rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, &pEnable->Hdr);
     2245    AssertRC(rc);
    18282246    return VINF_SUCCESS;
    18292247}
    18302248
    1831 static int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1832 {
    1833     if (ASMAtomicUoReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_STOPPED)
    1834         return VINF_SUCCESS;
    1835 
    1836     /* ensure no commands pending and one tries to submit them */
    1837     int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva);
     2249static DECLCALLBACK(void) vdmaVBVACtlSubmitSyncCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext)
     2250{
     2251    VDMA_VBVA_CTL_CYNC_COMPLETION *pData = (VDMA_VBVA_CTL_CYNC_COMPLETION*)pvContext;
     2252    pData->rc = rc;
     2253    rc = RTSemEventSignal(pData->hEvent);
     2254    if (!RT_SUCCESS(rc))
     2255        WARN(("RTSemEventSignal failed %d\n", rc));
     2256}
     2257
     2258static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource)
     2259{
     2260    VDMA_VBVA_CTL_CYNC_COMPLETION Data;
     2261    Data.rc = VERR_NOT_IMPLEMENTED;
     2262    int rc = RTSemEventCreate(&Data.hEvent);
     2263    if (!RT_SUCCESS(rc))
     2264    {
     2265        WARN(("RTSemEventCreate failed %d\n", rc));
     2266        return rc;
     2267    }
     2268
     2269    rc = vdmaVBVACtlSubmit(pVdma, pCtl, enmSource, vdmaVBVACtlSubmitSyncCompletion, &Data);
    18382270    if (RT_SUCCESS(rc))
    18392271    {
    1840         pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0;
    1841         memset(pCmdVbva, 0, sizeof (*pCmdVbva));
    1842         return VINF_SUCCESS;
    1843     }
    1844     return VERR_INVALID_STATE;
    1845 }
    1846 
    1847 static void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva)
    1848 {
    1849     /* ensure the processor is stopped */
    1850     if (ASMAtomicUoReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_STOPPED)
    1851         return;
    1852 
    1853     /* ensure no one tries to submit the command */
    1854     vboxVBVAExHSPause(pCmdVbva);
    1855     pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0;
    1856     memset(pCmdVbva, 0, sizeof (*pCmdVbva));
    1857 }
    1858 
    1859 /* Saves state
    1860  * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail
    1861  */
    1862 static int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM)
    1863 {
    1864     int rc;
    1865     if (ASMAtomicUoReadU32(&pCmdVbva->u32State) != VBVAEXHOSTCONTEXT_STATE_STOPPED)
    1866     {
    1867         vboxVBVAExHSPause(pCmdVbva);
    1868         rc = SSMR3PutU32(pSSM, (uint32_t)(((uint8_t*)pCmdVbva->pVBVA) - pu8VramBase));
    1869         AssertRCReturn(rc, rc);
    1870         return vboxVBVAExHSResume(pCmdVbva);
    1871     }
    1872 
    1873     rc = SSMR3PutU32(pSSM, 0xffffffff);
    1874     AssertRCReturn(rc, rc);
    1875 
    1876     return VINF_EOF;
    1877 }
    1878 
    1879 /* Loads state
    1880  * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail
    1881  */
    1882 static int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version)
    1883 {
    1884     uint32_t u32;
    1885     int rc = SSMR3GetU32(pSSM, &u32);
    1886     AssertRCReturn(rc, rc);
    1887     if (u32 != 0xffffffff)
    1888     {
    1889         VBVABUFFER *pVBVA = (VBVABUFFER*)pu8VramBase + u32;
    1890         rc = VBoxVBVAExHSEnable(pCmdVbva, pVBVA);
    1891         AssertRCReturn(rc, rc);
    1892         return VBoxVBVAExHSCheckCommands(pCmdVbva);
    1893     }
    1894 
    1895     return VINF_EOF;
    1896 }
    1897 
    1898 int vboxCmdVBVAEnable(PVGASTATE pVGAState, VBVABUFFER *pVBVA)
    1899 {
    1900     struct VBOXVDMAHOST *pVdma = pVGAState->pVdma;
    1901     return VBoxVBVAExHSEnable(&pVdma->CmdVbva, pVBVA);
    1902 }
    1903 
    1904 int vboxCmdVBVADisable(PVGASTATE pVGAState)
    1905 {
    1906     struct VBOXVDMAHOST *pVdma = pVGAState->pVdma;
    1907     return VBoxVBVAExHSDisable(&pVdma->CmdVbva);
    1908 }
    1909 
    1910 static int vboxCmdVBVACmdSubmitPerform(PVGASTATE pVGAState)
    1911 {
    1912     struct VBOXVDMAHOST *pVdma = pVGAState->pVdma;
     2272        rc = RTSemEventWait(Data.hEvent, RT_INDEFINITE_WAIT);
     2273        if (RT_SUCCESS(rc))
     2274        {
     2275            rc = Data.rc;
     2276            if (!RT_SUCCESS(rc))
     2277                WARN(("vdmaVBVACtlSubmitSyncCompletion returned %d\n", rc));
     2278        }
     2279        else
     2280            WARN(("RTSemEventWait failed %d\n", rc));
     2281    }
     2282    else
     2283        WARN(("vdmaVBVACtlSubmit failed %d\n", rc));
     2284
     2285    RTSemEventDestroy(Data.hEvent);
     2286
     2287    return rc;
     2288}
     2289
     2290static int vdmaVBVAPause(PVBOXVDMAHOST pVdma)
     2291{
     2292    VBVAEXHOSTCTL Ctl;
     2293    Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_INTERNAL_PAUSE;
     2294    return vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY);
     2295}
     2296
     2297static int vdmaVBVAResume(PVBOXVDMAHOST pVdma)
     2298{
     2299    VBVAEXHOSTCTL Ctl;
     2300    Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_INTERNAL_RESUME;
     2301    return vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY);
     2302}
     2303
     2304static int vboxVDMACmdSubmitPerform(struct VBOXVDMAHOST *pVdma)
     2305{
    19132306    int rc = VBoxVBVAExHSCheckCommands(&pVdma->CmdVbva);
    19142307    switch (rc)
    19152308    {
    19162309        case VINF_SUCCESS:
    1917             return pVGAState->pDrv->pfnCrCmdNotifyCmds(pVGAState->pDrv);
     2310            return VBoxVDMAThreadEventNotify(&pVdma->Thread);
    19182311        case VINF_ALREADY_INITIALIZED:
    19192312        case VINF_EOF:
     
    19262319}
    19272320
     2321
     2322int vboxCmdVBVACmdHostCtl(PPDMIDISPLAYVBVACALLBACKS pInterface,
     2323                                                               struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
     2324                                                               PFNCRCTLCOMPLETION pfnCompletion,
     2325                                                               void *pvCompletion)
     2326{
     2327    PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
     2328    struct VBOXVDMAHOST *pVdma = pVGAState->pVdma;
     2329    return vdmaVBVACtlOpaqueHostSubmit(pVdma, pCmd, cbCmd, pfnCompletion, pvCompletion);
     2330}
     2331
     2332int vboxCmdVBVACmdCtl(PVGASTATE pVGAState, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl)
     2333{
     2334    struct VBOXVDMAHOST *pVdma = pVGAState->pVdma;
     2335    int rc = VINF_SUCCESS;
     2336    switch (pCtl->u32Type)
     2337    {
     2338        case VBOXCMDVBVACTL_TYPE_3DCTL:
     2339            return vdmaVBVACtlOpaqueGuestSubmit(pVdma, pCtl, cbCtl);
     2340        case VBOXCMDVBVACTL_TYPE_ENABLE:
     2341            if (cbCtl != sizeof (VBOXCMDVBVA_CTL_ENABLE))
     2342            {
     2343                WARN(("incorrect enable size\n"));
     2344                rc = VERR_INVALID_PARAMETER;
     2345                break;
     2346            }
     2347            return vdmaVBVACtlEnableDisableSubmit(pVdma, (VBOXCMDVBVA_CTL_ENABLE*)pCtl);
     2348        default:
     2349            WARN(("unsupported type\n"));
     2350            rc = VERR_INVALID_PARAMETER;
     2351            break;
     2352    }
     2353
     2354    pCtl->i32Result = rc;
     2355    rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCtl);
     2356    AssertRC(rc);
     2357    return VINF_SUCCESS;
     2358}
     2359
    19282360int vboxCmdVBVACmdSubmit(PVGASTATE pVGAState)
    19292361{
    1930     return vboxCmdVBVACmdSubmitPerform(pVGAState);
     2362    if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva))
     2363    {
     2364        WARN(("vdma VBVA is disabled\n"));
     2365        return VERR_INVALID_STATE;
     2366    }
     2367
     2368    return vboxVDMACmdSubmitPerform(pVGAState->pVdma);
    19312369}
    19322370
    19332371int vboxCmdVBVACmdFlush(PVGASTATE pVGAState)
    19342372{
    1935     return vboxCmdVBVACmdSubmitPerform(pVGAState);
     2373    WARN(("flush\n"));
     2374    if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva))
     2375    {
     2376        WARN(("vdma VBVA is disabled\n"));
     2377        return VERR_INVALID_STATE;
     2378    }
     2379    return vboxVDMACmdSubmitPerform(pVGAState->pVdma);
    19362380}
    19372381
    19382382void vboxCmdVBVACmdTimer(PVGASTATE pVGAState)
    19392383{
    1940     vboxCmdVBVACmdSubmitPerform(pVGAState);
    1941 }
     2384    if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva))
     2385        return;
     2386    vboxVDMACmdSubmitPerform(pVGAState->pVdma);
     2387}
  • trunk/src/VBox/GuestHost/OpenGL/include/cr_server.h

    r50394 r50754  
    3434#include <VBox/Hardware/VBoxVideoVBE.h>
    3535#include <VBox/VBoxVideo3D.h>
     36#include <VBox/VBoxVideoHost3D.h>
    3637
    3738#ifdef __cplusplus
     
    406407    uint32_t fBlitterMode;
    407408    CR_BLITTER Blitter;
    408 
    409     VBOXCRCMD_CLTINFO CltInfo;
    410409
    411410    CR_SERVER_RPW RpwWorker;
     
    486485    SPUDispatchTable TmpCtxDispatch;
    487486
     487    VBOXCRCMD_SVRENABLE_INFO CrCmdClientInfo;
     488
    488489#ifdef VBOX_WITH_CRSERVER_DUMPER
    489490    CR_RECORDER Recorder;
     
    566567extern DECLEXPORT(int32_t) crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t cbCtl);
    567568
    568 extern DECLEXPORT(int32_t) crVBoxServerCrCmdNotifyCmds();
    569569#endif
    570570
  • trunk/src/VBox/GuestHost/OpenGL/include/cr_vreg.h

    r50412 r50754  
    6464    VBoxRectScale(pResult, xScale, yScale);
    6565}
     66
     67DECLINLINE(void) VBoxRectUnscale(PRTRECT pRect, float xScale, float yScale)
     68{
     69    pRect->xLeft = CR_FLOAT_RCAST(int32_t, pRect->xLeft / xScale);
     70    pRect->yTop = CR_FLOAT_RCAST(int32_t, pRect->yTop / yScale);
     71    pRect->xRight = CR_FLOAT_RCAST(int32_t, pRect->xRight / xScale);
     72    pRect->yBottom = CR_FLOAT_RCAST(int32_t, pRect->yBottom / yScale);
     73}
     74
     75DECLINLINE(void) VBoxRectUnscaled(const RTRECT *pRect, float xScale, float yScale, PRTRECT pResult)
     76{
     77    *pResult = *pRect;
     78    VBoxRectUnscale(pResult, xScale, yScale);
     79}
    6680#endif
    6781
  • trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp

    r50394 r50754  
    962962 * We differentiate between a function handler for the guest and one for the host.
    963963 */
    964 static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     964static int svcHostCallPerform(void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    965965{
    966966    int rc = VINF_SUCCESS;
     
    980980    switch (u32Function)
    981981    {
    982         case SHCRGL_HOST_FN_CRCMD_NOTIFY_CMDS:
    983         {
    984             rc = crVBoxServerCrCmdNotifyCmds();
    985         } break;
    986982#ifdef VBOX_WITH_CRHGSMI
    987983        case SHCRGL_HOST_FN_CRHGSMI_CMD:
     
    14771473}
    14781474
     1475static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     1476{
     1477    switch (u32Function)
     1478    {
     1479        case SHCRGL_HOST_FN_CTL:
     1480        {
     1481            if (cParms != 1)
     1482            {
     1483                WARN(("cParams != 1"));
     1484                return VERR_INVALID_PARAMETER;
     1485            }
     1486
     1487            if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
     1488            {
     1489                WARN(("invalid param type"));
     1490                return VERR_INVALID_PARAMETER;
     1491            }
     1492
     1493            if (paParms->u.pointer.size < sizeof (VBOXCRCMDCTL))
     1494            {
     1495                WARN(("invalid param size"));
     1496                return VERR_INVALID_PARAMETER;
     1497            }
     1498
     1499            if ((paParms->u.pointer.size - sizeof (VBOXCRCMDCTL)) % sizeof(VBOXHGCMSVCPARM))
     1500            {
     1501                WARN(("invalid param size"));
     1502                return VERR_INVALID_PARAMETER;
     1503            }
     1504
     1505            VBOXCRCMDCTL *pCtl = (VBOXCRCMDCTL*)paParms->u.pointer.addr;
     1506            uint32_t cParams = (paParms->u.pointer.size - sizeof (VBOXCRCMDCTL)) / sizeof (VBOXHGCMSVCPARM);
     1507            return svcHostCallPerform(NULL, pCtl->u32Function, cParms, (VBOXHGCMSVCPARM*)(pCtl + 1));
     1508        }
     1509        case VBOXCRCMDCTL_TYPE_DISABLE:
     1510            AssertMsgFailed(("VBOXCRCMDCTL_TYPE_DISABLE\n"));
     1511            return VERR_NOT_IMPLEMENTED;
     1512        case VBOXCRCMDCTL_TYPE_ENABLE:
     1513            AssertMsgFailed(("VBOXCRCMDCTL_TYPE_ENABLE\n"));
     1514            return VERR_NOT_IMPLEMENTED;
     1515        default:
     1516            return svcHostCallPerform(NULL, u32Function, cParms, paParms);
     1517    }
     1518
     1519}
     1520
    14791521extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
    14801522{
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h

    r50625 r50754  
    428428void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext);
    429429int CrFbResize(HCR_FRAMEBUFFER hFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM);
    430 int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pPrects, CR_BLITTER_IMG *pImg);
     430int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pPrects, CR_BLITTER_IMG *pImg);
    431431bool CrFbIsEnabled(HCR_FRAMEBUFFER hFb);
    432432int CrFbEntryCreateForTexId(HCR_FRAMEBUFFER hFb, GLuint idTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry);
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c

    r50625 r50754  
    31863186}
    31873187
    3188 static int32_t crVBoxServerCrCmdProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd)
    3189 {
     3188static DECLCALLBACK(int) crVBoxCrCmdEnable(HVBOXCRCMDSVR hSvr, VBOXCRCMD_SVRENABLE_INFO *pInfo)
     3189{
     3190    cr_server.CrCmdClientInfo = *pInfo;
     3191    AssertFailed();
     3192    return VERR_NOT_IMPLEMENTED;
     3193}
     3194
     3195static DECLCALLBACK(int) crVBoxCrCmdDisable(HVBOXCRCMDSVR hSvr)
     3196{
     3197    AssertFailed();
     3198    memset(&cr_server.CrCmdClientInfo, 0, sizeof (cr_server.CrCmdClientInfo));
     3199    return VERR_NOT_IMPLEMENTED;
     3200}
     3201
     3202static DECLCALLBACK(int) crVBoxCrCmdHostCtl(HVBOXCRCMDSVR hSvr, uint8_t* pCmd, uint32_t cbCmd)
     3203{
     3204    AssertFailed();
     3205    return VERR_NOT_IMPLEMENTED;
     3206}
     3207
     3208static DECLCALLBACK(int) crVBoxCrCmdGuestCtl(HVBOXCRCMDSVR hSvr, uint8_t* pCmd, uint32_t cbCmd)
     3209{
     3210    AssertFailed();
     3211    return VERR_NOT_IMPLEMENTED;
     3212}
     3213
     3214static DECLCALLBACK(int) crVBoxCrCmdSaveState(HVBOXCRCMDSVR hSvr, PSSMHANDLE pSSM)
     3215{
     3216    AssertFailed();
     3217    return VERR_NOT_IMPLEMENTED;
     3218}
     3219
     3220static DECLCALLBACK(int) crVBoxCrCmdLoadState(HVBOXCRCMDSVR hSvr, PSSMHANDLE pSSM, uint32_t u32Version)
     3221{
     3222    AssertFailed();
     3223    return VERR_NOT_IMPLEMENTED;
     3224}
     3225
     3226
     3227static DECLCALLBACK(int) crVBoxCrCmdCmd(HVBOXCRCMDSVR hSvr, PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd)
     3228{
     3229    AssertFailed();
    31903230    switch (pCmd->u8OpCode)
    31913231    {
     
    32193259}
    32203260
    3221 int32_t crVBoxServerCrCmdNotifyCmds()
    3222 {
    3223     PVBOXCMDVBVA_HDR pCmd = NULL;
    3224     uint32_t cbCmd;
    3225 
    3226     for (;;)
    3227     {
    3228         int rc = cr_server.CltInfo.pfnCmdGet(cr_server.CltInfo.hClient, &pCmd, &cbCmd);
    3229         if (rc == VINF_EOF)
    3230             return VINF_SUCCESS;
    3231         if (!RT_SUCCESS(rc))
    3232             return rc;
    3233 
    3234         rc = crVBoxServerCrCmdProcess(pCmd, cbCmd);
    3235         if (!RT_SUCCESS(rc))
    3236             return rc;
    3237     }
    3238 
    3239     /* should not be here! */
    3240     AssertFailed();
    3241     return VERR_INTERNAL_ERROR;
    3242 }
    3243 
    32443261/* We moved all CrHgsmi command processing to crserverlib to keep the logic of dealing with CrHgsmi commands in one place.
    32453262 *
     
    35943611            g_pvVRamBase = (uint8_t*)pSetup->pvVRamBase;
    35953612            g_cbVRam = pSetup->cbVRam;
    3596             cr_server.CltInfo = *pSetup->pCrCmdClientInfo;
     3613            pSetup->CrCmdServerInfo.hSvr = NULL;
     3614            pSetup->CrCmdServerInfo.pfnEnable = crVBoxCrCmdEnable;
     3615            pSetup->CrCmdServerInfo.pfnDisable = crVBoxCrCmdDisable;
     3616            pSetup->CrCmdServerInfo.pfnCmd = crVBoxCrCmdCmd;
     3617            pSetup->CrCmdServerInfo.pfnHostCtl = crVBoxCrCmdHostCtl;
     3618            pSetup->CrCmdServerInfo.pfnGuestCtl = crVBoxCrCmdGuestCtl;
     3619            pSetup->CrCmdServerInfo.pfnSaveState = crVBoxCrCmdSaveState;
     3620            pSetup->CrCmdServerInfo.pfnLoadState = crVBoxCrCmdLoadState;
    35973621            rc = VINF_SUCCESS;
    35983622            break;
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp

    r50625 r50754  
    687687            || pScreen->u16BitsPerPixel != 32)
    688688    {
    689         RTRECT Rect;
     689        RTRECT SrcRect;
     690        RTRECT DstRect;
    690691
    691692        pScreenshot->Img.cbData = pScreen->u32LineSize * pScreen->u32Height;
     
    711712        pScreenshot->Img.bpp = 32;
    712713        pScreenshot->Img.pitch = pitch;
    713         Rect.xLeft = 0;
    714         Rect.yTop = 0;
    715         Rect.xRight = pScreen->u32Width;
    716         Rect.yBottom = pScreen->u32Height;
    717         int rc = CrFbBltGetContents(hFb, &Rect, 1, &Rect, &pScreenshot->Img);
     714        SrcRect.xLeft = 0;
     715        SrcRect.yTop = 0;
     716        SrcRect.xRight = pScreen->u32Width;
     717        SrcRect.yBottom = pScreen->u32Height;
     718        DstRect.xLeft = 0;
     719        DstRect.yTop = 0;
     720        DstRect.xRight = width;
     721        DstRect.yBottom = height;
     722        int rc = CrFbBltGetContents(hFb, &SrcRect, &DstRect, 1, &DstRect, &pScreenshot->Img);
    718723        if (!RT_SUCCESS(rc))
    719724        {
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp

    r50430 r50754  
    320320}
    321321
     322static void crFbBltImgScaledRects(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, const RTPOINT *pDstDataPoint, float strX, float strY, CR_BLITTER_IMG *pDst)
     323{
     324    int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x;
     325    int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y;
     326    Assert(srcX >= 0);
     327    Assert(srcY >= 0);
     328
     329    RTRECT UnscaledCopyRect;
     330    VBoxRectUnscaled(pCopyRect, strX, strY, &UnscaledCopyRect);
     331
     332    srcX = CR_FLOAT_RCAST(int32_t, srcX / strX);
     333    srcY = CR_FLOAT_RCAST(int32_t, srcY / strY);
     334
     335    int32_t UnscaledSrcWidth = UnscaledCopyRect.xRight - UnscaledCopyRect.xLeft;
     336    int32_t delta = (int32_t)pSrc->width - srcX - UnscaledSrcWidth;
     337    if (delta < 0)
     338        UnscaledSrcWidth += delta;
     339
     340    if (UnscaledSrcWidth <= 0)
     341    {
     342        LOG(("UnscaledSrcWidth <= 0"));
     343        if (UnscaledSrcWidth < 0)
     344            WARN(("src width (%d) < 0", UnscaledSrcWidth));
     345        return;
     346    }
     347
     348    int32_t UnscaledSrcHeight = UnscaledCopyRect.yBottom - UnscaledCopyRect.yTop;
     349    delta = (int32_t)pSrc->height - srcY - UnscaledSrcHeight;
     350    if (delta < 0)
     351        UnscaledSrcHeight += delta;
     352
     353    if (UnscaledSrcHeight <= 0)
     354    {
     355        LOG(("UnscaledSrcHeight <= 0"));
     356        if (UnscaledSrcHeight < 0)
     357            WARN(("src height (%d) < 0", UnscaledSrcHeight));
     358        return;
     359    }
     360
     361    int32_t dstX = pCopyRect->xLeft - pDstDataPoint->x;
     362    int32_t dstY = pCopyRect->yTop - pDstDataPoint->y;
     363    Assert(dstX >= 0);
     364    Assert(dstY >= 0);
     365
     366
     367    uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4;
     368    uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4;
     369
     370    CrBmpScale32(pu8Dst, pDst->pitch,
     371                        pCopyRect->xRight - pCopyRect->xLeft,
     372                        pCopyRect->yBottom - pCopyRect->yTop,
     373                        pu8Src,
     374                        fSrcInvert ? -pSrc->pitch : pSrc->pitch,
     375                        UnscaledSrcWidth,
     376                        UnscaledSrcHeight
     377                        );
     378}
     379
    322380static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
    323381{
     
    338396}
    339397
    340 static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
     398static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    341399{
    342400    VBOXVR_LIST List;
     
    348406
    349407    VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    350     RTPOINT SrcPoint = {pSrcRect->xLeft, pSrcRect->yTop};
    351     float strX = ((float)pImg->width) / (pSrcRect->xRight - pSrcRect->xLeft);
    352     float strY = ((float)pImg->height) / (pSrcRect->yBottom - pSrcRect->yTop);
    353 
    354     RTPOINT ScaledSrcPoint;
    355     ScaledSrcPoint.x = CR_FLOAT_RCAST(int32_t, strX * SrcPoint.x);
    356     ScaledSrcPoint.y = CR_FLOAT_RCAST(int32_t, strY * SrcPoint.y);
    357 
    358     RTPOINT ZeroPoint = {0, 0};
     408    int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
     409    int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
     410    int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
     411    int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
     412
     413    RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
     414    float strX = ((float)dstWidth) / srcWidth;
     415    float strY = ((float)dstHeight) / srcHeight;
     416    bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
     417
     418    const RTPOINT ZeroPoint = {0, 0};
    359419
    360420    VBoxVrListInit(&List);
     
    388448        }
    389449
    390         for (uint32_t i = 0; i < cRects; ++i)
    391         {
    392             const RTRECT * pRect = &pRects[i];
    393             for (uint32_t j = 0; j < cRegions; ++j)
     450        for (uint32_t j = 0; j < cRegions; ++j)
     451        {
     452            /* rects are in dst coordinates,
     453             * while the pReg is in source coords
     454             * convert */
     455            const RTRECT * pReg = &pRegions[j];
     456            RTRECT ScaledReg;
     457            /* scale */
     458            VBoxRectScaled(pReg, strX, strY, &ScaledReg);
     459            /* translate */
     460            VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
     461
     462            for (uint32_t i = 0; i < cRects; ++i)
    394463            {
    395                 const RTRECT * pReg = &pRegions[j];
     464                const RTRECT * pRect = &pRects[i];
     465
    396466                RTRECT Intersection;
    397                 VBoxRectIntersected(pRect, pReg, &Intersection);
    398                 if (VBoxRectIsZero(&Intersection))
    399                     continue;
    400 
    401                 VBoxRectScale(&Intersection, strX, strY);
     467                VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
    402468                if (VBoxRectIsZero(&Intersection))
    403469                    continue;
     
    455521                    width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
    456522                    height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
    457                     ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft);
    458                     ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop);
     523                    ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
     524                    ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
    459525                }
    460526
     
    468534                bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    469535
    470                 crFbBltImg(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, &ScaledSrcPoint, pImg);
     536                crFbBltImg(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, &ZeroPoint, pImg);
    471537
    472538                CrTdBltDataReleaseScaled(pTex, pSrcImg);
     
    503569        }
    504570
     571        const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
     572
     573        CR_BLITTER_IMG FbImg;
     574
     575        crFbImgFromFb(hFb, &FbImg);
     576
     577        for (uint32_t j = 0; j < c2DRects; ++j)
     578        {
     579            const RTRECT * p2DRect = &p2DRects[j];
     580            RTRECT ScaledReg;
     581            /* scale */
     582            VBoxRectScaled(p2DRect, strX, strY, &ScaledReg);
     583            /* translate */
     584            VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
     585
     586            for (uint32_t i = 0; i < cRects; ++i)
     587            {
     588                const RTRECT * pRect = &pRects[i];
     589                RTRECT Intersection;
     590
     591                VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
     592                if (VBoxRectIsZero(&Intersection))
     593                    continue;
     594
     595                if (!fScale)
     596                    crFbBltImg(&FbImg, &DstPoint, false, &Intersection, &ZeroPoint, pImg);
     597                else
     598                    crFbBltImgScaledRects(&FbImg, &DstPoint, false, &Intersection, &ZeroPoint, strX, strY, pImg);
     599            }
     600        }
     601    }
     602
     603end:
     604
     605    if (pEnteredTex)
     606        CrTdBltLeave(pEnteredTex);
     607
     608    if (pEnteredBlitter)
     609        CrBltLeave(pEnteredBlitter);
     610
     611    VBoxVrListClear(&List);
     612
     613    return rc;
     614}
     615
     616static int crFbBltGetContentsScaleCPU(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
     617{
     618    int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
     619    int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
     620    int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
     621    int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
     622
     623    RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
     624    float strX = ((float)dstWidth) / srcWidth;
     625    float strY = ((float)dstHeight) / srcHeight;
     626
     627    RTRECT DstRect;
     628    VBoxRectUnscaled(pDstRect, strX, strY, &DstRect);
     629    DstRect.xRight = DstRect.xLeft + srcWidth;
     630    DstRect.yBottom = DstRect.yTop + srcHeight;
     631
     632    /* destination is bigger than the source, do 3D data stretching with CPU */
     633    CR_BLITTER_IMG Img;
     634    Img.cbData = srcWidth * srcHeight * 4;
     635    Img.pvData = RTMemAlloc(Img.cbData);
     636    if (!Img.pvData)
     637    {
     638        WARN(("RTMemAlloc Failed"));
     639        return VERR_NO_MEMORY;
     640    }
     641    Img.enmFormat = pImg->enmFormat;
     642    Img.width = srcWidth;
     643    Img.height = srcHeight;
     644    Img.bpp = pImg->bpp;
     645    Img.pitch = Img.width * 4;
     646
     647    int rc = CrFbBltGetContents(hFb, pSrcRect, &DstRect, cRects, pRects, &Img);
     648    if (RT_SUCCESS(rc))
     649    {
     650        CrBmpScale32((uint8_t *)pImg->pvData,
     651                            pImg->pitch,
     652                            pImg->width, pImg->height,
     653                            (const uint8_t *)Img.pvData,
     654                            Img.pitch,
     655                            Img.width, Img.height);
     656    }
     657    else
     658        WARN(("CrFbBltGetContents failed %d", rc));
     659
     660    RTMemFree(Img.pvData);
     661
     662    return rc;
     663
     664}
     665
     666int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
     667{
     668    uint32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
     669    uint32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
     670    uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
     671    uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
     672    if ((srcWidth == dstWidth
     673            && srcHeight == dstHeight)
     674            || !CrFbHas3DData(hFb)
     675            || (srcWidth * srcHeight > dstWidth * dstHeight))
     676    {
     677        return crFbBltGetContentsDirect(hFb, pSrcRect, pDstRect, cRects, pRects, pImg);
     678    }
     679
     680    return crFbBltGetContentsScaleCPU(hFb, pSrcRect, pDstRect, cRects, pRects, pImg);
     681}
     682
     683#if 0
     684static int crFbBltPutContentsVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pDstPoint, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg, float strX, float strY)
     685{
     686    const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
     687    const RTPOINT ZeroPoint = {0};
     688
     689    uint32_t fbWidth = (pCompRect->xRight - pCompRect->xLeft);
     690    uint32_t fbHeight = pCompRect->yBottom - pCompRect->yTop;
     691
     692    uint32_t stretchedWidth = CR_FLOAT_RCAST(uint32_t, strX * fbWidth);
     693    uint32_t stretchedHeight = CR_FLOAT_RCAST(uint32_t, strY * fbHeight);
     694
     695    CR_BLITTER_IMG FbImg;
     696
     697    bool fScale = fbWidth != stretchedWidth || fbHeight != stretchedHeight;
     698
     699    crFbImgFromFb(hFb, &FbImg);
     700
     701    RTRECT Intersection;
     702
     703    for (uint32_t i = 0; i < cRects; ++i)
     704    {
     705        const RTRECT * pRect = &pRects[i];
     706        VBoxRectIntersected(pRect, pCompRect, &Intersection);
     707
     708        if (VBoxRectIsZero(&Intersection))
     709            continue;
     710
     711        if (!fScale)
     712            crFbBltImg(pImg, pDstPoint, false, &Intersection, &ZeroPoint, &FbImg);
     713        else
     714            crFbBltImgScaled(pImg, pDstPoint, false, &Intersection, &ZeroPoint, strX, strY, &FbImg);
     715    }
     716
     717    return VINF_SUCCESS;
     718}
     719
     720int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
     721{
     722    RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
     723    float strX = ((float)pImg->width) / (pDstRect->xRight - pDstRect->xLeft);
     724    float strY = ((float)pImg->height) / (pDstRect->yBottom - pDstRect->yTop);
     725
     726    int rc = CrFbEntryRegionsAdd(hFb, NULL, const RTPOINT *pPos, cRects, pRects, true)
     727    if (!hFb->cUpdating)
     728    {
     729        WARN(("not updating\n"));
     730        return VERR_INVALID_STATE;
     731    }
     732}
     733
     734int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
     735{
     736    uint32_t cCompRects;
     737    const RTRECT *pCompRects;
     738    int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects);
     739    if (!RT_SUCCESS(rc))
     740    {
     741        WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
     742        return rc;
     743    }
     744
     745    bool fRegChanged = false;
     746    for (uint32_t i = 0; i < cCompRects; ++i)
     747    {
     748        const RTRECT *pCompRect = pCompRects[i];
     749        for (uint32_t j = 0; j < cRects; ++j)
     750        {
     751            const RTRECT *pRect = pRects[j];
     752            if (VBoxRectIsIntersect(pCompRect, pRect))
     753            {
     754                fRegChanged = true;
     755                break;
     756            }
     757        }
     758    }
     759
     760    if (fRegChanged)
     761    {
     762        rc = CrFbUpdateBegin(hFb);
     763        if (RT_SUCCESS(rc))
     764        {
     765            rc = CrFbBltPutContents(hFb, pDstRect, cRects, pRects, pImg);
     766            if (!RT_SUCCESS(rc))
     767                WARN(("CrFbBltPutContents failed rc %d", rc));
     768            CrFbUpdateEnd(hFb);
     769        }
     770        else
     771            WARN(("CrFbUpdateBegin failed rc %d", rc));
     772
     773        return rc;
     774    }
     775
     776    return crFbBltPutContentsVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pDstPoint, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg, float strX, float strY);
     777
     778    const RTPOINT ZeroPoint = {0, 0};
     779
     780    c2DRects = VBoxVrListRectsCount(&List);
     781    if (c2DRects)
     782    {
     783        if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
     784        {
     785            if (g_CrPresenter.pvTmpBuf2)
     786                RTMemFree(g_CrPresenter.pvTmpBuf2);
     787
     788            g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
     789            g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
     790            if (!g_CrPresenter.pvTmpBuf2)
     791            {
     792                WARN(("RTMemAlloc failed!"));
     793                g_CrPresenter.cbTmpBuf2 = 0;
     794                rc = VERR_NO_MEMORY;
     795                goto end;
     796            }
     797        }
     798
     799        RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
     800
     801        rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
     802        if (!RT_SUCCESS(rc))
     803        {
     804            WARN(("VBoxVrListRectsGet failed, rc %d", rc));
     805            goto end;
     806        }
     807
    505808        RTPOINT Pos = {0};
    506809        const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    507810
    508         uint32_t fbWidth = (pCompRect->xRight - pCompRect->xLeft);
    509         uint32_t fbHeight = pCompRect->yBottom - pCompRect->yTop;
    510 
    511         uint32_t stretchedWidth = CR_FLOAT_RCAST(uint32_t, strX * fbWidth);
    512         uint32_t stretchedHeight = CR_FLOAT_RCAST(uint32_t, strY * fbHeight);
    513 
    514811        CR_BLITTER_IMG FbImg;
    515 
    516         bool fScale = fbWidth != stretchedWidth || fbHeight != stretchedHeight;
    517812
    518813        crFbImgFromFb(hFb, &FbImg);
     
    549844    return rc;
    550845}
    551 
    552 static int crFbBltGetContentsScaleCPU(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    553 {
    554     uint32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
    555     uint32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
    556 
    557     /* destination is bigger than the source, do 3D data stretching with CPU */
    558     CR_BLITTER_IMG Img;
    559     Img.cbData = srcWidth * srcHeight * 4;
    560     Img.pvData = RTMemAlloc(Img.cbData);
    561     if (!Img.pvData)
    562     {
    563         WARN(("RTMemAlloc Failed"));
    564         return VERR_NO_MEMORY;
    565     }
    566     Img.enmFormat = pImg->enmFormat;
    567     Img.width = srcWidth;
    568     Img.height = srcHeight;
    569     Img.bpp = pImg->bpp;
    570     Img.pitch = Img.width * 4;
    571 
    572     int rc = CrFbBltGetContents(hFb, pSrcRect, cRects, pRects, &Img);
    573     if (RT_SUCCESS(rc))
    574     {
    575         CrBmpScale32((uint8_t *)pImg->pvData,
    576                             pImg->pitch,
    577                             pImg->width, pImg->height,
    578                             (const uint8_t *)Img.pvData,
    579                             Img.pitch,
    580                             Img.width, Img.height);
    581     }
    582     else
    583         WARN(("CrFbBltGetContents failed %d", rc));
    584 
    585     RTMemFree(Img.pvData);
    586 
    587     return rc;
    588 
    589 }
    590 
    591 int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    592 {
    593     uint32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
    594     uint32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
    595     if ((srcWidth == pImg->width
    596             && srcHeight == pImg->height)
    597             || !CrFbHas3DData(hFb)
    598             || (srcWidth * srcHeight > pImg->width * pImg->height))
    599     {
    600         return crFbBltGetContentsDirect(hFb, pSrcRect, cRects, pRects, pImg);
    601     }
    602 
    603     return crFbBltGetContentsScaleCPU(hFb, pSrcRect, cRects, pRects, pImg);
    604 }
    605 
     846#endif
    606847
    607848int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM)
     
    44734714                    uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
    44744715                    texId = 0;
     4716//                    cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr);
    44754717                    /*todo: notify VGA device to perform updates */
    44764718                }
     
    45124754                uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
    45134755
    4514                 RTRECT Rect;
    4515                 Rect.xLeft = pBlt->Pos.x;
    4516                 Rect.yTop = pBlt->Pos.y;
    4517                 Rect.xRight = Rect.xLeft + pScreen->u32Width;
    4518                 Rect.yBottom = Rect.yTop + pScreen->u32Height;
     4756                RTRECT SrcRect;
     4757                SrcRect.xLeft = 0;
     4758                SrcRect.yTop = 0;
     4759                SrcRect.xRight = pScreen->u32Width;
     4760                SrcRect.yBottom = pScreen->u32Height;
     4761                RTRECT DstRect;
     4762                DstRect.xLeft = pBlt->Pos.x;
     4763                DstRect.yTop = pBlt->Pos.y;
     4764                DstRect.xRight = DstRect.xLeft + pScreen->u32Width;
     4765                DstRect.yBottom = DstRect.yTop + pScreen->u32Height;
    45194766                CR_BLITTER_IMG Img;
    45204767                crFbImgFromScreenVram(pScreen, pu8Buf, &Img);
    4521                 int rc = CrFbBltGetContents(hFb, &Rect, cRects, pRects, &Img);
     4768                int rc = CrFbBltGetContents(hFb, &SrcRect, &DstRect, cRects, pRects, &Img);
    45224769                if (!RT_SUCCESS(rc))
    45234770                {
  • trunk/src/VBox/Main/include/DisplayImpl.h

    r50677 r50754  
    174174    void handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
    175175#endif
    176 
     176    int  handleCrHgcmCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
     177                                        PFNCRCTLCOMPLETION pfnCompletion,
     178                                        void *pvCompletion);
    177179#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    178180    void  handleCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
     
    271273    static DECLCALLBACK(void)  displayCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext);
    272274#endif
    273 
     275    static DECLCALLBACK(int)  displayCrHgcmCtlSubmit(PPDMIDISPLAYCONNECTOR pInterface,
     276                                        struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
     277                                        PFNCRCTLCOMPLETION pfnCompletion,
     278                                        void *pvCompletion);
     279    static DECLCALLBACK(void)  displayCrHgcmCtlSubmitCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext);
    274280#ifdef VBOX_WITH_HGSMI
    275281    static DECLCALLBACK(int)   displayVBVAEnable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, PVBVAHOSTFLAGS pHostFlags);
  • trunk/src/VBox/Main/src-client/DisplayImpl.cpp

    r50677 r50754  
    43044304void Display::handleCrHgsmiCommandProcess(PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd)
    43054305{
    4306     int rc = VERR_INVALID_FUNCTION;
     4306    int rc = VERR_NOT_SUPPORTED;
    43074307    VBOXHGCMSVCPARM parm;
    43084308    parm.type = VBOX_HGCM_SVC_PARM_PTR;
     
    43324332void Display::handleCrHgsmiControlProcess(PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl)
    43334333{
    4334     int rc = VERR_INVALID_FUNCTION;
     4334    int rc = VERR_NOT_SUPPORTED;
    43354335    VBOXHGCMSVCPARM parm;
    43364336    parm.type = VBOX_HGCM_SVC_PARM_PTR;
     
    43834383}
    43844384#endif
     4385
     4386DECLCALLBACK(void)  Display::displayCrHgcmCtlSubmitCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
     4387{
     4388    VBOXCRCMDCTL *pCmd = (VBOXCRCMDCTL*)pParam->u.pointer.addr;
     4389    if (pCmd->pfnInternal)
     4390        ((PFNCRCTLCOMPLETION)pCmd->pfnInternal)(pCmd, pParam->u.pointer.size, result, pvContext);
     4391}
     4392
     4393int  Display::handleCrHgcmCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
     4394                                        PFNCRCTLCOMPLETION pfnCompletion,
     4395                                        void *pvCompletion)
     4396{
     4397    VMMDev *pVMMDev = mParent->getVMMDev();
     4398    if (!pVMMDev)
     4399    {
     4400        AssertMsgFailed(("no vmmdev\n"));
     4401        return VERR_INVALID_STATE;
     4402    }
     4403
     4404    Assert(mhCrOglSvc);
     4405    VBOXHGCMSVCPARM parm;
     4406    parm.type = VBOX_HGCM_SVC_PARM_PTR;
     4407    parm.u.pointer.addr = pCmd;
     4408    parm.u.pointer.size = cbCmd;
     4409
     4410    pCmd->pfnInternal = (void(*)())pfnCompletion;
     4411    int rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_CTL, &parm, displayCrHgcmCtlSubmitCompletion, pvCompletion);
     4412    if (!RT_SUCCESS(rc))
     4413        AssertMsgFailed(("hgcmHostFastCallAsync failed rc %n", rc));
     4414
     4415    return rc;
     4416}
     4417
     4418DECLCALLBACK(int)  Display::displayCrHgcmCtlSubmit(PPDMIDISPLAYCONNECTOR pInterface,
     4419                                    struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
     4420                                    PFNCRCTLCOMPLETION pfnCompletion,
     4421                                    void *pvCompletion)
     4422{
     4423    PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
     4424    Display *pThis = pDrv->pDisplay;
     4425    return pThis->handleCrHgcmCtlSubmit(pCmd, cbCmd, pfnCompletion, pvCompletion);
     4426}
    43854427
    43864428#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
     
    50075049    pThis->IConnector.pfnCrHgsmiControlProcess = Display::displayCrHgsmiControlProcess;
    50085050#endif
     5051    pThis->IConnector.pfnCrHgcmCtlSubmit       = Display::displayCrHgcmCtlSubmit;
    50095052#ifdef VBOX_WITH_HGSMI
    50105053    pThis->IConnector.pfnVBVAEnable            = Display::displayVBVAEnable;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette