VirtualBox

Changeset 27383 in vbox


Ignore:
Timestamp:
Mar 15, 2010 9:47:46 PM (15 years ago)
Author:
vboxsync
Message:

wddm: basic Video DMA impl, guest driver bugfix

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/VBoxVideo.h

    r27286 r27383  
    11641164     * VERR_xxx         - on error */
    11651165    int32_t  rc;
     1166    uint64_t u64GuestContext;
    11661167    union
    11671168    {
     
    11711172} VBOXVDMACBUF_DR, *PVBOXVDMACBUF_DR;
    11721173
    1173 #define VBOXVDMACBUF_DR_TAIL(_pCmd, _t) ( (_t)(((uint8_t*)(_pCmd)) + sizeof (VBOXVDMACBUF_DR)) )
     1174#define VBOXVDMACBUF_DR_TAIL(_pCmd, _t) ( (_t*)(((uint8_t*)(_pCmd)) + sizeof (VBOXVDMACBUF_DR)) )
    11741175
    11751176typedef struct VBOXVDMACMD
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVdma.cpp

    r27286 r27383  
    165165}
    166166
    167 PVBOXVDMACBUF_DR vboxVdmaCBufDrCreate (PVBOXVDMAINFO pInfo, PVBOXVDMACMDBUF_INFO pBufInfo)
    168 {
    169     PVBOXVDMACBUF_DR pCmdDr;
    170 
    171     if (pBufInfo->fFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR)
    172     {
    173         /* data info is a pointer to the buffer to be coppied and included in the command */
    174         pCmdDr = (PVBOXVDMACBUF_DR)VBoxSHGSMICommandAlloc (&pInfo->CmdHeap, sizeof (VBOXVDMACBUF_DR) + pBufInfo->cbBuf, HGSMI_CH_VBVA, VBVA_VDMA_CMD);
    175         Assert(pCmdDr);
    176         if (!pCmdDr)
    177             return NULL;
    178 
    179         void * pvData = VBOXVDMACBUF_DR_TAIL(pCmdDr, void*);
    180         memcpy(pvData, (void*)pBufInfo->Location.pvBuf, pBufInfo->cbBuf);
    181     }
    182     else
    183     {
    184         pCmdDr = (PVBOXVDMACBUF_DR)VBoxSHGSMICommandAlloc (&pInfo->CmdHeap, sizeof (VBOXVDMACBUF_DR), HGSMI_CH_VBVA, VBVA_VDMA_CMD);
    185         Assert(pCmdDr);
    186         if (!pCmdDr)
    187             return NULL;
    188 
    189         if (!(pBufInfo->fFlags & VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET))
    190             pCmdDr->Location.phBuf = pBufInfo->Location.phBuf;
    191         else
    192             pCmdDr->Location.offVramBuf = pBufInfo->Location.offVramBuf;
    193     }
    194 
    195     pCmdDr->fFlags = pBufInfo->fFlags;
    196     pCmdDr->cbBuf = pBufInfo->cbBuf;
    197     pCmdDr->u32FenceId = pBufInfo->u32FenceId;
    198 
    199     return pCmdDr;
     167PVBOXVDMACBUF_DR vboxVdmaCBufDrCreate (PVBOXVDMAINFO pInfo, uint32_t cbTrailingData)
     168{
     169    uint32_t cbDr = sizeof (VBOXVDMACBUF_DR) + cbTrailingData;
     170    PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)VBoxSHGSMICommandAlloc (&pInfo->CmdHeap, cbDr, HGSMI_CH_VBVA, VBVA_VDMA_CMD);
     171    Assert(pDr);
     172    if (pDr)
     173        memset (pDr, 0, cbDr);
     174    else
     175        drprintf((__FUNCTION__": VBoxSHGSMICommandAlloc returned NULL\n"));
     176
     177    return pDr;
    200178}
    201179
     
    218196    memset(&notify, 0, sizeof(DXGKARGCB_NOTIFY_INTERRUPT_DATA));
    219197
     198    PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pDr->u64GuestContext;
     199
    220200    if (RT_SUCCESS(pDr->rc))
    221201    {
    222202        notify.InterruptType = DXGK_INTERRUPT_DMA_COMPLETED;
    223203        notify.DmaCompleted.SubmissionFenceId = pDr->u32FenceId;
    224         notify.DmaCompleted.NodeOrdinal = 0; /* @todo: ? */
    225         notify.DmaCompleted.EngineOrdinal = 0; /* @todo: ? */
    226         pVdma->uLastCompletedCmdFenceId = pDr->u32FenceId;
     204        if (pContext)
     205        {
     206            notify.DmaCompleted.NodeOrdinal = pContext->NodeOrdinal;
     207            notify.DmaCompleted.EngineOrdinal = 0;
     208            pContext->uLastCompletedCmdFenceId = pDr->u32FenceId;
     209        }
     210        else
     211            pVdma->uLastCompletedPagingBufferCmdFenceId = pDr->u32FenceId;
    227212        pDevExt->bSetNotifyDxDpc = TRUE;
    228213    }
     
    231216        notify.InterruptType = DXGK_INTERRUPT_DMA_PREEMPTED;
    232217        notify.DmaPreempted.PreemptionFenceId = pDr->u32FenceId;
    233         notify.DmaPreempted.LastCompletedFenceId = pVdma->uLastCompletedCmdFenceId;
    234         notify.DmaPreempted.NodeOrdinal = 0; /* @todo: ? */
    235         notify.DmaPreempted.EngineOrdinal = 0; /* @todo: ? */
     218        if (pContext)
     219        {
     220            notify.DmaPreempted.LastCompletedFenceId = pContext->uLastCompletedCmdFenceId;
     221            notify.DmaPreempted.NodeOrdinal = pContext->NodeOrdinal;
     222            notify.DmaPreempted.EngineOrdinal = 0;
     223        }
     224        else
     225            notify.DmaPreempted.LastCompletedFenceId = pVdma->uLastCompletedPagingBufferCmdFenceId;
     226
    236227        pDevExt->bSetNotifyDxDpc = TRUE;
    237228    }
     
    242233        notify.DmaFaulted.FaultedFenceId = pDr->u32FenceId;
    243234        notify.DmaFaulted.Status = STATUS_UNSUCCESSFUL; /* @todo: better status ? */
    244         notify.DmaFaulted.NodeOrdinal = 0; /* @todo: ? */
    245         notify.DmaFaulted.EngineOrdinal = 0; /* @todo: ? */
     235        if (pContext)
     236        {
     237            notify.DmaFaulted.NodeOrdinal = pContext->NodeOrdinal;
     238            notify.DmaFaulted.EngineOrdinal = 0;
     239        }
    246240        pDevExt->bSetNotifyDxDpc = TRUE;
    247241    }
     
    258252    VBoxSHGSMICommandSubmitAsynchIrq (&pInfo->CmdHeap, pDr, vboxVdmaCBufDrCompletionIrq, pDevExt, VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE);
    259253}
    260 
    261 int vboxVdmaCBufSubmit (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACMDBUF_INFO pBufInfo)
    262 {
    263     dfprintf((__FUNCTION__"\n"));
    264 
    265     PVBOXVDMACBUF_DR pdr = vboxVdmaCBufDrCreate (pInfo, pBufInfo);
    266     if (!pdr)
    267         return VERR_OUT_OF_RESOURCES;
    268 
    269     vboxVdmaCBufDrSubmit (pDevExt, pInfo, pdr);
    270 
    271     return VINF_SUCCESS;
    272 }
    273 
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVdma.h

    r26661 r27383  
    2424{
    2525    HGSMIHEAP CmdHeap;
    26     UINT      uLastCompletedCmdFenceId;
     26    UINT      uLastCompletedPagingBufferCmdFenceId;
    2727    BOOL      fEnabled;
    2828} VBOXVDMAINFO, *PVBOXVDMAINFO;
    29 
    30 typedef struct VBOXVDMACMDBUF_INFO
    31 {
    32     uint32_t fFlags;
    33     uint32_t cbBuf;
    34     union
    35     {
    36         RTGCPHYS phBuf;
    37         ULONG offVramBuf;
    38         void *pvBuf;
    39     } Location;
    40     uint32_t u32FenceId;
    41 } VBOXVDMACMDBUF_INFO, *PVBOXVDMACMDBUF_INFO;
    4229
    4330int vboxVdmaCreate (struct _DEVICE_EXTENSION* pDevExt, VBOXVDMAINFO *pInfo, ULONG offBuffer, ULONG cbBuffer);
     
    4633int vboxVdmaFlush (struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo);
    4734int vboxVdmaDestroy (struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo);
    48 int vboxVdmaCBufSubmit (struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACMDBUF_INFO pBufInfo);
     35void vboxVdmaCBufDrSubmit (struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr);
     36struct VBOXVDMACBUF_DR* vboxVdmaCBufDrCreate (PVBOXVDMAINFO pInfo, uint32_t cbTrailingData);
     37void vboxVdmaCBufDrFree (PVBOXVDMAINFO pInfo, struct VBOXVDMACBUF_DR* pDr);
    4938
    5039#endif /* #ifndef ___VBoxVideoVdma_h___ */
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.cpp

    r27308 r27383  
    16981698
    16991699    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
    1700     VBOXVDMACMDBUF_INFO BufInfo = {0};
    17011700
    17021701    Assert(!pSubmitCommand->DmaBufferSegmentId);
     
    17041703    /* the DMA command buffer is located in system RAM, the host will need to pick it from there */
    17051704    //BufInfo.fFlags = 0; /* see VBOXVDMACBUF_FLAG_xx */
    1706     BufInfo.cbBuf =  pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset;
    1707     BufInfo.Location.phBuf = pSubmitCommand->DmaBufferPhysicalAddress.QuadPart + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset;
    1708     BufInfo.u32FenceId = pSubmitCommand->SubmissionFenceId;
    1709 
    1710     int rc = vboxVdmaCBufSubmit (pDevExt, &pDevExt->u.primary.Vdma, &BufInfo);
    1711     AssertRC(rc);
    1712     if (!RT_SUCCESS(rc))
    1713     {
    1714         switch (rc)
    1715         {
    1716             case VERR_OUT_OF_RESOURCES:
    1717                 /* @todo: try flushing.. */
    1718                 Status = STATUS_INSUFFICIENT_RESOURCES;
    1719                 break;
    1720             default:
    1721                 Status = STATUS_UNSUCCESSFUL;
    1722                 break;
    1723         }
    1724     }
     1705    Assert(pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA));
     1706    if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset < sizeof (VBOXWDDM_DMA_PRIVATE_DATA))
     1707    {
     1708        drprintf((__FUNCTION__": DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATE_DATA) (%d)\n",
     1709                pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset,
     1710                pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset,
     1711                sizeof (VBOXWDDM_DMA_PRIVATE_DATA)));
     1712        return STATUS_INVALID_PARAMETER;
     1713    }
     1714
     1715    PVBOXWDDM_DMA_PRIVATE_DATA pPrivateData = (PVBOXWDDM_DMA_PRIVATE_DATA)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
     1716    Assert(pPrivateData);
     1717    PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, 0);
     1718    if (!pDr)
     1719    {
     1720        /* @todo: try flushing.. */
     1721        drprintf((__FUNCTION__": vboxVdmaCBufDrCreate returned NULL\n"));
     1722        return STATUS_INSUFFICIENT_RESOURCES;
     1723    }
     1724    // vboxVdmaCBufDrCreate zero initializes the pDr
     1725    //pDr->fFlags = 0;
     1726    pDr->cbBuf = pSubmitCommand->DmaBufferSubmissionEndOffset - pSubmitCommand->DmaBufferSubmissionStartOffset;
     1727    pDr->u32FenceId = pSubmitCommand->SubmissionFenceId;
     1728    pDr->rc = VERR_NOT_IMPLEMENTED;
     1729    if (pPrivateData)
     1730        pDr->u64GuestContext = (uint64_t)pPrivateData->pContext;
     1731//    else    // vboxVdmaCBufDrCreate zero initializes the pDr
     1732//        pDr->u64GuestContext = NULL;
     1733    pDr->Location.phBuf = pSubmitCommand->DmaBufferPhysicalAddress.QuadPart + pSubmitCommand->DmaBufferSubmissionStartOffset;
     1734
     1735    vboxVdmaCBufDrSubmit (pDevExt, &pDevExt->u.primary.Vdma, pDr);
    17251736
    17261737    dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", hAdapter));
     
    17681779        case DXGK_OPERATION_TRANSFER:
    17691780        {
    1770             pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_TRANSFER);
     1781//            pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_TRANSFER);
    17711782            break;
    17721783        }
    17731784        case DXGK_OPERATION_FILL:
    17741785        {
    1775             pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_FILL);
     1786//            pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_FILL);
    17761787            break;
    17771788        }
     
    19181929    PAGED_CODE();
    19191930
    1920     dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
     1931//    dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
    19211932
    19221933    vboxVDbgBreakFv();
     
    20092020    pIsSupportedVidPnArg->IsVidPnSupported = bSupported;
    20102021
    2011     dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
     2022//    dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
    20122023
    20132024    return Status;
     
    20832094    PAGED_CODE();
    20842095
    2085     dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
     2096//    dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
    20862097
    20872098    vboxVDbgBreakFv();
     
    21292140        drprintf((__FUNCTION__ ": DxgkCbQueryVidPnInterface failed Status(0x%x)\n", Status));
    21302141
    2131     dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
     2142//    dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
    21322143
    21332144    return Status;
     
    26602671    PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
    26612672    PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
     2673
     2674    Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA));
     2675    if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATE_DATA))
     2676    {
     2677        drprintf((__FUNCTION__": Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATE_DATA (%d)\n", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATE_DATA)));
     2678        /* @todo: can this actually happen? what status tu return? */
     2679        return STATUS_INVALID_PARAMETER;
     2680    }
     2681
     2682    PVBOXWDDM_DMA_PRIVATE_DATA pPrivateData = (PVBOXWDDM_DMA_PRIVATE_DATA)pPresent->pDmaBufferPrivateData;
     2683    pPrivateData->pContext = (PVBOXWDDM_CONTEXT)hContext;
    26622684
    26632685    if (pPresent->Flags.Blt)
     
    27222744                        Assert(i);
    27232745                        pTransfer->cDstSubRects = i;
     2746                        pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATE_DATA);
    27242747                    }
    27252748                    else
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.h

    r27286 r27383  
    1717#define ___VBoxVideoWddm_h___
    1818
    19 #define VBOXWDDM_C_DMA_BUFFER_SIZE         0x10000
     19/* one page size */
     20#define VBOXWDDM_C_DMA_BUFFER_SIZE         0x1000
    2021#define VBOXWDDM_C_ALLOC_LIST_SIZE         0xc00
    2122#define VBOXWDDM_C_PATH_LOCATION_LIST_SIZE 0xc00
     
    120121    UINT  NodeOrdinal;
    121122    UINT  EngineAffinity;
     123    UINT uLastCompletedCmdFenceId;
    122124} VBOXWDDM_CONTEXT, *PVBOXWDDM_CONTEXT;
    123125
    124126typedef struct VBOXWDDM_DMA_PRIVATE_DATA
    125127{
    126     uint8_t Reserved[64];
     128    PVBOXWDDM_CONTEXT pContext;
     129    uint8_t Reserved[8];
    127130}VBOXWDDM_DMA_PRIVATE_DATA, *PVBOXWDDM_DMA_PRIVATE_DATA;
    128131
  • trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp

    r27340 r27383  
    8686    RTTHREAD hWorkerThread;
    8787    PHGSMIINSTANCE pHgsmi;
     88    PVGASTATE pVGAState;
    8889    VBOXVDMAPIPE_CMD_POOL CmdPool;
    8990} VBOXVDMAHOST, *PVBOXVDMAHOST;
     91
     92/* to simplify things and to avoid extra backend if modifications we assume the VBOXVDMA_RECTL is the same as VBVACMDHDR */
     93AssertCompile(sizeof(VBOXVDMA_RECTL) == sizeof(VBVACMDHDR));
     94AssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, left) == RT_SIZEOFMEMB(VBVACMDHDR, x));
     95AssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, top) == RT_SIZEOFMEMB(VBVACMDHDR, y));
     96AssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, width) == RT_SIZEOFMEMB(VBVACMDHDR, w));
     97AssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, height) == RT_SIZEOFMEMB(VBVACMDHDR, h));
     98AssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, left) == RT_OFFSETOF(VBVACMDHDR, x));
     99AssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, top) == RT_OFFSETOF(VBVACMDHDR, y));
     100AssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, width) == RT_OFFSETOF(VBVACMDHDR, w));
     101AssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, height) == RT_OFFSETOF(VBVACMDHDR, h));
     102
     103static int vboxVDMANotifyPrimaryUpdate (PVGASTATE pVGAState, unsigned uScreenId, const VBOXVDMA_RECTL * pRectl)
     104{
     105    pVGAState->pDrv->pfnVBVAUpdateBegin (pVGAState->pDrv, uScreenId);
     106
     107    /* Updates the rectangle and sends the command to the VRDP server. */
     108    pVGAState->pDrv->pfnVBVAUpdateProcess (pVGAState->pDrv, uScreenId,
     109            (const PVBVACMDHDR)pRectl /* <- see above AssertCompile's and comments */,
     110            sizeof (VBOXVDMA_RECTL));
     111
     112    pVGAState->pDrv->pfnVBVAUpdateEnd (pVGAState->pDrv, uScreenId, pRectl->left, pRectl->top,
     113                                               pRectl->width, pRectl->height);
     114
     115    return VINF_SUCCESS;
     116}
     117
     118static int vboxVDMACmdExecBltPerform(PVBOXVDMAHOST pVdma,
     119        uint8_t *pvDstSurf, const uint8_t *pvSrcSurf,
     120        const PVBOXVDMA_SURF_DESC pDstDesc, const PVBOXVDMA_SURF_DESC pSrcDesc,
     121        const VBOXVDMA_RECTL * pDstRectl, const VBOXVDMA_RECTL * pSrcRectl)
     122{
     123    /* we do not support color conversion */
     124    Assert(pDstDesc->format == pSrcDesc->format);
     125    /* we do not support stretching */
     126    Assert(pDstRectl->height == pSrcRectl->height);
     127    Assert(pDstRectl->width == pSrcRectl->width);
     128    if (pDstDesc->format != pSrcDesc->format)
     129        return VERR_INVALID_FUNCTION;
     130    if (pDstDesc->width == pDstRectl->width
     131            && pSrcDesc->width == pSrcRectl->width
     132            && pSrcDesc->width == pDstDesc->width)
     133    {
     134        Assert(!pDstRectl->left);
     135        Assert(!pSrcRectl->left);
     136        uint32_t cbOff = pDstDesc->pitch * pDstRectl->top;
     137        uint32_t cbSize = pDstDesc->pitch * pDstRectl->height;
     138        memcpy(pvDstSurf + cbOff, pvSrcSurf + cbOff, cbSize);
     139    }
     140    else
     141    {
     142        uint32_t offDstStart = pDstDesc->pitch * pDstRectl->top + pDstRectl->left;
     143        uint32_t cbDstLine = pDstDesc->bpp * pDstRectl->width;
     144        cbDstLine = !(cbDstLine & 7) ? cbDstLine >> 3 : (cbDstLine >> 3) + 1;
     145        Assert(cbDstLine <= pDstDesc->pitch);
     146        uint32_t cbDstSkip = pDstDesc->pitch - cbDstLine;
     147        uint8_t * pvDstStart = pvDstSurf + offDstStart;
     148
     149        uint32_t offSrcStart = pSrcDesc->pitch * pSrcRectl->top + pSrcRectl->left;
     150        uint32_t cbSrcLine = pSrcDesc->bpp * pSrcRectl->width;
     151        cbSrcLine = !(cbSrcLine & 7) ? cbSrcLine >> 3 : (cbSrcLine >> 3) + 1;
     152        Assert(cbSrcLine <= pSrcDesc->pitch);
     153        uint32_t cbSrcSkip = pSrcDesc->pitch - cbSrcLine;
     154        const uint8_t * pvSrcStart = pvSrcSurf + offSrcStart;
     155
     156        Assert(cbDstLine == cbSrcLine);
     157
     158        for (uint32_t i = 0; ; ++i)
     159        {
     160            memcpy (pvDstStart, pvSrcStart, cbDstLine);
     161            if (i == pDstRectl->height)
     162                break;
     163            pvDstStart += cbDstSkip;
     164            pvSrcStart += cbSrcSkip;
     165        }
     166    }
     167    return VINF_SUCCESS;
     168}
     169
     170/*
     171 * @return on success the number of bytes the command contained, otherwise - VERR_xxx error code
     172 */
     173static int vboxVDMACmdExecBlt(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_PRESENT_BLT pBlt, uint32_t cbBuffer)
     174{
     175    const uint32_t cbBlt = VBOXVDMACMD_BODY_FIELD_OFFSET(uint32_t, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[pBlt->cDstSubRects]);
     176    Assert(cbBlt <= cbBuffer);
     177    if (cbBuffer < cbBlt)
     178        return VERR_INVALID_FUNCTION;
     179
     180    /* we do not support stretching for now */
     181    Assert(pBlt->srcRectl.width == pBlt->dstRectl.width);
     182    Assert(pBlt->srcRectl.height == pBlt->dstRectl.height);
     183    if (pBlt->srcRectl.width != pBlt->dstRectl.width)
     184        return VERR_INVALID_FUNCTION;
     185    if (pBlt->srcRectl.height != pBlt->dstRectl.height)
     186        return VERR_INVALID_FUNCTION;
     187    Assert(pBlt->cDstSubRects);
     188
     189    uint8_t * pvRam = pVdma->pVGAState->vram_ptrR3;
     190
     191    if (pBlt->cDstSubRects)
     192    {
     193        VBOXVDMA_RECTL dstRectl, srcRectl;
     194        const VBOXVDMA_RECTL *pDstRectl, *pSrcRectl;
     195        for (uint32_t i = 0; i < pBlt->cDstSubRects; ++i)
     196        {
     197            pDstRectl = &pBlt->aDstSubRects[i];
     198            if (pBlt->dstRectl.left || pBlt->dstRectl.top)
     199            {
     200                dstRectl.left = pDstRectl->left + pBlt->dstRectl.left;
     201                dstRectl.top = pDstRectl->top + pBlt->dstRectl.top;
     202                dstRectl.width = pDstRectl->width;
     203                dstRectl.height = pDstRectl->height;
     204                pDstRectl = &dstRectl;
     205            }
     206
     207            pSrcRectl = &pBlt->aDstSubRects[i];
     208            if (pBlt->srcRectl.left || pBlt->srcRectl.top)
     209            {
     210                srcRectl.left = pSrcRectl->left + pBlt->srcRectl.left;
     211                srcRectl.top = pSrcRectl->top + pBlt->srcRectl.top;
     212                srcRectl.width = pSrcRectl->width;
     213                srcRectl.height = pSrcRectl->height;
     214                pSrcRectl = &srcRectl;
     215            }
     216
     217            int rc = vboxVDMACmdExecBltPerform(pVdma, pvRam + pBlt->offDst, pvRam + pBlt->offSrc,
     218                    &pBlt->dstDesc, &pBlt->srcDesc,
     219                    pDstRectl,
     220                    pSrcRectl);
     221            AssertRC(rc);
     222            if (!RT_SUCCESS(rc))
     223                return rc;
     224        }
     225    }
     226    else
     227    {
     228        int rc = vboxVDMACmdExecBltPerform(pVdma, pvRam + pBlt->offDst, pvRam + pBlt->offSrc,
     229                &pBlt->dstDesc, &pBlt->srcDesc,
     230                &pBlt->dstRectl,
     231                &pBlt->srcRectl);
     232        AssertRC(rc);
     233        if (!RT_SUCCESS(rc))
     234            return rc;
     235    }
     236
     237    int iView = 0;
     238    /* @todo: fixme: check if update is needed and get iView */
     239    vboxVDMANotifyPrimaryUpdate (pVdma->pVGAState, iView, &pBlt->dstRectl);
     240
     241    return cbBlt;
     242}
     243
     244static int vboxVDMACmdExec(PVBOXVDMAHOST pVdma, const uint8_t *pvBuffer, uint32_t cbBuffer)
     245{
     246    do
     247    {
     248        Assert(pvBuffer);
     249        Assert(cbBuffer >= VBOXVDMACMD_HEADER_SIZE());
     250
     251        if (!pvBuffer)
     252            return VERR_INVALID_PARAMETER;
     253        if (cbBuffer < VBOXVDMACMD_HEADER_SIZE())
     254            return VERR_INVALID_PARAMETER;
     255
     256        PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pvBuffer;
     257        uint32_t cbCmd = 0;
     258        switch (pCmd->enmType)
     259        {
     260            case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
     261            {
     262                const PVBOXVDMACMD_DMA_PRESENT_BLT pBlt = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
     263                int cbBlt = vboxVDMACmdExecBlt(pVdma, pBlt, cbBuffer);
     264                Assert(cbBlt >= 0);
     265                Assert((uint32_t)cbBlt <= cbBuffer);
     266                if (cbBlt >= 0)
     267                {
     268                    if (cbBlt == cbBuffer)
     269                        return VINF_SUCCESS;
     270                    else
     271                    {
     272                        cbBuffer -= (uint32_t)cbBlt;
     273                        pvBuffer -= cbBlt;
     274                    }
     275                }
     276                else
     277                    return cbBlt; /* error */
     278                break;
     279            }
     280            default:
     281                AssertBreakpoint();
     282                return VERR_INVALID_FUNCTION;
     283        }
     284    } while (1);
     285
     286    /* we should not be here */
     287    AssertBreakpoint();
     288    return VERR_INVALID_STATE;
     289}
    90290
    91291int vboxVDMAPipeConstruct(PVBOXVDMAPIPE pPipe)
     
    317517}
    318518
    319 void vboxVDMACommandProcess(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd)
     519static void vboxVDMACommandProcess(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd)
    320520{
    321521    PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
    322     pCmd->rc = VINF_SUCCESS;
    323     int rc = VBoxSHGSMICommandComplete (pHgsmi, pCmd);
    324     AssertRC(rc);
    325 }
    326 
    327 void vboxVDMAControlProcess(PVBOXVDMAHOST pVdma, PVBOXVDMA_CTL pCmd)
     522    const uint8_t * pvBuf;
     523    PGMPAGEMAPLOCK Lock;
     524    int rc;
     525    bool bReleaseLocked = false;
     526
     527    do
     528    {
     529        PPDMDEVINS pDevIns = pVdma->pVGAState->pDevInsR3;
     530
     531        if (pCmd->fFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR)
     532            pvBuf = VBOXVDMACBUF_DR_TAIL(pCmd, const uint8_t);
     533        else if (pCmd->fFlags & VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET)
     534        {
     535            uint8_t * pvRam = pVdma->pVGAState->vram_ptrR3;
     536            pvBuf = pvRam + pCmd->Location.offVramBuf;
     537        }
     538        else
     539        {
     540            RTGCPHYS phPage = pCmd->Location.phBuf & ~0xfffULL;
     541            uint32_t offset = pCmd->Location.phBuf & 0xfff;
     542            Assert(offset + pCmd->cbBuf <= 0x1000);
     543            if (offset + pCmd->cbBuf > 0x1000)
     544            {
     545                /* @todo: more advanced mechanism of command buffer proc is actually needed */
     546                rc = VERR_INVALID_PARAMETER;
     547                break;
     548            }
     549
     550            const void * pvPageBuf;
     551            rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvPageBuf, &Lock);
     552            AssertRC(rc);
     553            if (!RT_SUCCESS(rc))
     554            {
     555                /* @todo: if (rc == VERR_PGM_PHYS_PAGE_RESERVED) -> fall back on using PGMPhysRead ?? */
     556                break;
     557            }
     558
     559            pvBuf = (const uint8_t *)pvPageBuf;
     560            pvBuf += offset;
     561
     562            bReleaseLocked = true;
     563        }
     564
     565        rc = vboxVDMACmdExec(pVdma, pvBuf, pCmd->cbBuf);
     566        AssertRC(rc);
     567
     568        if (bReleaseLocked)
     569            PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
     570    } while (0);
     571
     572    pCmd->rc = rc;
     573
     574    rc = VBoxSHGSMICommandComplete (pHgsmi, pCmd);
     575    AssertRC(rc);
     576}
     577
     578static void vboxVDMAControlProcess(PVBOXVDMAHOST pVdma, PVBOXVDMA_CTL pCmd)
    328579{
    329580    PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
     
    340591} VBOXVDMACMD_PROCESS_CONTEXT, *PVBOXVDMACMD_PROCESS_CONTEXT;
    341592
    342 DECLCALLBACK(bool) vboxVDMACommandProcessCb(PVBOXVDMAPIPE pPipe, void *pvCallback)
     593static DECLCALLBACK(bool) vboxVDMACommandProcessCb(PVBOXVDMAPIPE pPipe, void *pvCallback)
    343594{
    344595    PVBOXVDMACMD_PROCESS_CONTEXT pContext = (PVBOXVDMACMD_PROCESS_CONTEXT)pvCallback;
     
    359610}
    360611
    361 DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD ThreadSelf, void *pvUser)
     612static DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD ThreadSelf, void *pvUser)
    362613{
    363614    PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvUser;
     
    421672        hgsmiListInit(&pVdma->PendingList);
    422673        pVdma->pHgsmi = pVGAState->pHGSMI;
    423 
     674        pVdma->pVGAState = pVGAState;
    424675        rc = vboxVDMAPipeConstruct(&pVdma->Pipe);
    425676        AssertRC(rc);
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