Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

850 lines
27 KiB

/******************************Public*Routine******************************\
* bbddi.cxx
*
* This contains the bitblt simulations code.
*
* Copyright (c) 1993-1999 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
/******************************Public*Routine******************************\
* EngBitBlt
*
* DDI entry point. Blts to a engine managed surface.
*
* History:
* 16-Feb-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL
EngBitBlt(
SURFOBJ *psoDst, // Target surface
SURFOBJ *psoSrc, // Source surface
SURFOBJ *psoMask, // Mask
CLIPOBJ *pco, // Clip through this
XLATEOBJ *pxlo, // Color translation
RECTL *prclDst, // Target offset and extent
POINTL *pptlSrc, // Source offset
POINTL *pptlMask, // Mask offset
BRUSHOBJ *pdbrush, // Brush data (from cbRealizeBrush)
POINTL *pptlBrush, // Brush offset (origin)
ROP4 rop4 // Raster operation
)
{
//
// Validate the ROP
//
ASSERTGDI(psoDst != (SURFOBJ *) NULL, "NULL target passed in\n");
ASSERTGDI(prclDst != (PRECTL) NULL, "Target range\n");
ASSERTGDI(prclDst->left <= prclDst->right, "ERROR Target width not ordered\n");
ASSERTGDI(prclDst->top <= prclDst->bottom, "ERROR Target height not ordered\n");
ASSERTGDI(!(ROP4NEEDPAT(rop4) && (pdbrush == (BRUSHOBJ *) NULL)), "EngBitBlt: Pattern\n");
ASSERTGDI(!(ROP4NEEDPAT(rop4) && (pdbrush->iSolidColor == 0xFFFFFFFF) && (pptlBrush == (PPOINTL) NULL)), "EngBitBlt: Pattern offset\n");
ASSERTGDI(!((psoSrc == (SURFOBJ *) NULL) && ROP4NEEDSRC(rop4)), "EngBitBlt: Source\n");
ASSERTGDI(!((pptlSrc == (PPOINTL) NULL) && ROP4NEEDSRC(rop4)), "EngBitBlt: Source offset\n");
PSURFACE pSurfDst = SURFOBJ_TO_SURFACE_NOT_NULL(psoDst);
PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE(psoSrc);
PSURFACE pSurfMask = SURFOBJ_TO_SURFACE(psoMask);
RECTL rclSrc;
ASSERTGDI(pSurfDst->iFormat() != BMF_JPEG, "EngBitBlt: dst BMF_JPEG not supported\n");
ASSERTGDI(pSurfDst->iFormat() != BMF_PNG, "EngBitBlt: dst BMF_PNG not supported\n");
ASSERTGDI(!(ROP4NEEDSRC(rop4) && (pSurfSrc->iFormat() == BMF_JPEG)), "EngBitBlt: src BMF_JPEG not supported\n");
ASSERTGDI(!(ROP4NEEDSRC(rop4) && (pSurfSrc->iFormat() == BMF_PNG)), "EngBitBlt: src BMF_PNG not supported\n");
if (psoDst->iType == STYPE_BITMAP)
{
//
// For profiling purposes, set a flag in the PDEV to indicate that the
// driver punted this call.
//
{
PDEVOBJ po(pSurfDst->hdev());
if (po.bValid())
{
po.vDriverPuntedCall(TRUE);
}
}
//
// Synchronize with the device driver before touching the device surface.
//
{
PDEVOBJ po(pSurfDst->hdev());
po.vSync(psoDst,NULL, 0);
}
//
// inc surface uniq for all cases
//
INC_SURF_UNIQ(pSurfDst);
//
// Quick check for dst and pattern rops, and source copy
//
switch(rop4)
{
case 0x00000000: // DDx (BLACKNESS)
case 0x0000FFFF: // DDxn (WHITENESS)
vDIBSolidBlt(pSurfDst,
prclDst,
pco,
((rop4 != 0) ? ~0 : 0),
0);
return(TRUE);
case 0x0000F0F0: // P (PATCOPY)
case 0x00000F0F: // Pn (NOTPATCOPY)
if (pdbrush->iSolidColor != 0xFFFFFFFF)
{
vDIBSolidBlt(pSurfDst,
prclDst,
pco,
(rop4 & 0x00000001) ? ~(pdbrush->iSolidColor) : pdbrush->iSolidColor,
0);
return(TRUE);
}
if ((pSurfDst->iFormat() == BMF_8BPP) && (rop4 == 0x0000F0F0))
{
//
// We only support 8x8 DIB8 patterns with SRCCOPY right now
//
if (pvGetEngRbrush(pdbrush)) // Can we use this brush?
{
if ((((EBRUSHOBJ *) pdbrush)->pengbrush()->cxPat == 8) &&
(((EBRUSHOBJ *) pdbrush)->pengbrush()->cyPat == 8))
{
vDIBPatBltSrccopy8x8(pSurfDst,
pco,
prclDst,
pdbrush,
pptlBrush,
vPatCpyRect8_8x8);
return(TRUE);
}
}
}
if (pSurfDst->iFormat() >= BMF_8BPP)
{
if (pvGetEngRbrush(pdbrush)) // Can we use this brush?
{
if (((EBRUSHOBJ *) pdbrush)->pengbrush()->cxPat >= 4)
{
vDIBPatBlt(pSurfDst,
pco,
prclDst,
pdbrush,
pptlBrush,
(rop4 == 0x0000F0F0) ? DPA_PATCOPY : DPA_PATNOT);
return(TRUE);
}
}
}
else if ((pSurfDst->iFormat() == BMF_4BPP) &&
(rop4 == 0x0000F0F0))
{
//
// We only support 8x8 DIB4 patterns with SRCCOPY right now
//
if (pvGetEngRbrush(pdbrush)) // Can we use this brush?
{
if ((((EBRUSHOBJ *) pdbrush)->pengbrush()->cxPat == 8) &&
(((EBRUSHOBJ *) pdbrush)->pengbrush()->cyPat == 8))
{
ASSERTGDI(((EBRUSHOBJ *) pdbrush)->pengbrush()->lDeltaPat == 4,
"BBDDI.CXX: lDeltaPat != 4");
vDIBPatBltSrccopy8x8(pSurfDst,
pco,
prclDst,
pdbrush,
pptlBrush,
vPatCpyRect4_8x8);
return(TRUE);
}
}
}
else if ((pSurfDst->iFormat() == BMF_1BPP) &&
(rop4 == 0x0000F0F0))
{
//
// We support 8x8 and 6x6 DIB1 patterns with SRCCOPY
//
if (pvGetEngRbrush(pdbrush)) // Can we use this brush?
{
//
// Look for 8x8 patterns
//
if ((((EBRUSHOBJ *) pdbrush)->pengbrush()->cxPat == 8) &&
(((EBRUSHOBJ *) pdbrush)->pengbrush()->cyPat == 8) )
{
ASSERTGDI(((EBRUSHOBJ *) pdbrush)->pengbrush()->lDeltaPat == 4,
"BBDDI.CXX: lDeltaPat != 4");
vDIBPatBltSrccopy8x8(pSurfDst,
pco,
prclDst,
pdbrush,
pptlBrush,
vPatCpyRect1_8x8 );
return(TRUE);
}
//
// Look for 6x6 patterns
//
if ((((EBRUSHOBJ *)pdbrush)->pengbrush()->cxPat == 6) &&
(((EBRUSHOBJ *)pdbrush)->pengbrush()->cyPat == 6) )
{
ASSERTGDI(((EBRUSHOBJ *) pdbrush)->pengbrush()->lDeltaPat == 8,
"BBDDI.CXX: lDeltaPat != 8");
vDIBnPatBltSrccopy6x6(pSurfDst,
pco,
prclDst,
pdbrush,
pptlBrush,
vPatCpyRect1_6x6 );
return(TRUE);
}
}
}
break;
case 0x00005A5A: // DPx
if (pdbrush->iSolidColor != 0xFFFFFFFF)
{
vDIBSolidBlt(pSurfDst,
prclDst,
pco,
pdbrush->iSolidColor,
1);
return(TRUE);
}
if (pSurfDst->iFormat() >= BMF_8BPP)
{
if (pvGetEngRbrush(pdbrush)) // Can we use this brush?
{
if (((EBRUSHOBJ *) pdbrush)->pengbrush()->cxPat >= 4)
{
vDIBPatBlt(pSurfDst,
pco,
prclDst,
pdbrush,
pptlBrush,
DPA_PATXOR);
return(TRUE);
}
}
}
break;
//
// Dn degenerates to DPx with a pattern of all ones (0xFFFFFFFF)
//
case 0x00005555: // Dn (DSTINVERT)
vDIBSolidBlt(pSurfDst,
prclDst,
pco,
(ULONG)~0,
1);
return(TRUE);
//
// 0xCCAA with a mask surface of NULL really means EngTransparentBlt
// or EngDrawStream.
// We do this as an optimization; see the tops of EngTransparentBlt
// and EngDrawStream for details.
//
case 0x0000CCAA: // Transparent blt or DrawStream
if (psoMask == NULL)
{
if(pdbrush->pvRbrush == NULL)
{
rclSrc.left = pptlSrc->x;
rclSrc.right = pptlSrc->x + (prclDst->right - prclDst->left);
rclSrc.top = pptlSrc->y;
rclSrc.bottom = pptlSrc->y + (prclDst->bottom - prclDst->top);
return(EngTransparentBlt(psoDst,
psoSrc,
pco,
pxlo,
prclDst,
&rclSrc,
pdbrush->iSolidColor,
TRUE));
}
else
{
PDRAWSTREAMINFO pdsi = (PDRAWSTREAMINFO) pdbrush->pvRbrush;
pdsi->bCalledFromBitBlt = TRUE;
return(EngDrawStream(psoDst, psoSrc, pco, pxlo, prclDst,
pdsi->pptlDstOffset,
pdsi->ulStreamLength,
pdsi->pvStream,
(DSSTATE*) pdsi));
}
}
break;
//
// We special case source copy since it must be one of the two following cases:
// a) DIB to DIB, which will just call EngCopyBits.
// b) Device format to DIB, which will just call DrvCopyBits.
//
// We also expect source copy to occur A LOT!
//
case 0x0000CCCC:
if (pSurfSrc->iType() == STYPE_BITMAP)
{
return(EngCopyBits(psoDst,
psoSrc,
pco,
pxlo,
prclDst,
pptlSrc));
}
else
{
PDEVOBJ pdoSrc(pSurfSrc->hdev());
return((*PPFNDRV(pdoSrc,CopyBits)) (psoDst,
psoSrc,
pco,
pxlo,
prclDst,
pptlSrc));
}
}
//
// Synchronize with the device driver before touching the device surface.
//
if ((psoSrc != (SURFOBJ *) NULL))
{
PDEVOBJ po(pSurfSrc->hdev());
po.vSync(psoSrc, NULL, 0);
}
//
// We have to create an empty DIB incase DrvCopyBits needs to be performed.
// We also have to have a POINTL for the final blt for use as the source org.
//
SURFMEM SurfDimo;
//
// Handle the Device ==> DIB conversion if required
//
if (ROP4NEEDSRC(rop4) && (pSurfSrc->iType() != STYPE_BITMAP))
{
PDEVOBJ pdoSrc(pSurfSrc->hdev());
//
// Allocate an intermediate DIB for a source.
//
ERECTL erclTmp(0L,
0L,
prclDst->right - prclDst->left,
prclDst->bottom - prclDst->top);
DEVBITMAPINFO dbmi;
dbmi.iFormat = pSurfDst->iFormat();
dbmi.cxBitmap = erclTmp.right;
dbmi.cyBitmap = erclTmp.bottom;
dbmi.hpal = 0;
dbmi.fl = pSurfSrc->bUMPD() ? UMPD_SURFACE : 0;
if (!SurfDimo.bCreateDIB(&dbmi, NULL))
{
WARNING("bCreateDIB failed in EngBitBlt\n");
return(FALSE);
}
(*PPFNDRV(pdoSrc,CopyBits)) ( (SURFOBJ *) SurfDimo.pSurfobj(),
psoSrc,
(CLIPOBJ *) NULL,
pxlo,
(PRECTL) &erclTmp,
pptlSrc);
//
// Make psoSrc and pptlSrc point to the correct thing.
//
pptlSrc = (POINTL *) &gptl00;
pSurfSrc = SurfDimo.ps;
//
// Color translation has already been performed, so make
// the XLATE an identity.
//
pxlo = &xloIdent;
}
//
// Call BltLnk to perform the ROP
//
if (!BltLnk(pSurfDst,
pSurfSrc,
pSurfMask,
(ECLIPOBJ *) pco,
(XLATE *) pxlo,
prclDst,
pptlSrc,
pptlMask,
pdbrush,
pptlBrush,
rop4)
)
{
WARNING1("BltLnk Returns FALSE\n");
}
}
else
{
//
// We have to do simulations on a device surface
//
return(SimBitBlt(psoDst,psoSrc,psoMask,
pco,pxlo,
prclDst,pptlSrc,pptlMask,
pdbrush,pptlBrush,rop4, NULL));
}
return(TRUE);
}
/******************************Public*Routine******************************\
* EngEraseSurface
*
* Asks GDI to erase the surface. The rcl will be filled with
* iColor.
*
* History:
* 02-May-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL
EngEraseSurface(
SURFOBJ *pso,
PRECTL prcl,
ULONG iColor
)
{
PSURFACE pSurf = (SURFACE *)(SURFOBJ_TO_SURFACE(pso));
if(pSurf == 0)
return FALSE;
ASSERTGDI(prcl != (PRECTL) NULL, "ERROR EngEraseSurface1");
ASSERTGDI(prcl->left >= 0, "ERROR EngEraseSurface2");
ASSERTGDI(prcl->top >= 0, "ERROR EngEraseSurface3");
ASSERTGDI(prcl->right <= pSurf->sizl().cx, "ERROR EngEraseSurface4");
ASSERTGDI(prcl->bottom <= pSurf->sizl().cy, "ERROR EngEraseSurface5");
//
// Synchronize with the device driver before touching the device surface.
//
{
PDEVOBJ po(pSurf->hdev());
po.vSync(pso,NULL, 0);
}
vDIBSolidBlt(pSurf, prcl, (CLIPOBJ *) NULL, iColor, 0);
return(TRUE);
}
/******************************Public*Routine******************************\
* SimBitBlt
*
* The engine sends EngBitBlt here if a DEVICE surface is passed as psoTrg
*
* History:
* 23-Feb-1994 -by- Eric Kutter [erick]
* Made it callable from other functions - allow device to device blts.
*
* 09-Sep-1992 -by- Donald Sidoroff [donalds]
* Made it callable from EngBitBlt only.
*
* 07-Sep-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL
SimBitBlt(
SURFOBJ *psoDst, // Target surface
SURFOBJ *psoSrc, // Source surface
SURFOBJ *psoMask, // Mask
CLIPOBJ *pco, // Clip through this
XLATEOBJ *pxlo, // Color translation
RECTL *prclDst, // Target offset and extent
POINTL *pptlSrc, // Source offset
POINTL *pptlMask, // Mask offset
BRUSHOBJ *pdbrush, // Brush data (from cbRealizeBrush)
POINTL *pptlBrush, // Brush offset (origin)
ROP4 rop4, // Raster operation
PVOID pdlo // for unlock if necessary
)
{
BOOL bNeedSrc = ROP4NEEDSRC(rop4);
PSURFACE pSurfDst = (SURFACE *)(SURFOBJ_TO_SURFACE(psoDst));
PSURFACE pSurfSrc = (SURFACE *)(SURFOBJ_TO_SURFACE(psoSrc));
PDEVOBJ pdoDst(pSurfDst->hdev());
ASSERTGDI(pdoDst.bValid(), "EngPuntBlt poDst.bValid");
//
// if source and destination are both engine managed
// bitmaps, then BitBlt directly
//
if (
(pSurfDst->iType() == STYPE_BITMAP) &&
((!bNeedSrc) || (pSurfSrc->iType() == STYPE_BITMAP)) &&
(psoMask == NULL)
)
{
BOOL bReturn;
if (!pdoDst.bUMPD())
{
bReturn = (*(pSurfDst->pfnBitBlt())) (
psoDst,
psoSrc,
psoMask,
pco,
pxlo,
prclDst,
pptlSrc,
pptlMask,
pdbrush,
pptlBrush,
rop4);
}
else
{
bReturn = EngBitBlt(
psoDst,
psoSrc,
psoMask,
pco,
pxlo,
prclDst,
pptlSrc,
pptlMask,
pdbrush,
pptlBrush,
rop4);
}
return(bReturn);
}
//
// For profiling purposes, set a flag in the PDEV to indicate that the
// driver punted this call.
//
{
PDEVOBJ po(pSurfDst->hdev());
if (po.bValid())
{
po.vDriverPuntedCall(TRUE);
}
}
// Get the bounds of the destination rectangle
RECTL rclDstBounds;
if( pSurfDst->iType() == STYPE_DEVICE &&
pdoDst.bValid() && pdoDst.bMetaDriver())
{
rclDstBounds.left = pdoDst.pptlOrigin()->x;
rclDstBounds.top = pdoDst.pptlOrigin()->y;
rclDstBounds.right = pdoDst.pptlOrigin()->x + pSurfDst->sizl().cx;
rclDstBounds.bottom = pdoDst.pptlOrigin()->y + pSurfDst->sizl().cy;
}
else
{
rclDstBounds.left = 0;
rclDstBounds.top = 0;
rclDstBounds.right = pSurfDst->sizl().cx;
rclDstBounds.bottom = pSurfDst->sizl().cy;
}
//
// Set up new rectangle clipped to destination surface. Clip source
// pointl and mask pointl accordingly.
//
RECTL rclReduced = *prclDst;
POINTL ptlSrc;
POINTL ptlMask;
if (bNeedSrc)
{
ptlSrc = *pptlSrc;
}
if (psoMask != NULL)
{
ptlMask = *pptlMask;
}
if (rclReduced.top < rclDstBounds.top)
{
ptlSrc.y += (rclDstBounds.top-rclReduced.top);
ptlMask.y += (rclDstBounds.top-rclReduced.top);
rclReduced.top = rclDstBounds.top;
}
if (rclReduced.left < rclDstBounds.left)
{
ptlSrc.x += (rclDstBounds.left-rclReduced.left);
ptlMask.x += (rclDstBounds.left-rclReduced.left);
rclReduced.left = rclDstBounds.left;
}
if (rclReduced.bottom > rclDstBounds.bottom)
{
rclReduced.bottom = rclDstBounds.bottom;
}
if (rclReduced.right > rclDstBounds.right)
{
rclReduced.right = rclDstBounds.right;
}
if( rclReduced.top >= rclReduced.bottom ||
rclReduced.left >= rclReduced.right )
{
// Destination rectangle is outside of the
// destination surface
return TRUE;
}
//
// Ok we clipped everything to our reduced rectangle, now use the clipped offsets.
//
prclDst = &rclReduced;
pptlSrc = &ptlSrc;
pptlMask = &ptlMask;
//
// Set up our temporary DIB rectangle to blt to.
//
ERECTL erclDst(0, 0, prclDst->right - prclDst->left,
prclDst->bottom - prclDst->top);
//
// iDitherFormat must match destination format
//
if (pSurfDst->iFormat() != pdoDst.iDitherFormat())
{
WARNING("SimBitBlt: pSurfDst->iFormat != pdoDst.iDitherFormat\n");
return(FALSE);
}
//
// We have to create an empty DIB incase DrvCopyBits needs to be performed.
// We also have to have a POINTL for the final blt for use as the source org.
//
SURFMEM SurfDimoSrc;
//
// Handle the Device ==> DIB conversion if required
//
if (bNeedSrc && (pSurfSrc->iType() != STYPE_BITMAP))
{
PDEVOBJ pdoSrc(pSurfSrc->hdev());
//
// Allocate an intermediate DIB for a source.
//
DEVBITMAPINFO dbmiSrc;
dbmiSrc.iFormat = pdoDst.iDitherFormat();
dbmiSrc.cxBitmap = erclDst.right;
dbmiSrc.cyBitmap = erclDst.bottom;
dbmiSrc.hpal = 0;
dbmiSrc.fl = pSurfSrc->bUMPD() ? UMPD_SURFACE : 0;
if (!SurfDimoSrc.bCreateDIB(&dbmiSrc, NULL))
{
WARNING("Failed dimoSrc memory alloc in EngPuntBlt\n");
return(FALSE);
}
(*PPFNGET(pdoSrc,CopyBits,pSurfSrc->flags())) (SurfDimoSrc.pSurfobj(),
psoSrc,
(CLIPOBJ *) NULL,
pxlo,
(PRECTL) &erclDst,
pptlSrc);
//
// Make psoSrc and pptlSrc point to the correct thing.
//
pptlSrc = &gptl00;
psoSrc = SurfDimoSrc.pSurfobj();
//
// Color translation has already been performed, so make
// the XLATEOBJ an identity.
//
pxlo = &xloIdent;
}
DEVBITMAPINFO dbmiDst;
dbmiDst.iFormat = pdoDst.iDitherFormat();
dbmiDst.cxBitmap = erclDst.right;
dbmiDst.cyBitmap = erclDst.bottom;
dbmiDst.hpal = 0;
dbmiDst.fl = pSurfDst->bUMPD() ? UMPD_SURFACE : 0;
SURFMEM SurfDimoDst;
SurfDimoDst.bCreateDIB(&dbmiDst, NULL);
if (!SurfDimoDst.bValid())
{
return(FALSE);
}
POINTL ptlDst;
ptlDst.x = prclDst->left;
ptlDst.y = prclDst->top;
POINTL ptlBrush;
if (pptlBrush != (POINTL *) NULL)
{
ptlBrush.x = pptlBrush->x - prclDst->left;
ptlBrush.y = pptlBrush->y - prclDst->top;
}
//
// if we are going out to the user mode printer driver
// unlock the DEVLOCKBLTOBJ. Only the src might be locked
// and from here we are only going to deal with the temp src dib
// so it's safe to unlock here.
//
if (pdoDst.bPrinter() && pdlo)
{
((DEVLOCKBLTOBJ *)pdlo)->vUnLock();
}
// WINBUG #206475 bhouse 10-18-2000 Old potential perf bug
// We should only copy the destination if the ROP requires
// destination data.
(*PPFNGET(pdoDst,CopyBits,pSurfDst->flags())) (SurfDimoDst.pSurfobj(),
psoDst,
(CLIPOBJ *) NULL,
&xloIdent,
&erclDst,
&ptlDst);
ASSERTGDI(SurfDimoDst.ps->iType() == STYPE_BITMAP, "ERROR dimoDst.iType 1");
//
// Call off to BitBlt, if it fails who cares.
//
EngBitBlt(SurfDimoDst.pSurfobj(),
psoSrc,
psoMask,
(ECLIPOBJ *) NULL,
pxlo,
&erclDst,
pptlSrc,
pptlMask,
pdbrush,
&ptlBrush,
rop4);
//
// Inc output surface uniqueness
//
INC_SURF_UNIQ(pSurfDst);
return((*PPFNGET(pdoDst,CopyBits,pSurfDst->flags())) (
psoDst,
SurfDimoDst.pSurfobj(),
pco,
&xloIdent,
prclDst,
&gptl00));
}