|
|
/******************************Module*Header*******************************\
* Module Name: * * bltlnk.cxx * * Abstract * * This module does general bit blt functions for 1,4,8,16,24,and 32 bpp * DIB format bitmaps. SrcBltxx routines are used to align and copy data. * * Author: * * Mark Enstrom (marke) 9-27-93 * * Copyright (c) 1993-1999 Microsoft Corporation \**************************************************************************/
#include "precomp.hxx"
PVOID pvGetEngRbrush(BRUSHOBJ *pbo);
extern PFN_SRCCPY SrcCopyFunctionTable[];
PFN_BLTLNKROP RopFunctionTable[] = { vRop2Function0,vRop2Function1,vRop2Function2,vRop2Function3, vRop2Function4,vRop2Function5,vRop2Function6,vRop2Function7, vRop2Function8,vRop2Function9,vRop2FunctionA,vRop2FunctionB, vRop2FunctionC,vRop2FunctionD,vRop2FunctionE,vRop2FunctionF };
#define DBG_BLTLNK 0
#if DBG_BLTLNK
ULONG DbgBltLnk = 0; #endif
#define SCAN_LINE_BUFFER_LENGTH 64
/******************************Public*Routine******************************\
* * Routine Name * * BltLnk * * Routine Description: * * BltLnk prepares all parameters then breaks the BitBlt region into * rectangles based on clip information. Each rect is sent to BltLnkRect * for operation. * * Arguments: * * pdioDst - Destination surface information * pdioSrc - Source surface information * pdioMsk - Mask information * pco - Clip Object * pxlo - Color translation object * prclDst - Destination rectangle * pptlSrc - Source Starting offset point * pptlMsk - Mask Starting offset point * pdbrush - Brush Information * pptlBrush - Brush Starting offset point * rop4 - Logical Raster Operation * * Return Value: * * BOOLEAN Status * \**************************************************************************/
BOOL BltLnk( SURFACE *pdioDst, // Target surface
SURFACE *pdioSrc, // Source surface
SURFACE *pdioMsk, // Msk
ECLIPOBJ *pco, // Clip through this
XLATE *pxlo, // Color translation
RECTL *prclDst, // Target offset and extent
POINTL *pptlSrc, // Source offset
POINTL *pptlMsk, // Msk offset
BRUSHOBJ *pdbrush, // Brush data (from cbRealizeBrush)
POINTL *pptlBrush, // Brush offset (origin)
ROP4 rop4) // Raster operation
{
BOOL bMore; ULONG ircl; LONG MaxWidth; BLTLNKINFO bltInfo; CLIPENUMRECT clenr; BYTE Rop3Low; BYTE Rop3High; BYTE RopSrcLow; BYTE RopSrcHigh; BYTE RopDstLow; BYTE RopDstHigh; BOOL bNeedMsk = FALSE; BOOL bNeedPat = FALSE; BOOL bNeedSrc = FALSE; BOOL bNeedDst = FALSE; BOOL bNeedPatLow = FALSE; BOOL bNeedSrcLow = FALSE; BOOL bNeedDstLow = FALSE; BOOL bNeedPatHigh = FALSE; BOOL bNeedSrcHigh = FALSE; BOOL bNeedDstHigh = FALSE; BOOL bLocalAlloc = FALSE; SURFMEM SurfDimo; PENGBRUSH pBrush = NULL;
#if DBG_BLTLNK
if (DbgBltLnk >= 1) {
DbgPrint("BltLnk: rop4 = %lx\n",rop4); DbgPrint("pdioDst = 0x%p\n",pdioDst); DbgPrint("pdioSrc = 0x%p\n",pdioSrc);
DbgPrint(" Destination Format = %li\n",pdioDst->iFormat());
DbgPrint(" prclDst = %li,%li to %li,%li\n", prclDst->left, prclDst->top, prclDst->right, prclDst->bottom);
}
#endif
//
// make sure destination format is not a device format or
// unknown format
//
ASSERTGDI(pdioDst->iFormat() != 0, "ERROR device dst format in BltLnk\n"); ASSERTGDI(pdioDst->iFormat() <= 7, "ERROR invalid dst format in BltLnk\n");
//
// check rectangle bounds
//
ASSERTGDI(prclDst->left < prclDst->right, "ERROR prclDst->left < right"); ASSERTGDI(prclDst->top < prclDst->bottom, "ERROR prclDst->top < bottom");
//
// calculate the widest blt using based on the width of scan line storage
//
// These numbers assume worst case unaligned transfers
//
switch(pdioDst->iFormat()) { case BMF_1BPP: MaxWidth = (SCAN_LINE_BUFFER_LENGTH << 5) -62; break; case BMF_4BPP: MaxWidth = (SCAN_LINE_BUFFER_LENGTH << 3) -14; break; case BMF_8BPP: MaxWidth = (SCAN_LINE_BUFFER_LENGTH << 2) -6; break; case BMF_16BPP: MaxWidth = (SCAN_LINE_BUFFER_LENGTH << 1) -2; break; case BMF_24BPP: MaxWidth = ((SCAN_LINE_BUFFER_LENGTH * 4) / 3) - 2; break; case BMF_32BPP: MaxWidth = SCAN_LINE_BUFFER_LENGTH; break; }
//
// set bltInfo params
//
if (pxlo == NULL) { bltInfo.pxlo = &xloIdent; } else { bltInfo.pxlo = pxlo; }
bltInfo.pdioDst = pdioDst; bltInfo.pdioSrc = pdioSrc; bltInfo.pco = (ECLIPOBJ *)pco; bltInfo.rclDst = *prclDst; bltInfo.pdbrush = (EBRUSHOBJ *) pdbrush;
//
// rop4 is a logical combination of Src,Dst,Pattern,Mask
//
// rop4[15:08] represents the rop3 used when Mask is high
// rop4[07:00] represents the rop3 used when Mask is low
//
// When rop4[15:08] == rop4[07:00], this indicates that no mask
// is needed for the operation.
//
// rop3 [07:04] represents the rop2 to be used is pattern is high
// rop3 [03:00] represents the rop2 to be used is pattern is low
//
// when rop3[07:04] == rop3[03:00], this indicates that no pattern
// is needed for the operation.
//
// By exchanging Src and Dst with Pattern and Mask, it is possible
// to compare rop4s to also determine is Src and Dst are needed for
// the logical operation. BltLnk does this below.
//
// A rop2 represents 16 different ways 2 variables may be combined, this
// is the basic logic element used in BltLnk.
//
// As an example of logic reduction rop4 = B8B8 would
// immediatly reduce to a rop3 because rop4[15:08] == rop4[07:00]. This
// leaves rop3 = B8. This is expressed as a Karnaugh map as:
//
//
// PS 00 01 11 10
// �����������Ŀ
// D 0� 0� 0� 0� 1�
// �����������Ĵ
// 1� 0� 1� 1� 1�
// �������������
// This reduces to a logic operation of Dst = (Pat & ~Src) | (Dst & Src)
//
// This is a special case rop handled by unique functions, but in gereral BltLnk
// will handle a rop like this by reducing it to functions of rop2s, in this case
//
// Pat and (Src and Dst) OR ~pat and (~Src or Dst)
//
// BltLnk will always try to manipulate the variables so that a rop2
// function may be performed directly. If this is not possible, a rop3
// functions is broken into 2 rop2 functions, one for pat=high and one
// for pat = low. (or mask in a rop3 in which pat is not needed but mask is)
// For a full rop4, two rop 3 passes are made, one for mask = high and
// one for mask = low.
//
// Actual Mask Blt, rop4 = AACC is handled by a special case accelerator.
//
// Masked Solid fill (Src = 1bpp mask), rop4 = B8B8 is also handled by a
// special case accelerator.
//
Rop3Low = (BYTE)(rop4 & 0xff); Rop3High = (BYTE)(rop4 >> 8);
RopSrcLow = (Rop3Low & 0xC3) | ((Rop3Low & 0x0C) << 2) | ((Rop3Low & 0x30) >> 2); RopDstLow = (Rop3Low & 0xA5) | ((Rop3Low & 0x0A) << 3) | ((Rop3Low & 0x50) >> 3);
RopSrcHigh = (Rop3High & 0xC3)|((Rop3High & 0x0C) << 2)|((Rop3High & 0x30) >> 2); RopDstHigh = (Rop3High & 0xA5)|((Rop3High & 0x0A) << 3)|((Rop3High & 0x50) >> 3);
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint (" RopSrcLow = %lx, RopDstLow = %lx\n", RopSrcLow,RopDstLow); DbgPrint (" RopSrcHigh = %lx, RopDstHigh = %lx\n", RopSrcHigh,RopDstHigh); } #endif
//
// if rop4[15:08] = rop4[07:00] then no mask is needed
//
if ((rop4 & 0xff) != ((rop4) >> 8)) { bNeedMsk = TRUE; }
//
// if Rop3Low[7:4] = Rop3Low[3:0] and
// if Rop3High[7:4] = Rop3High[3:0] Then no pat is needed
//
if ((Rop3Low & 0x0f) != ((Rop3Low & 0xf0) >> 4)) { bNeedPatLow = TRUE; }
if ((Rop3High & 0x0f) != ((Rop3High & 0xf0) >> 4)) { bNeedPatHigh = TRUE; }
bNeedPat = bNeedPatLow || bNeedPatHigh;
//
// if RopSrcLow[7:4] = RopSrcLow[3:0] and
// if RopSrcHigh[7:4] = RopSrcHigh[3:0] Then no src is needed
//
if ((RopSrcLow & 0x0F) != ((RopSrcLow & 0xF0) >> 4)) { bNeedSrcLow = TRUE; }
if ((RopSrcHigh & 0x0F) != ((RopSrcHigh & 0xF0) >> 4)) { bNeedSrcHigh = TRUE; }
bNeedSrc = bNeedSrcLow || bNeedSrcHigh;
//
// if RopDstLow[7:4] = RopDstLow[3:0] and
// if RopDstHigh[7:4] = RopDstHigh[3:0] Then no Dst is needed
//
if (((RopDstLow & 0x0f) != ((RopDstLow & 0xF0) >> 4))) { bNeedDstLow = TRUE; }
if (((RopDstHigh & 0x0f) != ((RopDstHigh & 0xF0) >> 4))) { bNeedDstHigh = TRUE; }
bNeedDst = bNeedDstHigh || bNeedDstLow;
//
// get the brush realization if we'll need it. This is either
// when the rop specifies a pattern is needed or when the rop specifies
// that a mask is needed but no mask is passed in, meaning the mask
// must be taken from the brush
//
if ((bNeedPat) || (bNeedMsk && (pdioMsk == (SURFACE*) NULL))) { if ((pdbrush != NULL) && (pdbrush->iSolidColor == -1)) { pBrush = (PENGBRUSH) pvGetEngRbrush(pdbrush); } else { pBrush = (PENGBRUSH) pdbrush; } }
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint(" pBrush = %p\n",pBrush); DbgPrint(" bNeedMsk = %x\n",bNeedMsk); DbgPrint(" bNeedPat = %x\n",bNeedPat); DbgPrint(" bNeedSrc = %x\n",bNeedSrc); DbgPrint(" bNeedDst = %x\n",bNeedDst); } #endif
//
// Compute the direction of clipping enumeration
//
bltInfo.xDir = bltInfo.yDir = 1L; bltInfo.iDir = CD_ANY;
//
// Get clip rectangle enumeration and directions set up. BltLnkRect
// always performs blt operations left to right using a temp
// scan line buffer.
// xDir is set to 1 or -1 as a flag
// for accelerators to not accelerate a special case if xDir < 0
//
if (bNeedSrc) { ASSERTGDI(pdioSrc != (SURFACE*) NULL, "ERROR: Bltlnk: no pdioSrc");
//
// fill out bltinfo for calls to BltLnkRect
//
bltInfo.pjSrc = (PBYTE) pdioSrc->pvScan0(); bltInfo.lDeltaSrc = pdioSrc->lDelta(); bltInfo.xSrcOrg = pptlSrc->x; bltInfo.ySrcOrg = pptlSrc->y;
#if DBG_BLTLNK
if (DbgBltLnk >= 1) { DbgPrint(" Src Format = %li\n",pdioSrc->iFormat()); DbgPrint(" Src Point = %li,%li\n",pptlSrc->x,pptlSrc->y); }
if (DbgBltLnk >= 2) { DbgPrint(" pjSrc = %p, lDeltaSrc = %li\n", bltInfo.pjSrc,bltInfo.lDeltaSrc); DbgPrint(" xSrcOrg = %li, ySrcOrg = %li\n", bltInfo.xSrcOrg,bltInfo.ySrcOrg); }
#endif
//
// Only BLT bottom to top if the source and destination are on the
// same surface and the Dst is below the Src.
//
// �������Ŀ
// ����ijSrc �
// �Dst � �
// � � �
// � ���������
// ���������
//
// Also check if it is the same surface for BLTs that must be
// done right to left. This is a case where the starting scan
// lines for Src and Dst are the same and the Src is to the
// left of the dst. We do this by comparing the pvScan0 pointers.
// The reason is that if we were to compare surface pointers or
// handles this won't work on some drivers that punt this call
// to GDI but pass us different SURFOBJs for the source and
// destination even when they're really the same surface.
//
// ������������Ŀ
// �Src �Dst �
// � � �
// � � �
// ��������������
//
if (pdioSrc->pvScan0() == pdioDst->pvScan0()) {
if (pptlSrc->y < prclDst->top) { bltInfo.yDir = -1; bltInfo.iDir = CD_RIGHTUP; }
//
// check if:
//
// Src scan line = Dst Scan line AND Src < Dst
// and width > Scan line buffer
// OR
// MaskBlt needing Src for RopHigh and RopLow
// AND Src and Dst rect intersect
//
if ((pptlSrc->y == prclDst->top) && (pptlSrc->x < prclDst->left)) {
//
// This blt requires right to left operation. This will
// disable special accelerators in BltLnkRect.
//
bltInfo.xDir = -1; }
//
// cases requiring temp Src:
//
if ( (bNeedMsk && bNeedSrcLow && bNeedSrcHigh) || ( ((bltInfo.xDir == -1) || (bltInfo.yDir == -1)) && ((prclDst->right - prclDst->left) > MaxWidth) ) ) {
//
// create a temp src surface of width prclDst->right - prclDst->left
// and height prclDst->bottom - prclDst->top
//
DEVBITMAPINFO dbmi; dbmi.iFormat = pdioSrc->iFormat(); dbmi.cxBitmap = prclDst->right - prclDst->left; dbmi.cyBitmap = prclDst->bottom - prclDst->top; dbmi.hpal = (HPALETTE) 0; dbmi.fl = BMF_TOPDOWN;
SurfDimo.bCreateDIB(&dbmi, (PVOID) NULL);
if (!SurfDimo.bValid()) { //
// (common return?)
//
return(FALSE); }
//
// fill DIB with data from actual Src
//
POINTL ptlSrc; ptlSrc.x = pptlSrc->x; ptlSrc.y = pptlSrc->y;
RECTL rclDst; rclDst.left = 0; rclDst.right = dbmi.cxBitmap; rclDst.top = 0; rclDst.bottom = dbmi.cyBitmap;
if (!EngCopyBits(SurfDimo.pSurfobj(), pdioSrc->pSurfobj(), (CLIPOBJ *)NULL, &xloIdent, &rclDst, &ptlSrc) ) {
//
// return error
//
return(FALSE); }
//
// fill in new Src info for BltLnkRect
//
bltInfo.pjSrc = (PBYTE) SurfDimo.ps->pvScan0(); bltInfo.lDeltaSrc = SurfDimo.ps->lDelta(); bltInfo.xSrcOrg = 0; bltInfo.ySrcOrg = 0;
#if DBG_BLTLNK
if (DbgBltLnk >= 1) { DbgPrint(" Allocate temp buffer: pjSrc = 0x%p\n",bltInfo.pjSrc); DbgPrint(" lDeltaSrc = 0x%lx, SrcOrg = (0,0)\n",bltInfo.lDeltaSrc); }
#endif
} }
//
// set DeltaSrcDir based on yDir
//
if (bltInfo.yDir == 1) { bltInfo.lDeltaSrcDir = bltInfo.lDeltaSrc; } else { bltInfo.lDeltaSrcDir = -bltInfo.lDeltaSrc; }
} else {
//
// no src to worry about
//
bltInfo.pjSrc = (PBYTE) NULL; }
//
// Set up the destination information in bltInfo based on +/- yDir
//
// pjDst points to the upper left corner of the dest bitmap
//
// lDeltaDst is the number of (bytes) from one scan line to the next
//
bltInfo.pjDst = (PBYTE) pdioDst->pvScan0(); bltInfo.lDeltaDst = pdioDst->lDelta();
if (bltInfo.yDir == 1) { bltInfo.lDeltaDstDir = bltInfo.lDeltaDst; } else { bltInfo.lDeltaDstDir = -bltInfo.lDeltaDst; }
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint(" pjDst = %p, lDeltaDst = %li\n",bltInfo.pjDst,bltInfo.lDeltaDst); } #endif
//
// Set up the Mask
//
if (!bNeedMsk || (pdioMsk == (SURFACE*) NULL)) { //
// no mask to deal with
//
bltInfo.pdioMsk = (SURFACE*) NULL; bltInfo.pjMsk = (PBYTE) NULL; } else {
ASSERTGDI(pdioMsk->iType() == STYPE_BITMAP, "ERROR: BltLnk: Mask is not STYPE_BITMAP\n"); ASSERTGDI(pdioMsk->iFormat() == BMF_1BPP, "ERROR: BltLnk: Mask not 1Bpp\n"); ASSERTGDI(pptlMsk->x >= 0, "Illegal mask offset x\n"); ASSERTGDI(pptlMsk->y >= 0, "Illegal mask offset y\n");
//
// info for BltLnkRect
//
bltInfo.pdioMsk = pdioMsk; bltInfo.pjMsk = (PBYTE) pdioMsk->pvScan0(); bltInfo.cxMsk = (pdioMsk->sizl()).cx; bltInfo.cyMsk = (pdioMsk->sizl()).cy; bltInfo.xMskOrg = pptlMsk->x; bltInfo.yMskOrg = pptlMsk->y;
//
// Normalize mask x
//
if (bltInfo.xMskOrg >= (LONG)bltInfo.cxMsk) { bltInfo.xMskOrg %= bltInfo.cxMsk; } else { if (bltInfo.xMskOrg < 0) { bltInfo.xMskOrg = (bltInfo.cxMsk - 1) - ((-bltInfo.xMskOrg - 1) % bltInfo.cxMsk); } }
//
// Normalize Mask y
//
if (bltInfo.yMskOrg >= (LONG)bltInfo.cyMsk) { bltInfo.yMskOrg %= bltInfo.cyMsk; } else { if (bltInfo.yMskOrg < 0) { bltInfo.yMskOrg = (bltInfo.cyMsk - 1) - ((-bltInfo.yMskOrg - 1) % bltInfo.cyMsk); } }
//
// Scan line offsets
//
bltInfo.lDeltaMsk = pdioMsk->lDelta();
if (bltInfo.yDir == 1) { bltInfo.lDeltaMskDir = bltInfo.lDeltaMsk; } else { bltInfo.lDeltaMskDir = -bltInfo.lDeltaMsk; }
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint(" pjMask = %p\n",bltInfo.pjMsk); DbgPrint(" cxMask = %li\n",bltInfo.cxMsk); DbgPrint(" cyMask = %li\n",bltInfo.cyMsk); DbgPrint(" xMskOrg = %li\n",bltInfo.xMskOrg); DbgPrint(" yMskOrg = %li\n",bltInfo.yMskOrg); DbgPrint(" yMskDelta = %li\n",bltInfo.lDeltaMsk); } #endif
}
//
// Set up the pat and possibly the mask if a mask is included in pat
//
if (!bNeedPat) { //
// no Pat in this Blt
//
bltInfo.pjPat = (PBYTE) NULL;
} else {
//
// check for valid brush pointer
//
if (pdbrush == (BRUSHOBJ *) NULL) { RIP("ERROR BltLnk brush Null"); return(FALSE); }
ircl = pdbrush->iSolidColor;
//
// check for solid color of 0xffffffff... this indicates
// a real brush, not a solid color
//
if (ircl == 0xFFFFFFFF) {
if (pBrush != (PENGBRUSH) NULL) {
bltInfo.iSolidColor = ircl;
//
// Could have a brush that just has mask information.
//
if (pBrush->pjPat != (PBYTE) NULL) {
//
// fill in Pat info for BltLnkrect
//
bltInfo.lDeltaPat = pBrush->lDeltaPat; bltInfo.pjPat = pBrush->pjPat; bltInfo.cxPat = pBrush->cxPat; bltInfo.cyPat = pBrush->cyPat; bltInfo.xPatOrg = pptlBrush->x; bltInfo.yPatOrg = pptlBrush->y;
if (bltInfo.yDir == 1) { bltInfo.lDeltaPatDir = bltInfo.lDeltaPat; } else { bltInfo.lDeltaPatDir = -bltInfo.lDeltaPat; } }
} else {
//
// routine failed due to brush, return
//
return(FALSE); } } else {
//
// Set pjPat to Null.
//
bltInfo.pjPat = (PBYTE) NULL;
//
// Build iSolidColor into a 32 bit quantity
//
// Note cascaded fall through on switch to build up iColor.
//
switch(pdioDst->iFormat()) { case BMF_1BPP:
if (ircl) { ircl = 0xFFFFFFFF; } break;
case BMF_4BPP:
ircl = ircl | (ircl << 4);
case BMF_8BPP:
ircl = ircl | (ircl << 8);
case BMF_16BPP:
ircl = ircl | (ircl << 16); }
bltInfo.iSolidColor = ircl; } }
//
// Check if there is a mask with this brush. The Mask passed
// in with the call takes precedence over the brush mask.
//
if ((bNeedMsk) && (bltInfo.pjMsk == (PBYTE) NULL) && (pBrush != (PENGBRUSH) NULL) && (pBrush->pjMsk != (PBYTE) NULL)) {
bltInfo.pjMsk = pBrush->pjMsk; bltInfo.cxMsk = pBrush->cxMsk; bltInfo.cyMsk = pBrush->cyMsk; bltInfo.lDeltaMsk = pBrush->lDeltaMsk; bltInfo.xMskOrg = prclDst->left - pptlBrush->x; bltInfo.yMskOrg = prclDst->top - pptlBrush->y;
//
// Normalize Mask x
//
if (bltInfo.xMskOrg >= (LONG)bltInfo.cxMsk) { bltInfo.xMskOrg %= bltInfo.cxMsk; } else { if (bltInfo.xMskOrg < 0) { bltInfo.xMskOrg = (bltInfo.cxMsk-1) - ((-bltInfo.xMskOrg-1) % bltInfo.cxMsk); } }
//
// Normalize Mask y
//
if (bltInfo.yMskOrg >= (LONG)bltInfo.cyMsk) { bltInfo.yMskOrg %= bltInfo.cyMsk; } else { if (bltInfo.yMskOrg < 0) { bltInfo.yMskOrg = (bltInfo.cyMsk-1) - ((-bltInfo.yMskOrg-1) % bltInfo.cyMsk); } }
//
// set sign on lDeltaMask based on a bottom to top or
// top to bottom blt
//
if (bltInfo.yDir == 1) { bltInfo.lDeltaMskDir = bltInfo.lDeltaMsk; } else { bltInfo.lDeltaMskDir = -bltInfo.lDeltaMsk; } }
//
// make sure that if a mask is specified by the rop ,then a mask is available
//
if (bNeedMsk && (bltInfo.pjMsk == (PBYTE)NULL)) {
RIP("ERROR: Bltlnk: ROP specifies mask but mask is null"); return(FALSE); }
//
// set up clipping boundaries and call blt routine for each rect
//
if (pco != (CLIPOBJ *) NULL) { switch(pco->iDComplexity) { case DC_TRIVIAL:
//
// use the target for clipping
//
bMore = FALSE; clenr.c = 1; clenr.arcl[0] = *prclDst; break;
case DC_RECT:
//
// use the bounding rect for clipping
//
bMore = FALSE; clenr.c = 1; clenr.arcl[0] = pco->rclBounds; break;
case DC_COMPLEX:
//
// set up clipping enumeration
//
bMore = TRUE; ((ECLIPOBJ *) pco)->cEnumStart(FALSE,CT_RECTANGLES,bltInfo.iDir,CLIPOBJ_ENUM_LIMIT); break;
default: RIP("ERROR: BltLnk - bad clipping type"); return (FALSE); }
} else {
//
// use target for clipping
//
bMore = FALSE; clenr.c = 1; clenr.arcl[0] = *prclDst; }
//
// blt each rect
//
do {
if (bMore) { bMore = ((ECLIPOBJ *) pco)->bEnum(sizeof(clenr), (PVOID) &clenr); }
for (ircl = 0; ircl < clenr.c; ircl++) { PRECTL prcl = &clenr.arcl[ircl];
if (prcl->left < prclDst->left) { prcl->left = prclDst->left; }
if (prcl->right > prclDst->right){ prcl->right = prclDst->right; }
if (prcl->top < prclDst->top) { prcl->top = prclDst->top; }
if (prcl->bottom > prclDst->bottom){ prcl->bottom = prclDst->bottom; }
//
// We check for NULL or inverted rectanges because we may get them.
//
if (prcl->top < prcl->bottom) { ASSERTGDI(prcl->top >= 0, "ERROR prcl->top >= 0"); ASSERTGDI(prcl->left >= 0, "ERROR prcl->left >= 0");
//
// call BltLnkRect once for each vertical stripe that has width <=
// to the size of the temporary scan line storage
//
// ulong count = (prcl->right - prcl->left)/(pixels per ulong) + 1;
//
while ((prcl->right - prcl->left) > 0) {
RECTL TempRect;
TempRect.left = prcl->right; TempRect.right = prcl->right;
if (!bLocalAlloc) { if ((prcl->right - prcl->left) > MaxWidth) { prcl->right = prcl->left + MaxWidth; TempRect.left = prcl->right; } }
//
// if there is a mask, 2 passes will be required, one with negative
// mask using the Rop3Low and then once with a positive mask flag
// using Rop3High
//
if (Rop3Low != 0xAA) {
bltInfo.rop3 = Rop3Low; bltInfo.RopSrc = RopSrcLow; bltInfo.RopDst = RopDstLow; bltInfo.bNeedSrc = bNeedSrcLow; bltInfo.bNeedDst = bNeedDstLow; bltInfo.bNeedPat = bNeedPatLow; bltInfo.bNeedMsk = bNeedMsk; bltInfo.NegateMsk = 0x00; BltLnkRect(&bltInfo,prcl);
}
if (bNeedMsk &&(Rop3High != 0xAA) ) {
//
// perform second call to write the high mask ROP pixels
//
bltInfo.rop3 = Rop3High; bltInfo.RopSrc = RopSrcHigh; bltInfo.RopDst = RopDstHigh; bltInfo.bNeedSrc = bNeedSrcHigh; bltInfo.bNeedDst = bNeedDstHigh; bltInfo.bNeedPat = bNeedPatHigh; bltInfo.bNeedMsk = bNeedMsk; bltInfo.NegateMsk = 0xFF;
BltLnkRect(&bltInfo,prcl); }
prcl->left = TempRect.left; prcl->right = TempRect.right;
}
}
}
} while (bMore);
return(TRUE); }
/******************************Public*Routine******************************\
* * Routine Name: * * BltLnkRect * * Routine Description: * * Perform rectangular BitBlt using rop3 passed from BltLnk. The rops are * performed using temporary scan line buffers so that the logical * operations are done 1 DWORD at a time. The Src data is copied to the * temporary buffer using SrcBlt so the the bitmap format and color * translation is done to match Src to Dst. Also Src alignment in matched * to Dst alignment in SrcBlt. The result of the logical combination is * copied to the destination using the appropriate SrcBlt routine. * * Arguments: * * pBlt - BLT specific information * prcl - clipping rectangle * * Return Value: * * None * \**************************************************************************/
VOID BltLnkRect( PBLTLNKINFO pBlt, PRECTL prcl )
{ LONG cy; LONG DwordCount; ULONG ByteOffset; ULONG PixelOffset; ULONG PixelCount; ULONG rop2; BLTINFO SrcCopyBltInfo; BLTINFO DstCopyBltInfo; PFN_SRCCPY pfnSrcCopy; PFN_SRCCPY pfnDstCopy; PFN_BLTLNKROP pfnRop1,pfnRop2; PFN_READPAT pfnReadPat; PFN_SRCCOPYMASK pfnCopyMask; ULONG SrcBuffer[SCAN_LINE_BUFFER_LENGTH]; ULONG DstBuffer[SCAN_LINE_BUFFER_LENGTH]; ULONG RopBuffer0[SCAN_LINE_BUFFER_LENGTH]; ULONG RopBuffer1[SCAN_LINE_BUFFER_LENGTH]; PBYTE pjSrc = (PBYTE)NULL; PBYTE pjDst = (PBYTE)NULL; PBYTE pjPat = (PBYTE)NULL; ULONG cxPat; ULONG ixPat; LONG cyPat; LONG iyPat; ULONG ixMsk; LONG iyMsk; ULONG iSolidColor; ULONG ulDstStart; ULONG Index; ULONG ulIndex; ULONG BytesPerPixel = 0; ULONG ByteOffset24Bpp = 0; BLTLNK_MASKINFO bmskMaskInfo;
#if DBG_BLTLNK
if (DbgBltLnk >= 1) { DbgPrint("BltLnkRect:\n"); DbgPrint(" prcl = %li,%li to %li,%li\n", prcl->left,prcl->top,prcl->right,prcl->bottom); DbgPrint(" yDir = %li, xDir = %li\n", pBlt->yDir,pBlt->xDir); DbgPrint(" pjSrc = 0x%lx, pjDst = 0x%lx\n",pBlt->pjSrc,pBlt->pjDst);
}
if (DbgBltLnk >= 2) { DbgPrint(" Address of SrcBuffer = 0x%p\n",&SrcBuffer[0]); DbgPrint(" Address of DstBuffer = 0x%p\n",&DstBuffer[0]); DbgPrint(" Address of RopBuffer0 = 0x%p\n",&RopBuffer0[0]); DbgPrint(" Address of RopBuffer1 = 0x%p\n",&RopBuffer1[0]); } #endif
//
// Calculate all temporary parameters needed to perform the BitBlt
// based on source and destination bitmap formats (which may be different)
//
// cy = number of scan lines to Blt
//
cy = prcl->bottom - prcl->top; PixelCount = prcl->right - prcl->left;
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint(" cy = %li\n",cy); } #endif
//
// calculate parameters for:
//
// 1) SrcBlt routine to load source into DWORD buffer
// transformed to Dst alignment, format and color
// 2) ROP2 routine to operate on DWORDS
// 3) SrcBlt routine to store DWORD buffer to pjDst
//
switch(pBlt->pdioDst->iFormat()) { case BMF_1BPP: ulDstStart = prcl->left >> 5; ByteOffset = (prcl->left >> 3) & 0x03; PixelOffset = prcl->left & 0x1f; DwordCount = (PixelOffset + PixelCount + 31) >> 5; break; case BMF_4BPP: ulDstStart = prcl->left >> 3; ByteOffset = (prcl->left >> 1) & 0x03; PixelOffset = prcl->left & 0x07; DwordCount = (PixelOffset + PixelCount + 7) >> 3; break; case BMF_8BPP: ulDstStart = prcl->left >> 2; ByteOffset = prcl->left & 0x03; PixelOffset = prcl->left & 0x03; DwordCount = (PixelOffset + PixelCount + 3) >> 2; BytesPerPixel = 1; break; case BMF_16BPP: ulDstStart = prcl->left >> 1; ByteOffset = (prcl->left & 0x01) << 1; PixelOffset = prcl->left & 0x01; DwordCount = (PixelOffset + PixelCount + 1) >> 1; BytesPerPixel = 2; break; case BMF_24BPP: ulDstStart = (prcl->left * 3) >> 2; ByteOffset = (prcl->left * 3) & 0x03; PixelOffset = 0; ByteOffset24Bpp = ByteOffset; BytesPerPixel = 3; DwordCount = (ByteOffset + 3 * PixelCount + 3) >> 2; break; case BMF_32BPP: ulDstStart = prcl->left; DwordCount = PixelCount; ByteOffset = 0; PixelOffset = 0; BytesPerPixel = 4; break; }
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint(" ulDstStart = %li\n",ulDstStart); DbgPrint(" DwordCount = %li\n",DwordCount); DbgPrint(" ByteOffset = 0x%lx\n",ByteOffset); DbgPrint(" PixelOffset = 0x%lx\n",PixelOffset); } #endif
//
// if there is a pat that isn't a solid color then
// set up params based on prcl
//
if (pBlt->pjPat != (PBYTE) NULL) {
//
// Set up format-specific pattern parameters for the call to
// ReadPat. Note: there is only one call for reading
// 8,16,24 and 32 Bpp patterns so cxPat, the pixel count is
// adjusted to become a byte count for these cases. ixPat is
// also adjusted to be a byte offset in these cases.
//
switch(pBlt->pdioDst->iFormat()) { case BMF_1BPP: cxPat = pBlt->cxPat; ixPat = prcl->left - pBlt->xPatOrg; pfnReadPat = BltLnkReadPat1; break; case BMF_4BPP: cxPat = pBlt->cxPat; ixPat = prcl->left - pBlt->xPatOrg; pfnReadPat = BltLnkReadPat4; break; case BMF_8BPP: cxPat = pBlt->cxPat; ixPat = prcl->left - pBlt->xPatOrg; pfnReadPat = BltLnkReadPat; break; case BMF_16BPP: cxPat = pBlt->cxPat << 1; ixPat = ((prcl->left - pBlt->xPatOrg) << 1); pfnReadPat = BltLnkReadPat; break; case BMF_24BPP: cxPat = pBlt->cxPat * 3; ixPat = ((prcl->left - pBlt->xPatOrg) * 3); pfnReadPat = BltLnkReadPat; break; case BMF_32BPP: cxPat = pBlt->cxPat << 2; ixPat = ((prcl->left - pBlt->xPatOrg) << 2); pfnReadPat = BltLnkReadPat; break; }
//
// Normalize Pattern:
//
// make sure starting ixPat is within pattern limits
// and set up iyPat and cyPat
//
if (ixPat >= cxPat) { ixPat %= cxPat; }// else if (ixPat < 0) {
// ixPat = (cxPat - 1) - ((-(LONG)ixPat - 1) % cxPat);
// }
cyPat = pBlt->cyPat; iyPat = prcl->top - pBlt->yPatOrg;
if (pBlt->yDir < 0) { iyPat = iyPat + (cy - 1); }
if (iyPat >= cyPat) { iyPat %= cyPat; } else if (iyPat < 0) { iyPat = (cyPat - 1) - ((-(LONG)iyPat - 1) % cyPat); }
pjPat = pBlt->pjPat + (iyPat * pBlt->lDeltaPat);
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint(" cxPat = 0x%lx cyPat = 0x%lx\n",cxPat,cyPat); DbgPrint(" ixPat = 0x%lx iyPat = 0x%lx\n",ixPat,iyPat); DbgPrint(" pjPat = 0x%p\n",pjPat); DbgPrint(" lDeltaPat = 0x%lx\n",pBlt->lDeltaPat); } #endif
} else {
//
// solid color for pat
//
iSolidColor = pBlt->iSolidColor;
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint(" iSolidColor = 0x%lx\n",iSolidColor); } #endif
}
//
// pjDst pointer to the beginning of the Dst scan line
//
// ulDstStart is added to (PULONG)pjDst to get the
// address of the first ULONG containing pixels needed in
// the blt
//
if (pBlt->yDir > 0) { pjDst = pBlt->pjDst + prcl->top * pBlt->lDeltaDst; } else { pjDst = pBlt->pjDst + (prcl->bottom - 1) * pBlt->lDeltaDst; }
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint(" ulDstStart = 0x%lx\n",ulDstStart); DbgPrint(" starting pjDst = 0x%p\n",pjDst); DbgPrint(" Byte Offset = 0x%lx\n",ByteOffset); } #endif
//
// calculate Src parameters if the Src is needed. Src paramters are
// used to load the entire Src into the temp buffer, aligned to
// Dst and converted to Dst format, one scan line at a time
//
if (pBlt->pjSrc != (PBYTE) NULL) {
//
// set up color translate routines
//
SrcCopyBltInfo.pxlo = pBlt->pxlo;
//
// ySrc is the offset in scan lines from the start of the src bitmap
//
// xSrctart is the pixel offset from the strart of the scan line
// to the first pixel neded
//
// xSrcEnd is 1 pixel beyond the last one needed for the scan line
//
pBlt->ySrc = pBlt->ySrcOrg + prcl->top - pBlt->rclDst.top; pBlt->xSrcStart = pBlt->xSrcOrg + prcl->left - pBlt->rclDst.left; pBlt->xSrcEnd = pBlt->xSrcStart + (PixelCount);
//
// initialize pjSrc to point to the start of each scan line to be
// copied
//
pjSrc = pBlt->pjSrc;
if (pBlt->yDir > 0) { pjSrc = pjSrc + (pBlt->ySrc * pBlt->lDeltaSrc); } else { pjSrc = pjSrc + (pBlt->ySrc + cy - 1) * pBlt->lDeltaSrc; }
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint(" starting pjSrc = %p\n",pjSrc); DbgPrint(" ySrc = %li\n",pBlt->ySrc); DbgPrint(" xSrcStart = %li\n",pBlt->xSrcStart); DbgPrint(" ySrcEnd = %li\n",pBlt->xSrcEnd); } #endif
}
//
// set up mask params
//
if (pBlt->bNeedMsk) {
bmskMaskInfo.cxMsk = pBlt->cxMsk; ixMsk = pBlt->xMskOrg + prcl->left - pBlt->rclDst.left; iyMsk = pBlt->yMskOrg + prcl->top - pBlt->rclDst.top;
//
// # of pixels offsets to first pixel for src from start of scan
//
if (pBlt->yDir < 0) { iyMsk += (cy - 1); }
//
// Normalize Msk again since prcl->left-pBlt->rclDst.left has
// been added.
//
// ixMsk should not be < 0 because MskOrg has already
// been normalized.
//
ASSERTGDI(iyMsk >= 0, " ERROR, negative iyMsk that has already been normalized");
if (ixMsk >= pBlt->cxMsk) { ixMsk = ixMsk % pBlt->cxMsk; }
if (iyMsk >= pBlt->cyMsk) { iyMsk = iyMsk % pBlt->cyMsk; }
//
// info for SrcCopyMsk routines
//
bmskMaskInfo.pjMskBase = pBlt->pjMsk; bmskMaskInfo.pjMsk = pBlt->pjMsk + (iyMsk * pBlt->lDeltaMsk); bmskMaskInfo.ixMsk = ixMsk; bmskMaskInfo.cxMsk = pBlt->cxMsk; bmskMaskInfo.iyMsk = iyMsk; bmskMaskInfo.cyMsk = pBlt->cyMsk; bmskMaskInfo.NegateMsk = pBlt->NegateMsk; bmskMaskInfo.lDeltaMskDir = pBlt->lDeltaMskDir;
//
// select mask store routine
//
switch(pBlt->pdioDst->iFormat()) { case BMF_1BPP: pfnCopyMask = BltLnkSrcCopyMsk1; break; case BMF_4BPP: pfnCopyMask = BltLnkSrcCopyMsk4; break; case BMF_8BPP: pfnCopyMask = BltLnkSrcCopyMsk8; break; case BMF_16BPP: pfnCopyMask = BltLnkSrcCopyMsk16; break; case BMF_24BPP: pfnCopyMask = BltLnkSrcCopyMsk24; break; case BMF_32BPP: pfnCopyMask = BltLnkSrcCopyMsk32; break; } }
////////////////////////////////////////////////////////////////
// //
// Place Accelerators Here for special cases that can not //
// go through the normal load/combine/store procedure. Only //
// positive x and y blts are accelerated (left to right), //
// top to bottom. //
// //
////////////////////////////////////////////////////////////////
if ((pBlt->xDir > 0) && (pBlt->yDir > 0)) {
//
// Mask Blt
//
if ((pBlt->rop3 == 0xCC) && pBlt->bNeedMsk && (pBlt->pdioSrc->iFormat() == pBlt->pdioDst->iFormat()) && (pBlt->pxlo->bIsIdentity())) {
//
// customize DstCopyBltInfo for MaskBlt 0xAACC or 0xCCAA will
// reach this point with a rop3 of CC. Color translations use the
// normal path.
//
DstCopyBltInfo.pjDst = pjDst; DstCopyBltInfo.pjSrc = pjSrc; DstCopyBltInfo.xDir = 1; DstCopyBltInfo.yDir = pBlt->yDir; DstCopyBltInfo.cx = PixelCount; DstCopyBltInfo.cy = cy; DstCopyBltInfo.lDeltaSrc = pBlt->lDeltaSrcDir; DstCopyBltInfo.lDeltaDst = pBlt->lDeltaDstDir; DstCopyBltInfo.xSrcStart = pBlt->xSrcStart; DstCopyBltInfo.xSrcEnd = pBlt->xSrcStart + PixelCount; DstCopyBltInfo.xDstStart = prcl->left; DstCopyBltInfo.yDstStart = 0; DstCopyBltInfo.pxlo = &xloIdent;
(*pfnCopyMask)(&DstCopyBltInfo,&bmskMaskInfo,&SrcBuffer[0],&DstBuffer[0]);
return; }
//
// ROP B8B8, src = 1bpp, translate to 00,ff. this is a src of 1bpp used as a mask
// to blt a solid color to dst as Dst = (Src & Dst) | (~Src & Pat)
//
// Also accelerate ROP E2E2 which is the opposite of B8B8 ie:
//
// Dst = (~Src & Dst) | (Src & Pat)
//
if ( ((pBlt->rop3 == 0xB8) || (pBlt->rop3 == 0xE2)) && (!pBlt->bNeedMsk) && (pBlt->iSolidColor != 0xffffffff) && (pBlt->pdioSrc->iFormat() == BMF_1BPP) && ((pBlt->pdioDst->iFormat() >= BMF_8BPP) && (pBlt->pdioDst->iFormat() <= BMF_32BPP)) ) { PFN_PATMASKCOPY pfnCopy; ULONG colormask;
switch (pBlt->pdioDst->iFormat()) { //
// BltLnkPatMaskCopy4 (and probably BltLnkPatMaskCopy1) are
// broken, so don't use them for now.
//
case BMF_8BPP: pfnCopy = BltLnkPatMaskCopy8; colormask = 0x0000ff; break; case BMF_16BPP: pfnCopy = BltLnkPatMaskCopy16; colormask = 0x00ffff; break; case BMF_24BPP: pfnCopy = BltLnkPatMaskCopy24; colormask = 0xffffff; break; case BMF_32BPP: pfnCopy = BltLnkPatMaskCopy32; colormask = 0xffffff; break; default: RIP("Unexpected case."); }
PULONG pulTranslate = pBlt->pxlo->pulXlate;
if ( ((pulTranslate[1] & colormask) == colormask) && ((pulTranslate[0] & colormask) == 0)) {
BYTE Invert = 0x00;
if (pBlt->rop3 == 0xE2) { Invert = 0xFF; }
//
// set up blt info
//
DstCopyBltInfo.pjDst = pjDst; DstCopyBltInfo.pjSrc = pjSrc; DstCopyBltInfo.xDir = 1; DstCopyBltInfo.yDir = pBlt->yDir; DstCopyBltInfo.cx = PixelCount; DstCopyBltInfo.cy = cy; DstCopyBltInfo.lDeltaSrc = pBlt->lDeltaSrcDir; DstCopyBltInfo.lDeltaDst = pBlt->lDeltaDstDir; DstCopyBltInfo.xSrcStart = pBlt->xSrcStart; DstCopyBltInfo.xSrcEnd = pBlt->xSrcStart + PixelCount; DstCopyBltInfo.xDstStart = prcl->left; DstCopyBltInfo.yDstStart = 0; DstCopyBltInfo.pxlo = pBlt->pxlo;
(*pfnCopy)(&DstCopyBltInfo,pBlt->iSolidColor,&SrcBuffer[0],Invert);
return; } }
//
// accelerators for VGA 256 special cases
//
if ((!pBlt->bNeedMsk) && (pBlt->bNeedSrc) && (pBlt->bNeedDst) && (pBlt->pdioDst->iFormat() == BMF_8BPP) && (pBlt->pdioSrc->iFormat() == BMF_8BPP) && (pBlt->pxlo->bIsIdentity()) ) { //
// ROP 6666 DSx
//
if (pBlt->rop3 == 0x66) { BltLnkAccel6666( pjSrc + pBlt->xSrcStart, pjDst + prcl->left, pBlt->lDeltaSrcDir, pBlt->lDeltaDstDir, PixelCount, cy ); return; }
//
// ROP 8888 DSa
//
if (pBlt->rop3 == 0x88) { BltLnkAccel8888( pjSrc + pBlt->xSrcStart, pjDst + prcl->left, pBlt->lDeltaSrcDir, pBlt->lDeltaDstDir, PixelCount, cy ); return; }
//
// ROP EEEE DSo
//
if (pBlt->rop3 == 0xEE) { BltLnkAccelEEEE( pjSrc + pBlt->xSrcStart, pjDst + prcl->left, pBlt->lDeltaSrcDir, pBlt->lDeltaDstDir, PixelCount, cy ); return; } }
//
// END OF ACCELERATORS
//
}
////////////////////////////////////////////////////////////////
// //
// Non-accelerated cases //
// //
////////////////////////////////////////////////////////////////
if (pBlt->bNeedSrc) { //
// fill out the SrcCopyBltInfo structure to be used by SrcBltxxx routine
// to read the src bitmap and copy it to dst format and alignment
//
SrcCopyBltInfo.pjDst = (PBYTE)(&SrcBuffer[0]) + ByteOffset24Bpp; SrcCopyBltInfo.pjSrc = pjSrc; SrcCopyBltInfo.xDir = 1; SrcCopyBltInfo.yDir = pBlt->yDir; SrcCopyBltInfo.cx = PixelCount; SrcCopyBltInfo.cy = 1; SrcCopyBltInfo.lDeltaSrc = 1; SrcCopyBltInfo.lDeltaDst = 1; SrcCopyBltInfo.xSrcStart = pBlt->xSrcStart; SrcCopyBltInfo.xSrcEnd = pBlt->xSrcStart + SrcCopyBltInfo.cx; SrcCopyBltInfo.xDstStart = PixelOffset; SrcCopyBltInfo.yDstStart = 1; SrcCopyBltInfo.pxlo = pBlt->pxlo;
//
// select SrcCopy routine based on bitmap formats and color translation
//
Index = (pBlt->pdioDst->iFormat() << 5) | (pBlt->pdioSrc->iFormat() << 2);
if (pBlt->pxlo->bIsIdentity()) { Index += 1; }
pfnSrcCopy = SrcCopyFunctionTable[Index];
}
//
// fill out the DstCopyBltInfo structure to be used by SrcBltxxx routine
// to copy the dst scan line to the actual destination
//
DstCopyBltInfo.pjDst = pjDst; DstCopyBltInfo.pjSrc = (PBYTE)&DstBuffer[0] + ByteOffset24Bpp; DstCopyBltInfo.xDir = 1; DstCopyBltInfo.yDir = pBlt->yDir; DstCopyBltInfo.cx = PixelCount; DstCopyBltInfo.cy = 1; DstCopyBltInfo.lDeltaSrc = 1; DstCopyBltInfo.lDeltaDst = 1; DstCopyBltInfo.xSrcStart = PixelOffset; DstCopyBltInfo.xSrcEnd = PixelOffset + DstCopyBltInfo.cx; DstCopyBltInfo.xDstStart = prcl->left; DstCopyBltInfo.yDstStart = 0; DstCopyBltInfo.pxlo = &xloIdent;
//
// select DstCopy routine based on bitmap formats and color translation,
// only need SrcCopy routine selection if not using mask
//
if (!pBlt->bNeedMsk) {
Index = (pBlt->pdioDst->iFormat() << 5) | (pBlt->pdioDst->iFormat() << 2);
//
// color translation already done
//
Index += 1;
pfnDstCopy = SrcCopyFunctionTable[Index]; }
//
// define the ROP function, there are 4 possible ROP functions:
//
// if Pat is not need then it is a ROP 2 without Pat
//
// if Dst is not need then it is a ROP 2 without Dst
//
// if Src is not need then it is a ROP 2 without Src
//
// If src,dst and pat are needed to calculate the new dest then it is a
// full ROP3
//
//
if (!pBlt->bNeedPat) {
rop2 = pBlt->rop3 & 0x0F;
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint(" Select no pat rop, rop2 function = %li\n",rop2); } #endif
//
// ROP without Pat
//
pfnRop1 = RopFunctionTable[rop2];
//
// blt each scan line
//
Index = cy;
while (Index--) {
if (pBlt->bNeedSrc) {
//
// get src scan line if offset or
// color translation are needed
//
(*pfnSrcCopy)(&SrcCopyBltInfo);
//
// update pointer for next src line
//
SrcCopyBltInfo.pjSrc += pBlt->lDeltaSrcDir; }
//
// ROP the buffers together
//
(*pfnRop1)(&DstBuffer[0],(PULONG)pjDst + ulDstStart,&SrcBuffer[0],DwordCount);
//
// copy the buffer to the dest
//
if (!pBlt->bNeedMsk) {
(*pfnDstCopy)(&DstCopyBltInfo);
} else {
//
// call store routine with mask
//
(*pfnCopyMask)(&DstCopyBltInfo,&bmskMaskInfo,&RopBuffer0[0],NULL);
//
// increment to the next mask scan line,
// check for going off the edge. This must
// be done for pos and neg blts
//
// should be an inline function!
//
if (pBlt->yDir > 0) {
iyMsk++; bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir;
if (iyMsk >= pBlt->cyMsk) { iyMsk = 0; bmskMaskInfo.pjMsk = pBlt->pjMsk; }
} else {
if (iyMsk == 0) { iyMsk = pBlt->cyMsk - 1; bmskMaskInfo.pjMsk = pBlt->pjMsk + (pBlt->lDeltaMsk * (pBlt->cyMsk - 1)); } else { iyMsk--; bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir; } } }
//
// increment to the next scan line
//
pjDst += pBlt->lDeltaDstDir; DstCopyBltInfo.pjDst = pjDst;
}
//
// ROP that doesn't require Dst
//
} else if (!pBlt->bNeedDst) {
rop2 = pBlt->RopDst & 0x0f; pfnRop1 = RopFunctionTable[rop2];
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint(" Select no dst rop, rop2 function = %lx\n",rop2); } #endif
//
// fill in solid color if there is no pjPat;
//
if (pjPat == (PBYTE) NULL) {
if (pBlt->pdioDst->iFormat() != BMF_24BPP) {
//
// fill in RopBuffer1 with the 32 bit solid color.
// Number of DWORDS = Number of BYTES/4
//
ulIndex = DwordCount;
while (ulIndex > 0) { RopBuffer1[--ulIndex] = iSolidColor; }
} else {
PBYTE pjSolidPat = (PBYTE)(&RopBuffer1[0]) + ByteOffset24Bpp;
//
// read in 24bpp solid color
//
ulIndex = PixelCount;
while (ulIndex > 0) { *pjSolidPat = (BYTE)(iSolidColor & 0x0000FF); *(pjSolidPat+1) = (BYTE)((iSolidColor >> 8) & 0x0000FF); *(pjSolidPat+2) = (BYTE)((iSolidColor >> 16) & 0x0000FF); pjSolidPat+=3; ulIndex--; }
} }
//
// ROP without Dst
//
while (cy--) {
if (pBlt->bNeedSrc) {
//
// get src scan line
//
(*pfnSrcCopy)(&SrcCopyBltInfo);
//
// update pointer for next src line
//
SrcCopyBltInfo.pjSrc += pBlt->lDeltaSrcDir; }
if (pjPat != (PBYTE) NULL) {
if (pjPat != (PBYTE) NULL) {
(*pfnReadPat)((PBYTE)&RopBuffer1[0]+ByteOffset,PixelOffset,pjPat,cxPat,ixPat,PixelCount,BytesPerPixel);
if (pBlt->yDir == 1) {
iyPat++; pjPat += pBlt->lDeltaPatDir;
if (iyPat >= cyPat) { iyPat = 0; pjPat = pBlt->pjPat; }
} else {
if (iyPat == 0) { iyPat = cyPat - 1; pjPat = pBlt->pjPat + (pBlt->lDeltaPat * (cyPat - 1)); } else { iyPat--; pjPat -= pBlt->lDeltaPat; }
}
} }
//
// ROP the buffers together
//
(*pfnRop1)(&DstBuffer[0],&RopBuffer1[0],&SrcBuffer[0],DwordCount);
//
// copy the result to the screen
//
if (!pBlt->bNeedMsk) {
(*pfnDstCopy)(&DstCopyBltInfo);
} else {
//
// call store routine with mask
//
(*pfnCopyMask)(&DstCopyBltInfo,&bmskMaskInfo,&SrcBuffer[0],NULL);
//
// increment to the next mask scan line,
// check for going off the edge. This must
// be done for pos and neg blts
//
// should be an inline function!
//
if (pBlt->yDir > 0) {
iyMsk++; bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir;
if (iyMsk >= pBlt->cyMsk) { iyMsk = 0; bmskMaskInfo.pjMsk = pBlt->pjMsk; }
} else {
if (iyMsk == 0) { iyMsk = pBlt->cyMsk - 1; bmskMaskInfo.pjMsk = pBlt->pjMsk + (pBlt->lDeltaMsk * (pBlt->cyMsk - 1)); } else { iyMsk--; bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir; } } }
//
// increment to the next scan line
//
pjDst += pBlt->lDeltaDstDir; DstCopyBltInfo.pjDst = pjDst; }
//
// ROP that doesn't require Src
//
} else if (!pBlt->bNeedSrc) {
//
// fill in solid color if there is no pjPat;
//
if (pjPat == (PBYTE) NULL) {
if (pBlt->pdioDst->iFormat() != BMF_24BPP) {
//
// Replicate solid pattern to buffer
// Number of DWORDS = Number of BYTES/4
//
ulIndex = DwordCount;
while (ulIndex > 0) { RopBuffer1[--ulIndex] = iSolidColor; }
} else {
PBYTE pjSolidPat = (PBYTE)(&RopBuffer1[0]) + ByteOffset24Bpp;
ulIndex = PixelCount;
//
// read in 24bpp solid color
//
while (ulIndex > 0) { *pjSolidPat = (BYTE)(iSolidColor & 0x0000FF); *(pjSolidPat+1) = (BYTE)((iSolidColor >> 8) & 0x0000FF); *(pjSolidPat+2) = (BYTE)((iSolidColor >> 16) & 0x0000FF); pjSolidPat+=3; ulIndex--; }
} }
//
// Rop without SRC
//
rop2 = pBlt->RopSrc & 0x0f;
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint(" Select no src rop, rop2 function = %lx\n",rop2); } #endif
pfnRop1 = RopFunctionTable[rop2];
//
// blt each scan line
//
Index = cy;
while (Index--) {
//
// will need pat for sure
//
if (pBlt->bNeedPat) {
if (pjPat != (PBYTE) NULL) {
(*pfnReadPat)((PBYTE)&RopBuffer1[0]+ByteOffset,PixelOffset,pjPat,cxPat,ixPat,PixelCount,BytesPerPixel);
if (pBlt->yDir == 1) {
iyPat++; pjPat += pBlt->lDeltaPatDir;
if (iyPat >= cyPat) { iyPat = 0; pjPat = pBlt->pjPat; }
} else {
if (iyPat == 0) { iyPat = cyPat - 1; pjPat = pBlt->pjPat + (pBlt->lDeltaPat * (cyPat - 1)); } else { iyPat--; pjPat -= pBlt->lDeltaPat; }
}
} }
//
// ROP the memory buffers together
//
(*pfnRop1)(&DstBuffer[0],(PULONG)pjDst + ulDstStart,&RopBuffer1[0],DwordCount);
//
// copy the result to the dest
//
if (!pBlt->bNeedMsk) {
(*pfnDstCopy)(&DstCopyBltInfo);
} else {
//
// call store routine with mask
//
(*pfnCopyMask)(&DstCopyBltInfo,&bmskMaskInfo,&SrcBuffer[0],NULL);
//
// increment to the next mask scan line,
// check for going off the edge. This must
// be done for pos and neg blts
//
// should be an inline function!
//
if (pBlt->yDir > 0) {
iyMsk++; bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir;
if (iyMsk >= pBlt->cyMsk) { iyMsk = 0; bmskMaskInfo.pjMsk = pBlt->pjMsk; }
} else {
if (iyMsk == 0) { iyMsk = pBlt->cyMsk - 1; bmskMaskInfo.pjMsk = pBlt->pjMsk + (pBlt->lDeltaMsk * (pBlt->cyMsk - 1)); } else { iyMsk--; bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir; } } }
//
// increment to next dest
//
pjDst += pBlt->lDeltaDstDir; DstCopyBltInfo.pjDst = pjDst; }
//
// FULL rop3
//
} else {
PULONG pTmpDstBuffer; PULONG pTmpRopBuffer0; PULONG pTmpRopBuffer1; PULONG pTmpSrcBuffer; ULONG SrcColor;
//
// full ROP 3, perform in 2 passes through ROP 2, 1 for
// not Pat and one for Pat. This rop will need src,dst and pat
//
rop2 = pBlt->rop3;
#if DBG_BLTLNK
if (DbgBltLnk >= 2) { DbgPrint(" Select full rop, rop2 function = %lx\n",rop2 & 0x0f); DbgPrint(" rop2 function = %lx\n",(rop2 & 0xf0) >> 4); } #endif
pfnRop1 = RopFunctionTable[ rop2 & 0x0f ]; pfnRop2 = RopFunctionTable[ ( rop2 & 0xf0 ) >> 4 ];
Index = cy;
while (Index--) {
//
// get src scan line
//
(*pfnSrcCopy)(&SrcCopyBltInfo);
//
// update pointer for next src line
//
SrcCopyBltInfo.pjSrc += pBlt->lDeltaSrcDir;
//
// set dst buffer pointer to dst
//
pTmpDstBuffer = (PULONG)pjDst + ulDstStart;
//
// perform both rop passes
//
(*pfnRop1)(&RopBuffer0[0],pTmpDstBuffer,&SrcBuffer[0],DwordCount); (*pfnRop2)(&RopBuffer1[0],pTmpDstBuffer,&SrcBuffer[0],DwordCount);
if (pjPat != (PBYTE) NULL) {
//
// fill up a buffer with the pattern
//
(*pfnReadPat)((PBYTE)&SrcBuffer[0] + ByteOffset,PixelOffset,pjPat,cxPat,ixPat,PixelCount,BytesPerPixel);
if (pBlt->yDir == 1) {
iyPat++; pjPat += pBlt->lDeltaPatDir;
if (iyPat >= cyPat) { iyPat = 0; pjPat = pBlt->pjPat; }
} else {
if (iyPat == 0) { iyPat = cyPat - 1; pjPat = pBlt->pjPat + (pBlt->lDeltaPat * (cyPat - 1)); } else { iyPat--; pjPat -= pBlt->lDeltaPat; }
}
//
// combine ROPs based on pat
//
pTmpDstBuffer = &DstBuffer[0]; pTmpRopBuffer0 = &RopBuffer0[0]; pTmpRopBuffer1 = &RopBuffer1[0]; pTmpSrcBuffer = &SrcBuffer[0];
ulIndex = DwordCount;
while (ulIndex > 0) {
SrcColor = *pTmpSrcBuffer;
*pTmpDstBuffer = (*pTmpRopBuffer1 & SrcColor | *pTmpRopBuffer0 & ~SrcColor);
pTmpSrcBuffer++; pTmpDstBuffer++; pTmpRopBuffer0++; pTmpRopBuffer1++; ulIndex--; }
} else {
//
// solid pattern
//
if (pBlt->pdioDst->iFormat() != BMF_24BPP) {
pTmpDstBuffer = &DstBuffer[0]; pTmpRopBuffer0 = &RopBuffer0[0]; pTmpRopBuffer1 = &RopBuffer1[0];
ulIndex = DwordCount;
while (ulIndex > 0) {
*pTmpDstBuffer = (*pTmpRopBuffer1 & iSolidColor | *pTmpRopBuffer0 & ~iSolidColor); pTmpDstBuffer++; pTmpRopBuffer0++; pTmpRopBuffer1++; ulIndex--; }
} else {
//
// fill up a buffer with 24bpp solid pat
//
PBYTE pjSolidPat = (PBYTE)(&SrcBuffer[0]) + ByteOffset24Bpp;
//
// read in 24bpp solid color
//
ulIndex = PixelCount;
while (ulIndex>0) { *pjSolidPat = (BYTE)(iSolidColor & 0x0000FF); *(pjSolidPat+1) = (BYTE)((iSolidColor >> 8) & 0x0000FF); *(pjSolidPat+2) = (BYTE)((iSolidColor >> 16) & 0x0000FF); pjSolidPat+=3; ulIndex--; }
//
// combine ROPs based on pat
//
pTmpDstBuffer = &DstBuffer[0]; pTmpRopBuffer0 = &RopBuffer0[0]; pTmpRopBuffer1 = &RopBuffer1[0]; pTmpSrcBuffer = &SrcBuffer[0];
ulIndex = DwordCount;
while (ulIndex > 0) {
SrcColor = *pTmpSrcBuffer;
*pTmpDstBuffer = (*pTmpRopBuffer1 & SrcColor | *pTmpRopBuffer0 & ~SrcColor); pTmpSrcBuffer++; pTmpDstBuffer++; pTmpRopBuffer0++; pTmpRopBuffer1++; ulIndex--; }
}
}
//
// write out temp buffer to destination
//
if (!pBlt->bNeedMsk) {
(*pfnDstCopy)(&DstCopyBltInfo);
} else {
//
// call store routine with mask
//
(*pfnCopyMask)(&DstCopyBltInfo,&bmskMaskInfo,&SrcBuffer[0],NULL);
//
// increment to the next mask scan line,
// check for going off the edge. This must
// be done for pos and neg blts
//
// should be an inline function!
//
if (pBlt->yDir > 0) {
iyMsk++; bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir;
if (iyMsk >= pBlt->cyMsk) { iyMsk = 0; bmskMaskInfo.pjMsk = pBlt->pjMsk; }
} else {
if (iyMsk == 0) { iyMsk = pBlt->cyMsk - 1; bmskMaskInfo.pjMsk = pBlt->pjMsk + (pBlt->lDeltaMsk * (pBlt->cyMsk - 1)); } else { iyMsk--; bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir; } } }
//
// increment Dst to next scan line
//
pjDst += pBlt->lDeltaDstDir; DstCopyBltInfo.pjDst = pjDst;
} } }
|