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.
3446 lines
87 KiB
3446 lines
87 KiB
|
|
/******************************Module*Header*******************************\
|
|
* Module Name:
|
|
*
|
|
* bltlnkfnc.cxx
|
|
*
|
|
* Abstract
|
|
*
|
|
* This module implements 2 operand ROP functions used by bltlnk
|
|
* as well as the routines needed to:
|
|
*
|
|
* 1: Perform masked bitblt operations
|
|
* 2: Perform color expansion
|
|
* 3: Read and expand patterns
|
|
*
|
|
* Author:
|
|
*
|
|
* Mark Enstrom (marke) 9-27-93
|
|
*
|
|
* Copyright (c) 1993-1999 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
extern ULONG DbgBltLnk;
|
|
ULONG DbgMask = 0;
|
|
ULONG DbgPat = 0;
|
|
|
|
BYTE StartMask[] = {0xff,0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01,0x00};
|
|
BYTE EndMask[] = {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};
|
|
|
|
//
|
|
//
|
|
// the following routins are the 16 ROP 2 functions generated
|
|
// by a combination of two variables:
|
|
//
|
|
// ROP Function
|
|
// -----------------------------
|
|
// 0 0
|
|
// 1 ~(S | D)
|
|
// 2 ~S & D
|
|
// 3 ~S
|
|
// 4 S & ~D
|
|
// 5 ~D
|
|
// 6 S ^ D
|
|
// 7 ~S | ~D
|
|
// 8 S & D
|
|
// 9 ~(S ^ D)
|
|
// A D
|
|
// B ~S | D
|
|
// C S
|
|
// D S | ~D
|
|
// E S | D
|
|
// F 1
|
|
//
|
|
//
|
|
// Each of these functions expects as input an array for S and and
|
|
// Array for D and output is written to another array, Y
|
|
//
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* vRop2Function 0 - F
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Perform Rop2 logical combination of cx DWORDS from pulSBuffer and
|
|
* pulDBuffer into pulDstBuffer
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pulDstBuffer - pointer to destination buffer
|
|
* pulDBuffer - pointer to source for destination data
|
|
* pulSBuffer - pointer to source for source data
|
|
* cx - number of DWORDS to combine
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
vRop2Function0(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
DONTUSE(pulDBuffer);
|
|
DONTUSE(pulSBuffer);
|
|
memset((void *)pulDstBuffer,0,(int)(cx<<2));
|
|
}
|
|
|
|
|
|
VOID
|
|
vRop2Function1(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
while (cx--) {
|
|
*pulDstBuffer++ = ~(*pulSBuffer++ | *pulDBuffer++);
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
vRop2Function2(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
while (cx--) {
|
|
*pulDstBuffer++ = (~*pulSBuffer++ & *pulDBuffer++);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
vRop2Function3(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
|
|
DONTUSE(pulDBuffer);
|
|
while (cx--) {
|
|
*pulDstBuffer++ = ~*pulSBuffer++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
vRop2Function4(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
while (cx--) {
|
|
*pulDstBuffer++ = *pulSBuffer++ & ~*pulDBuffer++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
vRop2Function5(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
DONTUSE(pulSBuffer);
|
|
while (cx--) {
|
|
*pulDstBuffer++ = ~*pulDBuffer++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
vRop2Function6(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
while (cx--) {
|
|
*pulDstBuffer++ = *pulSBuffer++ ^ *pulDBuffer++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
vRop2Function7(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
while (cx--) {
|
|
*pulDstBuffer++ = ~(*pulSBuffer++ & *pulDBuffer++);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
vRop2Function8(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
while (cx--) {
|
|
*pulDstBuffer++ = *pulSBuffer++ & *pulDBuffer++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
vRop2Function9(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
while (cx--) {
|
|
*pulDstBuffer++ = ~(*pulSBuffer++ ^ *pulDBuffer++);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
vRop2FunctionA(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
DONTUSE(pulSBuffer);
|
|
|
|
memcpy((void *)pulDstBuffer,(void *)pulDBuffer,(int)(cx<<2));
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
vRop2FunctionB(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
while (cx--) {
|
|
*pulDstBuffer++ = (~*pulSBuffer++) | *pulDBuffer++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
vRop2FunctionC(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
DONTUSE(pulDBuffer);
|
|
|
|
memcpy((void *)pulDstBuffer,(void *)pulSBuffer,(int)(cx<<2));
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
vRop2FunctionD(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
while (cx--) {
|
|
*pulDstBuffer++ = *pulSBuffer++ | (~*pulDBuffer++);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
vRop2FunctionE(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
while (cx--) {
|
|
*pulDstBuffer++ = *pulSBuffer++ | *pulDBuffer++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
vRop2FunctionF(
|
|
PULONG pulDstBuffer,
|
|
PULONG pulDBuffer,
|
|
PULONG pulSBuffer,
|
|
ULONG cx
|
|
)
|
|
{
|
|
|
|
DONTUSE(pulSBuffer);
|
|
DONTUSE(pulDBuffer);
|
|
|
|
memset((void *)pulDstBuffer,0xFF,(int)cx<<2);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkSrcCopyMsk1
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Routines to store src to dst based on 1 bit per pixel mask.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBltInfo - pointer to BLTINFO structure (src and dst info)
|
|
* pMaskInfo - pointer to MASKINFO structure (pjMsk,ixMsk etc)
|
|
* Bytes - Number of Bytes per pixel
|
|
* Buffer0 - Pointer to a temporary scan line buffer used to read mask
|
|
* Buffer1 - Pointer to a temporary scan line buffer used align src
|
|
* if necessary. Only used for Mask Blt, not ROPs which
|
|
* are already aligned
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkSrcCopyMsk1 (
|
|
PBLTINFO pBltInfo,
|
|
PBLTLNK_MASKINFO pMaskInfo,
|
|
PULONG Buffer0,
|
|
PULONG Buffer1
|
|
)
|
|
|
|
{
|
|
|
|
PBYTE pjSrcTmp = pBltInfo->pjSrc;
|
|
PBYTE pjDstTmp = pBltInfo->pjDst;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
ULONG ixDst;
|
|
ULONG ixMsk;
|
|
ULONG iyMsk = pMaskInfo->iyMsk;
|
|
PBYTE pjMsk = pMaskInfo->pjMsk;
|
|
LONG cx;
|
|
ULONG cy = pBltInfo->cy;
|
|
PBYTE pjBuffer = (PBYTE)&Buffer0[0];
|
|
BYTE Mask;
|
|
|
|
//
|
|
// if src and dst are not aligned then use SrcBlt1 to
|
|
// copy each scan line to temp buffer Buffer1 first
|
|
// to align it to dst
|
|
//
|
|
|
|
while (cy--)
|
|
{
|
|
|
|
cx = (LONG)pBltInfo->cx;
|
|
|
|
pjSrc = pjSrcTmp + (pBltInfo->xSrcStart >> 3);
|
|
pjDst = pjDstTmp + (pBltInfo->xDstStart >> 3);
|
|
|
|
ixMsk = pMaskInfo->ixMsk;
|
|
ixDst = pBltInfo->xDstStart;
|
|
|
|
//
|
|
// check Src and Dst alignment, if Src and Dst are not aligned,
|
|
// copy Src to a temp buffer at Dst alignment
|
|
//
|
|
|
|
if ((pBltInfo->xSrcStart & 0x07) != (pBltInfo->xDstStart & 0x07))
|
|
{
|
|
//
|
|
// copy and align src to dst
|
|
//
|
|
|
|
BltLnkReadPat1((PBYTE)Buffer1,
|
|
ixDst & 0x07,
|
|
pjSrc,
|
|
cx,
|
|
pBltInfo->xSrcStart & 0x07,
|
|
cx,0);
|
|
|
|
pjSrc = (PBYTE)Buffer1;
|
|
|
|
}
|
|
|
|
//
|
|
// align mask using BltLnkReadPat1
|
|
//
|
|
|
|
BltLnkReadPat1((PBYTE)Buffer0,ixDst,pjMsk,pMaskInfo->cxMsk,ixMsk,cx,0);
|
|
|
|
pjBuffer = (PBYTE)Buffer0;
|
|
|
|
//
|
|
// If pMaskInfo->NegateMsk is FALSE, then when a mask bit is set
|
|
// the Src is written to Dst, Dst is unchanged when the mask is clear.
|
|
//
|
|
// If pMaskInfo->NegateMsk is TRUE, then when a mask bit is clear
|
|
// the Src is written to Dst, Dst is unchanged when the mask is set.
|
|
//
|
|
// ReadPat1 will zero partial bits at the beginning and end of a
|
|
// scan line, this work fine for !Negate because zero mask bits are
|
|
// not copied. However, for Negate masks, partial bits at the
|
|
// beginning and end of scan lines must be masked so that these
|
|
// bits are "1"s so that Src will not be copied to Dst. This is
|
|
// done by ORing start and end masks onto the mask line.
|
|
//
|
|
|
|
if (!pMaskInfo->NegateMsk)
|
|
{
|
|
while (cx>0)
|
|
{
|
|
Mask = *pjBuffer;
|
|
|
|
if (Mask == 0xFF)
|
|
{
|
|
*pjDst = *pjSrc;
|
|
} else if (Mask != 0) {
|
|
*pjDst = (*pjSrc & Mask) | (*pjDst & ~Mask);
|
|
}
|
|
|
|
pjSrc++;
|
|
pjDst++;
|
|
pjBuffer++;
|
|
|
|
cx -= 8;
|
|
|
|
//
|
|
// check if this was a partial byte,
|
|
// in that case restore partial byte
|
|
// to cx (cx -= 8 -(ixDst & 0x07))
|
|
// but since already did cx -= 8,add
|
|
// ixDst & 0x07 back in
|
|
//
|
|
|
|
if (ixDst & 0x07)
|
|
{
|
|
cx += ixDst & 0x07;
|
|
|
|
//
|
|
// zero ixDst, will not be needed again
|
|
//
|
|
|
|
ixDst = 0;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
//
|
|
// In this case write src to dst bits when mask == 0.
|
|
// This means the beggining and end cases must have
|
|
// mask set to 1 for the bits of partial bytes that are
|
|
// not to be touched.
|
|
//
|
|
// ie : starting ixDst = 2
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// Mask = ³0³1³2³3³4³5³6³7³
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// or with ³1³1³0³0³0³0³0³0³
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ
|
|
//
|
|
// to make sure pixels 0 and 1 are not written.
|
|
// this is 0xFF << 6 = 0xFF << (8 - (ixDst & 7))
|
|
//
|
|
|
|
pjBuffer[0] |= (BYTE) (0xff << (8 - (ixDst & 0x07)));
|
|
|
|
//
|
|
// for the ending case, want to set all bits after the
|
|
// last.
|
|
//
|
|
// ie: ixDst = 2, cx = 8. This means store byte 0
|
|
// bits 2,3,4,5,6,7 and byte 1 bits 0 and 1
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// In this case the mask must be ³0³0³1³1³1³1³1³1³
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ
|
|
// which is 0xFF >> 2 = (ixDst + cx) & 0x07
|
|
//
|
|
|
|
|
|
pjBuffer[((ixDst&0x07) + cx) >> 3] |=
|
|
(BYTE) (0xff >> ((ixDst + cx) & 0x07));
|
|
|
|
while (cx>0)
|
|
{
|
|
Mask = *pjBuffer;
|
|
|
|
if (Mask == 0x00)
|
|
{
|
|
*pjDst = *pjSrc;
|
|
} else if (Mask != 0xFF) {
|
|
*pjDst = (*pjDst & Mask) | (*pjSrc & ~Mask);
|
|
}
|
|
pjSrc++;
|
|
pjDst++;
|
|
pjBuffer++;
|
|
|
|
cx -= 8;
|
|
|
|
//
|
|
// check if this was a partial byte,
|
|
// in that case restore partial byte
|
|
// to cx (cx -= 8 -(ixDst & 0x07))
|
|
// but since already did cx -= 8,add
|
|
// ixDst & 0x07 back in
|
|
//
|
|
|
|
if (ixDst & 0x07) {
|
|
cx += ixDst & 0x07;
|
|
|
|
//
|
|
// zero ixDst, will not be needed again
|
|
//
|
|
|
|
ixDst = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// increment for next scan line
|
|
//
|
|
|
|
pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
|
|
pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
|
|
|
|
if (pBltInfo->yDir > 0) {
|
|
|
|
iyMsk++;
|
|
|
|
pjMsk += pMaskInfo->lDeltaMskDir;
|
|
|
|
if ((LONG)iyMsk >= pMaskInfo->cyMsk)
|
|
{
|
|
iyMsk = 0;
|
|
pjMsk = pMaskInfo->pjMskBase;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (iyMsk == 0)
|
|
{
|
|
iyMsk = pMaskInfo->cyMsk - 1;
|
|
pjMsk = pMaskInfo->pjMskBase +
|
|
(pMaskInfo->lDeltaMskDir * (pMaskInfo->cyMsk - 1));
|
|
}
|
|
else
|
|
{
|
|
iyMsk--;
|
|
pjMsk += pMaskInfo->lDeltaMskDir;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkSrcCopyMsk4
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Routines to store src to dst based on 1 bit per pixel mask.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBltInfo - pointer to BLTINFO structure (src and dst info)
|
|
* pMaskInfo - pointer to MASKINFO structure (pjMsk,ixMsk etc)
|
|
* Bytes - Number of Bytes per pixel
|
|
* Buffer - Pointer to a temporary buffer that may be used
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkSrcCopyMsk4 (
|
|
PBLTINFO pBltInfo,
|
|
PBLTLNK_MASKINFO pMaskInfo,
|
|
PULONG Buffer0,
|
|
PULONG Buffer1
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PBYTE pjSrcTmp = pBltInfo->pjSrc;
|
|
PBYTE pjDstTmp = pBltInfo->pjDst;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
BYTE jMsk;
|
|
BYTE jSrc;
|
|
BYTE jDst;
|
|
BYTE jDstNew;
|
|
ULONG ixSrc;
|
|
ULONG ixDst;
|
|
ULONG ixMsk;
|
|
ULONG iyMsk = pMaskInfo->iyMsk;
|
|
PBYTE pjMsk = pMaskInfo->pjMsk;
|
|
ULONG cx;
|
|
ULONG cy = pBltInfo->cy;
|
|
|
|
DONTUSE(Buffer0);
|
|
DONTUSE(Buffer1);
|
|
|
|
while (cy--) {
|
|
|
|
cx = pBltInfo->cx;
|
|
|
|
pjSrc = pjSrcTmp + (pBltInfo->xSrcStart >> 1);
|
|
pjDst = pjDstTmp + (pBltInfo->xDstStart >> 1);
|
|
|
|
ixMsk = pMaskInfo->ixMsk;
|
|
ixSrc = pBltInfo->xSrcStart;
|
|
ixDst = pBltInfo->xDstStart;
|
|
//
|
|
// load first mask byte and align it
|
|
//
|
|
jMsk = pjMsk[ixMsk >> 3] ^ pMaskInfo->NegateMsk;
|
|
jMsk <<= ixMsk & 0x7;
|
|
//
|
|
// if destination is on odd nibble we'll handle it now so the main
|
|
// loop can process two nibbles per pass
|
|
//
|
|
if (ixDst & 1)
|
|
{
|
|
if (jMsk & 0x80)
|
|
{
|
|
if (ixSrc & 1)
|
|
*pjDst = (*pjDst & 0xf0) | (*pjSrc & 0x0f);
|
|
else
|
|
*pjDst = (*pjDst & 0xf0) | ((*pjSrc & 0xf0) >> 4);
|
|
}
|
|
pjDst++;
|
|
ixSrc++;
|
|
if (!(ixSrc & 1))
|
|
pjSrc++;
|
|
jMsk <<= 1;
|
|
ixMsk++;
|
|
cx--;
|
|
}
|
|
ixSrc &= 1;
|
|
//
|
|
// main loop, pack two pixels into each output byte per pass
|
|
//
|
|
while (cx >= 2)
|
|
{
|
|
BYTE jMskTmp;
|
|
//
|
|
// calculate the mask bits for both pixels
|
|
//
|
|
if ((LONG)ixMsk == pMaskInfo->cxMsk)
|
|
ixMsk = 0;
|
|
if (!(ixMsk & 0x07))
|
|
jMsk = pjMsk[ixMsk >> 3] ^ pMaskInfo->NegateMsk;
|
|
|
|
jMskTmp = jMsk;
|
|
jMsk <<= 1;
|
|
|
|
if ((LONG)++ixMsk == pMaskInfo->cxMsk)
|
|
ixMsk = 0;
|
|
if (!(ixMsk & 0x07))
|
|
jMsk = pjMsk[ixMsk >> 3] ^ pMaskInfo->NegateMsk;
|
|
//
|
|
// determine whether first nibble uses source
|
|
//
|
|
if (jMskTmp & 0x80)
|
|
{
|
|
if (jMsk & 0x80)
|
|
{
|
|
if (ixSrc)
|
|
*pjDst = (*pjSrc << 4) | ((pjSrc[1] & 0xf0) >> 4);
|
|
else
|
|
*pjDst = *pjSrc;
|
|
}
|
|
else
|
|
{
|
|
if (ixSrc)
|
|
*pjDst = (*pjDst & 0x0f) | (*pjSrc << 4);
|
|
else
|
|
*pjDst = (*pjDst & 0x0f) | (*pjSrc & 0xf0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (jMsk & 0x80)
|
|
{
|
|
if (ixSrc)
|
|
*pjDst = (*pjDst & 0xf0) | ((*pjSrc & 0xf0) >> 4);
|
|
else
|
|
*pjDst = (*pjDst & 0xf0) | (*pjSrc & 0x0f);
|
|
}
|
|
}
|
|
jMsk <<= 1;
|
|
ixMsk++;
|
|
pjDst++;
|
|
pjSrc++;
|
|
cx -= 2;
|
|
}
|
|
//
|
|
// handle remaining nibble if there is one
|
|
//
|
|
if (cx)
|
|
{
|
|
if ((LONG)ixMsk == pMaskInfo->cxMsk)
|
|
ixMsk = 0;
|
|
if (!(ixMsk & 0x07))
|
|
jMsk = pjMsk[ixMsk >> 3] ^ pMaskInfo->NegateMsk;
|
|
if (jMsk & 0x80)
|
|
{
|
|
if (ixSrc)
|
|
*pjDst = (*pjDst & 0x0f) | (*pjSrc << 4);
|
|
else
|
|
*pjDst = (*pjDst & 0x0f) | (*pjSrc & 0xf0);
|
|
}
|
|
}
|
|
//
|
|
// increment for next scan line
|
|
//
|
|
|
|
pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
|
|
pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
|
|
|
|
if (pBltInfo->yDir > 0) {
|
|
|
|
iyMsk++;
|
|
|
|
pjMsk += pMaskInfo->lDeltaMskDir;
|
|
|
|
if ((LONG)iyMsk >= pMaskInfo->cyMsk)
|
|
{
|
|
iyMsk = 0;
|
|
pjMsk = pMaskInfo->pjMskBase;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (iyMsk == 0)
|
|
{
|
|
iyMsk = pMaskInfo->cyMsk - 1;
|
|
pjMsk = pMaskInfo->pjMskBase +
|
|
(pMaskInfo->lDeltaMskDir * (pMaskInfo->cyMsk - 1));
|
|
}
|
|
else
|
|
{
|
|
iyMsk--;
|
|
pjMsk += pMaskInfo->lDeltaMskDir;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkSrcCopyMsk8
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Routines to store src to dst based on 1 bit per pixel mask.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBltInfo - pointer to BLTLNKCOPYINFO structure (src and dst info)
|
|
* pMaskInfo - pointer to MASKINFO structure (pjMsk,ixMsk etc)
|
|
* Bytes - Number of Bytes per pixel
|
|
* Buffer - Pointer to a temporary buffer that may be used
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkSrcCopyMsk8 (
|
|
PBLTINFO pBltInfo,
|
|
PBLTLNK_MASKINFO pMaskInfo,
|
|
PULONG Buffer0,
|
|
PULONG Buffer1
|
|
)
|
|
{
|
|
|
|
ULONG jMsk = 0;
|
|
LONG ixMsk;
|
|
LONG cxMsk = pMaskInfo->cxMsk;
|
|
LONG iyMsk = pMaskInfo->iyMsk;
|
|
LONG icx;
|
|
LONG cx;
|
|
ULONG cy = pBltInfo->cy;
|
|
PBYTE pjSrcTmp = pBltInfo->pjSrc;
|
|
PBYTE pjDstTmp = pBltInfo->pjDst;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
PBYTE pjMsk = pMaskInfo->pjMsk;
|
|
BYTE Negate = pMaskInfo->NegateMsk;
|
|
ULONG icxDst;
|
|
LONG DeltaMsk;
|
|
|
|
|
|
|
|
|
|
DONTUSE(Buffer0);
|
|
DONTUSE(Buffer1);
|
|
|
|
while (cy--)
|
|
{
|
|
|
|
//
|
|
// init loop params
|
|
//
|
|
|
|
cx = (LONG)pBltInfo->cx;
|
|
ixMsk = pMaskInfo->ixMsk;
|
|
pjSrc = pjSrcTmp + pBltInfo->xSrcStart;
|
|
pjDst = pjDstTmp + pBltInfo->xDstStart;
|
|
|
|
//
|
|
// finish the scan line 8 mask bits at a time
|
|
//
|
|
|
|
while (cx > 0)
|
|
{
|
|
|
|
jMsk = (ULONG)(pjMsk[ixMsk>>3] ^ Negate);
|
|
|
|
//
|
|
// icx is the number of pixels left in the mask byte
|
|
//
|
|
|
|
icx = 8 - (ixMsk & 0x07);
|
|
|
|
//
|
|
// icx is the number of pixels to operate on with this mask byte.
|
|
// Must make sure that icx is less than cx, the number of pixels
|
|
// remaining in the blt and cx is less than DeltaMsk, the number
|
|
// of bits in the mask still valid. If icx is reduced because of
|
|
// cx of DeltaMsk, then jMsk must be shifted right to compensate.
|
|
//
|
|
|
|
DeltaMsk = cxMsk - ixMsk;
|
|
icxDst = 0;
|
|
|
|
if (icx > cx) {
|
|
icxDst = icx - cx;
|
|
icx = cx;
|
|
}
|
|
|
|
if (icx > DeltaMsk) {
|
|
icxDst = icxDst + (icx - DeltaMsk);
|
|
icx = DeltaMsk;
|
|
}
|
|
|
|
//
|
|
// icxDst is now the number of pixels that can't be stored off
|
|
// the right side of the mask
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³0³1³2³3³4³5³6³7³ if mask 7 and 6 can't be written, this
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ mask gets shifted right 2 to
|
|
//
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³ ³ ³0³1³2³3³4³5³
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ
|
|
//
|
|
//
|
|
//
|
|
// the number of mask bits valid = 8 minus the offset (ixMsk & 0x07)
|
|
// minus the number of pixels that can't be stored because cx
|
|
// runs out or because cxMsk runs out (icxDst)
|
|
//
|
|
|
|
cx -= icx;
|
|
ixMsk += icx;
|
|
|
|
if (jMsk != 0) {
|
|
|
|
jMsk = jMsk >> icxDst;
|
|
|
|
switch (icx)
|
|
{
|
|
case 8:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+7) = *(pjSrc+7);
|
|
}
|
|
jMsk >>= 1;
|
|
case 7:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+6) = *(pjSrc+6);
|
|
}
|
|
jMsk >>= 1;
|
|
case 6:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+5) = *(pjSrc+5);
|
|
}
|
|
jMsk >>= 1;
|
|
case 5:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+4) = *(pjSrc+4);
|
|
}
|
|
jMsk >>= 1;
|
|
case 4:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+3) = *(pjSrc+3);
|
|
}
|
|
jMsk >>= 1;
|
|
case 3:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+2) = *(pjSrc+2);
|
|
}
|
|
jMsk >>= 1;
|
|
case 2:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+1) = *(pjSrc+1);
|
|
}
|
|
jMsk >>= 1;
|
|
case 1:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*pjDst = *pjSrc;
|
|
}
|
|
}
|
|
}
|
|
|
|
pjSrc += icx;
|
|
pjDst += icx;
|
|
|
|
if (ixMsk == cxMsk)
|
|
{
|
|
ixMsk = 0;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Increment address to the next scan line.
|
|
//
|
|
|
|
pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
|
|
pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
|
|
|
|
|
|
//
|
|
// Increment Mask address to the next scan line or
|
|
// back to ther start if iy exceeds cy
|
|
//
|
|
|
|
if (pBltInfo->yDir > 0) {
|
|
|
|
iyMsk++;
|
|
|
|
pjMsk += pMaskInfo->lDeltaMskDir;
|
|
|
|
if ((LONG)iyMsk >= pMaskInfo->cyMsk)
|
|
{
|
|
iyMsk = 0;
|
|
pjMsk = pMaskInfo->pjMskBase;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (iyMsk == 0)
|
|
{
|
|
iyMsk = pMaskInfo->cyMsk - 1;
|
|
pjMsk = pMaskInfo->pjMskBase +
|
|
(pMaskInfo->lDeltaMskDir * (pMaskInfo->cyMsk - 1));
|
|
}
|
|
else
|
|
{
|
|
iyMsk--;
|
|
pjMsk += pMaskInfo->lDeltaMskDir;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkSrcCopyMsk16
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Routines to store src to dst based on 1 bit per pixel mask.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBltInfo - pointer to BLTINFO structure (src and dst info)
|
|
* pMaskInfo - pointer to MASKINFO structure (pjMsk,ixMsk etc)
|
|
* Bytes - Number of Bytes per pixel
|
|
* Buffer - Pointer to a temporary buffer that may be used
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
VOID
|
|
BltLnkSrcCopyMsk16 (
|
|
PBLTINFO pBltInfo,
|
|
PBLTLNK_MASKINFO pMaskInfo,
|
|
PULONG Buffer0,
|
|
PULONG Buffer1
|
|
)
|
|
{
|
|
|
|
ULONG jMsk = 0;
|
|
LONG ixMsk;
|
|
LONG cxMsk = pMaskInfo->cxMsk;
|
|
LONG iyMsk = pMaskInfo->iyMsk;
|
|
LONG icx;
|
|
LONG cx;
|
|
ULONG cy = pBltInfo->cy;
|
|
PUSHORT pusSrcTmp = (PUSHORT)pBltInfo->pjSrc;
|
|
PUSHORT pusDstTmp = (PUSHORT)pBltInfo->pjDst;
|
|
PUSHORT pusSrc;
|
|
PUSHORT pusDst;
|
|
PBYTE pjMsk = pMaskInfo->pjMsk;
|
|
BYTE Negate = pMaskInfo->NegateMsk;
|
|
ULONG icxDst;
|
|
LONG DeltaMsk;
|
|
|
|
|
|
|
|
|
|
DONTUSE(Buffer0);
|
|
DONTUSE(Buffer1);
|
|
|
|
while (cy--)
|
|
{
|
|
//
|
|
// for each scan line, first do the writes necessary to
|
|
// align the mask (ixMsk) to zero, then operate on the
|
|
// mask 1 byte at a time (8 pixels) or cxMsk, whichever
|
|
// is less
|
|
//
|
|
|
|
//
|
|
// init loop params
|
|
//
|
|
|
|
cx = (LONG)pBltInfo->cx;
|
|
ixMsk = pMaskInfo->ixMsk;
|
|
pusSrc = pusSrcTmp + pBltInfo->xSrcStart;
|
|
pusDst = pusDstTmp + pBltInfo->xDstStart;
|
|
|
|
//
|
|
// finish the aligned scan line 8 mask bits at a time
|
|
//
|
|
|
|
while (cx > 0)
|
|
{
|
|
|
|
jMsk = (ULONG)(pjMsk[ixMsk>>3] ^ Negate);
|
|
|
|
//
|
|
// icx is the number of pixels left in the mask byte
|
|
//
|
|
|
|
icx = 8 - (ixMsk & 0x07);
|
|
|
|
//
|
|
// icx is the number of pixels to operate on with this mask byte.
|
|
// Must make sure that icx is less than cx, the number of pixels
|
|
// remaining in the blt and cx is less than DeltaMsk, the number
|
|
// of bits in the mask still valid. If icx is reduced because of
|
|
// cx of DeltaMsk, then jMsk must be shifted right to compensate.
|
|
//
|
|
|
|
DeltaMsk = cxMsk - ixMsk;
|
|
icxDst = 0;
|
|
|
|
if (icx > cx) {
|
|
icxDst = icx - cx;
|
|
icx = cx;
|
|
}
|
|
|
|
if (icx > DeltaMsk) {
|
|
icxDst = icxDst + (icx - DeltaMsk);
|
|
icx = DeltaMsk;
|
|
}
|
|
|
|
//
|
|
// icxDst is now the number of pixels that can't be stored off
|
|
// the right side of the mask
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³0³1³2³3³4³5³6³7³ if mask 7 and 6 can't be written, this
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ mask gets shifted right 2 to
|
|
//
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³ ³ ³0³1³2³3³4³5³
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ
|
|
//
|
|
//
|
|
//
|
|
// the number of mask bits valid = 8 minus the offset (MskAln)
|
|
// minus the number of pixels that can't be stored because cx
|
|
// runs out or because cxMsk runs out (icxDst)
|
|
//
|
|
|
|
cx -= icx;
|
|
ixMsk += icx;
|
|
|
|
|
|
if (jMsk != 0) {
|
|
|
|
jMsk = jMsk >> icxDst;
|
|
|
|
switch (icx)
|
|
{
|
|
case 8:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pusDst+7) = *(pusSrc+7);
|
|
}
|
|
jMsk >>= 1;
|
|
case 7:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pusDst+6) = *(pusSrc+6);
|
|
}
|
|
jMsk >>= 1;
|
|
case 6:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pusDst+5) = *(pusSrc+5);
|
|
}
|
|
jMsk >>= 1;
|
|
case 5:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pusDst+4) = *(pusSrc+4);
|
|
}
|
|
jMsk >>= 1;
|
|
case 4:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pusDst+3) = *(pusSrc+3);
|
|
}
|
|
jMsk >>= 1;
|
|
case 3:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pusDst+2) = *(pusSrc+2);
|
|
}
|
|
jMsk >>= 1;
|
|
case 2:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pusDst+1) = *(pusSrc+1);
|
|
}
|
|
jMsk >>= 1;
|
|
case 1:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*pusDst = *pusSrc;
|
|
}
|
|
}
|
|
}
|
|
|
|
pusSrc += icx;
|
|
pusDst += icx;
|
|
|
|
if (ixMsk == cxMsk)
|
|
{
|
|
ixMsk = 0;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Increment address to the next scan line. Note: lDelta
|
|
// is in bytes
|
|
//
|
|
|
|
pusDstTmp = (PUSHORT)((PBYTE)pusDstTmp + pBltInfo->lDeltaDst);
|
|
pusSrcTmp = (PUSHORT)((PBYTE)pusSrcTmp + pBltInfo->lDeltaSrc);
|
|
|
|
//
|
|
// Increment Mask address to the next scan line or
|
|
// back to ther start if iy exceeds cy
|
|
//
|
|
|
|
if (pBltInfo->yDir > 0) {
|
|
|
|
iyMsk++;
|
|
|
|
pjMsk += pMaskInfo->lDeltaMskDir;
|
|
|
|
if ((LONG)iyMsk >= pMaskInfo->cyMsk)
|
|
{
|
|
iyMsk = 0;
|
|
pjMsk = pMaskInfo->pjMskBase;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (iyMsk == 0)
|
|
{
|
|
iyMsk = pMaskInfo->cyMsk - 1;
|
|
pjMsk = pMaskInfo->pjMskBase +
|
|
(pMaskInfo->lDeltaMskDir * (pMaskInfo->cyMsk - 1));
|
|
}
|
|
else
|
|
{
|
|
iyMsk--;
|
|
pjMsk += pMaskInfo->lDeltaMskDir;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkSrcCopyMsk24
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Routines to store src to dst based on 1 bit per pixel mask.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBltInfo - pointer to BLTINFO structure (src and dst info)
|
|
* pMaskInfo - pointer to MASKINFO structure (pjMsk,ixMsk etc)
|
|
* Bytes - Number of Bytes per pixel
|
|
* Buffer - Pointer to a temporary buffer that may be used
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
VOID
|
|
BltLnkSrcCopyMsk24 (
|
|
PBLTINFO pBltInfo,
|
|
PBLTLNK_MASKINFO pMaskInfo,
|
|
PULONG Buffer0,
|
|
PULONG Buffer1
|
|
)
|
|
{
|
|
|
|
ULONG jMsk = 0;
|
|
LONG ixMsk;
|
|
LONG cxMsk = pMaskInfo->cxMsk;
|
|
LONG iyMsk = pMaskInfo->iyMsk;
|
|
LONG icx;
|
|
LONG cx;
|
|
ULONG cy = pBltInfo->cy;
|
|
PBYTE pjSrcTmp = pBltInfo->pjSrc;
|
|
PBYTE pjDstTmp = pBltInfo->pjDst;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
PBYTE pjMsk = pMaskInfo->pjMsk;
|
|
BYTE Negate = pMaskInfo->NegateMsk;
|
|
ULONG icxDst;
|
|
LONG DeltaMsk;
|
|
|
|
|
|
|
|
|
|
DONTUSE(Buffer0);
|
|
DONTUSE(Buffer1);
|
|
|
|
while (cy--)
|
|
{
|
|
|
|
//
|
|
// for each scan line, first do the writes necessary to
|
|
// align the mask (ixMsk) to zero, then operate on the
|
|
// mask 1 byte at a time (8 pixels) or cxMsk, whichever
|
|
// is less
|
|
//
|
|
|
|
//
|
|
// init loop params
|
|
//
|
|
|
|
cx = (LONG)pBltInfo->cx;
|
|
ixMsk = pMaskInfo->ixMsk;
|
|
pjSrc = pjSrcTmp + 3 * pBltInfo->xSrcStart;
|
|
pjDst = pjDstTmp + 3 * pBltInfo->xDstStart;
|
|
|
|
//
|
|
// finish the aligned scan line 8 mask bits at a time
|
|
//
|
|
|
|
while (cx > 0)
|
|
{
|
|
|
|
|
|
jMsk = (ULONG)(pjMsk[ixMsk>>3] ^ Negate);
|
|
|
|
//
|
|
// icx is the number of pixels left in the mask byte
|
|
//
|
|
|
|
icx = 8 - (ixMsk & 0x07);
|
|
|
|
//
|
|
// icx is the number of pixels to operate on with this mask byte.
|
|
// Must make sure that icx is less than cx, the number of pixels
|
|
// remaining in the blt and cx is less than DeltaMsk, the number
|
|
// of bits in the mask still valid. If icx is reduced because of
|
|
// cx of DeltaMsk, then jMsk must be shifted right to compensate.
|
|
//
|
|
|
|
DeltaMsk = cxMsk - ixMsk;
|
|
icxDst = 0;
|
|
|
|
if (icx > cx) {
|
|
icxDst = icx - cx;
|
|
icx = cx;
|
|
}
|
|
|
|
if (icx > DeltaMsk) {
|
|
icxDst = icxDst + (icx - DeltaMsk);
|
|
icx = DeltaMsk;
|
|
}
|
|
|
|
//
|
|
// icxDst is now the number of pixels that can't be stored off
|
|
// the right side of the mask
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³0³1³2³3³4³5³6³7³ if mask 7 and 6 can't be written, this
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ mask gets shifted right 2 to
|
|
//
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³ ³ ³0³1³2³3³4³5³
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ
|
|
//
|
|
//
|
|
//
|
|
// the number of mask bits valid = 8 minus the offset (MskAln)
|
|
// minus the number of pixels that can't be stored because cx
|
|
// runs out or because cxMsk runs out (icxDst)
|
|
//
|
|
|
|
cx -= icx;
|
|
ixMsk += icx;
|
|
|
|
if (jMsk != 0) {
|
|
|
|
jMsk = jMsk >> icxDst;
|
|
|
|
switch (icx)
|
|
{
|
|
case 8:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+23) = *(pjSrc+23);
|
|
*(pjDst+22) = *(pjSrc+22);
|
|
*(pjDst+21) = *(pjSrc+21);
|
|
}
|
|
jMsk >>= 1;
|
|
case 7:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+20) = *(pjSrc+20);
|
|
*(pjDst+19) = *(pjSrc+19);
|
|
*(pjDst+18) = *(pjSrc+18);
|
|
}
|
|
jMsk >>= 1;
|
|
case 6:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+17) = *(pjSrc+17);
|
|
*(pjDst+16) = *(pjSrc+16);
|
|
*(pjDst+15) = *(pjSrc+15);
|
|
}
|
|
jMsk >>= 1;
|
|
case 5:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+14) = *(pjSrc+14);
|
|
*(pjDst+13) = *(pjSrc+13);
|
|
*(pjDst+12) = *(pjSrc+12);
|
|
}
|
|
jMsk >>= 1;
|
|
case 4:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+11) = *(pjSrc+11);
|
|
*(pjDst+10) = *(pjSrc+10);
|
|
*(pjDst+9) = *(pjSrc+9);
|
|
}
|
|
jMsk >>= 1;
|
|
case 3:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+8) = *(pjSrc+8);
|
|
*(pjDst+7) = *(pjSrc+7);
|
|
*(pjDst+6) = *(pjSrc+6);
|
|
}
|
|
jMsk >>= 1;
|
|
case 2:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+5) = *(pjSrc+5);
|
|
*(pjDst+4) = *(pjSrc+4);
|
|
*(pjDst+3) = *(pjSrc+3);
|
|
}
|
|
jMsk >>= 1;
|
|
case 1:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pjDst+2) = *(pjSrc+2);
|
|
*(pjDst+1) = *(pjSrc+1);
|
|
*pjDst = *pjSrc;
|
|
}
|
|
}
|
|
}
|
|
|
|
pjSrc += 3*icx;
|
|
pjDst += 3*icx;
|
|
|
|
if (ixMsk == cxMsk)
|
|
{
|
|
ixMsk = 0;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// increment to next scan line
|
|
//
|
|
|
|
pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
|
|
pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
|
|
|
|
//
|
|
// Increment Mask address to the next scan line or
|
|
// back to ther start if iy exceeds cy
|
|
//
|
|
|
|
if (pBltInfo->yDir > 0) {
|
|
|
|
iyMsk++;
|
|
|
|
pjMsk += pMaskInfo->lDeltaMskDir;
|
|
|
|
if ((LONG)iyMsk >= pMaskInfo->cyMsk)
|
|
{
|
|
iyMsk = 0;
|
|
pjMsk = pMaskInfo->pjMskBase;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (iyMsk == 0)
|
|
{
|
|
iyMsk = pMaskInfo->cyMsk - 1;
|
|
pjMsk = pMaskInfo->pjMskBase +
|
|
(pMaskInfo->lDeltaMskDir * (pMaskInfo->cyMsk - 1));
|
|
}
|
|
else
|
|
{
|
|
iyMsk--;
|
|
pjMsk += pMaskInfo->lDeltaMskDir;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkSrcCopyMsk32
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Routines to store src to dst based on 1 bit per pixel mask.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBltInfo - pointer to BLTINFO structure (src and dst info)
|
|
* pMaskInfo - pointer to MASKINFO structure (pjMsk,ixMsk etc)
|
|
* Bytes - Number of Bytes per pixel
|
|
* Buffer - Pointer to a temporary buffer that may be used
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkSrcCopyMsk32 (
|
|
PBLTINFO pBltInfo,
|
|
PBLTLNK_MASKINFO pMaskInfo,
|
|
PULONG Buffer0,
|
|
PULONG Buffer1
|
|
)
|
|
{
|
|
|
|
ULONG jMsk = 0;
|
|
LONG ixMsk;
|
|
LONG cxMsk = pMaskInfo->cxMsk;
|
|
LONG iyMsk = pMaskInfo->iyMsk;
|
|
LONG icx;
|
|
LONG cx;
|
|
ULONG cy = pBltInfo->cy;
|
|
PULONG pulSrcTmp = (PULONG)pBltInfo->pjSrc;
|
|
PULONG pulDstTmp = (PULONG)pBltInfo->pjDst;
|
|
PULONG pulSrc;
|
|
PULONG pulDst;
|
|
PBYTE pjMsk = pMaskInfo->pjMsk;
|
|
BYTE Negate = pMaskInfo->NegateMsk;
|
|
ULONG icxDst;
|
|
LONG DeltaMsk;
|
|
|
|
|
|
|
|
|
|
DONTUSE(Buffer0);
|
|
DONTUSE(Buffer1);
|
|
|
|
while (cy--)
|
|
{
|
|
|
|
//
|
|
// for each scan line, first do the writes necessary to
|
|
// align the mask (ixMsk) to zero, then operate on the
|
|
// mask 1 byte at a time (8 pixels) or cxMsk, whichever
|
|
// is less
|
|
//
|
|
|
|
//
|
|
// init loop params
|
|
//
|
|
|
|
cx = (LONG)pBltInfo->cx;
|
|
ixMsk = pMaskInfo->ixMsk;
|
|
pulSrc = pulSrcTmp + pBltInfo->xSrcStart;
|
|
pulDst = pulDstTmp + pBltInfo->xDstStart;
|
|
|
|
//
|
|
// finish the aligned scan line 8 mask bits at a time
|
|
//
|
|
|
|
while (cx > 0)
|
|
{
|
|
|
|
jMsk = (ULONG)(pjMsk[ixMsk>>3] ^ Negate);
|
|
|
|
//
|
|
// icx is the number of pixels left in the mask byte
|
|
//
|
|
|
|
icx = 8 - (ixMsk & 0x07);
|
|
|
|
//
|
|
// icx is the number of pixels to operate on with this mask byte.
|
|
// Must make sure that icx is less than cx, the number of pixels
|
|
// remaining in the blt and cx is less than DeltaMsk, the number
|
|
// of bits in the mask still valid. If icx is reduced because of
|
|
// cx of DeltaMsk, then jMsk must be shifted right to compensate.
|
|
//
|
|
|
|
DeltaMsk = cxMsk - ixMsk;
|
|
icxDst = 0;
|
|
|
|
if (icx > cx) {
|
|
icxDst = icx - cx;
|
|
icx = cx;
|
|
}
|
|
|
|
if (icx > DeltaMsk) {
|
|
icxDst = icxDst + (icx - DeltaMsk);
|
|
icx = DeltaMsk;
|
|
}
|
|
|
|
//
|
|
// icxDst is now the number of pixels that can't be stored off
|
|
// the right side of the mask
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³0³1³2³3³4³5³6³7³ if mask 7 and 6 can't be written, this
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ mask gets shifted right 2 to
|
|
//
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³ ³ ³0³1³2³3³4³5³
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ
|
|
//
|
|
// the number of mask bits valid = 8 minus the offset (MskAln)
|
|
// minus the number of pixels that can't be stored because cx
|
|
// runs out or because cxMsk runs out (icxDst)
|
|
//
|
|
|
|
cx -= icx;
|
|
ixMsk += icx;
|
|
|
|
if (jMsk != 0) {
|
|
|
|
jMsk = jMsk >> icxDst;
|
|
|
|
switch (icx)
|
|
{
|
|
case 8:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pulDst+7) = *(pulSrc+7);
|
|
}
|
|
jMsk >>= 1;
|
|
case 7:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pulDst+6) = *(pulSrc+6);
|
|
}
|
|
jMsk >>= 1;
|
|
case 6:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pulDst+5) = *(pulSrc+5);
|
|
}
|
|
jMsk >>= 1;
|
|
case 5:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pulDst+4) = *(pulSrc+4);
|
|
}
|
|
jMsk >>= 1;
|
|
case 4:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pulDst+3) = *(pulSrc+3);
|
|
}
|
|
jMsk >>= 1;
|
|
case 3:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pulDst+2) = *(pulSrc+2);
|
|
}
|
|
jMsk >>= 1;
|
|
case 2:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*(pulDst+1) = *(pulSrc+1);
|
|
}
|
|
jMsk >>= 1;
|
|
case 1:
|
|
if (jMsk & 0x01)
|
|
{
|
|
*pulDst = *pulSrc;
|
|
}
|
|
}
|
|
}
|
|
|
|
pulSrc += icx;
|
|
pulDst += icx;
|
|
|
|
if (ixMsk == cxMsk)
|
|
{
|
|
ixMsk = 0;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Increment to next scan line, note: lDelta is
|
|
// in bytes.
|
|
//
|
|
|
|
pulDstTmp = (PULONG)((PBYTE)pulDstTmp + pBltInfo->lDeltaDst);
|
|
pulSrcTmp = (PULONG)((PBYTE)pulSrcTmp + pBltInfo->lDeltaSrc);
|
|
|
|
//
|
|
// Increment Mask address to the next scan line or
|
|
// back to ther start if iy exceeds cy
|
|
//
|
|
|
|
if (pBltInfo->yDir > 0) {
|
|
|
|
iyMsk++;
|
|
|
|
pjMsk += pMaskInfo->lDeltaMskDir;
|
|
|
|
if ((LONG)iyMsk >= pMaskInfo->cyMsk)
|
|
{
|
|
iyMsk = 0;
|
|
pjMsk = pMaskInfo->pjMskBase;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (iyMsk == 0)
|
|
{
|
|
iyMsk = pMaskInfo->cyMsk - 1;
|
|
pjMsk = pMaskInfo->pjMskBase +
|
|
(pMaskInfo->lDeltaMskDir * (pMaskInfo->cyMsk - 1));
|
|
}
|
|
else
|
|
{
|
|
iyMsk--;
|
|
pjMsk += pMaskInfo->lDeltaMskDir;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BltLnkReadPat
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Read pattern into a scan line buffer for 8,16,24,32 Bpp
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pjDst - destination buffer
|
|
* pjPat - pattern starting address
|
|
* cxPat - Width of pattern
|
|
* ixPat - initial pattern offset
|
|
* ByteCount - Number of Bytes to transfer
|
|
* BytesPerPixel - Number of Bytes per pixel(1,2,3,4)
|
|
*
|
|
* Return Value:
|
|
*
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkReadPat(
|
|
PBYTE pjDst,
|
|
ULONG ixDst,
|
|
PBYTE pjPat,
|
|
ULONG cxPat,
|
|
ULONG ixPat,
|
|
ULONG PixelCount,
|
|
ULONG BytesPerPixel
|
|
)
|
|
{
|
|
ULONG ixPatTemp = ixPat;
|
|
ULONG ByteCount = PixelCount;
|
|
|
|
DONTUSE(ixDst);
|
|
|
|
//
|
|
// expand byte count by number of bytes per
|
|
// pixel
|
|
//
|
|
|
|
if (BytesPerPixel == 2) {
|
|
ByteCount = ByteCount << 1;
|
|
} else if (BytesPerPixel == 3) {
|
|
ByteCount = ByteCount *3;
|
|
} else if (BytesPerPixel == 4) {
|
|
ByteCount = ByteCount << 2;
|
|
}
|
|
|
|
|
|
while (ByteCount--) {
|
|
|
|
//
|
|
// make sure ixPat stays within the pattern
|
|
//
|
|
|
|
if (ixPatTemp == cxPat) {
|
|
ixPatTemp = 0;
|
|
}
|
|
|
|
*pjDst++ = pjPat[ixPatTemp++];
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkReadPat4
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Build a byte array of specified length from a 4 bit per pixel mask
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pjDst - byte pointer to store pattern
|
|
* pjPat - Starting Pat address
|
|
* cxPat - Pattern width in nibbles
|
|
* ixPat - Starting nibble offset in pattern
|
|
* PixelCount - Number of pixels (nibbles) to transfer
|
|
* BytesPerPixel - Only used in ReadPat(8,16,24,32)
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkReadPat4 (
|
|
PBYTE pjDst,
|
|
ULONG ixDst,
|
|
PBYTE pjPat,
|
|
ULONG cxPat,
|
|
ULONG ixPat,
|
|
ULONG PixelCount,
|
|
ULONG BytesPerPixel
|
|
)
|
|
{
|
|
BYTE jDst;
|
|
LONG iOffset;
|
|
LONG Cnt;
|
|
|
|
DONTUSE(BytesPerPixel);
|
|
//
|
|
// handle case where destination starts on odd nibble
|
|
//
|
|
if ((ixDst & 1) && PixelCount)
|
|
{
|
|
jDst = pjPat[ixPat >> 1];
|
|
if (!(ixPat & 1))
|
|
jDst >>= 4;
|
|
*pjDst++ = jDst & 0x0f;
|
|
ixPat++;
|
|
PixelCount--;
|
|
}
|
|
//
|
|
// test whether it is worthwhile to implement fast version
|
|
// the offset needs to be a multiple of cxPat and even
|
|
//
|
|
iOffset = cxPat;
|
|
if (iOffset & 1)
|
|
iOffset *= 2;
|
|
if ((LONG)PixelCount > iOffset)
|
|
{
|
|
PixelCount -= iOffset;
|
|
iOffset >>= 1;
|
|
Cnt = iOffset;
|
|
}
|
|
else
|
|
{
|
|
Cnt = PixelCount >> 1;
|
|
PixelCount &= 1;
|
|
}
|
|
|
|
//
|
|
// handle packing two nibbles per loop to one destination byte
|
|
//
|
|
while (Cnt--)
|
|
{
|
|
if (ixPat == cxPat)
|
|
ixPat = 0;
|
|
jDst = pjPat[ixPat >> 1];
|
|
if (!(ixPat & 1))
|
|
{
|
|
if (++ixPat == cxPat)
|
|
{
|
|
ixPat = 0;
|
|
jDst = (jDst & 0xf0) | ((pjPat[0] & 0xf0) >> 4);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (++ixPat == cxPat)
|
|
ixPat = 0;
|
|
jDst = (jDst << 4) | ((pjPat[ixPat >> 1] & 0xf0) >> 4);
|
|
}
|
|
*pjDst++ = jDst;
|
|
ixPat++;
|
|
}
|
|
//
|
|
// test for fast mode
|
|
//
|
|
if (PixelCount > 1)
|
|
{
|
|
// loop while copying from the beginning of the pattern to the end
|
|
// we loop multiple times so that the Src and Dst don't overlap.
|
|
// each pass allows us to copy twice as many bytes the next time
|
|
// (a single RtlMoveMemory doesn't work)
|
|
Cnt = PixelCount >> 1;
|
|
while (1)
|
|
{
|
|
LONG i = iOffset;
|
|
if (i > Cnt)
|
|
i = Cnt;
|
|
RtlCopyMemory(pjDst,&pjDst[-iOffset],i);
|
|
pjDst += i;
|
|
if (!(Cnt -= i))
|
|
break;
|
|
iOffset *= 2;
|
|
}
|
|
if (PixelCount & 1)
|
|
*pjDst = pjDst[-iOffset] & 0xf0;
|
|
}
|
|
//
|
|
// handle case where destination ends on odd nibble
|
|
//
|
|
else if (PixelCount & 1)
|
|
{
|
|
if (ixPat == cxPat)
|
|
ixPat = 0;
|
|
if (ixPat & 1)
|
|
*pjDst = pjPat[ixPat >> 1] << 4;
|
|
else
|
|
*pjDst = pjPat[ixPat >> 1] & 0xf0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkReadPat1
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Build a byte array of specified length from a 1 bit per pixel mask
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pjDst - byte pointer to store pattern
|
|
* ixDst - starting bit offset in Dst
|
|
* pjPat - Starting Pat address
|
|
* cxPat - Pattern width in bits
|
|
* ixPat - Starting bit offset in pattern
|
|
* PixelCount - Number of pixels (bits) to transfer
|
|
* BytesPerPixel - Only used in ReadPat(8,16,24,32)
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
VOID
|
|
BltLnkReadPat1 (
|
|
PBYTE pjDst,
|
|
ULONG ixDst,
|
|
PBYTE pjPat,
|
|
ULONG cxPat,
|
|
ULONG ixPat,
|
|
ULONG PixelCount,
|
|
ULONG BytesPerPixel
|
|
)
|
|
{
|
|
ULONG jDst;
|
|
ULONG jPat;
|
|
ULONG DstAln;
|
|
ULONG PatAln;
|
|
ULONG icx;
|
|
|
|
DONTUSE(BytesPerPixel);
|
|
|
|
jDst = 0;
|
|
|
|
DstAln = ixDst & 0x07;
|
|
PatAln = ixPat & 0x07;
|
|
|
|
while (PixelCount>0) {
|
|
|
|
jPat = pjPat[ixPat>>3] & StartMask[PatAln];
|
|
|
|
if (DstAln > PatAln)
|
|
{
|
|
icx = 8 - DstAln;
|
|
|
|
if (icx > PixelCount)
|
|
{
|
|
icx = PixelCount;
|
|
}
|
|
|
|
if (icx > (cxPat - ixPat)) {
|
|
icx = cxPat - ixPat;
|
|
}
|
|
|
|
jPat &= EndMask[PatAln + icx];
|
|
|
|
jPat = jPat >> (DstAln - PatAln);
|
|
|
|
} else {
|
|
|
|
icx = 8 - PatAln;
|
|
|
|
if (icx > PixelCount)
|
|
{
|
|
icx = PixelCount;
|
|
}
|
|
|
|
if (icx > (cxPat - ixPat)) {
|
|
icx = cxPat - ixPat;
|
|
}
|
|
|
|
jPat &= EndMask[PatAln + icx];
|
|
|
|
jPat = jPat << (PatAln - DstAln);
|
|
|
|
}
|
|
|
|
jDst |= jPat;
|
|
ixDst += icx;
|
|
DstAln = ixDst & 0x07;
|
|
ixPat += icx;
|
|
PatAln = ixPat & 0x07;
|
|
PixelCount -= icx;
|
|
|
|
if (ixPat == cxPat) {
|
|
ixPat = 0;
|
|
PatAln = 0;
|
|
}
|
|
|
|
if (!(ixDst & 0x07) || (PixelCount == 0)) {
|
|
*pjDst = (BYTE)jDst;
|
|
pjDst++;
|
|
jDst = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkPatMaskCopy1
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Transparent Color Expansion to 1bpp
|
|
*
|
|
* Src is a 1 Bpp mask, where src is 0, copy 1 pixel solid color
|
|
* to Dst. Where src is 1, leave Dst unchanged.
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBltInfo - Pointer to BLTINFO structure containing Dst and Src information
|
|
* ulPat - Solid color pattern
|
|
* pBuffer - Scan line buffer if needed
|
|
* Invert - XOR mask used on Src to determine whether to write
|
|
* through "1" pixels or "0" pixels
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkPatMaskCopy1(
|
|
PBLTINFO pBltInfo,
|
|
ULONG ulPat,
|
|
PULONG pBuffer,
|
|
BYTE Invert
|
|
)
|
|
{
|
|
ULONG cx;
|
|
ULONG cy = pBltInfo->cy;
|
|
PBYTE pjSrcTmp = pBltInfo->pjSrc;
|
|
PBYTE pjDstTmp = pBltInfo->pjDst;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
ULONG ixDst;
|
|
ULONG SrcAln;
|
|
ULONG DstAln;
|
|
LONG ByteCount;
|
|
BYTE Pat;
|
|
|
|
//
|
|
// For each scan line, first make sure Src and Dst are aligned.
|
|
// If they are not aligned then copy Src to a temp buffer at
|
|
// Dst alignment.
|
|
//
|
|
// Next, the start and end of the scan line must be masked so that
|
|
// partial byte writes only store the correct bits. This is done by
|
|
// ORing "1"s to the start and end of the scan line where appropriate.
|
|
//
|
|
// Finally, the logic operation is performed:
|
|
//
|
|
// Dst = (Mask & Dst) | (~Mask & Pat);
|
|
//
|
|
// Pat is ulPat[0] replicated to 8 bits
|
|
//
|
|
|
|
Pat = (BYTE) (ulPat & 0x01);
|
|
Pat |= Pat << 1;
|
|
Pat |= Pat << 2;
|
|
Pat |= Pat << 4;
|
|
|
|
SrcAln = pBltInfo->xSrcStart & 0x07;
|
|
DstAln = pBltInfo->xDstStart & 0x07;
|
|
ixDst = pBltInfo->xDstStart;
|
|
cx = pBltInfo->cx;
|
|
|
|
while(cy--) {
|
|
|
|
pjSrc = pjSrcTmp + (pBltInfo->xSrcStart >> 3);
|
|
pjDst = pjDstTmp + (pBltInfo->xSrcStart >> 3);
|
|
|
|
BltLnkReadPat1((PBYTE)pBuffer,DstAln,pjSrc,cx,SrcAln,cx,0);
|
|
pjSrc = (PBYTE)pBuffer;
|
|
|
|
|
|
if (Invert == 0)
|
|
{
|
|
//
|
|
// mask start and end byte, if invert = 0x00 then start and end cases
|
|
// are masked by ORing with "1"s
|
|
//
|
|
|
|
pjSrc[0] |= (BYTE) (0xff >> (8 - DstAln));
|
|
pjSrc[(ixDst + cx) >> 3] |= (BYTE) (0xff << ((ixDst + cx) & 0x07));
|
|
|
|
|
|
//
|
|
// Number of whole bytes to transfer
|
|
//
|
|
|
|
ByteCount = (DstAln + cx + 7) >> 3;
|
|
|
|
while (ByteCount--)
|
|
{
|
|
BYTE Mask = *pjSrc;
|
|
|
|
*pjDst = (Mask & *pjDst) | (~Mask & Pat);
|
|
|
|
pjDst++;
|
|
pjSrc++;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// mask start and end byte, if invert = 0xFF then start and end cases
|
|
// are already masked to '0's by ReadPat1
|
|
//
|
|
|
|
//
|
|
// Number of whole bytes to transfer
|
|
//
|
|
|
|
ByteCount = (DstAln + cx + 7) >> 3;
|
|
|
|
while (ByteCount--)
|
|
{
|
|
BYTE Mask = *pjSrc;
|
|
|
|
*pjDst = (~Mask & *pjDst) | (Mask & Pat);
|
|
|
|
pjDst++;
|
|
pjSrc++;
|
|
}
|
|
|
|
}
|
|
|
|
pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
|
|
pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkPatMaskCopy4
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Transparent Color Expansion to 4bpp
|
|
*
|
|
* Src is a 1 Bpp mask, where src is 0, copy 1 pixel solid color
|
|
* to Dst. Where src is 1, leave Dst unchanged.
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBltInfo - Pointer to BLTINFO structure containing Dst and Src information
|
|
* ulPat - Solid color pattern
|
|
* pBuffer - Scan line buffer if needed
|
|
* Invert - XOR mask used on Src to determine whether to write
|
|
* through "1" pixels or "0" pixels
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkPatMaskCopy4(
|
|
PBLTINFO pBltInfo,
|
|
ULONG ulPat,
|
|
PULONG pBuffer,
|
|
BYTE Invert
|
|
)
|
|
{
|
|
ULONG ulSrc;
|
|
ULONG cy = pBltInfo->cy;
|
|
PBYTE pjSrcTmp = pBltInfo->pjSrc;
|
|
PBYTE pjDstTmp = pBltInfo->pjDst;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
ULONG ixSrc;
|
|
ULONG ixDst;
|
|
ULONG jDst = 0;
|
|
ULONG jDstNew = 0;
|
|
UCHAR ucPat0 = (UCHAR)ulPat & 0xF0;
|
|
UCHAR ucPat1 = (UCHAR)ulPat & 0x0F;
|
|
|
|
DONTUSE(pBuffer);
|
|
|
|
//
|
|
// for each scan line perform the transparency mask function
|
|
//
|
|
|
|
while(cy--)
|
|
{
|
|
|
|
PUCHAR pjDstEnd;
|
|
LONG xMask = 8 - (pBltInfo->xSrcStart & 0x0007);
|
|
UCHAR ucMask;
|
|
ixDst = pBltInfo->xDstStart;
|
|
|
|
pjSrc = pjSrcTmp + (pBltInfo->xSrcStart >> 3);
|
|
|
|
ucMask = (*pjSrc++ ^ Invert);
|
|
|
|
ulSrc = (ULONG)ucMask << (16 - xMask);
|
|
|
|
pjDst = pjDstTmp + (pBltInfo->xSrcStart >> 1);
|
|
|
|
pjDstEnd = pjDst + pBltInfo->cx;
|
|
|
|
//
|
|
// write partial nibble if needed
|
|
//
|
|
|
|
if ((ULONG_PTR)pjDst & 0x01)
|
|
{
|
|
if (!(ulSrc & 0x8000))
|
|
{
|
|
*pjDst = (*pjDst & 0xf0) | ucPat1;
|
|
}
|
|
|
|
pjDst++;
|
|
ulSrc <<=1;
|
|
xMask--;
|
|
}
|
|
|
|
//
|
|
// aligned 2-byte stores
|
|
//
|
|
|
|
while (pjDst < (pjDstEnd - 1))
|
|
{
|
|
|
|
//
|
|
// Need a new mask byte?
|
|
//
|
|
|
|
if (xMask < 2)
|
|
{
|
|
ucMask = (*pjSrc++ ^ Invert);
|
|
|
|
ulSrc |= ucMask << (8 - xMask);
|
|
|
|
xMask += 8;
|
|
}
|
|
|
|
//
|
|
// 2-nibble aligned store
|
|
//
|
|
|
|
switch (ulSrc & 0xc000)
|
|
{
|
|
case 0x0:
|
|
|
|
//
|
|
// write both
|
|
//
|
|
|
|
*pjDst = (UCHAR)ulPat;
|
|
break;
|
|
|
|
case 0x8000:
|
|
|
|
//
|
|
// don't write 0, write 1
|
|
//
|
|
|
|
*pjDst = (*pjDst & 0xf0) | ucPat1;
|
|
break;
|
|
|
|
case 0x4000:
|
|
|
|
//
|
|
// write 0, don't write 1
|
|
//
|
|
|
|
*pjDst = (*pjDst & 0x0f) | ucPat0;
|
|
break;
|
|
|
|
//
|
|
// case c000 does not draw anything
|
|
//
|
|
}
|
|
|
|
pjDst++;
|
|
ulSrc <<=2;
|
|
xMask -= 2;
|
|
}
|
|
|
|
//
|
|
// check if a partial jDst needs to be stored
|
|
//
|
|
|
|
if ((pjDst != pjDstEnd) && (!(ulSrc & 0x8000)))
|
|
{
|
|
*pjDst = (*pjDst & 0x0f) | ucPat0;
|
|
}
|
|
|
|
pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
|
|
pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkPatMaskCopy8
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Transparent Color Expansion to 8bpp
|
|
*
|
|
* Src is a 1 Bpp mask, where src is 0, copy 1 pixel solid color
|
|
* to Dst. Where src is 1, leave Dst unchanged.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBltInfo - Pointer to BLTINFO structure containing Dst and Src information
|
|
* ulPat - Solid color pattern
|
|
* pBuffer - Scan line buffer if needed
|
|
* Invert - XOR mask used on Src to determine whether to write
|
|
* through "1" pixels or "0" pixels
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkPatMaskCopy8 (
|
|
PBLTINFO pBltInfo,
|
|
ULONG ulPat,
|
|
PULONG pBuffer,
|
|
BYTE Invert
|
|
)
|
|
{
|
|
|
|
ULONG jMsk = 0;
|
|
LONG ixSrc;
|
|
LONG icx;
|
|
LONG cx;
|
|
ULONG cy = pBltInfo->cy;
|
|
PBYTE pjSrcTmp = pBltInfo->pjSrc;
|
|
PBYTE pjDstTmp = pBltInfo->pjDst;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
ULONG icxDst;
|
|
|
|
|
|
|
|
DONTUSE(pBuffer);
|
|
|
|
while (cy--)
|
|
{
|
|
//
|
|
// for each scan line, first do the writes necessary to
|
|
// align ixSrc to zero, then operate on the
|
|
// Src 1 byte at a time (8 pixels) or cxSrc, whichever
|
|
// is less
|
|
//
|
|
|
|
//
|
|
// init loop params
|
|
//
|
|
|
|
cx = (LONG)pBltInfo->cx;
|
|
ixSrc = pBltInfo->xSrcStart;
|
|
pjSrc = pjSrcTmp;
|
|
pjDst = pjDstTmp + pBltInfo->xDstStart;
|
|
|
|
//
|
|
// finish the aligned scan line 8 mask bits at a time
|
|
//
|
|
|
|
while (cx > 0)
|
|
{
|
|
|
|
jMsk = (ULONG)pjSrc[ixSrc>>3] ^ Invert;
|
|
|
|
//
|
|
// icx is the number of pixels left in the mask byte
|
|
//
|
|
|
|
icx = 8 - (ixSrc & 0x07);
|
|
|
|
//
|
|
// icx is the number of pixels to operate on with this mask byte.
|
|
// Must make sure that icx is less than cx, the number of pixels
|
|
// remaining in the blt. If icx is reduced because of
|
|
// cx, then jMsk must be shifted right to compensate.
|
|
//
|
|
|
|
icxDst = 0;
|
|
|
|
if (icx > cx) {
|
|
icxDst = icx - cx;
|
|
icx = cx;
|
|
}
|
|
|
|
//
|
|
// icxDst is now the number of pixels that can't be stored off
|
|
// the right side of the mask
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³0³1³2³3³4³5³6³7³ if mask 7 and 6 can't be written, this
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ mask gets shifted right 2 to
|
|
//
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³ ³ ³0³1³2³3³4³5³
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ
|
|
//
|
|
// the number of mask bits valid = 8 minus the offset (ixSrc & 0x07)
|
|
// minus the number of pixels that can't be stored because cx
|
|
// runs out or because cxMsk runs out (icxDst)
|
|
//
|
|
|
|
cx -= icx;
|
|
ixSrc += icx;
|
|
|
|
if (jMsk != 0xFF) {
|
|
|
|
jMsk = jMsk >> icxDst;
|
|
|
|
switch (icx)
|
|
{
|
|
case 8:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+7) = (BYTE)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 7:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+6) = (BYTE)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 6:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+5) = (BYTE)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 5:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+4) = (BYTE)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 4:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+3) = (BYTE)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 3:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+2) = (BYTE)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 2:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+1) = (BYTE)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 1:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*pjDst = (BYTE)ulPat;
|
|
}
|
|
}
|
|
}
|
|
|
|
pjDst += icx;
|
|
|
|
}
|
|
|
|
//
|
|
// increment 8 bpp Dst and 1 bpp Src to next scan line
|
|
//
|
|
|
|
pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
|
|
pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkPatMaskCopy16
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Transparent Color Expansion to 16bpp
|
|
*
|
|
* Src is a 1 Bpp mask, where src is 0, copy 1 pixel solid color
|
|
* to Dst. Where src is 1, leave Dst unchanged.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBltInfo - Pointer to BLTINFO structure containing Dst and Src information
|
|
* ulPat - Solid color pattern
|
|
* pBuffer - Scan line buffer if needed
|
|
* Invert - XOR mask used on Src to determine whether to write
|
|
* through "1" pixels or "0" pixels
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkPatMaskCopy16 (
|
|
PBLTINFO pBltInfo,
|
|
ULONG ulPat,
|
|
PULONG pBuffer,
|
|
BYTE Invert
|
|
)
|
|
{
|
|
|
|
ULONG jMsk = 0;
|
|
LONG ixSrc;
|
|
LONG icx;
|
|
LONG cx;
|
|
ULONG cy = pBltInfo->cy;
|
|
PBYTE pjSrcTmp = pBltInfo->pjSrc;
|
|
PUSHORT pusDstTmp = (PUSHORT)pBltInfo->pjDst;
|
|
PBYTE pjSrc;
|
|
PUSHORT pusDst;
|
|
ULONG icxDst;
|
|
|
|
|
|
|
|
DONTUSE(pBuffer);
|
|
|
|
while (cy--)
|
|
{
|
|
//
|
|
// for each scan line, first do the writes necessary to
|
|
// align ixSrc to zero, then operate on the
|
|
// Src 1 byte at a time (8 pixels) or cxSrc, whichever
|
|
// is less
|
|
//
|
|
|
|
//
|
|
// init loop params
|
|
//
|
|
|
|
cx = (LONG)pBltInfo->cx;
|
|
ixSrc = pBltInfo->xSrcStart;
|
|
pjSrc = pjSrcTmp;
|
|
pusDst = pusDstTmp + pBltInfo->xDstStart;
|
|
|
|
//
|
|
// load first mask byte if the mask is not aligned to 0
|
|
//
|
|
|
|
//
|
|
// finish the aligned scan line 8 mask bits at a time
|
|
//
|
|
|
|
while (cx > 0)
|
|
{
|
|
|
|
jMsk = (ULONG)pjSrc[ixSrc>>3] ^ Invert;
|
|
|
|
//
|
|
// icx is the number of pixels left in the mask byte
|
|
//
|
|
|
|
icx = 8 - (ixSrc & 0x07);
|
|
|
|
//
|
|
// icx is the number of pixels to operate on with this mask byte.
|
|
// Must make sure that icx is less than cx, the number of pixels
|
|
// remaining in the blt. If icx is reduced because of
|
|
// cx, then jMsk must be shifted right to compensate.
|
|
//
|
|
|
|
icxDst = 0;
|
|
|
|
if (icx > cx) {
|
|
icxDst = icx - cx;
|
|
icx = cx;
|
|
}
|
|
|
|
//
|
|
// icxDst is now the number of pixels that can't be stored off
|
|
// the right side of the mask
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³0³1³2³3³4³5³6³7³ if mask 7 and 6 can't be written, this
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ mask gets shifted right 2 to
|
|
//
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³ ³ ³0³1³2³3³4³5³
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ
|
|
//
|
|
//
|
|
//
|
|
// the number of mask bits valid = 8 minus the offset (ixSrc & 0x07)
|
|
// minus the number of pixels that can't be stored because cx
|
|
// runs out or because cxMsk runs out (icxDst)
|
|
//
|
|
|
|
cx -= icx;
|
|
ixSrc += icx;
|
|
|
|
if (jMsk != 0xFF) {
|
|
|
|
jMsk = jMsk >> icxDst;
|
|
|
|
switch (icx)
|
|
{
|
|
case 8:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pusDst+7) = (USHORT)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 7:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pusDst+6) = (USHORT)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 6:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pusDst+5) = (USHORT)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 5:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pusDst+4) = (USHORT)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 4:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pusDst+3) = (USHORT)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 3:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pusDst+2) = (USHORT)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 2:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pusDst+1) = (USHORT)ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 1:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*pusDst = (USHORT)ulPat;
|
|
}
|
|
}
|
|
}
|
|
|
|
pusDst += icx;
|
|
|
|
}
|
|
|
|
//
|
|
// increment 16 bpp Dst and 1 bpp Src to next scan line
|
|
//
|
|
|
|
pusDstTmp = (PUSHORT)((PBYTE)pusDstTmp + pBltInfo->lDeltaDst);
|
|
pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkPatMaskCopy24
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Transparent Color Expansion to 24bpp
|
|
*
|
|
* Src is a 1 Bpp mask, where src is 0, copy 1 pixel solid color
|
|
* to Dst. Where src is 1, leave Dst unchanged.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBltInfo - Pointer to BLTINFO structure containing Dst and Src information
|
|
* ulPat - Solid color pattern
|
|
* pBuffer - Scan line buffer if needed
|
|
* Invert - XOR mask used on Src to determine whether to write
|
|
* through "1" pixels or "0" pixels
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkPatMaskCopy24 (
|
|
PBLTINFO pBltInfo,
|
|
ULONG ulPat,
|
|
PULONG pBuffer,
|
|
BYTE Invert
|
|
)
|
|
{
|
|
|
|
ULONG jMsk = 0;
|
|
LONG ixSrc;
|
|
LONG icx;
|
|
LONG cx;
|
|
ULONG cy = pBltInfo->cy;
|
|
PBYTE pjSrcTmp = pBltInfo->pjSrc;
|
|
PBYTE pjDstTmp = pBltInfo->pjDst;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
ULONG icxDst;
|
|
BYTE jPat0 = (BYTE)ulPat;
|
|
BYTE jPat1 = (BYTE)(ulPat >> 8);
|
|
BYTE jPat2 = (BYTE)(ulPat >> 16);
|
|
|
|
DONTUSE(pBuffer);
|
|
|
|
while (cy--)
|
|
{
|
|
//
|
|
// for each scan line, first do the writes necessary to
|
|
// align ixSrc to zero, then operate on the
|
|
// Src 1 byte at a time (8 pixels) or cxSrc, whichever
|
|
// is less
|
|
//
|
|
|
|
//
|
|
// init loop params
|
|
//
|
|
|
|
cx = (LONG)pBltInfo->cx;
|
|
ixSrc = pBltInfo->xSrcStart;
|
|
pjSrc = pjSrcTmp;
|
|
pjDst = pjDstTmp + 3 * pBltInfo->xDstStart;
|
|
|
|
//
|
|
// finish the aligned scan line 8 mask bits at a time
|
|
//
|
|
|
|
while (cx > 0)
|
|
{
|
|
|
|
jMsk = (ULONG)pjSrc[ixSrc>>3] ^ Invert;
|
|
|
|
//
|
|
// icx is the number of pixels left in the mask byte
|
|
//
|
|
|
|
icx = 8 - (ixSrc & 0x07);
|
|
|
|
//
|
|
// icx is the number of pixels to operate on with this mask byte.
|
|
// Must make sure that icx is less than cx, the number of pixels
|
|
// remaining in the blt. If icx is reduced because of
|
|
// cx, then jMsk must be shifted right to compensate.
|
|
//
|
|
|
|
icxDst = 0;
|
|
|
|
if (icx > cx) {
|
|
icxDst = icx - cx;
|
|
icx = cx;
|
|
}
|
|
|
|
//
|
|
// icxDst is now the number of pixels that can't be stored off
|
|
// the right side of the mask
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³0³1³2³3³4³5³6³7³ if mask 7 and 6 can't be written, this
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ mask gets shifted right 2 to
|
|
//
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³ ³ ³0³1³2³3³4³5³
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ
|
|
//
|
|
//
|
|
// the number of mask bits valid = 8 minus the offset (ixSrc & 0x07)
|
|
// minus the number of pixels that can't be stored because cx
|
|
// runs out or because cxMsk runs out (icxDst)
|
|
//
|
|
|
|
cx -= icx;
|
|
ixSrc += icx;
|
|
|
|
if (jMsk != 0xFF) {
|
|
|
|
jMsk = jMsk >> icxDst;
|
|
|
|
switch (icx)
|
|
{
|
|
case 8:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+23) = (BYTE)jPat2;
|
|
*(pjDst+22) = (BYTE)jPat1;
|
|
*(pjDst+21) = (BYTE)jPat0;
|
|
}
|
|
jMsk >>= 1;
|
|
case 7:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+20) = (BYTE)jPat2;
|
|
*(pjDst+19) = (BYTE)jPat1;
|
|
*(pjDst+18) = (BYTE)jPat0;
|
|
}
|
|
jMsk >>= 1;
|
|
case 6:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+17) = (BYTE)jPat2;
|
|
*(pjDst+16) = (BYTE)jPat1;
|
|
*(pjDst+15) = (BYTE)jPat0;
|
|
}
|
|
jMsk >>= 1;
|
|
case 5:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+14) = (BYTE)jPat2;
|
|
*(pjDst+13) = (BYTE)jPat1;
|
|
*(pjDst+12) = (BYTE)jPat0;
|
|
}
|
|
jMsk >>= 1;
|
|
case 4:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+11) = (BYTE)jPat2;
|
|
*(pjDst+10) = (BYTE)jPat1;
|
|
*(pjDst+9) = (BYTE)jPat0;
|
|
}
|
|
jMsk >>= 1;
|
|
case 3:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+8) = (BYTE)jPat2;
|
|
*(pjDst+7) = (BYTE)jPat1;
|
|
*(pjDst+6) = (BYTE)jPat0;
|
|
}
|
|
jMsk >>= 1;
|
|
case 2:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+5) = (BYTE)jPat2;
|
|
*(pjDst+4) = (BYTE)jPat1;
|
|
*(pjDst+3) = (BYTE)jPat0;
|
|
}
|
|
jMsk >>= 1;
|
|
case 1:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pjDst+2) = (BYTE)jPat2;
|
|
*(pjDst+1) = (BYTE)jPat1;
|
|
*pjDst = (BYTE)jPat0;
|
|
}
|
|
}
|
|
}
|
|
|
|
pjDst += icx * 3;
|
|
|
|
}
|
|
|
|
//
|
|
// increment 24 bpp Dst and 1 bpp Src to next scan line
|
|
//
|
|
|
|
pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
|
|
pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkPatMaskCopy32
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Transparent Color Expansion to 32bpp
|
|
*
|
|
* Src is a 1 Bpp mask, where src is 0, copy 1 pixel solid color
|
|
* to Dst. Where src is 1, leave Dst unchanged.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBltInfo - Pointer to BLTINFO structure containing Dst and Src information
|
|
* ulPat - Solid color pattern
|
|
* pBuffer - Scan line buffer if needed
|
|
* Invert - XOR mask used on Src to determine whether to write
|
|
* through "1" pixels or "0" pixels
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkPatMaskCopy32 (
|
|
PBLTINFO pBltInfo,
|
|
ULONG ulPat,
|
|
PULONG pBuffer,
|
|
BYTE Invert
|
|
)
|
|
{
|
|
|
|
ULONG jMsk = 0;
|
|
LONG ixSrc;
|
|
LONG icx;
|
|
LONG cx;
|
|
ULONG cy = pBltInfo->cy;
|
|
PBYTE pjSrcTmp = pBltInfo->pjSrc;
|
|
PULONG pulDstTmp = (PULONG)pBltInfo->pjDst;
|
|
PBYTE pjSrc;
|
|
PULONG pulDst;
|
|
ULONG icxDst;
|
|
|
|
DONTUSE(pBuffer);
|
|
|
|
|
|
|
|
while (cy--)
|
|
{
|
|
//
|
|
// for each scan line, first do the writes necessary to
|
|
// align ixSrc to zero, then operate on the
|
|
// Src 1 byte at a time (8 pixels) or cxSrc, whichever
|
|
// is less
|
|
//
|
|
|
|
//
|
|
// init loop params
|
|
//
|
|
|
|
cx = (LONG)pBltInfo->cx;
|
|
ixSrc = pBltInfo->xSrcStart;
|
|
pjSrc = pjSrcTmp;
|
|
pulDst = pulDstTmp + pBltInfo->xDstStart;
|
|
|
|
//
|
|
// finish the aligned scan line 8 mask bits at a time
|
|
//
|
|
|
|
while (cx > 0)
|
|
{
|
|
|
|
jMsk = (ULONG)pjSrc[ixSrc>>3] ^ Invert;
|
|
|
|
//
|
|
// icx is the number of pixels left in the mask byte
|
|
//
|
|
|
|
icx = 8 - (ixSrc & 0x07);
|
|
|
|
//
|
|
// icx is the number of pixels to operate on with this mask byte.
|
|
// Must make sure that icx is less than cx, the number of pixels
|
|
// remaining in the blt. If icx is reduced because of
|
|
// cx, then jMsk must be shifted right to compensate.
|
|
//
|
|
|
|
icxDst = 0;
|
|
|
|
if (icx > cx) {
|
|
icxDst = icx - cx;
|
|
icx = cx;
|
|
}
|
|
|
|
//
|
|
// icxDst is now the number of pixels that can't be stored off
|
|
// the right side of the mask
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³0³1³2³3³4³5³6³7³ if mask 7 and 6 can't be written, this
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ mask gets shifted right 2 to
|
|
//
|
|
//
|
|
// Bit 7 6 5 4 3 2 1 0
|
|
// ÚÄÂÄÂÄÂÄÂÄÂÄÂÄÂÄ¿
|
|
// ixMsk³ ³ ³0³1³2³3³4³5³
|
|
// ÀÄÁÄÁÄÁÄÁÄÁÄÁÄÁÄÙ
|
|
//
|
|
//
|
|
//
|
|
// the number of mask bits valid = 8 minus the offset (ixSrc & 0x07)
|
|
// minus the number of pixels that can't be stored because cx
|
|
// runs out or because cxMsk runs out (icxDst)
|
|
//
|
|
|
|
cx -= icx;
|
|
ixSrc += icx;
|
|
|
|
if (jMsk != 0xFF) {
|
|
|
|
jMsk = jMsk >> icxDst;
|
|
|
|
|
|
switch (icx)
|
|
{
|
|
case 8:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pulDst+7) = ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 7:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pulDst+6) = ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 6:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pulDst+5) = ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 5:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pulDst+4) = ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 4:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pulDst+3) = ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 3:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pulDst+2) = ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 2:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*(pulDst+1) = ulPat;
|
|
}
|
|
jMsk >>= 1;
|
|
case 1:
|
|
if (!(jMsk & 0x01))
|
|
{
|
|
*pulDst = ulPat;
|
|
}
|
|
}
|
|
}
|
|
|
|
pulDst += icx;
|
|
|
|
}
|
|
|
|
//
|
|
// increment 32 bpp Dst and 1 bpp Src to next scan line
|
|
//
|
|
|
|
pulDstTmp = (PULONG)((PBYTE)pulDstTmp + pBltInfo->lDeltaDst);
|
|
pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkAccel6666
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Special case accelerator for 8bpp to 8bpp no translation ROP 6666
|
|
* D = S xor D
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pjSrcStart - address of first src byte
|
|
* pjDstStart - address of first dst byte
|
|
* lDeltaSrcDir - delta address for src scan lines
|
|
* lDeltaDstDir - delta address for dst scan lines
|
|
* cx - pixels per scan line
|
|
* cy - number of scan lines
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkAccel6666 (
|
|
PBYTE pjSrcStart,
|
|
PBYTE pjDstStart,
|
|
LONG lDeltaSrcDir,
|
|
LONG lDeltaDstDir,
|
|
LONG cx,
|
|
LONG cy
|
|
)
|
|
{
|
|
|
|
//
|
|
// ROP 6666 8Bpp
|
|
//
|
|
|
|
ULONG ulCx4 = cx >> 2;
|
|
ULONG ulCxOdd = cx & 0x03;
|
|
ULONG ulCxTemp;
|
|
ULONG ulSrc;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
|
|
while(cy--)
|
|
{
|
|
|
|
pjSrc = pjSrcStart;
|
|
pjDst = pjDstStart;
|
|
|
|
//
|
|
// NOTE PERF: We can have the loop handle dword aligned pels and
|
|
// take care of the non-aligned head/tail separately.
|
|
//
|
|
|
|
for (ulCxTemp = ulCx4; ulCxTemp > 0; ulCxTemp--)
|
|
{
|
|
ulSrc = *UNALIGNED_DWORD_POINTER(pjSrc);
|
|
if (ulSrc != 0) {
|
|
*UNALIGNED_DWORD_POINTER(pjDst) ^= ulSrc;
|
|
}
|
|
pjSrc += 4;
|
|
pjDst += 4;
|
|
}
|
|
|
|
for (ulCxTemp = ulCxOdd; ulCxTemp > 0; ulCxTemp--)
|
|
{
|
|
*pjDst++ ^= *pjSrc++;
|
|
}
|
|
|
|
pjDstStart = pjDstStart + lDeltaDstDir;
|
|
pjSrcStart = pjSrcStart + lDeltaSrcDir;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkAccel8888
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Special case accelerator for 8bpp to 8bpp no translation ROP 8888
|
|
* D = S and D
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pjSrcStart - address of first src byte
|
|
* pjDstStart - address of first dst byte
|
|
* lDeltaSrcDir - delta address for src scan lines
|
|
* lDeltaDstDir - delta address for dst scan lines
|
|
* cx - pixels per scan line
|
|
* cy - number of scan lines
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkAccel8888(
|
|
PBYTE pjSrcStart,
|
|
PBYTE pjDstStart,
|
|
LONG lDeltaSrcDir,
|
|
LONG lDeltaDstDir,
|
|
LONG cx,
|
|
LONG cy
|
|
)
|
|
{
|
|
|
|
//
|
|
// With no translation, we can go a dword at a time and really
|
|
// fly
|
|
//
|
|
|
|
ULONG ulCx4 = cx >> 2;
|
|
ULONG ulCxOdd = cx & 0x03;
|
|
ULONG ulCxTemp;
|
|
ULONG ulSrc;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
|
|
while(cy--)
|
|
{
|
|
pjSrc = pjSrcStart;
|
|
pjDst = pjDstStart;
|
|
|
|
//
|
|
// NOTE PERF: We can have the loop handle dword aligned pels and
|
|
// take care of the non-aligned head/tail separately.
|
|
// We could also special-case source 0 and 0xFF to avoid
|
|
// unnecessary reads and writes
|
|
//
|
|
|
|
for (ulCxTemp = ulCx4; ulCxTemp > 0; ulCxTemp--)
|
|
{
|
|
ulSrc = *UNALIGNED_DWORD_POINTER(pjSrc);
|
|
|
|
if (ulSrc != ~0) {
|
|
if (ulSrc == 0) {
|
|
*UNALIGNED_DWORD_POINTER(pjDst) = 0;
|
|
} else {
|
|
*UNALIGNED_DWORD_POINTER(pjDst) &= ulSrc;
|
|
}
|
|
}
|
|
|
|
pjSrc += 4;
|
|
pjDst += 4;
|
|
}
|
|
|
|
for (ulCxTemp = ulCxOdd; ulCxTemp > 0; ulCxTemp--)
|
|
{
|
|
*pjDst++ &= *pjSrc++;
|
|
}
|
|
|
|
pjDstStart = pjDstStart + lDeltaDstDir;
|
|
pjSrcStart = pjSrcStart + lDeltaSrcDir;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Routine Name:
|
|
*
|
|
* BltLnkAccelEEEE
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Special case accelerator for 8bpp to 8bpp no translation ROP EEEE7
|
|
* D = S or D
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pjSrcStart - address of first src byte
|
|
* pjDstStart - address of first dst byte
|
|
* lDeltaSrcDir - delta address for src scan lines
|
|
* lDeltaDstDir - delta address for dst scan lines
|
|
* cx - pixels per scan line
|
|
* cy - number of scan lines
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
BltLnkAccelEEEE (
|
|
PBYTE pjSrcStart,
|
|
PBYTE pjDstStart,
|
|
LONG lDeltaSrcDir,
|
|
LONG lDeltaDstDir,
|
|
LONG cx,
|
|
LONG cy
|
|
)
|
|
|
|
{
|
|
|
|
//
|
|
// With no translation, we can go a dword at a time and really
|
|
// fly
|
|
//
|
|
|
|
ULONG ulCx4 = cx >> 2;
|
|
ULONG ulCxOdd = cx & 0x03;
|
|
ULONG ulCxTemp;
|
|
ULONG ulSrc;
|
|
PBYTE pjSrc;
|
|
PBYTE pjDst;
|
|
|
|
while(cy--)
|
|
{
|
|
pjSrc = pjSrcStart;
|
|
pjDst = pjDstStart;
|
|
|
|
//
|
|
// NOTE PERF: We can have the loop handle dword aligned pels and
|
|
// take care of the non-dword-aligned pels separately.
|
|
// We could also special-case source 0 and 0xFF to avoid
|
|
// unnecessary reads and writes
|
|
//
|
|
|
|
for (ulCxTemp = ulCx4; ulCxTemp > 0; ulCxTemp--)
|
|
{
|
|
ulSrc = *UNALIGNED_DWORD_POINTER(pjSrc);
|
|
|
|
if (ulSrc != 0) {
|
|
if (ulSrc == ~0) {
|
|
*UNALIGNED_DWORD_POINTER(pjDst) = 0xffffffff;
|
|
} else {
|
|
*UNALIGNED_DWORD_POINTER(pjDst) |= ulSrc;
|
|
}
|
|
}
|
|
pjSrc += 4;
|
|
pjDst += 4;
|
|
}
|
|
|
|
for (ulCxTemp = ulCxOdd; ulCxTemp > 0; ulCxTemp--)
|
|
{
|
|
*pjDst++ |= *pjSrc++;
|
|
}
|
|
|
|
pjDstStart = pjDstStart + lDeltaDstDir;
|
|
pjSrcStart = pjSrcStart + lDeltaSrcDir;
|
|
}
|
|
}
|