1468 lines
40 KiB
C
1468 lines
40 KiB
C
/******************************Module*Header*******************************\
|
||
* Module Name: stretch.c
|
||
*
|
||
* Copyright (c) 1993-1995 Microsoft Corporation
|
||
\**************************************************************************/
|
||
|
||
#include "precomp.h"
|
||
|
||
#define STRETCH_MAX_EXTENT 32767
|
||
|
||
typedef DWORDLONG ULONGLONG;
|
||
|
||
/******************************Public*Routine******************************\
|
||
*
|
||
* Routine Name
|
||
*
|
||
* vDirectStretch8Narrow
|
||
*
|
||
* Routine Description:
|
||
*
|
||
* Stretch blt 8->8 when the width is 7 or less
|
||
*
|
||
* Arguments:
|
||
*
|
||
* pStrBlt - contains all params for blt
|
||
*
|
||
* Return Value:
|
||
*
|
||
* VOID
|
||
*
|
||
\**************************************************************************/
|
||
|
||
VOID vDirectStretch8Narrow(
|
||
STR_BLT* pStrBlt)
|
||
{
|
||
BYTE* pjSrc;
|
||
ULONG xAccum;
|
||
ULONG xTmp;
|
||
|
||
LONG xDst = pStrBlt->XDstStart;
|
||
LONG xSrc = pStrBlt->XSrcStart;
|
||
BYTE* pjSrcScan = pStrBlt->pjSrcScan + xSrc;
|
||
BYTE* pjDst = pStrBlt->pjDstScan + xDst;
|
||
LONG yCount = pStrBlt->YDstCount;
|
||
LONG WidthX = pStrBlt->XDstEnd - xDst;
|
||
ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
|
||
ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
|
||
ULONG yAccum = pStrBlt->ulYFracAccumulator;
|
||
ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
|
||
LONG lDstStride = pStrBlt->lDeltaDst - WidthX;
|
||
ULONG yInt = 0;
|
||
|
||
yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
|
||
|
||
//
|
||
// Narrow blt
|
||
//
|
||
|
||
do {
|
||
|
||
ULONG yTmp = yAccum + yFrac;
|
||
BYTE jSrc0;
|
||
BYTE* pjDstEndNarrow = pjDst + WidthX;
|
||
|
||
pjSrc = pjSrcScan;
|
||
xAccum = pStrBlt->ulXFracAccumulator;
|
||
|
||
do {
|
||
jSrc0 = *pjSrc;
|
||
xTmp = xAccum + xFrac;
|
||
pjSrc = pjSrc + xInt + (xTmp < xAccum);
|
||
*pjDst++ = jSrc0;
|
||
xAccum = xTmp;
|
||
} while (pjDst != pjDstEndNarrow);
|
||
|
||
pjSrcScan += yInt;
|
||
|
||
if (yTmp < yAccum)
|
||
{
|
||
pjSrcScan += pStrBlt->lDeltaSrc;
|
||
}
|
||
|
||
yAccum = yTmp;
|
||
pjDst += lDstStride;
|
||
|
||
} while (--yCount);
|
||
|
||
}
|
||
|
||
/******************************Public*Routine******************************\
|
||
*
|
||
* Routine Name
|
||
*
|
||
* vDirectStretch32
|
||
*
|
||
* Routine Description:
|
||
*
|
||
* Stretch blt 32->32
|
||
*
|
||
* Arguments:
|
||
*
|
||
* pStrBlt - contains all params for blt
|
||
*
|
||
* Return Value:
|
||
*
|
||
* VOID
|
||
*
|
||
\**************************************************************************/
|
||
|
||
VOID vM64DirectStretch32(
|
||
STR_BLT* pStrBlt)
|
||
{
|
||
BYTE* pjOldScan;
|
||
ULONG* pulSrc;
|
||
ULONG* pulDstEnd;
|
||
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 * 4;
|
||
ULONG* pulDst = (ULONG*)(pStrBlt->pjDstScan) + xDst;
|
||
LONG yDst = pStrBlt->YDstStart + ppdev->yOffset;
|
||
LONG yCount = pStrBlt->YDstCount;
|
||
LONG WidthX = pStrBlt->XDstEnd - xDst;
|
||
ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
|
||
ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
|
||
ULONG yAccum = pStrBlt->ulYFracAccumulator;
|
||
ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
|
||
LONG lDstStride = pStrBlt->lDeltaDst - 4*WidthX;
|
||
ULONG yInt = 0;
|
||
|
||
ULONG ulSrc;
|
||
BYTE* pjMmBase = ppdev->pjMmBase;
|
||
|
||
xDst += ppdev->xOffset;
|
||
|
||
//
|
||
// if this is a shrinking blt, calc src scan line stride
|
||
//
|
||
|
||
if (pStrBlt->ulYDstToSrcIntCeil != 0)
|
||
{
|
||
yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
|
||
}
|
||
|
||
do {
|
||
pulSrc = (ULONG*) pjSrcScan;
|
||
xAccum = pStrBlt->ulXFracAccumulator;
|
||
|
||
//
|
||
// a single src scan line is being written
|
||
//
|
||
|
||
pulDstEnd = pulDst + WidthX;
|
||
|
||
while (pulDst != pulDstEnd)
|
||
{
|
||
|
||
ulSrc = *pulSrc;
|
||
xTmp = xAccum + xFrac;
|
||
pulSrc = pulSrc + xInt + (xTmp < xAccum);
|
||
*(ULONG*)pulDst = ulSrc;
|
||
pulDst++;
|
||
xAccum = xTmp;
|
||
}
|
||
|
||
pjOldScan = pjSrcScan;
|
||
pjSrcScan += yInt;
|
||
|
||
yTmp = yAccum + yFrac;
|
||
if (yTmp < yAccum)
|
||
{
|
||
pjSrcScan += pStrBlt->lDeltaSrc;
|
||
}
|
||
yAccum = yTmp;
|
||
|
||
pulDst = (ULONG*) ((BYTE*) pulDst + 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;
|
||
|
||
pulDst = (ULONG*) ((BYTE*) pulDst + 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);
|
||
}
|
||
|
||
/******************************Public*Routine******************************\
|
||
*
|
||
* Routine Description:
|
||
*
|
||
* StretchBlt using integer math. Must be from one surface to another
|
||
* surface of the same format.
|
||
*
|
||
* Arguments:
|
||
*
|
||
* ppdev - PDEV for device
|
||
* pvDst - Pointer to start of dst bitmap
|
||
* lDeltaDst - Bytes from start of dst scan line to start of next
|
||
* DstCx - Width of Dst Bitmap in pixels
|
||
* DstCy - Height of Dst Bitmap in pixels
|
||
* prclDst - Pointer to rectangle of Dst extents
|
||
* pvSrc - Pointer to start of Src bitmap
|
||
* lDeltaSrc - Bytes from start of Src scan line to start of next
|
||
* SrcCx - Width of Src Bitmap in pixels
|
||
* SrcCy - Height of Src Bitmap in pixels
|
||
* prclSrc - Pointer to rectangle of Src extents
|
||
* prclSClip - Clip Dest to this rect
|
||
*
|
||
* Return Value:
|
||
*
|
||
* Status
|
||
*
|
||
\**************************************************************************/
|
||
|
||
BOOL bM64StretchDIB(
|
||
PDEV* ppdev,
|
||
VOID* pvDst,
|
||
LONG lDeltaDst,
|
||
RECTL* prclDst,
|
||
VOID* pvSrc,
|
||
LONG lDeltaSrc,
|
||
RECTL* prclSrc,
|
||
RECTL* prclClip)
|
||
{
|
||
STR_BLT StrBlt;
|
||
ULONG ulXDstToSrcIntCeil;
|
||
ULONG ulXDstToSrcFracCeil;
|
||
ULONG ulYDstToSrcIntCeil;
|
||
ULONG ulYDstToSrcFracCeil;
|
||
ULONG ulXFracAccumulator;
|
||
ULONG ulYFracAccumulator;
|
||
LONG LeftClipDistance;
|
||
LONG TopClipDistance;
|
||
BOOL bStretch;
|
||
BYTE* pjMmBase = ppdev->pjMmBase;
|
||
|
||
union {
|
||
LARGE_INTEGER large;
|
||
ULONGLONG li;
|
||
} liInit;
|
||
|
||
PFN_DIRSTRETCH pfnStr;
|
||
|
||
//
|
||
// Calculate exclusive start and end points:
|
||
//
|
||
|
||
LONG WidthDst = prclDst->right - prclDst->left;
|
||
LONG HeightDst = prclDst->bottom - prclDst->top;
|
||
LONG WidthSrc = prclSrc->right - prclSrc->left;
|
||
LONG HeightSrc = prclSrc->bottom - prclSrc->top;
|
||
|
||
LONG XSrcStart = prclSrc->left;
|
||
LONG XSrcEnd = prclSrc->right;
|
||
LONG XDstStart = prclDst->left;
|
||
LONG XDstEnd = prclDst->right;
|
||
LONG YSrcStart = prclSrc->top;
|
||
LONG YSrcEnd = prclSrc->bottom;
|
||
LONG YDstStart = prclDst->top;
|
||
LONG YDstEnd = prclDst->bottom;
|
||
|
||
//
|
||
// Validate parameters:
|
||
//
|
||
|
||
ASSERTDD(pvDst != (VOID*)NULL, "Bad destination bitmap pointer");
|
||
ASSERTDD(pvSrc != (VOID*)NULL, "Bad source bitmap pointer");
|
||
ASSERTDD(prclDst != (RECTL*)NULL, "Bad destination rectangle");
|
||
ASSERTDD(prclSrc != (RECTL*)NULL, "Bad source rectangle");
|
||
ASSERTDD((WidthDst > 0) && (HeightDst > 0) &&
|
||
(WidthSrc > 0) && (HeightSrc > 0),
|
||
"Can't do mirroring or empty rectangles here");
|
||
ASSERTDD((WidthDst <= STRETCH_MAX_EXTENT) &&
|
||
(HeightDst <= STRETCH_MAX_EXTENT) &&
|
||
(WidthSrc <= STRETCH_MAX_EXTENT) &&
|
||
(HeightSrc <= STRETCH_MAX_EXTENT), "Stretch exceeds limits");
|
||
ASSERTDD(prclClip != NULL, "Bad clip rectangle");
|
||
|
||
//
|
||
// Calculate X Dst to Src mapping
|
||
//
|
||
//
|
||
// dst->src = ( CEIL( (2k*WidthSrc)/WidthDst) ) / 2k
|
||
//
|
||
// = ( FLOOR( (2k*WidthSrc -1) / WidthDst) + 1) / 2k
|
||
//
|
||
// where 2k = 2 ^ 32
|
||
//
|
||
|
||
{
|
||
ULONGLONG liWidthSrc;
|
||
ULONGLONG liQuo;
|
||
ULONG ulTemp;
|
||
|
||
//
|
||
// Work around a compiler bug dealing with the assignment
|
||
// 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
|
||
//
|
||
|
||
liInit.large.LowPart = (ULONG) -1;
|
||
liInit.large.HighPart = WidthSrc - 1;
|
||
liWidthSrc = liInit.li;
|
||
|
||
liQuo = liWidthSrc / (ULONGLONG) WidthDst;
|
||
|
||
ulXDstToSrcIntCeil = (ULONG)(liQuo >> 32);
|
||
ulXDstToSrcFracCeil = (ULONG)liQuo;
|
||
|
||
//
|
||
// Now add 1, use fake carry:
|
||
//
|
||
|
||
ulTemp = ulXDstToSrcFracCeil + 1;
|
||
|
||
ulXDstToSrcIntCeil += (ulTemp < ulXDstToSrcFracCeil);
|
||
ulXDstToSrcFracCeil = ulTemp;
|
||
}
|
||
|
||
//
|
||
// Calculate Y Dst to Src mapping
|
||
//
|
||
//
|
||
// dst->src = ( CEIL( (2k*HeightSrc)/HeightDst) ) / 2k
|
||
//
|
||
// = ( FLOOR( (2k*HeightSrc -1) / HeightDst) + 1) / 2k
|
||
//
|
||
// where 2k = 2 ^ 32
|
||
//
|
||
|
||
{
|
||
ULONGLONG liHeightSrc;
|
||
ULONGLONG liQuo;
|
||
ULONG ulTemp;
|
||
|
||
//
|
||
// Work around a compiler bug dealing with the assignment
|
||
// 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
|
||
//
|
||
|
||
liInit.large.LowPart = (ULONG) -1;
|
||
liInit.large.HighPart = HeightSrc - 1;
|
||
liHeightSrc = liInit.li;
|
||
|
||
liQuo = liHeightSrc / (ULONGLONG) HeightDst;
|
||
|
||
ulYDstToSrcIntCeil = (ULONG)(liQuo >> 32);
|
||
ulYDstToSrcFracCeil = (ULONG)liQuo;
|
||
|
||
//
|
||
// Now add 1, use fake carry:
|
||
//
|
||
|
||
ulTemp = ulYDstToSrcFracCeil + 1;
|
||
|
||
ulYDstToSrcIntCeil += (ulTemp < ulYDstToSrcFracCeil);
|
||
ulYDstToSrcFracCeil = ulTemp;
|
||
}
|
||
|
||
//
|
||
// Now clip Dst in X, and/or calc src clipping effect on dst
|
||
//
|
||
// adjust left and right edges if needed, record
|
||
// distance adjusted for fixing the src
|
||
//
|
||
|
||
if (XDstStart < prclClip->left)
|
||
{
|
||
XDstStart = prclClip->left;
|
||
}
|
||
|
||
if (XDstEnd > prclClip->right)
|
||
{
|
||
XDstEnd = prclClip->right;
|
||
}
|
||
|
||
//
|
||
// Check for totally clipped out destination:
|
||
//
|
||
|
||
if (XDstEnd <= XDstStart)
|
||
{
|
||
return(TRUE);
|
||
}
|
||
|
||
LeftClipDistance = XDstStart - prclDst->left;
|
||
|
||
{
|
||
ULONG ulTempInt;
|
||
ULONG ulTempFrac;
|
||
|
||
//
|
||
// Calculate displacement for .5 in destination and add:
|
||
//
|
||
|
||
ulTempFrac = (ulXDstToSrcFracCeil >> 1) | (ulXDstToSrcIntCeil << 31);
|
||
ulTempInt = (ulXDstToSrcIntCeil >> 1);
|
||
|
||
XSrcStart += ulTempInt;
|
||
ulXFracAccumulator = ulTempFrac;
|
||
|
||
if (LeftClipDistance != 0)
|
||
{
|
||
ULONGLONG ullFraction;
|
||
ULONG ulTmp;
|
||
|
||
ullFraction = UInt32x32To64(ulXDstToSrcFracCeil, LeftClipDistance);
|
||
|
||
ulTmp = ulXFracAccumulator;
|
||
ulXFracAccumulator += (ULONG) (ullFraction);
|
||
if (ulXFracAccumulator < ulTmp)
|
||
XSrcStart++;
|
||
|
||
XSrcStart += (ulXDstToSrcIntCeil * LeftClipDistance)
|
||
+ (ULONG) (ullFraction >> 32);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Now clip Dst in Y, and/or calc src clipping effect on dst
|
||
//
|
||
// adjust top and bottom edges if needed, record
|
||
// distance adjusted for fixing the src
|
||
//
|
||
|
||
if (YDstStart < prclClip->top)
|
||
{
|
||
YDstStart = prclClip->top;
|
||
}
|
||
|
||
if (YDstEnd > prclClip->bottom)
|
||
{
|
||
YDstEnd = prclClip->bottom;
|
||
}
|
||
|
||
//
|
||
// Check for totally clipped out destination:
|
||
//
|
||
|
||
if (YDstEnd <= YDstStart)
|
||
{
|
||
return(TRUE);
|
||
}
|
||
|
||
TopClipDistance = YDstStart - prclDst->top;
|
||
|
||
{
|
||
ULONG ulTempInt;
|
||
ULONG ulTempFrac;
|
||
|
||
//
|
||
// Calculate displacement for .5 in destination and add:
|
||
//
|
||
|
||
ulTempFrac = (ulYDstToSrcFracCeil >> 1) | (ulYDstToSrcIntCeil << 31);
|
||
ulTempInt = ulYDstToSrcIntCeil >> 1;
|
||
|
||
YSrcStart += (LONG)ulTempInt;
|
||
ulYFracAccumulator = ulTempFrac;
|
||
|
||
if (TopClipDistance != 0)
|
||
{
|
||
ULONGLONG ullFraction;
|
||
ULONG ulTmp;
|
||
|
||
ullFraction = UInt32x32To64(ulYDstToSrcFracCeil, TopClipDistance);
|
||
|
||
ulTmp = ulYFracAccumulator;
|
||
ulYFracAccumulator += (ULONG) (ullFraction);
|
||
if (ulYFracAccumulator < ulTmp)
|
||
YSrcStart++;
|
||
|
||
YSrcStart += (ulYDstToSrcIntCeil * TopClipDistance)
|
||
+ (ULONG) (ullFraction >> 32);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Warm up the hardware if doing an expanding stretch in 'y':
|
||
//
|
||
|
||
bStretch = (HeightDst > HeightSrc);
|
||
if (bStretch)
|
||
{
|
||
M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
|
||
//M64_OD(pjMmBase, CONTEXT_LOAD_CNTL, CONTEXT_LOAD_CmdLoad | ppdev->iDefContext );
|
||
M64_OD(pjMmBase, SRC_OFF_PITCH, ppdev->ulScreenOffsetAndPitch);
|
||
M64_OD(pjMmBase, DP_MIX, OVERPAINT << 16 );
|
||
M64_OD(pjMmBase, DP_SRC, DP_SRC_Blit << 8 );
|
||
M64_OD(pjMmBase, SRC_CNTL, SRC_CNTL_PatEna );
|
||
}
|
||
|
||
//
|
||
// Fill out blt structure, then call format-specific stretch code
|
||
//
|
||
|
||
StrBlt.ppdev = ppdev;
|
||
StrBlt.XDstEnd = XDstEnd;
|
||
StrBlt.YDstStart = YDstStart;
|
||
StrBlt.YDstCount = YDstEnd - YDstStart;
|
||
|
||
if (StrBlt.YDstCount > 0)
|
||
{
|
||
//
|
||
// Caclulate starting scan line address. Since the inner loop
|
||
// routines are format dependent, they must add XDstStart/XSrcStart
|
||
// to pjDstScan/pjSrcScan to get the actual starting pixel address.
|
||
//
|
||
|
||
StrBlt.pjSrcScan = (BYTE*) pvSrc + (YSrcStart * lDeltaSrc);
|
||
StrBlt.pjDstScan = (BYTE*) pvDst + (YDstStart * lDeltaDst);
|
||
|
||
StrBlt.lDeltaSrc = lDeltaSrc;
|
||
StrBlt.XSrcStart = XSrcStart;
|
||
StrBlt.XDstStart = XDstStart;
|
||
StrBlt.lDeltaDst = lDeltaDst;
|
||
StrBlt.ulXDstToSrcIntCeil = ulXDstToSrcIntCeil;
|
||
StrBlt.ulXDstToSrcFracCeil = ulXDstToSrcFracCeil;
|
||
StrBlt.ulYDstToSrcIntCeil = ulYDstToSrcIntCeil;
|
||
StrBlt.ulYDstToSrcFracCeil = ulYDstToSrcFracCeil;
|
||
StrBlt.ulXFracAccumulator = ulXFracAccumulator;
|
||
StrBlt.ulYFracAccumulator = ulYFracAccumulator;
|
||
|
||
if (ppdev->iBitmapFormat == BMF_8BPP)
|
||
{
|
||
if ((XDstEnd - XDstStart) < 7)
|
||
pfnStr = vDirectStretch8Narrow;
|
||
else
|
||
pfnStr = vM64DirectStretch8;
|
||
}
|
||
else if (ppdev->iBitmapFormat == BMF_16BPP)
|
||
{
|
||
pfnStr = vM64DirectStretch16;
|
||
}
|
||
else
|
||
{
|
||
ASSERTDD(ppdev->iBitmapFormat == BMF_32BPP,
|
||
"Only handle stretchs at 8, 16 and 32bpp");
|
||
|
||
pfnStr = vM64DirectStretch32;
|
||
}
|
||
|
||
(*pfnStr)(&StrBlt);
|
||
}
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
BOOL bM32StretchDIB(
|
||
PDEV* ppdev,
|
||
VOID* pvDst,
|
||
LONG lDeltaDst,
|
||
RECTL* prclDst,
|
||
VOID* pvSrc,
|
||
LONG lDeltaSrc,
|
||
RECTL* prclSrc,
|
||
RECTL* prclClip)
|
||
{
|
||
STR_BLT StrBlt;
|
||
ULONG ulXDstToSrcIntCeil;
|
||
ULONG ulXDstToSrcFracCeil;
|
||
ULONG ulYDstToSrcIntCeil;
|
||
ULONG ulYDstToSrcFracCeil;
|
||
ULONG ulXFracAccumulator;
|
||
ULONG ulYFracAccumulator;
|
||
LONG LeftClipDistance;
|
||
LONG TopClipDistance;
|
||
BOOL bStretch;
|
||
BYTE* pjMmBase = ppdev->pjMmBase;
|
||
|
||
union {
|
||
LARGE_INTEGER large;
|
||
ULONGLONG li;
|
||
} liInit;
|
||
|
||
PFN_DIRSTRETCH pfnStr;
|
||
|
||
//
|
||
// Calculate exclusive start and end points:
|
||
//
|
||
|
||
LONG WidthDst = prclDst->right - prclDst->left;
|
||
LONG HeightDst = prclDst->bottom - prclDst->top;
|
||
LONG WidthSrc = prclSrc->right - prclSrc->left;
|
||
LONG HeightSrc = prclSrc->bottom - prclSrc->top;
|
||
|
||
LONG XSrcStart = prclSrc->left;
|
||
LONG XSrcEnd = prclSrc->right;
|
||
LONG XDstStart = prclDst->left;
|
||
LONG XDstEnd = prclDst->right;
|
||
LONG YSrcStart = prclSrc->top;
|
||
LONG YSrcEnd = prclSrc->bottom;
|
||
LONG YDstStart = prclDst->top;
|
||
LONG YDstEnd = prclDst->bottom;
|
||
|
||
//
|
||
// Validate parameters:
|
||
//
|
||
|
||
ASSERTDD(pvDst != (VOID*)NULL, "Bad destination bitmap pointer");
|
||
ASSERTDD(pvSrc != (VOID*)NULL, "Bad source bitmap pointer");
|
||
ASSERTDD(prclDst != (RECTL*)NULL, "Bad destination rectangle");
|
||
ASSERTDD(prclSrc != (RECTL*)NULL, "Bad source rectangle");
|
||
ASSERTDD((WidthDst > 0) && (HeightDst > 0) &&
|
||
(WidthSrc > 0) && (HeightSrc > 0),
|
||
"Can't do mirroring or empty rectangles here");
|
||
ASSERTDD((WidthDst <= STRETCH_MAX_EXTENT) &&
|
||
(HeightDst <= STRETCH_MAX_EXTENT) &&
|
||
(WidthSrc <= STRETCH_MAX_EXTENT) &&
|
||
(HeightSrc <= STRETCH_MAX_EXTENT), "Stretch exceeds limits");
|
||
ASSERTDD(prclClip != NULL, "Bad clip rectangle");
|
||
|
||
//
|
||
// Calculate X Dst to Src mapping
|
||
//
|
||
//
|
||
// dst->src = ( CEIL( (2k*WidthSrc)/WidthDst) ) / 2k
|
||
//
|
||
// = ( FLOOR( (2k*WidthSrc -1) / WidthDst) + 1) / 2k
|
||
//
|
||
// where 2k = 2 ^ 32
|
||
//
|
||
|
||
{
|
||
ULONGLONG liWidthSrc;
|
||
ULONGLONG liQuo;
|
||
ULONG ulTemp;
|
||
|
||
//
|
||
// Work around a compiler bug dealing with the assignment
|
||
// 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
|
||
//
|
||
|
||
liInit.large.LowPart = (ULONG) -1;
|
||
liInit.large.HighPart = WidthSrc - 1;
|
||
liWidthSrc = liInit.li;
|
||
|
||
liQuo = liWidthSrc / (ULONGLONG) WidthDst;
|
||
|
||
ulXDstToSrcIntCeil = (ULONG)(liQuo >> 32);
|
||
ulXDstToSrcFracCeil = (ULONG)liQuo;
|
||
|
||
//
|
||
// Now add 1, use fake carry:
|
||
//
|
||
|
||
ulTemp = ulXDstToSrcFracCeil + 1;
|
||
|
||
ulXDstToSrcIntCeil += (ulTemp < ulXDstToSrcFracCeil);
|
||
ulXDstToSrcFracCeil = ulTemp;
|
||
}
|
||
|
||
//
|
||
// Calculate Y Dst to Src mapping
|
||
//
|
||
//
|
||
// dst->src = ( CEIL( (2k*HeightSrc)/HeightDst) ) / 2k
|
||
//
|
||
// = ( FLOOR( (2k*HeightSrc -1) / HeightDst) + 1) / 2k
|
||
//
|
||
// where 2k = 2 ^ 32
|
||
//
|
||
|
||
{
|
||
ULONGLONG liHeightSrc;
|
||
ULONGLONG liQuo;
|
||
ULONG ulTemp;
|
||
|
||
//
|
||
// Work around a compiler bug dealing with the assignment
|
||
// 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
|
||
//
|
||
|
||
liInit.large.LowPart = (ULONG) -1;
|
||
liInit.large.HighPart = HeightSrc - 1;
|
||
liHeightSrc = liInit.li;
|
||
|
||
liQuo = liHeightSrc / (ULONGLONG) HeightDst;
|
||
|
||
ulYDstToSrcIntCeil = (ULONG)(liQuo >> 32);
|
||
ulYDstToSrcFracCeil = (ULONG)liQuo;
|
||
|
||
//
|
||
// Now add 1, use fake carry:
|
||
//
|
||
|
||
ulTemp = ulYDstToSrcFracCeil + 1;
|
||
|
||
ulYDstToSrcIntCeil += (ulTemp < ulYDstToSrcFracCeil);
|
||
ulYDstToSrcFracCeil = ulTemp;
|
||
}
|
||
|
||
//
|
||
// Now clip Dst in X, and/or calc src clipping effect on dst
|
||
//
|
||
// adjust left and right edges if needed, record
|
||
// distance adjusted for fixing the src
|
||
//
|
||
|
||
if (XDstStart < prclClip->left)
|
||
{
|
||
XDstStart = prclClip->left;
|
||
}
|
||
|
||
if (XDstEnd > prclClip->right)
|
||
{
|
||
XDstEnd = prclClip->right;
|
||
}
|
||
|
||
//
|
||
// Check for totally clipped out destination:
|
||
//
|
||
|
||
if (XDstEnd <= XDstStart)
|
||
{
|
||
return(TRUE);
|
||
}
|
||
|
||
LeftClipDistance = XDstStart - prclDst->left;
|
||
|
||
{
|
||
ULONG ulTempInt;
|
||
ULONG ulTempFrac;
|
||
|
||
//
|
||
// Calculate displacement for .5 in destination and add:
|
||
//
|
||
|
||
ulTempFrac = (ulXDstToSrcFracCeil >> 1) | (ulXDstToSrcIntCeil << 31);
|
||
ulTempInt = (ulXDstToSrcIntCeil >> 1);
|
||
|
||
XSrcStart += ulTempInt;
|
||
ulXFracAccumulator = ulTempFrac;
|
||
|
||
if (LeftClipDistance != 0)
|
||
{
|
||
ULONGLONG ullFraction;
|
||
ULONG ulTmp;
|
||
|
||
ullFraction = UInt32x32To64(ulXDstToSrcFracCeil, LeftClipDistance);
|
||
|
||
ulTmp = ulXFracAccumulator;
|
||
ulXFracAccumulator += (ULONG) (ullFraction);
|
||
if (ulXFracAccumulator < ulTmp)
|
||
XSrcStart++;
|
||
|
||
XSrcStart += (ulXDstToSrcIntCeil * LeftClipDistance)
|
||
+ (ULONG) (ullFraction >> 32);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Now clip Dst in Y, and/or calc src clipping effect on dst
|
||
//
|
||
// adjust top and bottom edges if needed, record
|
||
// distance adjusted for fixing the src
|
||
//
|
||
|
||
if (YDstStart < prclClip->top)
|
||
{
|
||
YDstStart = prclClip->top;
|
||
}
|
||
|
||
if (YDstEnd > prclClip->bottom)
|
||
{
|
||
YDstEnd = prclClip->bottom;
|
||
}
|
||
|
||
//
|
||
// Check for totally clipped out destination:
|
||
//
|
||
|
||
if (YDstEnd <= YDstStart)
|
||
{
|
||
return(TRUE);
|
||
}
|
||
|
||
TopClipDistance = YDstStart - prclDst->top;
|
||
|
||
{
|
||
ULONG ulTempInt;
|
||
ULONG ulTempFrac;
|
||
|
||
//
|
||
// Calculate displacement for .5 in destination and add:
|
||
//
|
||
|
||
ulTempFrac = (ulYDstToSrcFracCeil >> 1) | (ulYDstToSrcIntCeil << 31);
|
||
ulTempInt = ulYDstToSrcIntCeil >> 1;
|
||
|
||
YSrcStart += (LONG)ulTempInt;
|
||
ulYFracAccumulator = ulTempFrac;
|
||
|
||
if (TopClipDistance != 0)
|
||
{
|
||
ULONGLONG ullFraction;
|
||
ULONG ulTmp;
|
||
|
||
ullFraction = UInt32x32To64(ulYDstToSrcFracCeil, TopClipDistance);
|
||
|
||
ulTmp = ulYFracAccumulator;
|
||
ulYFracAccumulator += (ULONG) (ullFraction);
|
||
if (ulYFracAccumulator < ulTmp)
|
||
YSrcStart++;
|
||
|
||
YSrcStart += (ulYDstToSrcIntCeil * TopClipDistance)
|
||
+ (ULONG) (ullFraction >> 32);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Warm up the hardware if doing an expanding stretch in 'y':
|
||
//
|
||
|
||
bStretch = (HeightDst > HeightSrc);
|
||
if (bStretch)
|
||
{
|
||
M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 3);
|
||
M32_OW(pjMmBase, DP_CONFIG, 0x6011 );
|
||
M32_OW(pjMmBase, ALU_FG_FN, OVERPAINT );
|
||
M32_OW(pjMmBase, SRC_Y_DIR, 1 );
|
||
}
|
||
|
||
//
|
||
// Fill out blt structure, then call format-specific stretch code
|
||
//
|
||
|
||
StrBlt.ppdev = ppdev;
|
||
StrBlt.XDstEnd = XDstEnd;
|
||
StrBlt.YDstStart = YDstStart;
|
||
StrBlt.YDstCount = YDstEnd - YDstStart;
|
||
|
||
if (StrBlt.YDstCount > 0)
|
||
{
|
||
//
|
||
// Caclulate starting scan line address. Since the inner loop
|
||
// routines are format dependent, they must add XDstStart/XSrcStart
|
||
// to pjDstScan/pjSrcScan to get the actual starting pixel address.
|
||
//
|
||
|
||
StrBlt.pjSrcScan = (BYTE*) pvSrc + (YSrcStart * lDeltaSrc);
|
||
StrBlt.pjDstScan = (BYTE*) pvDst + (YDstStart * lDeltaDst);
|
||
|
||
StrBlt.lDeltaSrc = lDeltaSrc;
|
||
StrBlt.XSrcStart = XSrcStart;
|
||
StrBlt.XDstStart = XDstStart;
|
||
StrBlt.lDeltaDst = lDeltaDst;
|
||
StrBlt.ulXDstToSrcIntCeil = ulXDstToSrcIntCeil;
|
||
StrBlt.ulXDstToSrcFracCeil = ulXDstToSrcFracCeil;
|
||
StrBlt.ulYDstToSrcIntCeil = ulYDstToSrcIntCeil;
|
||
StrBlt.ulYDstToSrcFracCeil = ulYDstToSrcFracCeil;
|
||
StrBlt.ulXFracAccumulator = ulXFracAccumulator;
|
||
StrBlt.ulYFracAccumulator = ulYFracAccumulator;
|
||
|
||
if (ppdev->iBitmapFormat == BMF_8BPP)
|
||
{
|
||
if ((XDstEnd - XDstStart) < 7)
|
||
pfnStr = vDirectStretch8Narrow;
|
||
else
|
||
pfnStr = vM32DirectStretch8;
|
||
}
|
||
else if (ppdev->iBitmapFormat == BMF_16BPP)
|
||
{
|
||
pfnStr = vM32DirectStretch16;
|
||
}
|
||
else
|
||
{
|
||
return FALSE; // should never come here.
|
||
}
|
||
|
||
(*pfnStr)(&StrBlt);
|
||
}
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
BOOL bI32StretchDIB(
|
||
PDEV* ppdev,
|
||
VOID* pvDst,
|
||
LONG lDeltaDst,
|
||
RECTL* prclDst,
|
||
VOID* pvSrc,
|
||
LONG lDeltaSrc,
|
||
RECTL* prclSrc,
|
||
RECTL* prclClip)
|
||
{
|
||
STR_BLT StrBlt;
|
||
ULONG ulXDstToSrcIntCeil;
|
||
ULONG ulXDstToSrcFracCeil;
|
||
ULONG ulYDstToSrcIntCeil;
|
||
ULONG ulYDstToSrcFracCeil;
|
||
ULONG ulXFracAccumulator;
|
||
ULONG ulYFracAccumulator;
|
||
LONG LeftClipDistance;
|
||
LONG TopClipDistance;
|
||
BOOL bStretch;
|
||
BYTE* pjIoBase = ppdev->pjIoBase;
|
||
|
||
union {
|
||
LARGE_INTEGER large;
|
||
ULONGLONG li;
|
||
} liInit;
|
||
|
||
PFN_DIRSTRETCH pfnStr;
|
||
|
||
//
|
||
// Calculate exclusive start and end points:
|
||
//
|
||
|
||
LONG WidthDst = prclDst->right - prclDst->left;
|
||
LONG HeightDst = prclDst->bottom - prclDst->top;
|
||
LONG WidthSrc = prclSrc->right - prclSrc->left;
|
||
LONG HeightSrc = prclSrc->bottom - prclSrc->top;
|
||
|
||
LONG XSrcStart = prclSrc->left;
|
||
LONG XSrcEnd = prclSrc->right;
|
||
LONG XDstStart = prclDst->left;
|
||
LONG XDstEnd = prclDst->right;
|
||
LONG YSrcStart = prclSrc->top;
|
||
LONG YSrcEnd = prclSrc->bottom;
|
||
LONG YDstStart = prclDst->top;
|
||
LONG YDstEnd = prclDst->bottom;
|
||
|
||
//
|
||
// Validate parameters:
|
||
//
|
||
|
||
ASSERTDD(pvDst != (VOID*)NULL, "Bad destination bitmap pointer");
|
||
ASSERTDD(pvSrc != (VOID*)NULL, "Bad source bitmap pointer");
|
||
ASSERTDD(prclDst != (RECTL*)NULL, "Bad destination rectangle");
|
||
ASSERTDD(prclSrc != (RECTL*)NULL, "Bad source rectangle");
|
||
ASSERTDD((WidthDst > 0) && (HeightDst > 0) &&
|
||
(WidthSrc > 0) && (HeightSrc > 0),
|
||
"Can't do mirroring or empty rectangles here");
|
||
ASSERTDD((WidthDst <= STRETCH_MAX_EXTENT) &&
|
||
(HeightDst <= STRETCH_MAX_EXTENT) &&
|
||
(WidthSrc <= STRETCH_MAX_EXTENT) &&
|
||
(HeightSrc <= STRETCH_MAX_EXTENT), "Stretch exceeds limits");
|
||
ASSERTDD(prclClip != NULL, "Bad clip rectangle");
|
||
|
||
//
|
||
// Calculate X Dst to Src mapping
|
||
//
|
||
//
|
||
// dst->src = ( CEIL( (2k*WidthSrc)/WidthDst) ) / 2k
|
||
//
|
||
// = ( FLOOR( (2k*WidthSrc -1) / WidthDst) + 1) / 2k
|
||
//
|
||
// where 2k = 2 ^ 32
|
||
//
|
||
|
||
{
|
||
ULONGLONG liWidthSrc;
|
||
ULONGLONG liQuo;
|
||
ULONG ulTemp;
|
||
|
||
//
|
||
// Work around a compiler bug dealing with the assignment
|
||
// 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
|
||
//
|
||
|
||
liInit.large.LowPart = (ULONG) -1;
|
||
liInit.large.HighPart = WidthSrc - 1;
|
||
liWidthSrc = liInit.li;
|
||
|
||
liQuo = liWidthSrc / (ULONGLONG) WidthDst;
|
||
|
||
ulXDstToSrcIntCeil = (ULONG)(liQuo >> 32);
|
||
ulXDstToSrcFracCeil = (ULONG)liQuo;
|
||
|
||
//
|
||
// Now add 1, use fake carry:
|
||
//
|
||
|
||
ulTemp = ulXDstToSrcFracCeil + 1;
|
||
|
||
ulXDstToSrcIntCeil += (ulTemp < ulXDstToSrcFracCeil);
|
||
ulXDstToSrcFracCeil = ulTemp;
|
||
}
|
||
|
||
//
|
||
// Calculate Y Dst to Src mapping
|
||
//
|
||
//
|
||
// dst->src = ( CEIL( (2k*HeightSrc)/HeightDst) ) / 2k
|
||
//
|
||
// = ( FLOOR( (2k*HeightSrc -1) / HeightDst) + 1) / 2k
|
||
//
|
||
// where 2k = 2 ^ 32
|
||
//
|
||
|
||
{
|
||
ULONGLONG liHeightSrc;
|
||
ULONGLONG liQuo;
|
||
ULONG ulTemp;
|
||
|
||
//
|
||
// Work around a compiler bug dealing with the assignment
|
||
// 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
|
||
//
|
||
|
||
liInit.large.LowPart = (ULONG) -1;
|
||
liInit.large.HighPart = HeightSrc - 1;
|
||
liHeightSrc = liInit.li;
|
||
|
||
liQuo = liHeightSrc / (ULONGLONG) HeightDst;
|
||
|
||
ulYDstToSrcIntCeil = (ULONG)(liQuo >> 32);
|
||
ulYDstToSrcFracCeil = (ULONG)liQuo;
|
||
|
||
//
|
||
// Now add 1, use fake carry:
|
||
//
|
||
|
||
ulTemp = ulYDstToSrcFracCeil + 1;
|
||
|
||
ulYDstToSrcIntCeil += (ulTemp < ulYDstToSrcFracCeil);
|
||
ulYDstToSrcFracCeil = ulTemp;
|
||
}
|
||
|
||
//
|
||
// Now clip Dst in X, and/or calc src clipping effect on dst
|
||
//
|
||
// adjust left and right edges if needed, record
|
||
// distance adjusted for fixing the src
|
||
//
|
||
|
||
if (XDstStart < prclClip->left)
|
||
{
|
||
XDstStart = prclClip->left;
|
||
}
|
||
|
||
if (XDstEnd > prclClip->right)
|
||
{
|
||
XDstEnd = prclClip->right;
|
||
}
|
||
|
||
//
|
||
// Check for totally clipped out destination:
|
||
//
|
||
|
||
if (XDstEnd <= XDstStart)
|
||
{
|
||
return(TRUE);
|
||
}
|
||
|
||
LeftClipDistance = XDstStart - prclDst->left;
|
||
|
||
{
|
||
ULONG ulTempInt;
|
||
ULONG ulTempFrac;
|
||
|
||
//
|
||
// Calculate displacement for .5 in destination and add:
|
||
//
|
||
|
||
ulTempFrac = (ulXDstToSrcFracCeil >> 1) | (ulXDstToSrcIntCeil << 31);
|
||
ulTempInt = (ulXDstToSrcIntCeil >> 1);
|
||
|
||
XSrcStart += ulTempInt;
|
||
ulXFracAccumulator = ulTempFrac;
|
||
|
||
if (LeftClipDistance != 0)
|
||
{
|
||
ULONGLONG ullFraction;
|
||
ULONG ulTmp;
|
||
|
||
ullFraction = UInt32x32To64(ulXDstToSrcFracCeil, LeftClipDistance);
|
||
|
||
ulTmp = ulXFracAccumulator;
|
||
ulXFracAccumulator += (ULONG) (ullFraction);
|
||
if (ulXFracAccumulator < ulTmp)
|
||
XSrcStart++;
|
||
|
||
XSrcStart += (ulXDstToSrcIntCeil * LeftClipDistance)
|
||
+ (ULONG) (ullFraction >> 32);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Now clip Dst in Y, and/or calc src clipping effect on dst
|
||
//
|
||
// adjust top and bottom edges if needed, record
|
||
// distance adjusted for fixing the src
|
||
//
|
||
|
||
if (YDstStart < prclClip->top)
|
||
{
|
||
YDstStart = prclClip->top;
|
||
}
|
||
|
||
if (YDstEnd > prclClip->bottom)
|
||
{
|
||
YDstEnd = prclClip->bottom;
|
||
}
|
||
|
||
//
|
||
// Check for totally clipped out destination:
|
||
//
|
||
|
||
if (YDstEnd <= YDstStart)
|
||
{
|
||
return(TRUE);
|
||
}
|
||
|
||
TopClipDistance = YDstStart - prclDst->top;
|
||
|
||
{
|
||
ULONG ulTempInt;
|
||
ULONG ulTempFrac;
|
||
|
||
//
|
||
// Calculate displacement for .5 in destination and add:
|
||
//
|
||
|
||
ulTempFrac = (ulYDstToSrcFracCeil >> 1) | (ulYDstToSrcIntCeil << 31);
|
||
ulTempInt = ulYDstToSrcIntCeil >> 1;
|
||
|
||
YSrcStart += (LONG)ulTempInt;
|
||
ulYFracAccumulator = ulTempFrac;
|
||
|
||
if (TopClipDistance != 0)
|
||
{
|
||
ULONGLONG ullFraction;
|
||
ULONG ulTmp;
|
||
|
||
ullFraction = UInt32x32To64(ulYDstToSrcFracCeil, TopClipDistance);
|
||
|
||
ulTmp = ulYFracAccumulator;
|
||
ulYFracAccumulator += (ULONG) (ullFraction);
|
||
if (ulYFracAccumulator < ulTmp)
|
||
YSrcStart++;
|
||
|
||
YSrcStart += (ulYDstToSrcIntCeil * TopClipDistance)
|
||
+ (ULONG) (ullFraction >> 32);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Warm up the hardware if doing an expanding stretch in 'y':
|
||
//
|
||
|
||
bStretch = (HeightDst > HeightSrc);
|
||
if (bStretch)
|
||
{
|
||
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 3);
|
||
I32_OW(pjIoBase, DP_CONFIG, 0x6011 );
|
||
I32_OW(pjIoBase, ALU_FG_FN, OVERPAINT );
|
||
I32_OW(pjIoBase, SRC_Y_DIR, 1 );
|
||
}
|
||
|
||
//
|
||
// Fill out blt structure, then call format-specific stretch code
|
||
//
|
||
|
||
StrBlt.ppdev = ppdev;
|
||
StrBlt.XDstEnd = XDstEnd;
|
||
StrBlt.YDstStart = YDstStart;
|
||
StrBlt.YDstCount = YDstEnd - YDstStart;
|
||
|
||
if (StrBlt.YDstCount > 0)
|
||
{
|
||
//
|
||
// Caclulate starting scan line address. Since the inner loop
|
||
// routines are format dependent, they must add XDstStart/XSrcStart
|
||
// to pjDstScan/pjSrcScan to get the actual starting pixel address.
|
||
//
|
||
|
||
StrBlt.pjSrcScan = (BYTE*) pvSrc + (YSrcStart * lDeltaSrc);
|
||
StrBlt.pjDstScan = (BYTE*) pvDst + (YDstStart * lDeltaDst);
|
||
|
||
StrBlt.lDeltaSrc = lDeltaSrc;
|
||
StrBlt.XSrcStart = XSrcStart;
|
||
StrBlt.XDstStart = XDstStart;
|
||
StrBlt.lDeltaDst = lDeltaDst;
|
||
StrBlt.ulXDstToSrcIntCeil = ulXDstToSrcIntCeil;
|
||
StrBlt.ulXDstToSrcFracCeil = ulXDstToSrcFracCeil;
|
||
StrBlt.ulYDstToSrcIntCeil = ulYDstToSrcIntCeil;
|
||
StrBlt.ulYDstToSrcFracCeil = ulYDstToSrcFracCeil;
|
||
StrBlt.ulXFracAccumulator = ulXFracAccumulator;
|
||
StrBlt.ulYFracAccumulator = ulYFracAccumulator;
|
||
|
||
if (ppdev->iBitmapFormat == BMF_8BPP)
|
||
{
|
||
if ((XDstEnd - XDstStart) < 7)
|
||
pfnStr = vDirectStretch8Narrow;
|
||
else
|
||
pfnStr = vI32DirectStretch8;
|
||
}
|
||
else if (ppdev->iBitmapFormat == BMF_16BPP)
|
||
{
|
||
pfnStr = vI32DirectStretch16;
|
||
}
|
||
else
|
||
{
|
||
return FALSE; // should never come here.
|
||
}
|
||
|
||
(*pfnStr)(&StrBlt);
|
||
}
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
/******************************Public*Routine******************************\
|
||
* BOOL bBankedStretch
|
||
*
|
||
\**************************************************************************/
|
||
|
||
BOOL bBankedStretch(
|
||
PDEV* ppdev,
|
||
VOID* pvDst,
|
||
LONG lDeltaDst,
|
||
RECTL* prclDst,
|
||
VOID* pvSrc,
|
||
LONG lDeltaSrc,
|
||
RECTL* prclSrc,
|
||
RECTL* prclClip)
|
||
{
|
||
BANK bnk;
|
||
BOOL b;
|
||
RECTL rclDst;
|
||
|
||
b = TRUE;
|
||
if (bIntersect(prclDst, prclClip, &rclDst))
|
||
{
|
||
vBankStart(ppdev, &rclDst, NULL, &bnk);
|
||
|
||
do {
|
||
b &= ppdev->pfnStretchDIB(ppdev,
|
||
bnk.pso->pvScan0,
|
||
lDeltaDst,
|
||
prclDst,
|
||
pvSrc,
|
||
lDeltaSrc,
|
||
prclSrc,
|
||
&bnk.pco->rclBounds);
|
||
|
||
} while (bBankEnum(&bnk));
|
||
}
|
||
|
||
return(b);
|
||
}
|
||
|
||
/******************************Public*Routine******************************\
|
||
* BOOL DrvStretchBlt
|
||
*
|
||
\**************************************************************************/
|
||
|
||
#if defined(ALPHA)
|
||
#define DENSE(ppdev) (ppdev->FeatureFlags & EVN_DENSE_CAPABLE)
|
||
#else
|
||
#define DENSE(ppdev) (ppdev->iAperture != APERTURE_NONE)
|
||
#endif
|
||
|
||
BOOL DrvStretchBlt(
|
||
SURFOBJ* psoDst,
|
||
SURFOBJ* psoSrc,
|
||
SURFOBJ* psoMsk,
|
||
CLIPOBJ* pco,
|
||
XLATEOBJ* pxlo,
|
||
COLORADJUSTMENT* pca,
|
||
POINTL* pptlHTOrg,
|
||
RECTL* prclDst,
|
||
RECTL* prclSrc,
|
||
POINTL* pptlMsk,
|
||
ULONG iMode)
|
||
{
|
||
DSURF* pdsurfSrc;
|
||
DSURF* pdsurfDst;
|
||
PDEV* ppdev;
|
||
OH* poh;
|
||
|
||
// GDI guarantees us that for a StretchBlt the destination surface
|
||
// will always be a device surface, and not a DIB:
|
||
|
||
ppdev = (PDEV*) psoDst->dhpdev;
|
||
|
||
// It's quicker for GDI to do a StretchBlt when the source surface
|
||
// is not a device-managed surface, because then it can directly
|
||
// read the source bits without having to allocate a temporary
|
||
// buffer and call DrvCopyBits to get a copy that it can use.
|
||
|
||
if (psoSrc->iType == STYPE_DEVBITMAP)
|
||
{
|
||
pdsurfSrc = (DSURF*) psoSrc->dhsurf;
|
||
if (pdsurfSrc->dt == DT_SCREEN)
|
||
goto Punt_It;
|
||
|
||
ASSERTDD(pdsurfSrc->dt == DT_DIB, "Can only handle DIB DFBs here");
|
||
|
||
psoSrc = pdsurfSrc->pso;
|
||
}
|
||
|
||
pdsurfDst = (DSURF*) psoDst->dhsurf;
|
||
if (pdsurfDst->dt == DT_DIB)
|
||
{
|
||
// The destination was a device bitmap that we just converted
|
||
// to a DIB:
|
||
|
||
psoDst = pdsurfDst->pso;
|
||
goto Punt_It;
|
||
}
|
||
|
||
poh = pdsurfDst->poh;
|
||
ppdev->xOffset = poh->x;
|
||
ppdev->yOffset = poh->y;
|
||
|
||
// Our special-case StretchBlt code assumes a dense frame buffer
|
||
// space, so this code can't be executed when using sparse space
|
||
// on the Alpha. Note that since we don't read from the frame
|
||
// buffer, we can allow this to go through even when
|
||
// CAPS_NO_DIRECT_ACCESS is set on the PPC.
|
||
//
|
||
// Also, because of the VTA4 screen source FIFO problem, we punt
|
||
// stretch blits for the VTA4.
|
||
|
||
if (DENSE(ppdev) && !(ppdev->FeatureFlags & EVN_SDRAM_1M))
|
||
{
|
||
RECTL rclClip;
|
||
RECTL* prclClip;
|
||
ULONG cxDst;
|
||
ULONG cyDst;
|
||
ULONG cxSrc;
|
||
ULONG cySrc;
|
||
BOOL bMore;
|
||
CLIPENUM ce;
|
||
LONG c;
|
||
LONG i;
|
||
|
||
if ((psoSrc->iType == STYPE_BITMAP) &&
|
||
(psoMsk == NULL) &&
|
||
((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) &&
|
||
((psoSrc->iBitmapFormat == ppdev->iBitmapFormat)) &&
|
||
(ppdev->iBitmapFormat != BMF_24BPP))
|
||
{
|
||
cxDst = prclDst->right - prclDst->left;
|
||
cyDst = prclDst->bottom - prclDst->top;
|
||
cxSrc = prclSrc->right - prclSrc->left;
|
||
cySrc = prclSrc->bottom - prclSrc->top;
|
||
|
||
// Our 'bStretchDIB' routine requires that the stretch be
|
||
// non-inverting, within a certain size, to have no source
|
||
// clipping, and to have no empty rectangles (the latter is the
|
||
// reason for the '- 1' on the unsigned compare here):
|
||
|
||
if (((cxSrc - 1) < STRETCH_MAX_EXTENT) &&
|
||
((cySrc - 1) < STRETCH_MAX_EXTENT) &&
|
||
((cxDst - 1) < STRETCH_MAX_EXTENT) &&
|
||
((cyDst - 1) < STRETCH_MAX_EXTENT) &&
|
||
(prclSrc->left >= 0) &&
|
||
(prclSrc->top >= 0) &&
|
||
(prclSrc->right <= psoSrc->sizlBitmap.cx) &&
|
||
(prclSrc->bottom <= psoSrc->sizlBitmap.cy))
|
||
{
|
||
// Our snazzy routine only does COLORONCOLOR. But for
|
||
// stretching blts, BLACKONWHITE and WHITEONBLACK are also
|
||
// equivalent to COLORONCOLOR:
|
||
|
||
if ((iMode == COLORONCOLOR) ||
|
||
((iMode < COLORONCOLOR) && (cxSrc <= cxDst) && (cySrc <= cyDst)))
|
||
{
|
||
if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
|
||
{
|
||
rclClip.left = 0;
|
||
rclClip.top = 0;
|
||
rclClip.right = poh->cx;
|
||
rclClip.bottom = poh->cy; // Extents of surface
|
||
prclClip = &rclClip;
|
||
|
||
StretchSingleClipRect:
|
||
|
||
if (bBankedStretch(ppdev,
|
||
NULL,
|
||
ppdev->lDelta,
|
||
prclDst,
|
||
psoSrc->pvScan0,
|
||
psoSrc->lDelta,
|
||
prclSrc,
|
||
prclClip))
|
||
{
|
||
return(TRUE);
|
||
}
|
||
}
|
||
else if (pco->iDComplexity == DC_RECT)
|
||
{
|
||
prclClip = &pco->rclBounds;
|
||
goto StretchSingleClipRect;
|
||
}
|
||
else
|
||
{
|
||
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
|
||
|
||
do {
|
||
bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
|
||
|
||
c = cIntersect(prclDst, ce.arcl, ce.c);
|
||
|
||
if (c != 0)
|
||
{
|
||
for (i = 0; i < c; i++)
|
||
{
|
||
if (!bBankedStretch(ppdev,
|
||
NULL,
|
||
ppdev->lDelta,
|
||
prclDst,
|
||
psoSrc->pvScan0,
|
||
psoSrc->lDelta,
|
||
prclSrc,
|
||
&ce.arcl[i]))
|
||
{
|
||
goto Punt_It;
|
||
}
|
||
}
|
||
}
|
||
|
||
} while (bMore);
|
||
|
||
return(TRUE);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Punt_It:
|
||
|
||
// GDI is nice enough to handle the cases where 'psoDst' and/or 'psoSrc'
|
||
// are device-managed surfaces, but it ain't gonna be fast...
|
||
|
||
return(EngStretchBlt(psoDst, psoSrc, psoMsk, pco, pxlo, pca, pptlHTOrg,
|
||
prclDst, prclSrc, pptlMsk, iMode));
|
||
}
|
||
|