int Display::i_videoAccelFlush(PPDMIDISPLAYPORT pUpPort) { VIDEOACCEL *pVideoAccel = &mVideoAccelLegacy; VBVAMEMORY *pVbvaMemory = pVideoAccel->pVbvaMemory; #ifdef DEBUG_sunlover_2 LogFlowFunc(("fVideoAccelEnabled = %d\n", pVideoAccel->fVideoAccelEnabled)); #endif /* DEBUG_sunlover_2 */ if (!pVideoAccel->fVideoAccelEnabled) { Log(("Display::VideoAccelFlush: called with disabled VBVA!!! Ignoring.\n")); return VINF_SUCCESS; } /* Here VBVA is enabled and we have the accelerator memory pointer. */ Assert(pVbvaMemory); #ifdef DEBUG_sunlover_2 LogFlowFunc(("indexRecordFirst = %d, indexRecordFree = %d, off32Data = %d, off32Free = %d\n", pVbvaMemory->indexRecordFirst, pVbvaMemory->indexRecordFree, pVbvaMemory->off32Data, pVbvaMemory->off32Free)); #endif /* DEBUG_sunlover_2 */ /* Quick check for "nothing to update" case. */ if (pVbvaMemory->indexRecordFirst == pVbvaMemory->indexRecordFree) { return VINF_SUCCESS; } /* Process the ring buffer */ unsigned uScreenId; /* Initialize dirty rectangles accumulator. */ VBVADIRTYREGION rgn; vbvaRgnInit(&rgn, maFramebuffers, mcMonitors, this, pUpPort); for (;;) { VBVACMDHDR *phdr = NULL; uint32_t cbCmd = ~0; /* Fetch the command data. */ if (!i_vbvaFetchCmd(pVideoAccel, &phdr, &cbCmd)) { Log(("Display::VideoAccelFlush: unable to fetch command. off32Data = %d, off32Free = %d. Disabling VBVA!!!\n", pVbvaMemory->off32Data, pVbvaMemory->off32Free)); return VERR_INVALID_STATE; } if (cbCmd == uint32_t(~0)) { /* No more commands yet in the queue. */ #ifdef DEBUG_sunlover LogFlowFunc(("no command\n")); #endif /* DEBUG_sunlover */ break; } if (cbCmd != 0) { #ifdef DEBUG_sunlover LogFlowFunc(("hdr: cbCmd = %d, x=%d, y=%d, w=%d, h=%d\n", cbCmd, phdr->x, phdr->y, phdr->w, phdr->h)); #endif /* DEBUG_sunlover */ VBVACMDHDR hdrSaved = *phdr; int x = phdr->x; int y = phdr->y; int w = phdr->w; int h = phdr->h; uScreenId = mapCoordsToScreen(maFramebuffers, mcMonitors, &x, &y, &w, &h); phdr->x = (int16_t)x; phdr->y = (int16_t)y; phdr->w = (uint16_t)w; phdr->h = (uint16_t)h; /* Handle the command. * * Guest is responsible for updating the guest video memory. * The Windows guest does all drawing using Eng*. * * For local output, only dirty rectangle information is used * to update changed areas. * * Dirty rectangles are accumulated to exclude overlapping updates and * group small updates to a larger one. */ /* Accumulate the update. */ vbvaRgnDirtyRect(&rgn, uScreenId, phdr); /* Forward the command to VRDP server. */ mParent->i_consoleVRDPServer()->SendUpdate(uScreenId, phdr, cbCmd); *phdr = hdrSaved; } i_vbvaReleaseCmd(pVideoAccel, phdr, cbCmd); } for (uScreenId = 0; uScreenId < mcMonitors; uScreenId++) { /* Draw the framebuffer. */ vbvaRgnUpdateFramebuffer(&rgn, uScreenId); } return VINF_SUCCESS; }
/** * Called regularly on the DisplayRefresh timer. * Also on behalf of guest, when the ring buffer is full. * * @thread EMT */ void Display::VideoAccelFlush (void) { #ifdef DEBUG_sunlover LogFlow(("Display::VideoAccelFlush: mfVideoAccelEnabled = %d\n", mfVideoAccelEnabled)); #endif /* DEBUG_sunlover */ if (!mfVideoAccelEnabled) { Log(("Display::VideoAccelFlush: called with disabled VBVA!!! Ignoring.\n")); return; } /* Here VBVA is enabled and we have the accelerator memory pointer. */ Assert(mpVbvaMemory); #ifdef DEBUG_sunlover LogFlow(("Display::VideoAccelFlush: indexRecordFirst = %d, indexRecordFree = %d, off32Data = %d, off32Free = %d\n", mpVbvaMemory->indexRecordFirst, mpVbvaMemory->indexRecordFree, mpVbvaMemory->off32Data, mpVbvaMemory->off32Free)); #endif /* DEBUG_sunlover */ /* Quick check for "nothing to update" case. */ if (mpVbvaMemory->indexRecordFirst == mpVbvaMemory->indexRecordFree) return; /* Process the ring buffer */ bool fFramebufferIsNull = (mFramebuffer == NULL); if (!fFramebufferIsNull) mFramebuffer->Lock(); /* Initialize dirty rectangles accumulator. */ VBVADIRTYREGION rgn; vbvaRgnInit (&rgn, mFramebuffer, this, mpDrv->pUpPort); for (;;) { VBVACMDHDR *phdr = NULL; uint32_t cbCmd = 0; /* Fetch the command data. */ if (!vbvaFetchCmd (&phdr, &cbCmd)) { Log(("Display::VideoAccelFlush: unable to fetch command. off32Data = %d, off32Free = %d. Disabling VBVA!!!\n", mpVbvaMemory->off32Data, mpVbvaMemory->off32Free)); /* Disable VBVA on those processing errors. */ VideoAccelEnable (false, NULL); break; } if (!cbCmd) { /* No more commands yet in the queue. */ break; } if (!fFramebufferIsNull) { #ifdef DEBUG_sunlover LogFlow(("MAIN::DisplayImpl::VideoAccelFlush: hdr: cbCmd = %d, x=%d, y=%d, w=%d, h=%d\n", cbCmd, phdr->x, phdr->y, phdr->w, phdr->h)); #endif /* DEBUG_sunlover */ /* Handle the command. * * Guest is responsible for updating the guest video memory. * The Windows guest does all drawing using Eng*. * * For local output, only dirty rectangle information is used * to update changed areas. * * Dirty rectangles are accumulated to exclude overlapping updates and * group small updates to a larger one. */ /* Accumulate the update. */ vbvaRgnDirtyRect (&rgn, phdr); // /* Forward the command to VRDP server. */ // mParent->consoleVRDPServer()->SendUpdate (phdr, cbCmd); } vbvaReleaseCmd (phdr, cbCmd); } if (!fFramebufferIsNull) mFramebuffer->Unlock (); /* Draw the framebuffer. */ vbvaRgnUpdateFramebuffer (&rgn); }