void vrdpDrvBitBlt(SURFOBJ *psoTrg, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo, RECTL *prclTrg, POINTL *pptlSrc, POINTL *pptlMask, BRUSHOBJ *pbo, POINTL *pptlBrush, ROP4 rop4) { PVBOXDISPDEV pDev = (PVBOXDISPDEV)psoTrg->dhpdev; /* * BitBlt operation is supported by following RDP orders: * RDP_ORDER_DESTBLT ROP on the screen bits (BLACKNESS, WHITENESS, DSTINVERT). * RDP_ORDER_PATBLT ROP with screen bits and a brush. * RDP_ORDER_SCREENBLT Screen to screen with ROP. * RDP_ORDER_RECT Solid fill (SRCCOPY). * RDP_ORDER_MEMBLT ROP with screen and cached offscreen bitmap. * RDP_ORDER_TRIBLT ROP with screen, cached offscreen bitmap and a brush. * * Actual BitBlts must be mapped to these RDP operations. * Anything that can not be mapped must be emulated with dirty rect. * */ VRDPCLIPRECTS clipRects; int clipResult; RECTL rclTrg = *prclTrg; vrdpOrderRect (&rclTrg); LOGF_ENTER(); clipResult = vrdpGetIntersectingClipRects(&clipRects, psoTrg, &rclTrg, pco, VBoxDispIsScreenSurface(psoSrc)? pptlSrc: NULL); if (clipResult == VRDP_CLIP_NO_INTERSECTION) { /* Do nothing. The Blt does not affect anything. */ WARN(("VRDP_CLIP_NO_INTERSECTION!!!")); dumpPCO (&rclTrg, pco); } else if (clipResult == VRDP_CLIP_TOO_MANY_RECTS) { /* A very complex clip. Better to emulate it. */ WARN(("VRDP_CLIP_TOO_MANY_RECTS!!!")); dumpPCO (&rclTrg, pco); vrdpReportDirtyRects(pDev, &clipRects); } else if (ROP4_NEED_MASK (rop4)) { /* Operation with mask is not supported. */ WARN(("Operation with mask is not supported.")); vrdpReportDirtyRects(pDev, &clipRects); } else if (ROP3_NEED_BRUSH(rop4)) { LOG(("Operation requires brush.")); /* Operation requires brush. */ if (ROP3_NEED_SRC(rop4)) { /* @todo Three way blt. RDP_ORDER_TRIBLT. */ LOG(("TRIBLT pbo->iSolidColor = 0x%08X.", pbo->iSolidColor)); vrdpReportDirtyRects(pDev, &clipRects); } else { /* Only brush and destination. Check if the brush is solid. */ if (pbo->iSolidColor != 0xFFFFFFFF) { /* Solid brush. The iSolidColor is the target surface color. */ uint32_t rgb = vrdpColor2RGB(psoTrg, pbo->iSolidColor); /* Mix with solid brush. RDP_ORDER_PATBLT. Or RDP_ORDER_RECT for rop4 = 0xF0F0. */ LOG(("Solid PATBLT color = %08X, rgb %08X.", pbo->iSolidColor, rgb)); if (rop4 == 0xF0F0) { vrdpReportSolidRect(pDev, &rclTrg, &clipRects, rgb); } else { vrdpReportSolidBlt(pDev, &rclTrg, &clipRects, rgb, (uint8_t)rop4); } } else { /* Non solid brush. RDP_ORDER_PATBLT. */ LOG(("VRDP::vrdpBitBlt: PATBLT pbo->pvRbrush = %p.", pbo->pvRbrush)); /* Realize brush. */ if (!pbo->pvRbrush) { BRUSHOBJ_pvGetRbrush (pbo); } if (pbo->pvRbrush) { /* Brush has been realized. */ VRDPBRUSH *pBrush = (VRDPBRUSH *)pbo->pvRbrush; if (pBrush->fPattern) { vrdpReportPatBlt(pDev, &rclTrg, &clipRects, pBrush, pptlBrush, (uint8_t)rop4); } else { /* @todo BITMAPCACHE followed by MEMBLT? */ vrdpReportDirtyRects(pDev, &clipRects); } } else { /* Unsupported brush format. Fallback to dirty rects. */ vrdpReportDirtyRects(pDev, &clipRects); } } } } else { /* Operation does not require brush. */ if (ROP3_NEED_SRC(rop4)) { LOG(("MEMBLT or SCREENBLT.")); /* MEMBLT or SCREENBLT. */ if (VBoxDispIsScreenSurface(psoSrc)) { /* Screen to screen transfer. SCREENBLT. */ LOG(("SCREENBLT.")); vrdpReportScreenBlt(pDev, &rclTrg, &clipRects, pptlSrc, (uint8_t)rop4); } else { /* Offscreen bitmap to screen. MEMBLT. */ VRDPBCHASH hash; VRDPBCHASH hashDeleted; int cacheResult; LOG(("MEMBLT: bitmap %dx%d.", psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy)); if ( pDev->bBitmapCacheDisabled || (psoSrc->fjBitmap & BMF_DONTCACHE) != 0 || psoSrc->iUniq == 0 /* Bitmaps with hdev == 0 seems to have different RGB layout for 16BPP modes. * Just do not cache these bitmaps and report the dirty display area instead. */ || ( psoSrc->hdev == 0 && !(psoSrc->iBitmapFormat == BMF_24BPP || psoSrc->iBitmapFormat == BMF_32BPP) ) /* Do not try to cache large bitmaps. The cache should be mostly used for icons, etc. * Computing a bitmap hash increases CPU load. Up to 384K pixels (~620x620) */ || psoSrc->sizlBitmap.cx * psoSrc->sizlBitmap.cy > 384 * _1K ) { LOG(("MEMBLT: non cacheable bitmap.")); cacheResult = VRDPBMP_RC_NOT_CACHED; } else { LOG(("MEMBLT: going to cache.")); cacheResult = vrdpbmpCacheSurface(&pDev->vrdpCache, psoSrc, &hash, &hashDeleted, FALSE); } LOG(("MEMBLT: cacheResult 0x%08X", cacheResult)); if (cacheResult & VRDPBMP_RC_F_DELETED) { LOG(("VRDPBMP_RC_F_DELETED")); vrdpReportDeletedBitmap(pDev, &hashDeleted); cacheResult &= ~VRDPBMP_RC_F_DELETED; } switch (cacheResult) { case VRDPBMP_RC_CACHED: vrdpReportCachedBitmap(pDev, psoSrc, &hash); LOG(("MEMBLT: cached add %dx%d", psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy)); /* Continue and report MEMBLT order. */ case VRDPBMP_RC_ALREADY_CACHED: vrdpReportMemBlt(pDev, &clipRects, pptlSrc, (uint8_t)rop4, &hash); LOG(("MEMBLT: cached use %dx%d from %d,%d %dx%d", psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy, pptlSrc->x, pptlSrc->y, rclTrg.right - rclTrg.left, rclTrg.bottom - rclTrg.top)); LOG((" %08X %08X %08X %08X", *(uint32_t *)&((uint8_t *)&hash)[0], *(uint32_t *)&((uint8_t *)&hash)[4], *(uint32_t *)&((uint8_t *)&hash)[8], *(uint32_t *)&((uint8_t *)&hash)[12] )); break; default: /* The surface was not cached. Fallback to dirty rects. */ LOG(("MEMBLT: not cached %dx%d from %d,%d %dx%d", psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy, pptlSrc->x, pptlSrc->y, rclTrg.right - rclTrg.left, rclTrg.bottom - rclTrg.top)); VBoxDispDumpPSO(psoSrc, "psoSrc"); vrdpReportDirtyRects(pDev, &clipRects); } } } else { /* No source and no brush, only dest affected. DESTBLT. */ LOG(("DSTBLT with rop 0x%08X", rop4)); vrdpReportDstBlt(pDev, &rclTrg, &clipRects, (uint8_t)rop4); } } }
LONG GetColor( PPDEV pPDev, BRUSHOBJ *pbo, LPDWORD pColorFG, PDEVBRUSH *ppDevBrush, ROP4 Rop4 ) /*++ Routine Description: Realize the brush color and return the color Arguments: pPDev - Pointer to our DEV pbo - Engine brush object pColorFG - pointer to the ULONG to received forground color, NULL if not needed ppDevBrush - Pointer to the location to received brush, NULL if not needed Rop4 - Rop4 to be used, this function looks at this in order to determine if the brush can be used with the HPGL2 cmds or that the brush will have to be simulated. Return Value: LONG > 0 The Brush is compatible with device format (Fill command) = 0 Failed < 0 The brush must send to device via a bitblt Author: 13-Jan-1994 Thu 20:18:49 created 15-Jan-1994 Sat 06:58:56 updated Change parameters and return value 16-May-1994 Mon 15:59:45 updated Adding PDEV Revision History: --*/ { PDEVBRUSH pDevBrush = NULL; LONG RetVal = 1; DWORD SolidColor = 0xFFFFFF; DWORD RopBG; DWORD RopFG; // // Get the ROP for the foureground and background. This information is // used to determine if the brush has to be simulated, or can be // used with selectable pens in the target device. RopBG = ROP4_BG_ROP(Rop4); RopFG = ROP4_FG_ROP(Rop4); // // Get the current color and select the appropriate pen, this should // ONLY be a solid color as we don't support stroking with arbitrary // brushes. // if (pbo) { // // get the brush realization, and select a pen. // If the BRUSHOBJ's iSolidColor field is a valid color, then // we must do a solid fill with that pen. Otherwise, we must // check the realization of the brush to do a pattern fill. // // To return a Fillable pattern by DoFill, one of the following conditions // must be true and in this sequence // // 1. SOLID COLOR // 2. STANDARD PATTERN // 3. Device compatible bitmap // if ((SolidColor = (DWORD)pbo->iSolidColor) == CLR_INVALID) { PLOTDBG(DBG_GETCLR, ("iSolodColor == CLR_INVALID, pBrush=%08lx", pbo->pvRbrush)); // // This is a pattern brush, but we will just use its // foreground color. // if ((pDevBrush = (PDEVBRUSH)pbo->pvRbrush) || (pDevBrush = BRUSHOBJ_pvGetRbrush(pbo))) { // // Grab the foreground color and use it. // SolidColor = pDevBrush->ColorFG; if ((pDevBrush->PatIndex < HS_DDI_MAX) || (pDevBrush->pbgr24)) { ; } else { PLOTDBG(DBG_GETCLR, ("GETColor: NOT DEVICE_PAT")); RetVal = -1; } } else { RetVal = 0; PLOTDBG(DBG_GETCLR, ("GetColor(): couldn't realize brush!")); } } else { PLOTDBG(DBG_GETCLR, ("GETColor: is a SOLID COLOR=%08lx", pbo->iSolidColor)); } } else if ((RopFG == 0x00) || (RopBG == 0x00)) { if (IS_RASTER(pPDev)) { SolidColor = 0x0; } else { // // If we are not a raster device (which supports overprint) // match the best non-white pen, in order to fill with. // SolidColor = (DWORD)BestMatchNonWhitePen(pPDev, 0, 0, 0); PLOTDBG(DBG_GETCLR, ("GETColor: pbo=NULL, BLACK Pen Idx=%ld", SolidColor)); } } if ((!IS_RASTER(pPDev)) && (SolidColor == 0x00FFFFFF)) { SolidColor = WHITE_INDEX; PLOTDBG(DBG_GETCLR, ("GETColor: Pen plotter using WHITE COLOR Idx=%ld", SolidColor)); } if (pColorFG) { *pColorFG = SolidColor; } if (ppDevBrush) { *ppDevBrush = pDevBrush; } return(RetVal); }