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

1049 lines
30 KiB

/******************************Module*Header*******************************\
* Module Name: str.c
*
* Contains the 'C' versions of some inner-loop routines for the
* partially hardware accelerated StretchBlt.
*
* Copyright (c) 1993-1995 Microsoft Corporation
\**************************************************************************/
#include "precomp.h"
/******************************Public*Routine******************************\
*
* Routine Name
*
* vDirectStretch8
*
* Routine Description:
*
* Stretch blt 8->8
*
* NOTE: This routine doesn't handle cases where the blt stretch starts
* and ends in the same destination dword! vDirectStretchNarrow
* is expected to have been called for that case.
*
* Arguments:
*
* pStrBlt - contains all params for blt
*
* Return Value:
*
* VOID
*
\**************************************************************************/
VOID vM64DirectStretch8(
STR_BLT* pStrBlt)
{
BYTE* pjSrc;
BYTE* pjDstEnd;
LONG WidthXAln;
ULONG ulDst;
ULONG xAccum;
ULONG xTmp;
ULONG yTmp;
BYTE* pjOldScan;
LONG cyDuplicate;
PDEV* ppdev = pStrBlt->ppdev;
LONG xDst = pStrBlt->XDstStart;
LONG xSrc = pStrBlt->XSrcStart;
BYTE* pjSrcScan = pStrBlt->pjSrcScan + xSrc;
BYTE* pjDst = pStrBlt->pjDstScan + xDst;
LONG yDst = pStrBlt->YDstStart + ppdev->yOffset;
LONG yCount = pStrBlt->YDstCount;
ULONG StartAln = (ULONG)((ULONG_PTR)pjDst & 0x03);
LONG WidthX = pStrBlt->XDstEnd - xDst;
ULONG EndAln = (ULONG)((ULONG_PTR)(pjDst + WidthX) & 0x03);
ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
ULONG yAccum = pStrBlt->ulYFracAccumulator;
ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
ULONG yInt = 0;
LONG lDstStride = pStrBlt->lDeltaDst - WidthX;
BYTE jSrc0,jSrc1,jSrc2,jSrc3;
BYTE* pjMmBase = ppdev->pjMmBase;
xDst += ppdev->xOffset;
WidthXAln = WidthX - EndAln - ((- (LONG) StartAln) & 0x03);
//
// if this is a shrinking blt, calc src scan line stride
//
if (pStrBlt->ulYDstToSrcIntCeil != 0)
{
yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
}
//
// loop drawing each scan line
//
//
// at least 7 wide (DST) blt
//
do {
pjSrc = pjSrcScan;
xAccum = pStrBlt->ulXFracAccumulator;
//
// a single src scan line is being written
//
switch (StartAln) {
case 1:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 2:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 3:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
}
pjDstEnd = pjDst + WidthXAln;
while (pjDst != pjDstEnd)
{
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
jSrc1 = *pjSrc;
xAccum = xTmp + xFrac;
pjSrc = pjSrc + xInt + (xAccum < xTmp);
jSrc2 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
jSrc3 = *pjSrc;
xAccum = xTmp + xFrac;
pjSrc = pjSrc + xInt + (xAccum < xTmp);
ulDst = (jSrc3 << 24) | (jSrc2 << 16) | (jSrc1 << 8) | jSrc0;
*(PULONG)pjDst = ulDst;
pjDst += 4;
}
switch (EndAln) {
case 3:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 2:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 1:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
}
pjOldScan = pjSrcScan;
pjSrcScan += yInt;
yTmp = yAccum + yFrac;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pjDst = (pjDst + lDstStride);
yDst++;
yCount--;
if ((yCount != 0) && (pjSrcScan == pjOldScan))
{
// It's an expanding stretch in 'y'; the scan we just laid down
// will be copied at least once using the hardware:
cyDuplicate = 0;
do {
cyDuplicate++;
pjSrcScan += yInt;
yTmp = yAccum + yFrac;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pjDst = (pjDst + pStrBlt->lDeltaDst);
yCount--;
} while ((yCount != 0) && (pjSrcScan == pjOldScan));
// The scan is to be copied 'cyDuplicate' times using the
// hardware.
M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
M64_OD(pjMmBase, SRC_Y_X, (yDst - 1) | (xDst << 16) );
M64_OD(pjMmBase, DST_Y_X, yDst | (xDst << 16) );
M64_OD(pjMmBase, SRC_HEIGHT1_WIDTH1, 1 | (WidthX << 16) );
M64_OD(pjMmBase, DST_HEIGHT_WIDTH, cyDuplicate | (WidthX << 16) );
yDst += cyDuplicate;
}
} while (yCount != 0);
}
VOID vM32DirectStretch8(
STR_BLT* pStrBlt)
{
BYTE* pjSrc;
BYTE* pjDstEnd;
LONG WidthXAln;
ULONG ulDst;
ULONG xAccum;
ULONG xTmp;
ULONG yTmp;
BYTE* pjOldScan;
LONG cyDuplicate;
PDEV* ppdev = pStrBlt->ppdev;
LONG xDst = pStrBlt->XDstStart;
LONG xSrc = pStrBlt->XSrcStart;
BYTE* pjSrcScan = pStrBlt->pjSrcScan + xSrc;
BYTE* pjDst = pStrBlt->pjDstScan + xDst;
LONG yDst = pStrBlt->YDstStart + ppdev->yOffset;
LONG yCount = pStrBlt->YDstCount;
ULONG StartAln = (ULONG)((ULONG_PTR)pjDst & 0x03);
LONG WidthX = pStrBlt->XDstEnd - xDst;
ULONG EndAln = (ULONG)((ULONG_PTR)(pjDst + WidthX) & 0x03);
ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
ULONG yAccum = pStrBlt->ulYFracAccumulator;
ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
ULONG yInt = 0;
LONG lDstStride = pStrBlt->lDeltaDst - WidthX;
BYTE jSrc0,jSrc1,jSrc2,jSrc3;
BYTE* pjMmBase = ppdev->pjMmBase;
xDst += ppdev->xOffset;
WidthXAln = WidthX - EndAln - ((- (LONG) StartAln) & 0x03);
//
// if this is a shrinking blt, calc src scan line stride
//
if (pStrBlt->ulYDstToSrcIntCeil != 0)
{
yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
}
//
// loop drawing each scan line
//
//
// at least 7 wide (DST) blt
//
do {
pjSrc = pjSrcScan;
xAccum = pStrBlt->ulXFracAccumulator;
//
// a single src scan line is being written
//
switch (StartAln) {
case 1:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 2:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 3:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
}
pjDstEnd = pjDst + WidthXAln;
while (pjDst != pjDstEnd)
{
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
jSrc1 = *pjSrc;
xAccum = xTmp + xFrac;
pjSrc = pjSrc + xInt + (xAccum < xTmp);
jSrc2 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
jSrc3 = *pjSrc;
xAccum = xTmp + xFrac;
pjSrc = pjSrc + xInt + (xAccum < xTmp);
ulDst = (jSrc3 << 24) | (jSrc2 << 16) | (jSrc1 << 8) | jSrc0;
*(PULONG)pjDst = ulDst;
pjDst += 4;
}
switch (EndAln) {
case 3:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 2:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 1:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
}
pjOldScan = pjSrcScan;
pjSrcScan += yInt;
yTmp = yAccum + yFrac;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pjDst = (pjDst + lDstStride);
yDst++;
yCount--;
// 32 to fix bizarre hardware bug (?) -- totally heuristic
if ((yCount != 0) && (pjSrcScan == pjOldScan) && (WidthX >= 32))
{
// It's an expanding stretch in 'y'; the scan we just laid down
// will be copied at least once using the hardware:
cyDuplicate = 0;
do {
cyDuplicate++;
pjSrcScan += yInt;
yTmp = yAccum + yFrac;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pjDst = (pjDst + pStrBlt->lDeltaDst);
yCount--;
} while ((yCount != 0) && (pjSrcScan == pjOldScan));
// The scan is to be copied 'cyDuplicate' times using the
// hardware.
M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 9);
M32_OW(pjMmBase, M32_SRC_X, (SHORT) xDst );
M32_OW(pjMmBase, M32_SRC_X_START, (SHORT) xDst );
M32_OW(pjMmBase, M32_SRC_X_END, (SHORT) (xDst + WidthX) );
M32_OW(pjMmBase, M32_SRC_Y, (SHORT) (yDst - 1) ); // the line to replicate
M32_OW(pjMmBase, CUR_X, (SHORT) xDst );
M32_OW(pjMmBase, DEST_X_START, (SHORT) xDst );
M32_OW(pjMmBase, DEST_X_END, (SHORT) (xDst + WidthX) );
M32_OW(pjMmBase, CUR_Y, (SHORT) yDst );
vM32QuietDown(ppdev, pjMmBase);
M32_OW(pjMmBase, DEST_Y_END, (SHORT) (yDst + cyDuplicate) );
yDst += cyDuplicate;
}
} while (yCount != 0);
}
VOID vI32DirectStretch8(
STR_BLT* pStrBlt)
{
BYTE* pjSrc;
BYTE* pjDstEnd;
LONG WidthXAln;
ULONG ulDst;
ULONG xAccum;
ULONG xTmp;
ULONG yTmp;
BYTE* pjOldScan;
LONG cyDuplicate;
PDEV* ppdev = pStrBlt->ppdev;
LONG xDst = pStrBlt->XDstStart;
LONG xSrc = pStrBlt->XSrcStart;
BYTE* pjSrcScan = pStrBlt->pjSrcScan + xSrc;
BYTE* pjDst = pStrBlt->pjDstScan + xDst;
LONG yDst = pStrBlt->YDstStart + ppdev->yOffset;
LONG yCount = pStrBlt->YDstCount;
ULONG StartAln = (ULONG)((ULONG_PTR)pjDst & 0x03);
LONG WidthX = pStrBlt->XDstEnd - xDst;
ULONG EndAln = (ULONG)((ULONG_PTR)(pjDst + WidthX) & 0x03);
ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
ULONG yAccum = pStrBlt->ulYFracAccumulator;
ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
ULONG yInt = 0;
LONG lDstStride = pStrBlt->lDeltaDst - WidthX;
BYTE jSrc0,jSrc1,jSrc2,jSrc3;
BYTE* pjIoBase = ppdev->pjIoBase;
xDst += ppdev->xOffset;
WidthXAln = WidthX - EndAln - ((- (LONG) StartAln) & 0x03);
//
// if this is a shrinking blt, calc src scan line stride
//
if (pStrBlt->ulYDstToSrcIntCeil != 0)
{
yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
}
//
// loop drawing each scan line
//
//
// at least 7 wide (DST) blt
//
do {
pjSrc = pjSrcScan;
xAccum = pStrBlt->ulXFracAccumulator;
//
// a single src scan line is being written
//
switch (StartAln) {
case 1:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 2:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 3:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
}
pjDstEnd = pjDst + WidthXAln;
while (pjDst != pjDstEnd)
{
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
jSrc1 = *pjSrc;
xAccum = xTmp + xFrac;
pjSrc = pjSrc + xInt + (xAccum < xTmp);
jSrc2 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
jSrc3 = *pjSrc;
xAccum = xTmp + xFrac;
pjSrc = pjSrc + xInt + (xAccum < xTmp);
ulDst = (jSrc3 << 24) | (jSrc2 << 16) | (jSrc1 << 8) | jSrc0;
*(PULONG)pjDst = ulDst;
pjDst += 4;
}
switch (EndAln) {
case 3:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 2:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 1:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
}
pjOldScan = pjSrcScan;
pjSrcScan += yInt;
yTmp = yAccum + yFrac;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pjDst = (pjDst + lDstStride);
yDst++;
yCount--;
// 32 to fix bizarre hardware bug (?) -- totally heuristic
if ((yCount != 0) && (pjSrcScan == pjOldScan) && (WidthX >= 32))
{
// It's an expanding stretch in 'y'; the scan we just laid down
// will be copied at least once using the hardware:
cyDuplicate = 0;
do {
cyDuplicate++;
pjSrcScan += yInt;
yTmp = yAccum + yFrac;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pjDst = (pjDst + pStrBlt->lDeltaDst);
yCount--;
} while ((yCount != 0) && (pjSrcScan == pjOldScan));
// The scan is to be copied 'cyDuplicate' times using the
// hardware.
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 9);
I32_OW(pjIoBase, M32_SRC_X, (SHORT) xDst );
I32_OW(pjIoBase, M32_SRC_X_START, (SHORT) xDst );
I32_OW(pjIoBase, M32_SRC_X_END, (SHORT) (xDst + WidthX) );
I32_OW(pjIoBase, M32_SRC_Y, (SHORT) (yDst - 1) ); // the line to replicate
I32_OW(pjIoBase, CUR_X, (SHORT) xDst );
I32_OW(pjIoBase, DEST_X_START, (SHORT) xDst );
I32_OW(pjIoBase, DEST_X_END, (SHORT) (xDst + WidthX) );
I32_OW(pjIoBase, CUR_Y, (SHORT) yDst );
vI32QuietDown(ppdev, pjIoBase);
I32_OW(pjIoBase, DEST_Y_END, (SHORT) (yDst + cyDuplicate) );
yDst += cyDuplicate;
}
} while (yCount != 0);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* vDirectStretch16
*
* Routine Description:
*
* Stretch blt 16->16
*
* Arguments:
*
* pStrBlt - contains all params for blt
*
* Return Value:
*
* VOID
*
\**************************************************************************/
VOID vM64DirectStretch16(
STR_BLT* pStrBlt)
{
BYTE* pjOldScan;
USHORT* pusSrc;
USHORT* pusDstEnd;
LONG WidthXAln;
ULONG ulDst;
ULONG xAccum;
ULONG xTmp;
ULONG yTmp;
LONG cyDuplicate;
PDEV* ppdev = pStrBlt->ppdev;
LONG xDst = pStrBlt->XDstStart;
LONG xSrc = pStrBlt->XSrcStart;
BYTE* pjSrcScan = (pStrBlt->pjSrcScan) + xSrc * 2;
USHORT* pusDst = (USHORT*)(pStrBlt->pjDstScan) + xDst;
LONG yDst = pStrBlt->YDstStart + ppdev->yOffset;
LONG yCount = pStrBlt->YDstCount;
ULONG StartAln = (ULONG)(((ULONG_PTR)pusDst & 0x02) >> 1);
LONG WidthX = pStrBlt->XDstEnd - xDst;
ULONG EndAln = (ULONG)(((ULONG_PTR)(pusDst + WidthX) & 0x02) >> 1);
ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
ULONG yAccum = pStrBlt->ulYFracAccumulator;
ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
LONG lDstStride = pStrBlt->lDeltaDst - 2 * WidthX;
ULONG yInt = 0;
USHORT usSrc0,usSrc1;
BYTE* pjMmBase = ppdev->pjMmBase;
xDst += ppdev->xOffset;
WidthXAln = WidthX - EndAln - StartAln;
//
// if this is a shrinking blt, calc src scan line stride
//
if (pStrBlt->ulYDstToSrcIntCeil != 0)
{
yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
}
// Loop stretching each scan line
do {
pusSrc = (USHORT*) pjSrcScan;
xAccum = pStrBlt->ulXFracAccumulator;
// A single source scan line is being written:
if (StartAln)
{
usSrc0 = *pusSrc;
xTmp = xAccum + xFrac;
pusSrc = pusSrc + xInt + (xTmp < xAccum);
*pusDst++ = usSrc0;
xAccum = xTmp;
}
pusDstEnd = pusDst + WidthXAln;
while (pusDst != pusDstEnd)
{
usSrc0 = *pusSrc;
xTmp = xAccum + xFrac;
pusSrc = pusSrc + xInt + (xTmp < xAccum);
usSrc1 = *pusSrc;
xAccum = xTmp + xFrac;
pusSrc = pusSrc + xInt + (xAccum < xTmp);
ulDst = (ULONG)((usSrc1 << 16) | usSrc0);
*(ULONG*)pusDst = ulDst;
pusDst+=2;
}
if (EndAln)
{
usSrc0 = *pusSrc;
xTmp = xAccum + xFrac;
pusSrc = pusSrc + xInt + (xTmp < xAccum);
*pusDst++ = usSrc0;
}
pjOldScan = pjSrcScan;
pjSrcScan += yInt;
yTmp = yAccum + yFrac;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pusDst = (USHORT*) ((BYTE*) pusDst + lDstStride);
yDst++;
yCount--;
if ((yCount != 0) && (pjSrcScan == pjOldScan))
{
// It's an expanding stretch in 'y'; the scan we just laid down
// will be copied at least once using the hardware:
cyDuplicate = 0;
do {
cyDuplicate++;
pjSrcScan += yInt;
yTmp = yAccum + yFrac;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pusDst = (USHORT*) ((BYTE*) pusDst + pStrBlt->lDeltaDst);
yCount--;
} while ((yCount != 0) && (pjSrcScan == pjOldScan));
// The scan is to be copied 'cyDuplicate' times using the
// hardware.
M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
M64_OD(pjMmBase, SRC_Y_X, (yDst - 1) | (xDst << 16) );
M64_OD(pjMmBase, DST_Y_X, yDst | (xDst << 16) );
M64_OD(pjMmBase, SRC_HEIGHT1_WIDTH1, 1 | (WidthX << 16) );
M64_OD(pjMmBase, DST_HEIGHT_WIDTH, cyDuplicate | (WidthX << 16) );
yDst += cyDuplicate;
}
} while (yCount != 0);
}
VOID vM32DirectStretch16(
STR_BLT* pStrBlt)
{
BYTE* pjOldScan;
USHORT* pusSrc;
USHORT* pusDstEnd;
LONG WidthXAln;
ULONG ulDst;
ULONG xAccum;
ULONG xTmp;
ULONG yTmp;
LONG cyDuplicate;
PDEV* ppdev = pStrBlt->ppdev;
LONG xDst = pStrBlt->XDstStart;
LONG xSrc = pStrBlt->XSrcStart;
BYTE* pjSrcScan = (pStrBlt->pjSrcScan) + xSrc * 2;
USHORT* pusDst = (USHORT*)(pStrBlt->pjDstScan) + xDst;
LONG yDst = pStrBlt->YDstStart + ppdev->yOffset;
LONG yCount = pStrBlt->YDstCount;
ULONG StartAln = (ULONG)(((ULONG_PTR)pusDst & 0x02) >> 1);
LONG WidthX = pStrBlt->XDstEnd - xDst;
ULONG EndAln = (ULONG)(((ULONG_PTR)(pusDst + WidthX) & 0x02) >> 1);
ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
ULONG yAccum = pStrBlt->ulYFracAccumulator;
ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
LONG lDstStride = pStrBlt->lDeltaDst - 2 * WidthX;
ULONG yInt = 0;
USHORT usSrc0,usSrc1;
BYTE* pjMmBase = ppdev->pjMmBase;
xDst += ppdev->xOffset;
WidthXAln = WidthX - EndAln - StartAln;
//
// if this is a shrinking blt, calc src scan line stride
//
if (pStrBlt->ulYDstToSrcIntCeil != 0)
{
yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
}
// Loop stretching each scan line
do {
pusSrc = (USHORT*) pjSrcScan;
xAccum = pStrBlt->ulXFracAccumulator;
// A single source scan line is being written:
if (StartAln)
{
usSrc0 = *pusSrc;
xTmp = xAccum + xFrac;
pusSrc = pusSrc + xInt + (xTmp < xAccum);
*pusDst++ = usSrc0;
xAccum = xTmp;
}
pusDstEnd = pusDst + WidthXAln;
while (pusDst != pusDstEnd)
{
usSrc0 = *pusSrc;
xTmp = xAccum + xFrac;
pusSrc = pusSrc + xInt + (xTmp < xAccum);
usSrc1 = *pusSrc;
xAccum = xTmp + xFrac;
pusSrc = pusSrc + xInt + (xAccum < xTmp);
ulDst = (ULONG)((usSrc1 << 16) | usSrc0);
*(ULONG*)pusDst = ulDst;
pusDst+=2;
}
if (EndAln)
{
usSrc0 = *pusSrc;
xTmp = xAccum + xFrac;
pusSrc = pusSrc + xInt + (xTmp < xAccum);
*pusDst++ = usSrc0;
}
pjOldScan = pjSrcScan;
pjSrcScan += yInt;
yTmp = yAccum + yFrac;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pusDst = (USHORT*) ((BYTE*) pusDst + lDstStride);
yDst++;
yCount--;
// 32 to fix bizarre hardware bug (?) -- totally heuristic
if ((yCount != 0) && (pjSrcScan == pjOldScan) && (WidthX >= 32))
{
// It's an expanding stretch in 'y'; the scan we just laid down
// will be copied at least once using the hardware:
cyDuplicate = 0;
do {
cyDuplicate++;
pjSrcScan += yInt;
yTmp = yAccum + yFrac;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pusDst = (USHORT*) ((BYTE*) pusDst + pStrBlt->lDeltaDst);
yCount--;
} while ((yCount != 0) && (pjSrcScan == pjOldScan));
// The scan is to be copied 'cyDuplicate' times using the
// hardware.
M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 9);
M32_OW(pjMmBase, M32_SRC_X, (SHORT) xDst );
M32_OW(pjMmBase, M32_SRC_X_START, (SHORT) xDst );
M32_OW(pjMmBase, M32_SRC_X_END, (SHORT) (xDst + WidthX) );
M32_OW(pjMmBase, M32_SRC_Y, (SHORT) (yDst - 1) ); // the line to replicate
M32_OW(pjMmBase, CUR_X, (SHORT) xDst );
M32_OW(pjMmBase, DEST_X_START, (SHORT) xDst );
M32_OW(pjMmBase, DEST_X_END, (SHORT) (xDst + WidthX) );
M32_OW(pjMmBase, CUR_Y, (SHORT) yDst );
vM32QuietDown(ppdev, pjMmBase);
M32_OW(pjMmBase, DEST_Y_END, (SHORT) (yDst + cyDuplicate) );
yDst += cyDuplicate;
}
} while (yCount != 0);
}
VOID vI32DirectStretch16(
STR_BLT* pStrBlt)
{
BYTE* pjOldScan;
USHORT* pusSrc;
USHORT* pusDstEnd;
LONG WidthXAln;
ULONG ulDst;
ULONG xAccum;
ULONG xTmp;
ULONG yTmp;
LONG cyDuplicate;
PDEV* ppdev = pStrBlt->ppdev;
LONG xDst = pStrBlt->XDstStart;
LONG xSrc = pStrBlt->XSrcStart;
BYTE* pjSrcScan = (pStrBlt->pjSrcScan) + xSrc * 2;
USHORT* pusDst = (USHORT*)(pStrBlt->pjDstScan) + xDst;
LONG yDst = pStrBlt->YDstStart + ppdev->yOffset;
LONG yCount = pStrBlt->YDstCount;
ULONG StartAln = (ULONG)(((ULONG_PTR)pusDst & 0x02) >> 1);
LONG WidthX = pStrBlt->XDstEnd - xDst;
ULONG EndAln = (ULONG)(((ULONG_PTR)(pusDst + WidthX) & 0x02) >> 1);
ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
ULONG yAccum = pStrBlt->ulYFracAccumulator;
ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
LONG lDstStride = pStrBlt->lDeltaDst - 2 * WidthX;
ULONG yInt = 0;
USHORT usSrc0,usSrc1;
BYTE* pjIoBase = ppdev->pjIoBase;
xDst += ppdev->xOffset;
WidthXAln = WidthX - EndAln - StartAln;
//
// if this is a shrinking blt, calc src scan line stride
//
if (pStrBlt->ulYDstToSrcIntCeil != 0)
{
yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
}
// Loop stretching each scan line
do {
pusSrc = (USHORT*) pjSrcScan;
xAccum = pStrBlt->ulXFracAccumulator;
// A single source scan line is being written:
if (StartAln)
{
usSrc0 = *pusSrc;
xTmp = xAccum + xFrac;
pusSrc = pusSrc + xInt + (xTmp < xAccum);
*pusDst++ = usSrc0;
xAccum = xTmp;
}
pusDstEnd = pusDst + WidthXAln;
while (pusDst != pusDstEnd)
{
usSrc0 = *pusSrc;
xTmp = xAccum + xFrac;
pusSrc = pusSrc + xInt + (xTmp < xAccum);
usSrc1 = *pusSrc;
xAccum = xTmp + xFrac;
pusSrc = pusSrc + xInt + (xAccum < xTmp);
ulDst = (ULONG)((usSrc1 << 16) | usSrc0);
*(ULONG*)pusDst = ulDst;
pusDst+=2;
}
if (EndAln)
{
usSrc0 = *pusSrc;
xTmp = xAccum + xFrac;
pusSrc = pusSrc + xInt + (xTmp < xAccum);
*pusDst++ = usSrc0;
}
pjOldScan = pjSrcScan;
pjSrcScan += yInt;
yTmp = yAccum + yFrac;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pusDst = (USHORT*) ((BYTE*) pusDst + lDstStride);
yDst++;
yCount--;
// 32 to fix bizarre hardware bug (?) -- totally heuristic
if ((yCount != 0) && (pjSrcScan == pjOldScan) && (WidthX >= 32))
{
// It's an expanding stretch in 'y'; the scan we just laid down
// will be copied at least once using the hardware:
cyDuplicate = 0;
do {
cyDuplicate++;
pjSrcScan += yInt;
yTmp = yAccum + yFrac;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pusDst = (USHORT*) ((BYTE*) pusDst + pStrBlt->lDeltaDst);
yCount--;
} while ((yCount != 0) && (pjSrcScan == pjOldScan));
// The scan is to be copied 'cyDuplicate' times using the
// hardware.
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 9);
I32_OW(pjIoBase, M32_SRC_X, (SHORT) xDst );
I32_OW(pjIoBase, M32_SRC_X_START, (SHORT) xDst );
I32_OW(pjIoBase, M32_SRC_X_END, (SHORT) (xDst + WidthX) );
I32_OW(pjIoBase, M32_SRC_Y, (SHORT) (yDst - 1) ); // the line to replicate
I32_OW(pjIoBase, CUR_X, (SHORT) xDst );
I32_OW(pjIoBase, DEST_X_START, (SHORT) xDst );
I32_OW(pjIoBase, DEST_X_END, (SHORT) (xDst + WidthX) );
I32_OW(pjIoBase, CUR_Y, (SHORT) yDst );
vI32QuietDown(ppdev, pjIoBase);
I32_OW(pjIoBase, DEST_Y_END, (SHORT) (yDst + cyDuplicate) );
yDst += cyDuplicate;
}
} while (yCount != 0);
}