BOOL APIENTRY VBoxDispDrvStretchBlt(SURFOBJ *psoDest, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo, COLORADJUSTMENT *pca, POINTL *pptlHTOrg, RECTL *prclDest, RECTL *prclSrc, POINTL *pptlMask, ULONG iMode) { BOOL bRc; LOGF_ENTER(); STATDRVENTRY(StretchBlt, psoDest); bRc = EngStretchBlt(getSurfObj(psoDest), getSurfObj(psoSrc), psoMask, pco, pxlo, pca, pptlHTOrg, prclDest, prclSrc, pptlMask, iMode); VBVA_OPERATION(psoDest, StretchBlt, (psoDest, psoSrc, psoMask, pco, pxlo, pca, pptlHTOrg, prclDest, prclSrc, pptlMask, iMode)); LOGF_LEAVE(); return bRc; }
BOOL APIENTRY VBoxDispDrvBitBlt(SURFOBJ *psoTrg, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo, RECTL *prclTrg, POINTL *pptlSrc, POINTL *pptlMask, BRUSHOBJ *pbo, POINTL *pptlBrush, ROP4 rop4) { BOOL bRc; LOGF_ENTER(); STATDRVENTRY(BitBlt, psoTrg); LOG(("psoTrg = %p, psoSrc = %p, psoMask = %p, pco = %p, pxlo = %p, prclTrg = %p, pptlSrc = %p, " "pptlMask = %p, pbo = %p, pptlBrush = %p, rop4 = %08X", psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg, pptlSrc, pptlMask, pbo, pptlBrush, rop4)); bRc = EngBitBlt(getSurfObj(psoTrg), getSurfObj(psoSrc), psoMask, pco, pxlo, prclTrg, pptlSrc, pptlMask, pbo, pptlBrush, rop4); VBVA_OPERATION(psoTrg, BitBlt, (psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg, pptlSrc, pptlMask, pbo, pptlBrush, rop4)); LOGF_LEAVE(); return bRc; }
BOOL APIENTRY VBoxDispDrvPaint(SURFOBJ *pso, CLIPOBJ *pco, BRUSHOBJ *pbo, POINTL *pptlBrushOrg, MIX mix) { BOOL bRc; LOGF_ENTER(); STATDRVENTRY(Paint, pso); bRc = EngPaint (getSurfObj(pso), pco, pbo, pptlBrushOrg, mix); VBVA_OPERATION(pso, Paint, (pso, pco, pbo, pptlBrushOrg, mix)); LOGF_LEAVE(); return bRc; }
BOOL APIENTRY VBoxDispDrvFillPath(SURFOBJ *pso, PATHOBJ *ppo, CLIPOBJ *pco, BRUSHOBJ *pbo, POINTL *pptlBrushOrg, MIX mix, FLONG flOptions) { BOOL bRc; LOGF_ENTER(); STATDRVENTRY(FillPath, pso); bRc = EngFillPath(getSurfObj(pso), ppo, pco, pbo, pptlBrushOrg, mix, flOptions); VBVA_OPERATION(pso, FillPath, (pso, ppo, pco, pbo, pptlBrushOrg, mix, flOptions)); LOGF_LEAVE(); return bRc; }
BOOL APIENTRY VBoxDispDrvStrokePath(SURFOBJ *pso, PATHOBJ *ppo, CLIPOBJ *pco, XFORMOBJ *pxo, BRUSHOBJ *pbo, POINTL *pptlBrushOrg, LINEATTRS *plineattrs, MIX mix) { BOOL bRc; LOGF_ENTER(); STATDRVENTRY(StrokePath, pso); bRc = EngStrokePath(getSurfObj(pso), ppo, pco, pxo, pbo, pptlBrushOrg, plineattrs, mix); VBVA_OPERATION(pso, StrokePath, (pso, ppo, pco, pxo, pbo, pptlBrushOrg, plineattrs, mix)); LOGF_LEAVE(); return bRc; }
BOOL APIENTRY VBoxDispDrvLineTo(SURFOBJ *pso, CLIPOBJ *pco, BRUSHOBJ *pbo, LONG x1, LONG y1, LONG x2, LONG y2, RECTL *prclBounds, MIX mix) { BOOL bRc; LOGF_ENTER(); STATDRVENTRY(LineTo, pso); bRc = EngLineTo(getSurfObj(pso), pco, pbo, x1, y1, x2, y2, prclBounds, mix); VBVA_OPERATION(pso, LineTo, (pso, pco, pbo, x1, y1, x2, y2, prclBounds, mix)); LOGF_LEAVE(); return bRc; }
BOOL APIENTRY VBoxDispDrvTextOut(SURFOBJ *pso, STROBJ *pstro, FONTOBJ *pfo, CLIPOBJ *pco, RECTL *prclExtra, RECTL *prclOpaque, BRUSHOBJ *pboFore, BRUSHOBJ *pboOpaque, POINTL *pptlOrg, MIX mix) { BOOL bRc; LOGF_ENTER(); STATDRVENTRY(TextOut, pso); bRc = EngTextOut(getSurfObj(pso), pstro, pfo, pco, prclExtra, prclOpaque, pboFore, pboOpaque, pptlOrg, mix); VBVA_OPERATION(pso, TextOut, (pso, pstro, pfo, pco, prclExtra, prclOpaque, pboFore, pboOpaque, pptlOrg, mix)); LOGF_LEAVE(); return bRc; }
static int vrdpGetIntersectingClipRects(VRDPCLIPRECTS *pClipRects, SURFOBJ *pso, RECTL *prcl, CLIPOBJ *pco, POINTL *pptlSrc) { BOOL bTooManyRects = FALSE; LOGF(("pso = %p, pptlSrc = %p", pso, pptlSrc)); pso = getSurfObj(pso); pClipRects->rclDstOrig = *prcl; pClipRects->rclDst = *prcl; pClipRects->rects.c = 0; vrdpAdjustRect(pso, &pClipRects->rclDst); if (pco && (pco->iDComplexity != DC_TRIVIAL)) { ULONG iDirection = CD_ANY; if (pptlSrc) { /* Operation is performed on the same (screen) surface and enumeration direction * must take into account the position of source and target rectangles. */ if (pptlSrc->x <= prcl->left) { if (pptlSrc->y <= prcl->top) { iDirection = CD_LEFTUP; } else { iDirection = CD_LEFTDOWN; } } else { if (pptlSrc->y <= prcl->top) { iDirection = CD_RIGHTUP; } else { iDirection = CD_RIGHTDOWN; } } } /* Clip the target rect by entire clipping region. Obtain the effective target. */ vrdpIntersectRects(&pClipRects->rclDst, &pClipRects->rclDst, &pco->rclBounds); /* Enumerate rectangles. Try to get all rectangles at once and if there is not * enough space (too many rectangles) fail with the bTooManyRects condition. */ CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iDirection, 0); bTooManyRects = CLIPOBJ_bEnum(pco, sizeof(pClipRects->rects), &pClipRects->rects.c); if (!bTooManyRects) { RECTL *prclClipSrc = &pClipRects->rects.arcl[0]; RECTL *prclClipDst = prclClipSrc; ULONG cRects = pClipRects->rects.c; LOGF(("%d rects", cRects)); if (cRects > 0) { for (; cRects != 0; cRects--, prclClipSrc++) { vrdpIntersectRects(prclClipDst, prclClipSrc, &pClipRects->rclDst); if (vrdpIsRectEmpty(prclClipDst)) { pClipRects->rects.c--; } else { prclClipDst++; } } } if (pClipRects->rects.c == 0) { pClipRects->rclDst.left = pClipRects->rclDst.right = 0; } LOGF(("%d rects remains", pClipRects->rects.c)); } } if (vrdpIsRectEmpty(&pClipRects->rclDst)) { return VRDP_CLIP_NO_INTERSECTION; } if (bTooManyRects) { pClipRects->rects.c = 0; return VRDP_CLIP_TOO_MANY_RECTS; } return VRDP_CLIP_OK; }
void vrdpDrvSaveScreenBits(SURFOBJ *pso, ULONG iMode, ULONG_PTR ident, RECTL *prcl) { PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev; switch (iMode) { case SS_SAVE: { VRDEORDERSAVESCREEN order; order.pt1.x = (int16_t)prcl->left; order.pt1.y = (int16_t)prcl->top; order.pt2.x = (int16_t)prcl->right; order.pt2.y = (int16_t)prcl->bottom; order.ident = (uint8_t)ident; order.restore = 0; vrdpReportOrderGeneric(pDev, NULL, &order, sizeof (order), VRDE_ORDER_SAVESCREEN); } break; case SS_RESTORE: { VRDEORDERSAVESCREEN order; order.pt1.x = (int16_t)prcl->left; order.pt1.y = (int16_t)prcl->top; order.pt2.x = (int16_t)prcl->right; order.pt2.y = (int16_t)prcl->bottom; order.ident = (uint8_t)ident; order.restore = 1; if (vrdpReportOrderGeneric(pDev, NULL, &order, sizeof (order), VRDE_ORDER_SAVESCREEN)) { uint8_t *pu8Bits; int32_t lDelta; uint32_t w; uint32_t h; int cbPixel; pso = getSurfObj(pso); cbPixel = format2BytesPerPixel(pso); pu8Bits = (uint8_t *)pso->pvScan0 + pso->lDelta * prcl->top + cbPixel * prcl->left; lDelta = pso->lDelta; w = prcl->right - prcl->left; h = prcl->bottom - prcl->top; vrdpWriteBits(pDev, pu8Bits, lDelta, prcl->left, prcl->top, w, h, cbPixel); } } break; default: WARN(("Invalid mode %d!!!", iMode)); } }
BOOL APIENTRY VBoxDispDrvCopyBits(SURFOBJ *psoDest, SURFOBJ *psoSrc, CLIPOBJ *pco, XLATEOBJ *pxlo, RECTL *prclDest, POINTL *pptlSrc) { BOOL bRc; RECTL rclDest = *prclDest; POINTL ptlSrc = *pptlSrc; BOOL bDo = TRUE; LOGF_ENTER(); STATDRVENTRY(CopyBits, psoDest); LOG(("psoDest = %p, psoSrc = %p, pco = %p, pxlo = %p, prclDest = %p, pptlSrc = %p", psoDest, psoSrc, pco, pxlo, prclDest, pptlSrc)); DUMPSURF(psoSrc, "psoSrc"); DUMPSURF(psoDest, "psoDest"); STATPRINT; #ifdef VBOX_VBVA_ADJUST_RECT /* Experimental fix for too large bitmap updates. * * Some application do a large bitmap update event if only * a small part of the bitmap is actually changed. * * The driver will find the changed rectangle by comparing * the current framebuffer content with the source bitmap. * * The optimization is only active when: * - the VBVA extension is enabled; * - the source bitmap is not cacheable; * - the bitmap formats of both the source and the screen surfaces are equal. * */ if ( psoSrc && !VBoxDispIsScreenSurface(psoSrc) && VBoxDispIsScreenSurface(psoDest)) { PVBOXDISPDEV pDev = ((PVBOXDISPDEV))psoDest->dhpdev; LOG(("offscreen->screen")); if ( pDev->vbvaCtx.pVBVA && (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED)) { if ( (psoSrc->fjBitmap & BMF_DONTCACHE) != 0 || psoSrc->iUniq == 0) { LOG(("non-cacheable %d->%d (pDev %p)", psoSrc->iBitmapFormat, psoDest->iBitmapFormat, pDev)); /* It is possible to apply the fix. */ bDo = vbvaFindChangedRect(getSurfObj(psoDest), getSurfObj(psoSrc), &rclDest, &ptlSrc); } } } if (!bDo) { /* The operation is a NOP. Just return success. */ LOGF_LEAVE(); return TRUE; } #endif /* VBOX_VBVA_ADJUST_RECT */ bRc = EngCopyBits(getSurfObj(psoDest), getSurfObj(psoSrc), pco, pxlo, &rclDest, &ptlSrc); VBVA_OPERATION(psoDest, CopyBits, (psoDest, psoSrc, pco, pxlo, &rclDest, &ptlSrc)); LOGF_LEAVE(); return bRc; }
ULONG_PTR APIENTRY VBoxDispDrvSaveScreenBits(SURFOBJ *pso, ULONG iMode, ULONG_PTR ident, RECTL *prcl) { ULONG_PTR rc = 0; /* 0 means the function failure for every iMode. */ RECTL rcl; SSB *pSSB; SURFOBJ *psoOrg = pso; BOOL bCallVBVA = FALSE; PVBOXDISPDEV pDev = (PVBOXDISPDEV) pso->dhpdev; LOGF(("%p, %d, %d, %d,%d %d,%d", pso, iMode, ident, prcl->left, prcl->top, prcl->right, prcl->bottom)); if (!pDev) { return rc; } pso = getSurfObj(pso); /* Order the rectangle. */ if (prcl->left <= prcl->right) { rcl.left = prcl->left; rcl.right = prcl->right; } else { rcl.left = prcl->right; rcl.right = prcl->left; } if (prcl->top <= prcl->bottom) { rcl.top = prcl->top; rcl.bottom = prcl->bottom; } else { rcl.top = prcl->bottom; rcl.bottom = prcl->top; } /* Implementation of the save/restore is a bit complicated because RDP * requires "the sequencing of saves and restores is such that they * behave as a last-in, first-out stack.". */ switch (iMode) { case SS_SAVE: { LOG(("SS_SAVE %d", pDev->cSSB)); if (pDev->cSSB >= RT_ELEMENTS(pDev->aSSB)) { /* All slots are already in use. Fail. */ WARN(("no more slots %d!!!", pDev->cSSB)); break; } /* Get pointer to the slot where bits will be saved. */ pSSB = &pDev->aSSB[pDev->cSSB]; /* Allocate memory for screen bits and copy them to the buffer. */ if (ssbCopy(pSSB, pso, &rcl, FALSE /* bToScreen */)) { /* Bits where successfully copied. Increase the active slot number * and call VBVA levels, 'ident' is also assigned, the VBVA level * will use it even for the SS_SAVE. */ ident = rc = pSSB->ident = ++pDev->cSSB; bCallVBVA = TRUE; } } break; case SS_RESTORE: { LOG(("SS_RESTORE")); if (pDev->cSSB == 0 || ident == 0 || ident > pDev->cSSB) { WARN(("no slot: pDev->cSSB = %d!!!", pDev->cSSB)); break; } if (ident < pDev->cSSB) { ssbDiscardUpperSlots(pDev, ident); } Assert(ident == pDev->cSSB); Assert(ident != 0); pSSB = &pDev->aSSB[ident - 1]; ssbCopy(pSSB, pso, &rcl, TRUE /* bToScreen */); /* Bits must be discarded. */ ssbDiscardTopSlot (pDev); rc = TRUE; bCallVBVA = TRUE; } break; case SS_FREE: { LOG(("SS_FREE")); if (pDev->cSSB == 0 || ident == 0 || ident > pDev->cSSB) { WARN(("no slot: pDev->cSSB = %d!!!", pDev->cSSB)); break; } if (ident < pDev->cSSB) { ssbDiscardUpperSlots(pDev, ident); } Assert(ident == pDev->cSSB); Assert(ident != 0); /* Bits must be discarded. */ ssbDiscardTopSlot(pDev); rc = TRUE; } break; } /* Now call the VBVA/VRDP levels. */ if (bCallVBVA) { LOG(("calling VBVA")); VBVA_OPERATION(psoOrg, SaveScreenBits, (psoOrg, iMode, ident, &rcl)); } LOGF(("return %d", rc)); return rc; }