VBoxVideoVbva.cpp revision bd88a03fe4f970611c171f081be318fcd74e85e8
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/** @file
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * VirtualBox Windows Wddm guest video driver
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * VBVA dirty rectangles calculations.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2010 Sun Microsystems, Inc.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
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.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
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 */
d10b594ea1bfbfb3dbd7132080ab860abe618cb4vboxsync
d10b594ea1bfbfb3dbd7132080ab860abe618cb4vboxsync#include "../VBoxVideo.h"
d10b594ea1bfbfb3dbd7132080ab860abe618cb4vboxsync#include "../Helper.h"
d10b594ea1bfbfb3dbd7132080ab860abe618cb4vboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncstatic int vboxVBVAInformHost (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO * pVbva, BOOL bEnable)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync int rc = VERR_NO_MEMORY;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync void *p = vboxHGSMIBufferAlloc (pDevExt,
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync sizeof (VBVAENABLE_EX),
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync HGSMI_CH_VBVA,
35396ee506ef68dd1c161f1ef2c3c0b68a146ff2vboxsync VBVA_ENABLE);
35396ee506ef68dd1c161f1ef2c3c0b68a146ff2vboxsync Assert(p);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (!p)
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync {
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync drprintf((__FUNCTION__":vboxVBVAInformHost: HGSMIHeapAlloc failed\n"));
2d5ac59d51273f70a05a112ea103ebf0bee1a6e4vboxsync rc = VERR_NO_MEMORY;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync else
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync VBVAENABLE_EX *pEnableEx = (VBVAENABLE_EX *)p;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync pEnableEx->u32ScreenId = pVbva->srcId;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync VBVAENABLE *pEnable = &pEnableEx->Base;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync pEnable->u32Flags = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync pEnable->u32Flags |= VBVA_F_EXTENDED;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync pEnable->u32Offset = (uint32_t)pVbva->offVBVA;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync pEnable->i32Result = VERR_NOT_SUPPORTED;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync vboxHGSMIBufferSubmit (pDevExt, p);
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
54ae7b69a9aa4256e14122eaf595699d312cf901vboxsync if (bEnable)
54ae7b69a9aa4256e14122eaf595699d312cf901vboxsync {
d134558e26d3744503b2dbe50a75bcd3fa678432vboxsync rc = pEnable->i32Result;
d134558e26d3744503b2dbe50a75bcd3fa678432vboxsync AssertRC(rc);
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync }
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync else
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync rc = VINF_SUCCESS;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync vboxHGSMIBufferFree (pDevExt, p);
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync }
f2905347646a43ad687e0ceb9f4689f2bf76c4c2vboxsync return rc;
dae86d7bd26c4030c4cfa21231757d1a12f50bf8vboxsync}
f2905347646a43ad687e0ceb9f4689f2bf76c4c2vboxsync
f2905347646a43ad687e0ceb9f4689f2bf76c4c2vboxsync/*
f2905347646a43ad687e0ceb9f4689f2bf76c4c2vboxsync * Public hardware buffer methods.
dae86d7bd26c4030c4cfa21231757d1a12f50bf8vboxsync */
dae86d7bd26c4030c4cfa21231757d1a12f50bf8vboxsyncint vboxVbvaEnable (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva)
dae86d7bd26c4030c4cfa21231757d1a12f50bf8vboxsync{
f2905347646a43ad687e0ceb9f4689f2bf76c4c2vboxsync VBVABUFFER *pVBVA = pVbva->pVBVA;
dae86d7bd26c4030c4cfa21231757d1a12f50bf8vboxsync
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync// DISPDBG((1, "VBoxDisp::vboxVbvaEnable screen %p vbva off 0x%x\n", ppdev->pjScreen, ppdev->layout.offVBVABuffer));
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync pVBVA->hostFlags.u32HostEvents = 0;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync pVBVA->hostFlags.u32SupportedOrders = 0;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync pVBVA->off32Data = 0;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync pVBVA->off32Free = 0;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync RtlZeroMemory (pVBVA->aRecords, sizeof (pVBVA->aRecords));
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync pVBVA->indexRecordFirst = 0;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync pVBVA->indexRecordFree = 0;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync pVBVA->cbPartialWriteThreshold = 256;
f2905347646a43ad687e0ceb9f4689f2bf76c4c2vboxsync pVBVA->cbData = pVbva->cbVBVA - sizeof (VBVABUFFER) + sizeof (pVBVA->au8Data);
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync pVbva->fHwBufferOverflow = FALSE;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync pVbva->pRecord = NULL;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync int rc = vboxVBVAInformHost (pDevExt, pVbva, TRUE);
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync AssertRC(rc);
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync if (!RT_SUCCESS(rc))
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync vboxVbvaDisable (pDevExt, pVbva);
dae86d7bd26c4030c4cfa21231757d1a12f50bf8vboxsync
dae86d7bd26c4030c4cfa21231757d1a12f50bf8vboxsync return rc;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync}
f2905347646a43ad687e0ceb9f4689f2bf76c4c2vboxsync
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsyncint vboxVbvaDisable (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva)
f2905347646a43ad687e0ceb9f4689f2bf76c4c2vboxsync{
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync// DISPDBG((1, "VBoxDisp::vbvaDisable called.\n"));
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync pVbva->fHwBufferOverflow = FALSE;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync pVbva->pRecord = NULL;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync// ppdev->pVBVA = NULL;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync return vboxVBVAInformHost (pDevExt, pVbva, FALSE);
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync}
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsyncint vboxVbvaCreate(PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva, ULONG offBuffer, ULONG cbBuffer, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync{
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync memset(pVbva, 0, sizeof(VBOXVBVAINFO));
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync int rc = VBoxMapAdapterMemory (pDevExt,
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync (void**)&pVbva->pVBVA,
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync offBuffer,
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync cbBuffer);
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync AssertRC(rc);
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync if (RT_SUCCESS(rc))
78dc0b94d7cbd4c0d9a7c80614260f72559a12b1vboxsync {
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync Assert(pVbva->pVBVA);
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync pVbva->offVBVA = offBuffer;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync pVbva->cbVBVA = cbBuffer;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync pVbva->srcId = srcId;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync }
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync return rc;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync}
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync/*
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync * Private operations.
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync */
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsyncstatic uint32_t vboxHwBufferAvail (const VBVABUFFER *pVBVA)
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync{
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync int32_t i32Diff = pVBVA->off32Data - pVBVA->off32Free;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync
dae86d7bd26c4030c4cfa21231757d1a12f50bf8vboxsync return i32Diff > 0? i32Diff: pVBVA->cbData + i32Diff;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync}
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsyncstatic void vboxHwBufferFlush (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva)
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync{
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync /* Issue the flush command. */
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync void *p = vboxHGSMIBufferAlloc (pDevExt,
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync sizeof (VBVAFLUSH),
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync HGSMI_CH_VBVA,
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync VBVA_FLUSH);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync Assert(p);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync if (!p)
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync {
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync drprintf((__FUNCTION__":vboxHwBufferFlush: HGSMIHeapAlloc failed\n"));
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync }
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync else
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync {
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync VBVAFLUSH *pFlush = (VBVAFLUSH *)p;
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync
84918d5816927c515e57dcafa1f60f6c05241d11vboxsync pFlush->u32Reserved = 0;
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync vboxHGSMIBufferSubmit (pDevExt, p);
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync vboxHGSMIBufferFree (pDevExt, p);
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync }
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync return;
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync}
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsyncstatic void vboxHwBufferPlaceDataAt (VBVABUFFER *pVBVA, const void *p, uint32_t cb, uint32_t offset)
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync{
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync uint32_t u32BytesTillBoundary = pVBVA->cbData - offset;
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync uint8_t *dst = &pVBVA->au8Data[offset];
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync int32_t i32Diff = cb - u32BytesTillBoundary;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync if (i32Diff <= 0)
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync {
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync /* Chunk will not cross buffer boundary. */
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync memcpy (dst, p, cb);
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync }
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync else
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync {
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync /* Chunk crosses buffer boundary. */
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync memcpy (dst, p, u32BytesTillBoundary);
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync memcpy (&pVBVA->au8Data[0], (uint8_t *)p + u32BytesTillBoundary, i32Diff);
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync }
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync return;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync}
510c603ab35097ee39fb5b6350d1c4f59d7286e3vboxsync
658aae0e2708e6bfe85c620052d807fddd613e5evboxsyncBOOL vboxVbvaBufferBeginUpdate (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva)
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync{
dae86d7bd26c4030c4cfa21231757d1a12f50bf8vboxsync BOOL bRc = FALSE;
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync // DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate called flags = 0x%08X\n",
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync // ppdev->pVBVA? ppdev->pVBVA->u32HostEvents: -1));
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync if ( pVbva->pVBVA
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync && (pVbva->pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync {
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync uint32_t indexRecordNext;
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync Assert (!pVbva->fHwBufferOverflow);
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync Assert (pVbva->pRecord == NULL);
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync indexRecordNext = (pVbva->pVBVA->indexRecordFree + 1) % VBVA_MAX_RECORDS;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync if (indexRecordNext == pVbva->pVBVA->indexRecordFirst)
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync {
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync /* All slots in the records queue are used. */
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync vboxHwBufferFlush (pDevExt, pVbva);
658aae0e2708e6bfe85c620052d807fddd613e5evboxsync }
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync if (indexRecordNext == pVbva->pVBVA->indexRecordFirst)
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync {
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));
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync }
ba5dd00fabaa3475fa5da200d134c73f1c961b49vboxsync else
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync {
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync /* Initialize the record. */
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync VBVARECORD *pRecord = &pVbva->pVBVA->aRecords[pVbva->pVBVA->indexRecordFree];
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync
06913e4efbdb8192155c00fa59de4174c7a50b57vboxsync pRecord->cbRecord = VBVA_F_RECORD_PARTIAL;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync pVbva->pVBVA->indexRecordFree = indexRecordNext;
2f46a509fa35214396aedb4012d33b73fb4d6ec0vboxsync
3f2ab411e38c4f9aa3c3c46e8b94a34b4cad280avboxsync // DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate indexRecordNext = %d\n", indexRecordNext));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* Remember which record we are using. */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pVbva->pRecord = pRecord;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
84918d5816927c515e57dcafa1f60f6c05241d11vboxsync bRc = TRUE;
84918d5816927c515e57dcafa1f60f6c05241d11vboxsync }
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync }
84918d5816927c515e57dcafa1f60f6c05241d11vboxsync
84918d5816927c515e57dcafa1f60f6c05241d11vboxsync return bRc;
84918d5816927c515e57dcafa1f60f6c05241d11vboxsync}
84918d5816927c515e57dcafa1f60f6c05241d11vboxsync
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsyncvoid vboxVbvaBufferEndUpdate (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva)
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsync{
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsync VBVARECORD *pRecord;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
b67986b52286959154244a144c62c9f40091fbbbvboxsync // DISPDBG((1, "VBoxDisp::vboxHwBufferEndUpdate called\n"));
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsync
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsync Assert(pVbva->pVBVA);
b67986b52286959154244a144c62c9f40091fbbbvboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pRecord = pVbva->pRecord;
b67986b52286959154244a144c62c9f40091fbbbvboxsync Assert (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsync
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsync /* Mark the record completed. */
b67986b52286959154244a144c62c9f40091fbbbvboxsync pRecord->cbRecord &= ~VBVA_F_RECORD_PARTIAL;
b67986b52286959154244a144c62c9f40091fbbbvboxsync
b67986b52286959154244a144c62c9f40091fbbbvboxsync pVbva->fHwBufferOverflow = FALSE;
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsync pVbva->pRecord = NULL;
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsync
b67986b52286959154244a144c62c9f40091fbbbvboxsync return;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
b67986b52286959154244a144c62c9f40091fbbbvboxsync
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsyncstatic int vboxHwBufferWrite (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva, const void *p, uint32_t cb)
3b6727bcf40d710e50ad98533cc3f05adaae0226vboxsync{
3b6727bcf40d710e50ad98533cc3f05adaae0226vboxsync VBVARECORD *pRecord;
3b6727bcf40d710e50ad98533cc3f05adaae0226vboxsync uint32_t cbHwBufferAvail;
5fe168a4f5a9832162373822761a9968f3250959vboxsync
6e5bfe53da4b5c41db5c5ccdb84d733f2a5817c6vboxsync uint32_t cbWritten = 0;
6e5bfe53da4b5c41db5c5ccdb84d733f2a5817c6vboxsync
6e5bfe53da4b5c41db5c5ccdb84d733f2a5817c6vboxsync VBVABUFFER *pVBVA = pVbva->pVBVA;
6e5bfe53da4b5c41db5c5ccdb84d733f2a5817c6vboxsync Assert(pVBVA);
6e5bfe53da4b5c41db5c5ccdb84d733f2a5817c6vboxsync
a75d03f806dd80f2690fd9fc8b6f2e55faf388a1vboxsync if (!pVBVA || pVbva->fHwBufferOverflow)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return VERR_INVALID_STATE;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync Assert (pVBVA->indexRecordFirst != pVBVA->indexRecordFree);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pRecord = pVbva->pRecord;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync Assert (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync dfprintf((__FUNCTION__": VW %d\n", cb));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync while (cb > 0)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync uint32_t cbChunk = cb;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
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));
d134558e26d3744503b2dbe50a75bcd3fa678432vboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (cbChunk >= cbHwBufferAvail)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync dfprintf((__FUNCTION__": 1) avail %d, chunk %d\n", cbHwBufferAvail, cbChunk));
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync vboxHwBufferFlush (pDevExt, pVbva);
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync if (cbChunk >= cbHwBufferAvail)
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync {
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync dprintf((__FUNCTION__": no place for %d bytes. Only %d bytes available after flush. Going to partial writes.\n",
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync cb, cbHwBufferAvail));
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync if (cbHwBufferAvail <= pVBVA->cbPartialWriteThreshold)
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync {
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync drprintf((__FUNCTION__": Buffer overflow!!!\n"));
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync pVbva->fHwBufferOverflow = TRUE;
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync Assert(FALSE);
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync return VERR_NO_MEMORY;
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync }
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync cbChunk = cbHwBufferAvail - pVBVA->cbPartialWriteThreshold;
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync }
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync }
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync
d8ebb1b0155a5f076e545b7a4e52df41608e1c7dvboxsync Assert(cbChunk <= cb);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync Assert(cbChunk <= vboxHwBufferAvail (pVBVA));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync vboxHwBufferPlaceDataAt (pVbva->pVBVA, (uint8_t *)p + cbWritten, cbChunk, pVBVA->off32Free);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pVBVA->off32Free = (pVBVA->off32Free + cbChunk) % pVBVA->cbData;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pRecord->cbRecord += cbChunk;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync cbHwBufferAvail -= cbChunk;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync cb -= cbChunk;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync cbWritten += cbChunk;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return VINF_SUCCESS;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Public writer to the hardware buffer.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncint vboxWrite (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva, const void *pv, uint32_t cb)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return vboxHwBufferWrite (pDevExt, pVbva, pv, cb);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncint vboxVbvaReportDirtyRect (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva, RECT *pRectOrig)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync VBVACMDHDR hdr;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync RECT rect = *pRectOrig;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (rect.left < 0) rect.left = 0;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (rect.top < 0) rect.top = 0;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync// if (rect.right > (int)ppdev->cxScreen) rect.right = ppdev->cxScreen;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync// if (rect.bottom > (int)ppdev->cyScreen) rect.bottom = ppdev->cyScreen;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync hdr.x = (int16_t)rect.left;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync hdr.y = (int16_t)rect.top;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync hdr.w = (uint16_t)(rect.right - rect.left);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync hdr.h = (uint16_t)(rect.bottom - rect.top);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync// hdr.x += (int16_t)ppdev->ptlDevOrg.x;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync// hdr.y += (int16_t)ppdev->ptlDevOrg.y;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return vboxWrite (pDevExt, pVbva, &hdr, sizeof(hdr));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
f0679993bc62dafdcee7dfa8138b5edfdffd8b0evboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync#ifdef VBOXVDMA_WITH_VBVA
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncint vboxVbvaReportCmdOffset (PDEVICE_EXTENSION pDevExt, VBOXVBVAINFO *pVbva, uint32_t offCmd)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync VBOXVDMAVBVACMD cmd;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync cmd.offCmd = offCmd;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return vboxWrite (pDevExt, pVbva, &cmd, sizeof(cmd));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync#endif
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync