VBoxVideoVbva.cpp revision bd88a03fe4f970611c171f081be318fcd74e85e8
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * VirtualBox Windows Wddm guest video driver
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * VBVA dirty rectangles calculations.
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2010 Sun Microsystems, Inc.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * available from http://www.virtualbox.org. This file is free software;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * you can redistribute it and/or modify it under the terms of the GNU
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * General Public License (GPL) as published by the Free Software
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d10b594ea1bfbfb3dbd7132080ab860abe618cb4vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
d10b594ea1bfbfb3dbd7132080ab860abe618cb4vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
d10b594ea1bfbfb3dbd7132080ab860abe618cb4vboxsync * additional information or have any questions.
d10b594ea1bfbfb3dbd7132080ab860abe618cb4vboxsync#include "../Helper.h"
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncstatic int vboxVBVAInformHost (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO * pVbva, BOOL bEnable)
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync drprintf((__FUNCTION__":vboxVBVAInformHost: HGSMIHeapAlloc failed\n"));
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync pEnable->u32Flags = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
f2905347646a43ad687e0ceb9f4689f2bf76c4c2vboxsync * Public hardware buffer methods.
dae86d7bd26c4030c4cfa21231757d1a12f50bf8vboxsyncint vboxVbvaEnable (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva)
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync// DISPDBG((1, "VBoxDisp::vboxVbvaEnable screen %p vbva off 0x%x\n", ppdev->pjScreen, ppdev->layout.offVBVABuffer));
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync RtlZeroMemory (pVBVA->aRecords, sizeof (pVBVA->aRecords));
f2905347646a43ad687e0ceb9f4689f2bf76c4c2vboxsync pVBVA->cbData = pVbva->cbVBVA - sizeof (VBVABUFFER) + sizeof (pVBVA->au8Data);
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync int rc = vboxVBVAInformHost (pDevExt, pVbva, TRUE);
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsyncint vboxVbvaDisable (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva)
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync// DISPDBG((1, "VBoxDisp::vbvaDisable called.\n"));
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync// ppdev->pVBVA = NULL;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsyncint vboxVbvaCreate(PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva, ULONG offBuffer, ULONG cbBuffer, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync * Private operations.
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsyncstatic uint32_t vboxHwBufferAvail (const VBVABUFFER *pVBVA)
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync int32_t i32Diff = pVBVA->off32Data - pVBVA->off32Free;
dae86d7bd26c4030c4cfa21231757d1a12f50bf8vboxsync return i32Diff > 0? i32Diff: pVBVA->cbData + i32Diff;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsyncstatic void vboxHwBufferFlush (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva)
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync /* Issue the flush command. */
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync drprintf((__FUNCTION__":vboxHwBufferFlush: HGSMIHeapAlloc failed\n"));
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsyncstatic void vboxHwBufferPlaceDataAt (VBVABUFFER *pVBVA, const void *p, uint32_t cb, uint32_t offset)
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync uint32_t u32BytesTillBoundary = pVBVA->cbData - offset;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync /* Chunk will not cross buffer boundary. */
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync /* Chunk crosses buffer boundary. */
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync memcpy (&pVBVA->au8Data[0], (uint8_t *)p + u32BytesTillBoundary, i32Diff);
658aae0e2708e6bfe85c620052d807fddd613e5evboxsyncBOOL vboxVbvaBufferBeginUpdate (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva)
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync // DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate called flags = 0x%08X\n",
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync // ppdev->pVBVA? ppdev->pVBVA->u32HostEvents: -1));
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync && (pVbva->pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync indexRecordNext = (pVbva->pVBVA->indexRecordFree + 1) % VBVA_MAX_RECORDS;
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync if (indexRecordNext == pVbva->pVBVA->indexRecordFirst)
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync /* All slots in the records queue are used. */
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync if (indexRecordNext == pVbva->pVBVA->indexRecordFirst)
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync// /* Even after flush there is no place. Fail the request. */
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync// DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate no space in the queue of records!!! first %d, last %d\n",
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync// ppdev->pVBVA->indexRecordFirst, ppdev->pVBVA->indexRecordFree));
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync /* Initialize the record. */
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync VBVARECORD *pRecord = &pVbva->pVBVA->aRecords[pVbva->pVBVA->indexRecordFree];
3f2ab411e38c4f9aa3c3c46e8b94a34b4cad280avboxsync // DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate indexRecordNext = %d\n", indexRecordNext));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* Remember which record we are using. */
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsyncvoid vboxVbvaBufferEndUpdate (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva)
b67986b52286959154244a144c62c9f40091fbbbvboxsync // DISPDBG((1, "VBoxDisp::vboxHwBufferEndUpdate called\n"));
b67986b52286959154244a144c62c9f40091fbbbvboxsync Assert (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsync /* Mark the record completed. */
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsyncstatic int vboxHwBufferWrite (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva, const void *p, uint32_t cb)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync Assert (pVBVA->indexRecordFirst != pVBVA->indexRecordFree);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync Assert (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync while (cb > 0)
d134558e26d3744503b2dbe50a75bcd3fa678432vboxsync // DISPDBG((1, "VBoxDisp::vboxHwBufferWrite pVBVA->off32Free %d, pRecord->cbRecord 0x%08X, cbHwBufferAvail %d, cb %d, cbWritten %d\n",
d134558e26d3744503b2dbe50a75bcd3fa678432vboxsync // pVBVA->off32Free, pRecord->cbRecord, cbHwBufferAvail, cb, cbWritten));
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync dfprintf((__FUNCTION__": 1) avail %d, chunk %d\n", cbHwBufferAvail, cbChunk));
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync dprintf((__FUNCTION__": no place for %d bytes. Only %d bytes available after flush. Going to partial writes.\n",
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync if (cbHwBufferAvail <= pVBVA->cbPartialWriteThreshold)
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync cbChunk = cbHwBufferAvail - pVBVA->cbPartialWriteThreshold;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync vboxHwBufferPlaceDataAt (pVbva->pVBVA, (uint8_t *)p + cbWritten, cbChunk, pVBVA->off32Free);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pVBVA->off32Free = (pVBVA->off32Free + cbChunk) % pVBVA->cbData;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Public writer to the hardware buffer.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncint vboxWrite (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva, const void *pv, uint32_t cb)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncint vboxVbvaReportDirtyRect (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva, RECT *pRectOrig)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync// if (rect.right > (int)ppdev->cxScreen) rect.right = ppdev->cxScreen;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync// if (rect.bottom > (int)ppdev->cyScreen) rect.bottom = ppdev->cyScreen;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync// hdr.x += (int16_t)ppdev->ptlDevOrg.x;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync// hdr.y += (int16_t)ppdev->ptlDevOrg.y;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return vboxWrite (pDevExt, pVbva, &hdr, sizeof(hdr));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncint vboxVbvaReportCmdOffset (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva, uint32_t offCmd)