DevVGA_VDMA.cpp revision 1c43af4ec8987b1bed2306144f8bdce2d36d5572
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Video DMA (VDMA) support.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Copyright (C) 2006-2012 Oracle Corporation
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * available from http://www.virtualbox.org. This file is free software;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * General Public License (GPL) as published by the Free Software
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync#define WARN_BP() do { } while (0)
4569bf0ad094b40d2e177299a00d37e94d28616cvboxsync } while (0)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsynctypedef enum
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsynctypedef struct VBOXVDMAPIPE
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* critical section for accessing pipe properties */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* true iff the other end needs Event notification */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsynctypedef enum
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync#define VBOXVDMAPIPE_CMD_FROM_ENTRY(_pE) ( (PVBOXVDMAPIPE_CMD)((uint8_t *)(_pE) - RT_OFFSETOF(VBOXVDMAPIPE_CMD, Entry)) )
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync/* state transformations:
0c4004948fca34f2db87e7b38013137e9472c306vboxsync * submitter | processor
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * LISTENING ---> PROCESSING
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other,
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * but can be called with other VBoxVBVAExS** (submitter) functions except Init/Start/Term aparently.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Can only be called be the processor, i.e. the entity that acquired the processor state by direct or indirect call to the VBoxVBVAExHSCheckCommands
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync * see mor edetailed comments in headers for function definitions */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic bool VBoxVBVAExHPCmdCheckRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncstatic int VBoxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other,
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync/* can be called concurrently with istelf as well as with other VBoxVBVAEx** functions except Init/Start/Term aparently */
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncstatic int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncstatic void VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncstatic int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncstatic int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncstatic void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva);
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsyncstatic int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM);
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsyncstatic int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version);
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsynctypedef struct VBOXVDMAHOST
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsynctypedef DECLCALLBACK(void) FNVBOXVDMACRCTL_CALLBACK(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext);
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsynctypedef FNVBOXVDMACRCTL_CALLBACK *PFNVBOXVDMACRCTL_CALLBACK;
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync} VBOXVDMACMD_CHROMIUM_CTL_PRIVATE, *PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE;
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync#define VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(_p) ((PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CTL_PRIVATE, Cmd)))
93f91841f87620d1cb6d0238b3d0d5e52cd3b9a4vboxsyncstatic PVBOXVDMACMD_CHROMIUM_CTL vboxVDMACrCtlCreate(VBOXVDMACMD_CHROMIUM_CTL_TYPE enmCmd, uint32_t cbCmd)
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = (PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE)RTMemAllocZ(cbCmd + RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CTL_PRIVATE, Cmd));
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsyncDECLINLINE(void) vboxVDMACrCtlRelease (PVBOXVDMACMD_CHROMIUM_CTL pCmd)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncDECLINLINE(void) vboxVDMACrCtlRetain (PVBOXVDMACMD_CHROMIUM_CTL pCmd)
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncDECLINLINE(int) vboxVDMACrCtlGetRc (PVBOXVDMACMD_CHROMIUM_CTL pCmd)
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
0dd6dfbebcda0af90da4413aaea5f3b9d1817556vboxsyncstatic DECLCALLBACK(void) vboxVDMACrCtlCbSetEvent(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext)
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncstatic DECLCALLBACK(void) vboxVDMACrCtlCbReleaseCmd(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext)
7ccfefe49db4cd93c3701d7b60873ebf404b5b87vboxsyncstatic int vboxVDMACrCtlPostAsync (PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, uint32_t cbCmd, PFNVBOXVDMACRCTL_CALLBACK pfnCompletion, void *pvCompletion)
7ccfefe49db4cd93c3701d7b60873ebf404b5b87vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
64f58e4154eaa20c47782b429eeaff09070369bfvboxsync pVGAState->pDrv->pfnCrHgsmiControlProcess(pVGAState->pDrv, pCmd, cbCmd);
7ccfefe49db4cd93c3701d7b60873ebf404b5b87vboxsyncstatic int vboxVDMACrCtlPost(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, uint32_t cbCmd)
64f58e4154eaa20c47782b429eeaff09070369bfvboxsync rc = vboxVDMACrCtlPostAsync (pVGAState, pCmd, cbCmd, vboxVDMACrCtlCbSetEvent, (void*)hComplEvent);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTSemEventWaitNoResume(hComplEvent, RT_INDEFINITE_WAIT);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync /* the command is completed */
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncstatic void vboxVDMACrCmdNotifyPerform(struct VBOXVDMAHOST *pVdma)
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync pVGAState->pDrv->pfnCrCmdNotifyCmds(pVGAState->pDrv);
4569bf0ad094b40d2e177299a00d37e94d28616cvboxsyncstatic int vboxVDMACrCmdPreprocess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd)
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync /* check if the command is cancelled */
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync if (!ASMAtomicCmpXchgU8(&pCmd->u8State, VBOXCMDVBVA_STATE_IN_PROGRESS, VBOXCMDVBVA_STATE_SUBMITTED))
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync Assert(pCmd->u8State == VBOXCMDVBVA_STATE_CANCELLED);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync /* come commands can be handled right away? */
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncstatic DECLCALLBACK(int) vboxVDMACrCmdCltCmdGet(HVBOXCRCMDCLT hClt, PVBOXCMDVBVA_HDR *ppNextCmd, uint32_t *pcbNextCmd)
4569bf0ad094b40d2e177299a00d37e94d28616cvboxsync int rc = VBoxVBVAExHPCmdGet(&pVdma->CmdVbva, &pu8Cmd, &cbCmd);
4569bf0ad094b40d2e177299a00d37e94d28616cvboxsync rc = vboxVDMACrCmdPreprocess(pVdma, pu8Cmd, cbCmd);
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync /* processing was paused, processing state was released, only VBoxVBVAExHS*** calls are now allowed */
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync /* command processing was interrupted, processor state remains set. client can process any commands */
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync WARN(("Warning: vboxVDMACrCmdCltCmdGet unexpected state\n"));
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsyncstatic int vboxVDMACrCtlHgsmiSetup(struct VBOXVDMAHOST *pVdma)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pCmd = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP) vboxVDMACrCtlCreate (VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP,
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync sizeof (*pCmd));
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync int rc = vboxVDMACrCtlPost(pVGAState, &pCmd->Hdr, sizeof (*pCmd));
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync Assert(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED);
71f6a34b72f9cc873da208630959de49df1a28a5vboxsyncstatic int vboxVDMACmdExecBpbTransfer(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer, uint32_t cbBuffer);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/* check if this is external cmd to be passed to chromium backend */
d7125f3a1b435761c393f9ec406e85a73ae2a3e7vboxsyncstatic int vboxVDMACmdCheckCrCmd(struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmdDr, uint32_t cbCmdDr)
0c4004948fca34f2db87e7b38013137e9472c306vboxsync if (pCmdDr->fFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR)
d7125f3a1b435761c393f9ec406e85a73ae2a3e7vboxsync if (cbCmdDr < sizeof (*pCmdDr) + VBOXVDMACMD_HEADER_SIZE())
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync if (cbDmaCmd < cbCmdDr - sizeof (*pCmdDr) - VBOXVDMACMD_HEADER_SIZE())
0c4004948fca34f2db87e7b38013137e9472c306vboxsync pDmaCmd = VBOXVDMACBUF_DR_TAIL(pCmdDr, VBOXVDMACMD);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else if (pCmdDr->fFlags & VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync VBOXVIDEOOFFSET offBuf = pCmdDr->Location.offVramBuf;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (offBuf + cbDmaCmd > pVdma->pVGAState->vram_size)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgFailed(("invalid command buffer data from offset!"));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PVBOXVDMACMD_CHROMIUM_CMD pCrCmd = VBOXVDMACMD_BODY(pDmaCmd, VBOXVDMACMD_CHROMIUM_CMD);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgFailed(("invalid chromium command buffer size!"));
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync pVGAState->pDrv->pfnCrHgsmiCommandProcess(pVGAState->pDrv, pCrCmd, cbBody);
8a339f91959bb7a3315b51a23461b68c7b0cb50evboxsync int tmpRc = VBoxSHGSMICommandComplete (pVdma->pHgsmi, pCmdDr);
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer = VBOXVDMACMD_BODY(pDmaCmd, VBOXVDMACMD_DMA_BPB_TRANSFER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgFailed(("invalid bpb transfer buffer size!"));
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync rc = vboxVDMACmdExecBpbTransfer(pVdma, pTransfer, sizeof (*pTransfer));
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync rc = VBoxSHGSMICommandComplete (pVdma->pHgsmi, pCmdDr);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncint vboxVDMACrHgsmiCommandCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, int rc)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync VBOXVDMACMD *pDmaHdr = VBOXVDMACMD_FROM_BODY(pCmd);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync VBOXVDMACBUF_DR *pDr = VBOXVDMACBUF_DR_FROM_TAIL(pDmaHdr);
b0db50948c349fa76655abf252f7946b515e8204vboxsync Assert(pVGAState->fGuestCaps & VBVACAPS_COMPLETEGCMD_BY_IOREAD);
b0db50948c349fa76655abf252f7946b515e8204vboxsyncint vboxVDMACrHgsmiControlCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCmd, int rc)
b0db50948c349fa76655abf252f7946b515e8204vboxsync PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
b0db50948c349fa76655abf252f7946b515e8204vboxsync PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pCmdPrivate = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
b0db50948c349fa76655abf252f7946b515e8204vboxsync pCmdPrivate->pfnCompletion(pVGAState, pCmd, pCmdPrivate->pvCompletion);
b0db50948c349fa76655abf252f7946b515e8204vboxsync/* to simplify things and to avoid extra backend if modifications we assume the VBOXVDMA_RECTL is the same as VBVACMDHDR */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncAssertCompile(sizeof(VBOXVDMA_RECTL) == sizeof(VBVACMDHDR));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncAssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, left) == RT_SIZEOFMEMB(VBVACMDHDR, x));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncAssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, top) == RT_SIZEOFMEMB(VBVACMDHDR, y));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncAssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, width) == RT_SIZEOFMEMB(VBVACMDHDR, w));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncAssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, height) == RT_SIZEOFMEMB(VBVACMDHDR, h));
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncAssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, left) == RT_OFFSETOF(VBVACMDHDR, x));
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsyncAssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, top) == RT_OFFSETOF(VBVACMDHDR, y));
b0db50948c349fa76655abf252f7946b515e8204vboxsyncAssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, width) == RT_OFFSETOF(VBVACMDHDR, w));
b0db50948c349fa76655abf252f7946b515e8204vboxsyncAssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, height) == RT_OFFSETOF(VBVACMDHDR, h));
b0db50948c349fa76655abf252f7946b515e8204vboxsyncstatic int vboxVDMANotifyPrimaryUpdate (PVGASTATE pVGAState, unsigned uScreenId, const VBOXVDMA_RECTL * pRectl)
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync pVGAState->pDrv->pfnVBVAUpdateBegin (pVGAState->pDrv, uScreenId);
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync /* Updates the rectangle and sends the command to the VRDP server. */
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync pVGAState->pDrv->pfnVBVAUpdateProcess (pVGAState->pDrv, uScreenId,
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync (const PVBVACMDHDR)pRectl /* <- see above AssertCompile's and comments */,
ea779b55cc87f3e3fadddca4672c6697c82606edvboxsync pVGAState->pDrv->pfnVBVAUpdateEnd (pVGAState->pDrv, uScreenId, pRectl->left, pRectl->top,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int vboxVDMACmdExecBltPerform(PVBOXVDMAHOST pVdma,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync const PVBOXVDMA_SURF_DESC pDstDesc, const PVBOXVDMA_SURF_DESC pSrcDesc,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync const VBOXVDMA_RECTL * pDstRectl, const VBOXVDMA_RECTL * pSrcRectl)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* we do not support color conversion */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync /* we do not support stretching */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uint32_t cbSize = pDstDesc->pitch * pDstRectl->height;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync memcpy(pvDstSurf + cbOff, pvSrcSurf + cbOff, cbSize);
0c4004948fca34f2db87e7b38013137e9472c306vboxsync uint32_t offDstLineStart = pDstRectl->left * pDstDesc->bpp >> 3;
0c4004948fca34f2db87e7b38013137e9472c306vboxsync uint32_t offDstLineEnd = ((pDstRectl->left * pDstDesc->bpp + 7) >> 3) + ((pDstDesc->bpp * pDstRectl->width + 7) >> 3);
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync uint32_t cbDstLine = offDstLineEnd - offDstLineStart;
0c4004948fca34f2db87e7b38013137e9472c306vboxsync uint32_t offDstStart = pDstDesc->pitch * pDstRectl->top + offDstLineStart;
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync uint32_t offSrcLineStart = pSrcRectl->left * pSrcDesc->bpp >> 3;
71f6a34b72f9cc873da208630959de49df1a28a5vboxsync uint32_t offSrcLineEnd = ((pSrcRectl->left * pSrcDesc->bpp + 7) >> 3) + ((pSrcDesc->bpp * pSrcRectl->width + 7) >> 3);
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync uint32_t cbSrcLine = offSrcLineEnd - offSrcLineStart;
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync uint32_t offSrcStart = pSrcDesc->pitch * pSrcRectl->top + offSrcLineStart;
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync const uint8_t * pvSrcStart = pvSrcSurf + offSrcStart;
71f6a34b72f9cc873da208630959de49df1a28a5vboxsync for (uint32_t i = 0; ; ++i)
71f6a34b72f9cc873da208630959de49df1a28a5vboxsyncstatic void vboxVDMARectlUnite(VBOXVDMA_RECTL * pRectl1, const VBOXVDMA_RECTL * pRectl2)
71f6a34b72f9cc873da208630959de49df1a28a5vboxsync pRectl1->width = x21 < x22 ? x22 - pRectl1->left : x21 - pRectl1->left;
0c4004948fca34f2db87e7b38013137e9472c306vboxsync pRectl1->height = x21 < x22 ? x22 - pRectl1->top : x21 - pRectl1->top;
71f6a34b72f9cc873da208630959de49df1a28a5vboxsync * @return on success the number of bytes the command contained, otherwise - VERR_xxx error code
71f6a34b72f9cc873da208630959de49df1a28a5vboxsyncstatic int vboxVDMACmdExecBlt(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_PRESENT_BLT pBlt, uint32_t cbBuffer)
71f6a34b72f9cc873da208630959de49df1a28a5vboxsync const uint32_t cbBlt = VBOXVDMACMD_BODY_FIELD_OFFSET(uint32_t, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[pBlt->cDstSubRects]);
71f6a34b72f9cc873da208630959de49df1a28a5vboxsync /* we do not support stretching for now */
71f6a34b72f9cc873da208630959de49df1a28a5vboxsync Assert(pBlt->srcRectl.width == pBlt->dstRectl.width);
d4e9ccea0ea1ed303b5708ff94f6c202755f0dc6vboxsync Assert(pBlt->srcRectl.height == pBlt->dstRectl.height);
8f0fc87a72dee210b62acc9dd859a4bebf8bfb33vboxsync if (pBlt->srcRectl.height != pBlt->dstRectl.height)
0c4004948fca34f2db87e7b38013137e9472c306vboxsync dstRectl.left = pDstRectl->left + pBlt->dstRectl.left;
0c4004948fca34f2db87e7b38013137e9472c306vboxsync dstRectl.top = pDstRectl->top + pBlt->dstRectl.top;
71f6a34b72f9cc873da208630959de49df1a28a5vboxsync srcRectl.left = pSrcRectl->left + pBlt->srcRectl.left;
71f6a34b72f9cc873da208630959de49df1a28a5vboxsync srcRectl.top = pSrcRectl->top + pBlt->srcRectl.top;
71f6a34b72f9cc873da208630959de49df1a28a5vboxsync int rc = vboxVDMACmdExecBltPerform(pVdma, pvRam + pBlt->offDst, pvRam + pBlt->offSrc,
0c4004948fca34f2db87e7b38013137e9472c306vboxsync int rc = vboxVDMACmdExecBltPerform(pVdma, pvRam + pBlt->offDst, pvRam + pBlt->offSrc,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* @todo: fixme: check if update is needed and get iView */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync vboxVDMANotifyPrimaryUpdate (pVdma->pVGAState, iView, &updateRectl);
8cd2f2e64725096acb682f34a5568b7fb816eda7vboxsyncstatic int vboxVDMACmdExecBpbTransfer(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer, uint32_t cbBuffer)
26947320577c481b4afefdb0afbb855181e5b2e8vboxsync const void * pvSrc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync bool bSrcLocked = false;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync bool bDstLocked = false;
cba6719bd64ec749967bbe931230452664109857vboxsync if (pTransfer->fFlags & VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET)
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync pvSrc = pvRam + pTransfer->Src.offVramBuf + cbTransfered;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvSrc, &SrcLock);
cba6719bd64ec749967bbe931230452664109857vboxsync if (pTransfer->fFlags & VBOXVDMACMD_DMA_BPB_TRANSFER_F_DST_VRAMOFFSET)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pvDst = pvRam + pTransfer->Dst.offVramBuf + cbTransfered;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, phPage, 0, &pvDst, &DstLock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PDMDevHlpPhysReleasePageMappingLock(pDevIns, &SrcLock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PDMDevHlpPhysReleasePageMappingLock(pDevIns, &DstLock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return sizeof (*pTransfer);
9b789c281103a2489742bf32f6ab500e38b2ecd5vboxsyncstatic int vboxVDMACmdExec(PVBOXVDMAHOST pVdma, const uint8_t *pvBuffer, uint32_t cbBuffer)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync static int count = 0;
71f6a34b72f9cc873da208630959de49df1a28a5vboxsync LogRel(("100000 calls took %i ms, %i cps\n", (int)ems, (int)(100000.f*1000.f/ems) ));
71f6a34b72f9cc873da208630959de49df1a28a5vboxsync /* todo: post the buffer to chromium */
b0db50948c349fa76655abf252f7946b515e8204vboxsync const PVBOXVDMACMD_DMA_PRESENT_BLT pBlt = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
b0db50948c349fa76655abf252f7946b515e8204vboxsync int cbBlt = vboxVDMACmdExecBlt(pVdma, pBlt, cbBuffer);
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync const PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_BPB_TRANSFER);
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync int cbTransfer = vboxVDMACmdExecBpbTransfer(pVdma, pTransfer, cbBuffer);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync } while (1);
cba6719bd64ec749967bbe931230452664109857vboxsync /* we should not be here */
return VINF_SUCCESS;
return rc;
return rc;
return rc;
bool bNeedNotify = false;
if (bNeedNotify)
return rc;
if (bProcessing)
return rc;
bool bNeedNotify = false;
if (bModified)
if (bNeedNotify)
return rc;
return VERR_INVALID_STATE;
return VINF_SUCCESS;
int rc;
bool bReleaseLocked = false;
const void * pvPageBuf;
bReleaseLocked = true;
if (bReleaseLocked)
#ifdef VBOX_VDMA_WITH_WORKERTHREAD
bool bHasCmd;
if (pEntry)
return rc;
#ifdef VBOX_VDMA_WITH_WATCHDOG
if (cMillis)
return VINF_SUCCESS;
int rc;
#ifdef VBOX_VDMA_WITH_WORKERTHREAD
PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)RTMemAllocZ(RT_OFFSETOF(VBOXVDMAHOST, CmdPool.aCmds[cPipeElements]));
if (pVdma)
#ifdef VBOX_VDMA_WITH_WATCHDOG
#ifdef VBOX_VDMA_WITH_WORKERTHREAD
rc = RTThreadCreate(&pVdma->hWorkerThread, vboxVDMAWorkerThread, pVdma, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "VDMA");
#ifdef VBOX_WITH_CRHGSMI
int rcIgnored = vboxVDMACrCtlHgsmiSetup(pVdma); NOREF(rcIgnored); /** @todo is this ignoring intentional? */
return VINF_SUCCESS;
#ifdef VBOX_VDMA_WITH_WORKERTHREAD
return rc;
#ifdef VBOX_VDMA_WITH_WORKERTHREAD
return VINF_SUCCESS;
#ifdef VBOX_VDMA_WITH_WORKERTHREAD
bool bQueued;
if (pEntry)
#ifdef VBOX_WITH_CRHGSMI
if (pCmd)
return rc;
return VERR_NO_MEMORY;
return VINF_SUCCESS;
#ifdef VBOX_WITH_CRHGSMI
if (pCmd)
return rc;
return VERR_NO_MEMORY;
return VINF_SUCCESS;
case VBOXVDMA_CTL_TYPE_ENABLE:
case VBOXVDMA_CTL_TYPE_FLUSH:
#ifdef VBOX_VDMA_WITH_WATCHDOG
#ifdef VBOX_WITH_CRHGSMI
/* chromium commands are processed by crhomium hgcm thread independently from our internal cmd processing pipeline
#ifndef VBOX_VDMA_WITH_WORKERTHREAD
# ifdef DEBUG_misha
Assert(0);
if (ASMAtomicCmpXchgExU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PROCESSING, VBVAEXHOSTCONTEXT_STATE_LISTENING, &oldState))
return VINF_SUCCESS;
return VERR_INVALID_STATE;
static int vboxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
return VINF_EOF;
return VINF_TRY_AGAIN;
if (!cbRecord)
return VINF_TRY_AGAIN;
return VINF_SUCCESS;
return VERR_INVALID_STATE;
/* pause the command processing. this will make the processor stop the command processing and release the processing state
if (ASMAtomicCmpXchgU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PAUSED, VBVAEXHOSTCONTEXT_STATE_LISTENING))
* VINF_EOF - processor has completed all commands and release the processing state, only VBoxVBVAExHS*** calls are now allowed
* VINF_PERMISSION_DENIED - processing was paused, processing state was released, only VBoxVBVAExHS*** calls are now allowed
* VINF_INTERRUPTED - command processing was interrupted, processor state remains set. client can process any commands,
static int VBoxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
return VINF_PERMISSION_DENIED;
return VINF_INTERRUPTED;
switch (rc)
case VINF_SUCCESS:
return VINF_SUCCESS;
case VINF_EOF:
/* we need to prevent racing between us clearing the flag and command check/submission thread, i.e.
* 5. ->here we need to re-check the queue state to ensure we do not leak the notification of the above command
return VINF_EOF;
case VINF_TRY_AGAIN:
/* this is something really unexpected, i.e. most likely guest has written something incorrect to the VBVA buffer */
return rc;
return VERR_INTERNAL_ERROR;
return VERR_INTERNAL_ERROR;
* 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)
return VINF_EOF;
return VINF_SUCCESS;
return VINF_EOF;
return VINF_ALREADY_INITIALIZED;
return VERR_INVALID_STATE;
return VINF_ALREADY_INITIALIZED;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VERR_INVALID_STATE;
static int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM)
int rc;
return VINF_EOF;
static int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version)
return VINF_EOF;
switch (rc)
case VINF_SUCCESS:
case VINF_ALREADY_INITIALIZED:
case VINF_EOF:
case VERR_INVALID_STATE:
return VINF_SUCCESS;