VirtualBox

Changeset 27383 in vbox for trunk/src/VBox/Devices/Graphics


Ignore:
Timestamp:
Mar 15, 2010 9:47:46 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
58836
Message:

wddm: basic Video DMA impl, guest driver bugfix

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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.

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