2291 lines
72 KiB
C
2291 lines
72 KiB
C
|
/******************************************************************************\
|
|||
|
*
|
|||
|
* $Workfile: bltmm.c $
|
|||
|
*
|
|||
|
* Contains the low-level MM blt functions.
|
|||
|
*
|
|||
|
* Hopefully, if you're basing your display driver on this code, to support all
|
|||
|
* of DrvBitBlt and DrvCopyBits, you'll only have to implement the following
|
|||
|
* routines. You shouldn't have to modify much in 'bitblt.c'. I've tried to make
|
|||
|
* these routines as few, modular, simple, and efficient as I could, while still
|
|||
|
* accelerating as many calls as possible that would be cost-effective in terms
|
|||
|
* of performance wins versus size and effort.
|
|||
|
*
|
|||
|
* Note: In the following, 'relative' coordinates refers to coordinates that
|
|||
|
* haven't yet had the offscreen bitmap (DFB) offset applied. 'Absolute'
|
|||
|
* coordinates have had the offset applied. For example, we may be told to
|
|||
|
* blt to (1, 1) of the bitmap, but the bitmap may be sitting in offscreen
|
|||
|
* memory starting at coordinate (0, 768) -- (1, 1) would be the
|
|||
|
* 'relative' start coordinate, and (1, 769) would be the 'absolute' start
|
|||
|
* coordinate'.
|
|||
|
*
|
|||
|
* Copyright (c) 1992-1995 Microsoft Corporation
|
|||
|
* Copyright (c) 1996 Cirrus Logic, Inc.
|
|||
|
*
|
|||
|
* $Log: S:/projects/drivers/ntsrc/display/bltmm.c_v $
|
|||
|
*
|
|||
|
* Rev 1.4 Jan 14 1997 15:16:14 unknown
|
|||
|
* take out GR33 clearing after 80 blt.
|
|||
|
*
|
|||
|
* Rev 1.2 Nov 07 1996 16:47:52 unknown
|
|||
|
*
|
|||
|
*
|
|||
|
* Rev 1.1 Oct 10 1996 15:36:14 unknown
|
|||
|
*
|
|||
|
*
|
|||
|
* Rev 1.4 12 Aug 1996 16:58:56 frido
|
|||
|
* Removed unaccessed local variables.
|
|||
|
* Renamed vMmPatternBlt into vMmFillPat36.
|
|||
|
*
|
|||
|
* Rev 1.3 08 Aug 1996 16:55:10 frido
|
|||
|
* Added new vMmCopyBlt36 routine.
|
|||
|
*
|
|||
|
* Rev 1.2 08 Aug 1996 12:59:28 frido
|
|||
|
* bank#1 - Removed banking code since MMIO is always linear.
|
|||
|
*
|
|||
|
* Rev 1.1 31 Jul 1996 15:43:14 frido
|
|||
|
* Added new pattern blit.
|
|||
|
*
|
|||
|
* jl01 10-08-96 Do Transparent BLT w/o Solid Fill. Refer to PDRs#5511/6817.
|
|||
|
* chu01 01-09-97 Make sure to reset GR33.
|
|||
|
*
|
|||
|
\******************************************************************************/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
|
|||
|
|
|||
|
/**************************************************************************
|
|||
|
* VOID vMmFastPatRealize
|
|||
|
*
|
|||
|
* Realizes a pattern into offscreen memory.
|
|||
|
*
|
|||
|
**************************************************************************/
|
|||
|
|
|||
|
VOID vMmFastPatRealize(
|
|||
|
PDEV* ppdev,
|
|||
|
RBRUSH* prb) // Points to brush realization structure
|
|||
|
{
|
|||
|
BRUSHENTRY* pbe;
|
|||
|
LONG iBrushCache;
|
|||
|
BYTE* pjPattern;
|
|||
|
LONG cjPattern;
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
LONG lDeltaPat;
|
|||
|
LONG lDeltaSrc;
|
|||
|
LONG xCnt;
|
|||
|
LONG yCnt;
|
|||
|
ULONG ulDst;
|
|||
|
|
|||
|
DISPDBG((10,"vFastPatRealize called"));
|
|||
|
|
|||
|
pbe = prb->pbe;
|
|||
|
|
|||
|
if ((pbe == NULL) || (pbe->prbVerify != prb))
|
|||
|
{
|
|||
|
// We have to allocate a new offscreen cache brush entry for
|
|||
|
// the brush:
|
|||
|
|
|||
|
iBrushCache = ppdev->iBrushCache;
|
|||
|
pbe = &ppdev->abe[iBrushCache];
|
|||
|
|
|||
|
iBrushCache++;
|
|||
|
if (iBrushCache >= ppdev->cBrushCache)
|
|||
|
iBrushCache = 0;
|
|||
|
|
|||
|
ppdev->iBrushCache = iBrushCache;
|
|||
|
|
|||
|
// Update our links:
|
|||
|
|
|||
|
pbe->prbVerify = prb;
|
|||
|
prb->pbe = pbe;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Download brush into cache
|
|||
|
//
|
|||
|
|
|||
|
pjPattern = (PBYTE) &prb->aulPattern[0]; // Copy from brush buffer
|
|||
|
cjPattern = PELS_TO_BYTES(TOTAL_BRUSH_SIZE);
|
|||
|
|
|||
|
lDeltaPat = PELS_TO_BYTES(8);
|
|||
|
xCnt = PELS_TO_BYTES(8);
|
|||
|
yCnt = 8;
|
|||
|
|
|||
|
if (ppdev->cBitsPerPixel == 24)
|
|||
|
{
|
|||
|
lDeltaSrc = 32; // same as PELS_TO_BYTES(8) for 32bpp
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
lDeltaSrc = lDeltaPat; // PELS_TO_BYTES(8)
|
|||
|
}
|
|||
|
|
|||
|
ulDst = (pbe->y * ppdev->lDelta) + PELS_TO_BYTES(pbe->x);
|
|||
|
|
|||
|
#if BANKING //bank#1
|
|||
|
ppdev->pfnBankMap(ppdev, ppdev->lXferBank);
|
|||
|
#endif
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, (lDeltaSrc * 2));
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (xCnt - 1));
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (yCnt - 1));
|
|||
|
#if 1 // D5480
|
|||
|
CP_MM_BLT_MODE_PACKED(ppdev, pjBase, CL_PACKED_SRC_COPY | SRC_CPU_DATA);
|
|||
|
#else
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, SRC_CPU_DATA);
|
|||
|
CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
|
|||
|
CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
|
|||
|
#endif // D5480
|
|||
|
CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDst);
|
|||
|
|
|||
|
CP_MM_START_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
vImageTransfer(ppdev, pjPattern, lDeltaPat, xCnt, yCnt);
|
|||
|
|
|||
|
//
|
|||
|
// Duplicate brush horizontally
|
|||
|
//
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (xCnt - 1));
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (yCnt - 1));
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, 0);
|
|||
|
CP_MM_SRC_Y_OFFSET(ppdev, pjBase, (lDeltaSrc * 2));
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, ulDst);
|
|||
|
CP_MM_DST_ADDR_ABS(ppdev, pjBase, (ulDst + lDeltaPat));
|
|||
|
|
|||
|
CP_MM_START_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
//
|
|||
|
// Duplicate brush vertically
|
|||
|
//
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_SRC_Y_OFFSET(ppdev, pjBase, (lDeltaSrc * 2));
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, (lDeltaSrc * 2));
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, 0);
|
|||
|
CP_MM_XCNT(ppdev, pjBase, ((lDeltaSrc * 2) - 1));
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (yCnt - 1));
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, ulDst);
|
|||
|
|
|||
|
if (ppdev->cBitsPerPixel == 24)
|
|||
|
{
|
|||
|
CP_MM_DST_ADDR_ABS(ppdev, pjBase, (ulDst + 512)); // 128 * 4
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CP_MM_DST_ADDR_ABS(ppdev, pjBase, (ulDst + PELS_TO_BYTES(128)));
|
|||
|
}
|
|||
|
|
|||
|
CP_MM_START_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
#if 0
|
|||
|
{
|
|||
|
////////////////////////////////////////////////////////////////
|
|||
|
// DEBUG TILED PATTERNS
|
|||
|
//
|
|||
|
// The following code helps to debug patterns if you break the
|
|||
|
// realization code. It copies the 2x2 tiled copy of the brush
|
|||
|
// to the visible screen.
|
|||
|
//
|
|||
|
|
|||
|
POINTL ptl;
|
|||
|
RECTL rcl;
|
|||
|
|
|||
|
ptl.x = pbe->x;
|
|||
|
ptl.y = pbe->y;
|
|||
|
|
|||
|
rcl.left = 10;
|
|||
|
rcl.right = 10 + 16;
|
|||
|
rcl.top = ppdev->cyScreen - 10 - 16;
|
|||
|
rcl.bottom = ppdev->cyScreen - 10;
|
|||
|
|
|||
|
{
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
BYTE jHwRop;
|
|||
|
BYTE jMode;
|
|||
|
|
|||
|
//
|
|||
|
// Make sure we can write to the video registers.
|
|||
|
//
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
|
|||
|
CP_MM_SRC_Y_OFFSET(ppdev, pjBase, PELS_TO_BYTES(16));
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
|
|||
|
{
|
|||
|
//
|
|||
|
// Top to Bottom - Left to Right
|
|||
|
//
|
|||
|
|
|||
|
jMode |= DIR_TBLR;
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, ppdev->jModeColor);
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (PELS_TO_BYTES(rcl.right - rcl.left) - 1));
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (rcl.bottom - rcl.top - 1));
|
|||
|
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, (0 + ((ptl.y) * lDelta) + PELS_TO_BYTES(ptl.x)));
|
|||
|
CP_MM_DST_ADDR_ABS(ppdev, pjBase, ((rcl.top * lDelta) + PELS_TO_BYTES(rcl.left)));
|
|||
|
CP_MM_START_BLT(ppdev, pjBase);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
/**************************************************************************
|
|||
|
* VOID vMmFillPat
|
|||
|
*
|
|||
|
* This routine uses the pattern hardware to draw a patterned list of
|
|||
|
* rectangles.
|
|||
|
*
|
|||
|
**************************************************************************/
|
|||
|
|
|||
|
VOID vMmFillPat(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c, // Can't be zero
|
|||
|
RECTL* prcl, // Array of relative coordinate destination rects
|
|||
|
ROP4 rop4, // Obvious?
|
|||
|
RBRUSH_COLOR rbc, // Drawing color is rbc.iSolidColor
|
|||
|
POINTL* pptlBrush) //
|
|||
|
{
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
ULONG ulAlignedPatternOffset = ppdev->ulAlignedPatternOffset;
|
|||
|
ULONG ulPatternAddrBase;
|
|||
|
BYTE jHwRop;
|
|||
|
BYTE jMode;
|
|||
|
BRUSHENTRY* pbe; // Pointer to brush entry data, which is used
|
|||
|
// for keeping track of the location and status
|
|||
|
// of the pattern bits cached in off-screen
|
|||
|
// memory
|
|||
|
|
|||
|
DISPDBG((10,"vFillPat called"));
|
|||
|
|
|||
|
ASSERTDD(c > 0, "Can't handle zero rectangles");
|
|||
|
ASSERTDD(ppdev->cBpp < 4, "vFillPat only works at 8bpp, 16bpp, and 24bpp");
|
|||
|
|
|||
|
if ((rbc.prb->pbe == NULL) ||
|
|||
|
(rbc.prb->pbe->prbVerify != rbc.prb))
|
|||
|
{
|
|||
|
vMmFastPatRealize(ppdev, rbc.prb);
|
|||
|
DISPDBG((5, " -- Brush cache miss, put it at (%d,%d)", rbc.prb->pbe->x, rbc.prb->pbe->y));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
DISPDBG((5, " -- Brush cache hit on brush at (%d,%d)", rbc.prb->pbe->x, rbc.prb->pbe->y));
|
|||
|
}
|
|||
|
|
|||
|
pbe = rbc.prb->pbe;
|
|||
|
|
|||
|
//
|
|||
|
// Fill the list of rectangles
|
|||
|
//
|
|||
|
|
|||
|
ulPatternAddrBase = pbe->xy;
|
|||
|
jHwRop = gajHwMixFromRop2[(rop4 >> 2) & 0xf];
|
|||
|
jMode = ppdev->jModeColor | ENABLE_8x8_PATTERN_COPY;
|
|||
|
|
|||
|
do {
|
|||
|
ULONG offset = 0;
|
|||
|
ULONG XOffset, YOffset;
|
|||
|
|
|||
|
YOffset = ((prcl->top - pptlBrush->y) & 7) << 4;
|
|||
|
XOffset = (prcl->left - pptlBrush->x) & 7;
|
|||
|
|
|||
|
// align the pattern to a new location
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
#if 1 // D5480
|
|||
|
CP_MM_BLT_MODE_PACKED(ppdev, pjBase, CL_PACKED_SRC_COPY);
|
|||
|
#else
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, 0);
|
|||
|
CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
|
|||
|
#endif // D5480
|
|||
|
if (ppdev->cBitsPerPixel == 24)
|
|||
|
{
|
|||
|
offset = (YOffset * 4) + (XOffset * 3);
|
|||
|
|
|||
|
CP_MM_SRC_Y_OFFSET(ppdev, pjBase, 64);
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, 32);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
offset = PELS_TO_BYTES(YOffset + XOffset);
|
|||
|
|
|||
|
CP_MM_SRC_Y_OFFSET(ppdev, pjBase, PELS_TO_BYTES(16));
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, PELS_TO_BYTES(8));
|
|||
|
}
|
|||
|
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, (ulPatternAddrBase + offset));
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (PELS_TO_BYTES(8) - 1));
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (8 - 1));
|
|||
|
CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulAlignedPatternOffset);
|
|||
|
CP_MM_START_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
// fill using aligned pattern
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, jMode);
|
|||
|
CP_MM_ROP(ppdev, pjBase, jHwRop);
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, ulAlignedPatternOffset);
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (PELS_TO_BYTES(prcl->right - prcl->left) - 1));
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top - 1));
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ((prcl->top * lDelta) + PELS_TO_BYTES(prcl->left)));
|
|||
|
CP_MM_START_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
prcl++;
|
|||
|
|
|||
|
} while (--c != 0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**************************************************************************
|
|||
|
* VOID vMmFillSolid
|
|||
|
*
|
|||
|
* Does a solid fill to a list of rectangles.
|
|||
|
*
|
|||
|
**************************************************************************/
|
|||
|
|
|||
|
VOID vMmFillSolid(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c, // Can't be zero
|
|||
|
RECTL* prcl, // Array of relative coordinate destination rects
|
|||
|
ROP4 rop4, // Obvious?
|
|||
|
RBRUSH_COLOR rbc, // Drawing color is rbc.iSolidColor
|
|||
|
POINTL* pptlBrush) // Not used
|
|||
|
{
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
LONG cBpp = ppdev->cBpp;
|
|||
|
ULONG ulSolidColor;
|
|||
|
BYTE jHwRop;
|
|||
|
|
|||
|
DISPDBG((10,"vFillSolid called"));
|
|||
|
|
|||
|
ASSERTDD(c > 0, "Can't handle zero rectangles");
|
|||
|
|
|||
|
ulSolidColor = rbc.iSolidColor;
|
|||
|
|
|||
|
if (cBpp == 1)
|
|||
|
{
|
|||
|
ulSolidColor |= ulSolidColor << 8;
|
|||
|
ulSolidColor |= ulSolidColor << 16;
|
|||
|
}
|
|||
|
else if (cBpp == 2)
|
|||
|
{
|
|||
|
ulSolidColor |= ulSolidColor << 16;
|
|||
|
}
|
|||
|
|
|||
|
jHwRop = gajHwMixFromRop2[(rop4 >> 2) & 0xf];
|
|||
|
|
|||
|
//
|
|||
|
// Make sure we can write to the video registers.
|
|||
|
//
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_ROP(ppdev, pjBase, jHwRop);
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, ppdev->ulSolidColorOffset);
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, ENABLE_COLOR_EXPAND |
|
|||
|
ENABLE_8x8_PATTERN_COPY |
|
|||
|
ppdev->jModeColor);
|
|||
|
CP_MM_FG_COLOR(ppdev, pjBase, ulSolidColor);
|
|||
|
|
|||
|
if (ppdev->flCaps & CAPS_AUTOSTART)
|
|||
|
{
|
|||
|
CP_MM_BLT_EXT_MODE(ppdev, pjBase, ENABLE_SOLID_FILL);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Fill the list of rectangles
|
|||
|
//
|
|||
|
|
|||
|
while (TRUE)
|
|||
|
{
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (PELS_TO_BYTES(prcl->right - prcl->left) - 1));
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top - 1));
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ((prcl->top * lDelta) + PELS_TO_BYTES(prcl->left)));
|
|||
|
CP_MM_START_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
if (--c == 0)
|
|||
|
return;
|
|||
|
|
|||
|
prcl++;
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**************************************************************************
|
|||
|
* VOID vMmCopyBlt
|
|||
|
*
|
|||
|
* Does a screen-to-screen blt of a list of rectangles.
|
|||
|
*
|
|||
|
**************************************************************************/
|
|||
|
|
|||
|
VOID vMmCopyBlt(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c, // Can't be zero
|
|||
|
RECTL* prcl, // Array of relative coordinates destination rectangles
|
|||
|
ROP4 rop4, // Obvious?
|
|||
|
POINTL* pptlSrc, // Original unclipped source point
|
|||
|
RECTL* prclDst) // Original unclipped destination rectangle
|
|||
|
{
|
|||
|
LONG dx;
|
|||
|
LONG dy; // Add delta to destination to get source
|
|||
|
|
|||
|
LONG xyOffset = ppdev->xyOffset;
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
BYTE jHwRop;
|
|||
|
|
|||
|
DISPDBG((10,"vCopyBlt called"));
|
|||
|
|
|||
|
ASSERTDD(c > 0, "Can't handle zero rectangles");
|
|||
|
|
|||
|
//
|
|||
|
// The src-dst delta will be the same for all rectangles
|
|||
|
//
|
|||
|
|
|||
|
dx = pptlSrc->x - prclDst->left;
|
|||
|
dy = pptlSrc->y - prclDst->top;
|
|||
|
|
|||
|
//
|
|||
|
// Make sure we can write to the video registers.
|
|||
|
//
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
jHwRop = gajHwMixFromRop2[rop4 & 0xf];
|
|||
|
CP_MM_ROP(ppdev, pjBase, jHwRop);
|
|||
|
|
|||
|
CP_MM_SRC_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
|
|||
|
//
|
|||
|
// The accelerator may not be as fast at doing right-to-left copies, so
|
|||
|
// only do them when the rectangles truly overlap:
|
|||
|
//
|
|||
|
|
|||
|
if (!OVERLAP(prclDst, pptlSrc) ||
|
|||
|
(prclDst->top < pptlSrc->y) ||
|
|||
|
((prclDst->top == pptlSrc->y) && (prclDst->left <= pptlSrc->x))
|
|||
|
)
|
|||
|
{
|
|||
|
//
|
|||
|
// Top to Bottom - Left to Right
|
|||
|
//
|
|||
|
|
|||
|
DISPDBG((12,"Top to Bottom - Left to Right"));
|
|||
|
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, DIR_TBLR);
|
|||
|
|
|||
|
while (TRUE)
|
|||
|
{
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (PELS_TO_BYTES(prcl->right - prcl->left) - 1));
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top - 1));
|
|||
|
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, (xyOffset + ((prcl->top + dy) * lDelta) + PELS_TO_BYTES(prcl->left + dx)));
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ((prcl->top * lDelta) + PELS_TO_BYTES(prcl->left)));
|
|||
|
CP_MM_START_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
if (--c == 0)
|
|||
|
return;
|
|||
|
|
|||
|
prcl++;
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//
|
|||
|
// Bottom to Top - Right to Left
|
|||
|
//
|
|||
|
|
|||
|
DISPDBG((12,"Bottom to Top - Right to Left"));
|
|||
|
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, DIR_BTRL);
|
|||
|
|
|||
|
while (TRUE)
|
|||
|
{
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (PELS_TO_BYTES(prcl->right - prcl->left) - 1));
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top - 1));
|
|||
|
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, (xyOffset + ((prcl->bottom - 1 + dy) * lDelta) + PELS_TO_BYTES(prcl->right + dx) - 1));
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, (((prcl->bottom - 1) * lDelta) + PELS_TO_BYTES(prcl->right) - 1));
|
|||
|
CP_MM_START_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
if (--c == 0)
|
|||
|
return;
|
|||
|
|
|||
|
prcl++;
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************Public*Routine******************************\
|
|||
|
* VOID vMmXfer1bpp
|
|||
|
*
|
|||
|
* Low-level routine used to transfer monochrome data to the screen using
|
|||
|
* DWORD writes to the blt engine.
|
|||
|
*
|
|||
|
* This can handle opaque or transparent expansions. It does opaque
|
|||
|
* expansions by drawing the opaque rectangle first and then transparently
|
|||
|
* expands the foreground bits.
|
|||
|
*
|
|||
|
\**************************************************************************/
|
|||
|
|
|||
|
VOID vMmXfer1bpp(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c, // Count of rectangles, can't be zero
|
|||
|
RECTL* prcl, // List of destination rectangles, in relative
|
|||
|
// coordinates
|
|||
|
ROP4 rop4, // Actually had better be a rop3
|
|||
|
SURFOBJ* psoSrc, // Source surface
|
|||
|
POINTL* pptlSrc, // Original unclipped source point
|
|||
|
RECTL* prclDst, // Original unclipped destination rectangle
|
|||
|
XLATEOBJ* pxlo) // Translate that provides color-expansion information
|
|||
|
{
|
|||
|
ULONG* pulXfer;
|
|||
|
ULONG* pul;
|
|||
|
LONG ix;
|
|||
|
LONG iy;
|
|||
|
LONG cxWidthInBytes;
|
|||
|
BYTE* pjBits;
|
|||
|
POINTL ptlDst;
|
|||
|
POINTL ptlSrc;
|
|||
|
SIZEL sizlDst;
|
|||
|
LONG cxLeftMask;
|
|||
|
LONG cxRightMask;
|
|||
|
ULONG ulDstAddr;
|
|||
|
INT nDwords;
|
|||
|
ULONG ulLeftMask;
|
|||
|
ULONG ulRightMask;
|
|||
|
LONG dx;
|
|||
|
LONG dy;
|
|||
|
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
LONG lDeltaSrc = psoSrc->lDelta;
|
|||
|
LONG cBpp = ppdev->cBpp;
|
|||
|
ULONG ulFgColor = pxlo->pulXlate[1];
|
|||
|
ULONG ulBgColor = pxlo->pulXlate[0];
|
|||
|
|
|||
|
// Since the hardware clipping on some of the Cirrus chips is broken, we
|
|||
|
// do the clipping by rounding out the edges to dword boundaries and then
|
|||
|
// doing the blt transparently. In the event that we want the expansion
|
|||
|
// to be opaque, we do the opaquing blt in advance. One side effect of
|
|||
|
// this is that the destination bits are no longer valid for processing
|
|||
|
// the rop. This could probably be optimized by doing the edges seperately
|
|||
|
// and then doing the middle section in one pass. However, this is
|
|||
|
// complicated by a 5434 bug that breaks blts less than 10 pixels wide.
|
|||
|
|
|||
|
ASSERTDD(c > 0, "Can't handle zero rectangles");
|
|||
|
ASSERTDD(((rop4 & 0xff00) == 0xcc00), "Expected foreground rop of 0xcc");
|
|||
|
|
|||
|
//
|
|||
|
// The src-dst delta will be the same for all rectangles
|
|||
|
//
|
|||
|
|
|||
|
dx = pptlSrc->x - prclDst->left;
|
|||
|
dy = pptlSrc->y - prclDst->top;
|
|||
|
|
|||
|
if (cBpp == 1)
|
|||
|
{
|
|||
|
ulFgColor = (ulFgColor << 8) | (ulFgColor & 0xff);
|
|||
|
ulBgColor = (ulBgColor << 8) | (ulBgColor & 0xff);
|
|||
|
ulFgColor = (ulFgColor << 16) | (ulFgColor & 0xffff);
|
|||
|
ulBgColor = (ulBgColor << 16) | (ulBgColor & 0xffff);
|
|||
|
}
|
|||
|
else if (cBpp == 2)
|
|||
|
{
|
|||
|
ulFgColor = (ulFgColor << 16) | (ulFgColor & 0xffff);
|
|||
|
ulBgColor = (ulBgColor << 16) | (ulBgColor & 0xffff);
|
|||
|
}
|
|||
|
|
|||
|
pulXfer = ppdev->pulXfer;
|
|||
|
#if BANKING //bank#1
|
|||
|
ppdev->pfnBankMap(ppdev, ppdev->lXferBank);
|
|||
|
#endif
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
|
|||
|
if (rop4 != 0xCCAA)
|
|||
|
{
|
|||
|
LONG lCnt = c;
|
|||
|
RECTL* prclTmp = prcl;
|
|||
|
BYTE jHwBgRop = gajHwMixFromRop2[rop4 & 0xf];
|
|||
|
|
|||
|
CP_MM_ROP(ppdev, pjBase, jHwBgRop);
|
|||
|
CP_MM_FG_COLOR(ppdev, pjBase, ulBgColor);
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, ppdev->ulSolidColorOffset);
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, ppdev->jModeColor |
|
|||
|
ENABLE_COLOR_EXPAND |
|
|||
|
ENABLE_8x8_PATTERN_COPY);
|
|||
|
|
|||
|
do
|
|||
|
{
|
|||
|
// calculate the size of the blt
|
|||
|
|
|||
|
ptlDst.x = prclTmp->left;
|
|||
|
ptlDst.y = prclTmp->top;
|
|||
|
sizlDst.cx = prclTmp->right - ptlDst.x;
|
|||
|
sizlDst.cy = prclTmp->bottom - ptlDst.y;
|
|||
|
|
|||
|
//
|
|||
|
// Fill the background rectangle with the background color
|
|||
|
//
|
|||
|
|
|||
|
// Set the dest addresses
|
|||
|
|
|||
|
ulDstAddr = (ptlDst.y * lDelta) + PELS_TO_BYTES(ptlDst.x);
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(sizlDst.cx) - 1);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, sizlDst.cy - 1);
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstAddr);
|
|||
|
|
|||
|
// Start the blt operation
|
|||
|
|
|||
|
CP_MM_START_BLT(ppdev, pjBase);
|
|||
|
prclTmp++;
|
|||
|
} while (--lCnt != 0);
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
}
|
|||
|
|
|||
|
CP_MM_FG_COLOR(ppdev, pjBase, ulFgColor);
|
|||
|
CP_MM_BG_COLOR(ppdev, pjBase, ~ulFgColor);
|
|||
|
CP_IO_XPAR_COLOR(ppdev, pjBase, ~ulFgColor);
|
|||
|
CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, ppdev->jModeColor |
|
|||
|
ENABLE_COLOR_EXPAND |
|
|||
|
ENABLE_TRANSPARENCY_COMPARE |
|
|||
|
SRC_CPU_DATA);
|
|||
|
CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0); // jl01
|
|||
|
|
|||
|
do
|
|||
|
{
|
|||
|
// calculate the size of the blt
|
|||
|
|
|||
|
ptlDst.x = prcl->left;
|
|||
|
ptlDst.y = prcl->top;
|
|||
|
sizlDst.cx = prcl->right - ptlDst.x;
|
|||
|
sizlDst.cy = prcl->bottom - ptlDst.y;
|
|||
|
|
|||
|
// calculate the number of dwords per scan line
|
|||
|
|
|||
|
ptlSrc.x = prcl->left + dx;
|
|||
|
ptlSrc.y = prcl->top + dy;
|
|||
|
|
|||
|
// Floor the source.
|
|||
|
// Extend the width by the amount required to floor to a dword boundary.
|
|||
|
// Set the size of the left mask.
|
|||
|
// Floor the dest, so it aligns with the floored source.
|
|||
|
|
|||
|
if ((cxLeftMask = (ptlSrc.x & 31)))
|
|||
|
{
|
|||
|
sizlDst.cx += cxLeftMask;
|
|||
|
ptlSrc.x &= ~31;
|
|||
|
ptlDst.x -= cxLeftMask;
|
|||
|
}
|
|||
|
|
|||
|
ulLeftMask = gaulLeftClipMask[cxLeftMask];
|
|||
|
|
|||
|
// Ceil the cx to a dword boundary.
|
|||
|
|
|||
|
if (cxRightMask = (sizlDst.cx & 31))
|
|||
|
{
|
|||
|
cxRightMask = 32 - cxRightMask;
|
|||
|
sizlDst.cx = (sizlDst.cx + 31) & ~31;
|
|||
|
}
|
|||
|
|
|||
|
ulRightMask = gaulRightClipMask[cxRightMask];
|
|||
|
|
|||
|
if (sizlDst.cx == 32)
|
|||
|
{
|
|||
|
ulLeftMask &= ulRightMask;
|
|||
|
ulRightMask = 0;
|
|||
|
}
|
|||
|
|
|||
|
// Note: At this point sizlDst.cx is the width of the blt in pixels,
|
|||
|
// floored to a dword boundary, and ceiled to a dword boundary.
|
|||
|
|
|||
|
// Calculate the width in Bytes
|
|||
|
|
|||
|
cxWidthInBytes = sizlDst.cx >> 3;
|
|||
|
|
|||
|
// Calculate the number of Dwords and any remaining bytes
|
|||
|
|
|||
|
nDwords = cxWidthInBytes >> 2;
|
|||
|
|
|||
|
ASSERTDD(((cxWidthInBytes & 0x03) == 0),
|
|||
|
"cxWidthInBytes is not a DWORD multiple");
|
|||
|
|
|||
|
// Calculate the address of the source bitmap
|
|||
|
// This is to a byte boundary.
|
|||
|
|
|||
|
pjBits = (PBYTE) psoSrc->pvScan0;
|
|||
|
pjBits += ptlSrc.y * lDeltaSrc;
|
|||
|
pjBits += ptlSrc.x >> 3;
|
|||
|
|
|||
|
ASSERTDD((((ULONG_PTR)pjBits & 0x03) == 0),
|
|||
|
"pjBits not DWORD aligned like it should be");
|
|||
|
|
|||
|
//
|
|||
|
// Blt the 1 bpp bitmap
|
|||
|
//
|
|||
|
|
|||
|
ulDstAddr = (ptlDst.y * lDelta) + PELS_TO_BYTES(ptlDst.x);
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
//
|
|||
|
// Tell the hardware that we want to write (sizlDst.cx) X amd (sizlDst.cy) Y bytes
|
|||
|
//
|
|||
|
CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(sizlDst.cx) - 1);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, sizlDst.cy - 1);
|
|||
|
|
|||
|
//
|
|||
|
// The 542x chips require a write to the Src Address Register when
|
|||
|
// doing a host transfer with color expansion. The value is
|
|||
|
// irrelevant, but the write is crucial. This is documented in
|
|||
|
// the manual, not the errata. Go figure.
|
|||
|
//
|
|||
|
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, 0);
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstAddr);
|
|||
|
|
|||
|
CP_MM_START_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
//
|
|||
|
// Transfer the host bitmap.
|
|||
|
//
|
|||
|
|
|||
|
if (ulRightMask)
|
|||
|
{
|
|||
|
//
|
|||
|
// Blt is > 1 DWORD wide (nDwords > 1)
|
|||
|
//
|
|||
|
for (iy = 0; iy < sizlDst.cy; iy++)
|
|||
|
{
|
|||
|
pul = (ULONG*) pjBits;
|
|||
|
|
|||
|
//*pulXfer++ = *(((ULONG*)pul)++) & ulLeftMask;
|
|||
|
WRITE_REGISTER_ULONG(pulXfer, (*((ULONG*)pul) & ulLeftMask));
|
|||
|
pul++;
|
|||
|
|
|||
|
for (ix = 0; ix < (nDwords-2); ix++)
|
|||
|
{
|
|||
|
//*pulXfer++ = *(((ULONG*)pul)++);
|
|||
|
WRITE_REGISTER_ULONG(pulXfer, (*((ULONG*)pul)));
|
|||
|
pul++;
|
|||
|
}
|
|||
|
//*pulXfer++ = *(((ULONG*)pul)++) & ulRightMask;
|
|||
|
WRITE_REGISTER_ULONG(pulXfer, (*((ULONG*)pul) & ulRightMask));
|
|||
|
pul++;
|
|||
|
|
|||
|
pjBits += lDeltaSrc;
|
|||
|
//pulXfer = ppdev->pulXfer;
|
|||
|
CP_MEMORY_BARRIER(); // Flush memory cache when we reset the address
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//
|
|||
|
// Blt is 1 DWORD wide (nDwords == 1)
|
|||
|
//
|
|||
|
|
|||
|
for (iy = 0; iy < sizlDst.cy; iy++)
|
|||
|
{
|
|||
|
//*pulXfer = *((ULONG*)pjBits) & ulLeftMask;
|
|||
|
WRITE_REGISTER_ULONG(pulXfer, (*((ULONG*)pjBits) & ulLeftMask));
|
|||
|
pjBits += lDeltaSrc;
|
|||
|
|
|||
|
CP_MEMORY_BARRIER(); // Flush memory cache
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
prcl++;
|
|||
|
} while (--c != 0);
|
|||
|
}
|
|||
|
|
|||
|
/******************************Public*Routine******************************\
|
|||
|
* VOID vMmXfer4bpp
|
|||
|
*
|
|||
|
* Does a 4bpp transfer from a bitmap to the screen.
|
|||
|
*
|
|||
|
* NOTE: The screen must be 8bpp for this function to be called!
|
|||
|
*
|
|||
|
* The reason we implement this is that a lot of resources are kept as 4bpp,
|
|||
|
* and used to initialize DFBs, some of which we of course keep off-screen.
|
|||
|
*
|
|||
|
\**************************************************************************/
|
|||
|
|
|||
|
// XLATE_BUFFER_SIZE defines the size of the stack-based buffer we use
|
|||
|
// for doing the translate. Note that in general stack buffers should
|
|||
|
// be kept as small as possible. The OS guarantees us only 8k for stack
|
|||
|
// from GDI down to the display driver in low memory situations; if we
|
|||
|
// ask for more, we'll access violate. Note also that at any time the
|
|||
|
// stack buffer cannot be larger than a page (4k) -- otherwise we may
|
|||
|
// miss touching the 'guard page' and access violate then too.
|
|||
|
|
|||
|
#define XLATE_BUFFER_SIZE 256
|
|||
|
|
|||
|
VOID vMmXfer4bpp(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c, // Count of rectangles, can't be zero
|
|||
|
RECTL* prcl, // List of destination rectangles, in relative coordinates
|
|||
|
ULONG rop4, // rop4
|
|||
|
SURFOBJ* psoSrc, // Source surface
|
|||
|
POINTL* pptlSrc, // Original unclipped source point
|
|||
|
RECTL* prclDst, // Original unclipped destination rectangle
|
|||
|
XLATEOBJ* pxlo) // Translate that provides colour-expansion information
|
|||
|
{
|
|||
|
ULONG ulDstAddr;
|
|||
|
LONG dx;
|
|||
|
LONG dy;
|
|||
|
LONG cx;
|
|||
|
LONG cy;
|
|||
|
LONG lSrcDelta;
|
|||
|
BYTE* pjSrcScan0;
|
|||
|
BYTE* pjScan;
|
|||
|
BYTE* pjSrc;
|
|||
|
BYTE* pjDst;
|
|||
|
LONG cxThis;
|
|||
|
LONG cxToGo;
|
|||
|
LONG xSrc;
|
|||
|
LONG iLoop;
|
|||
|
BYTE jSrc;
|
|||
|
ULONG* pulXlate;
|
|||
|
LONG cdwThis;
|
|||
|
BYTE* pjBuf;
|
|||
|
BYTE ajBuf[XLATE_BUFFER_SIZE];
|
|||
|
|
|||
|
ULONG* pulXfer = ppdev->pulXfer;
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
|
|||
|
ASSERTDD(ppdev->iBitmapFormat == BMF_8BPP, "Screen must be 8bpp");
|
|||
|
ASSERTDD(psoSrc->iBitmapFormat == BMF_4BPP, "Source must be 4bpp");
|
|||
|
ASSERTDD(c > 0, "Can't handle zero rectangles");
|
|||
|
ASSERTDD(((rop4 & 0xff00) >> 8) == (rop4 & 0xff),
|
|||
|
"Expect only a rop2");
|
|||
|
|
|||
|
DISPDBG((5, "vXfer4bpp: entry"));
|
|||
|
|
|||
|
dx = pptlSrc->x - prclDst->left;
|
|||
|
dy = pptlSrc->y - prclDst->top; // Add to destination to get source
|
|||
|
|
|||
|
lSrcDelta = psoSrc->lDelta;
|
|||
|
pjSrcScan0 = psoSrc->pvScan0;
|
|||
|
|
|||
|
#if BANKING //bank#1
|
|||
|
ppdev->pfnBankMap(ppdev, ppdev->lXferBank);
|
|||
|
#endif
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
|
|||
|
#if 1 // D5480
|
|||
|
CP_MM_BLT_MODE_PACKED(ppdev, pjBase, gajHwPackedMixFromRop2[rop4 & 0xf] | SRC_CPU_DATA);
|
|||
|
#else
|
|||
|
CP_MM_ROP(ppdev, pjBase, gajHwMixFromRop2[rop4 & 0xf]);
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, SRC_CPU_DATA);
|
|||
|
#endif
|
|||
|
|
|||
|
while(TRUE)
|
|||
|
{
|
|||
|
ulDstAddr = (prcl->top * lDelta) + PELS_TO_BYTES(prcl->left);
|
|||
|
cx = prcl->right - prcl->left;
|
|||
|
cy = prcl->bottom - prcl->top;
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(cx) - 1);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, cy - 1);
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstAddr);
|
|||
|
|
|||
|
pulXlate = pxlo->pulXlate;
|
|||
|
xSrc = prcl->left + dx;
|
|||
|
pjScan = pjSrcScan0 + (prcl->top + dy) * lSrcDelta + (xSrc >> 1);
|
|||
|
|
|||
|
CP_MM_START_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
do {
|
|||
|
pjSrc = pjScan;
|
|||
|
cxToGo = cx; // # of pels per scan in 4bpp source
|
|||
|
do {
|
|||
|
cxThis = XLATE_BUFFER_SIZE;
|
|||
|
// We can handle XLATE_BUFFER_SIZE number
|
|||
|
// of pels in this xlate batch
|
|||
|
cxToGo -= cxThis; // cxThis will be the actual number of
|
|||
|
// pels we'll do in this xlate batch
|
|||
|
if (cxToGo < 0)
|
|||
|
cxThis += cxToGo;
|
|||
|
|
|||
|
pjDst = ajBuf; // Points to our temporary batch buffer
|
|||
|
|
|||
|
// We handle alignment ourselves because it's easy to
|
|||
|
// do, rather than pay the cost of setting/resetting
|
|||
|
// the scissors register:
|
|||
|
|
|||
|
if (xSrc & 1)
|
|||
|
{
|
|||
|
// When unaligned, we have to be careful not to read
|
|||
|
// past the end of the 4bpp bitmap (that could
|
|||
|
// potentially cause us to access violate):
|
|||
|
|
|||
|
iLoop = cxThis >> 1; // Each loop handles 2 pels;
|
|||
|
// we'll handle odd pel
|
|||
|
// separately
|
|||
|
jSrc = *pjSrc;
|
|||
|
while (iLoop-- != 0)
|
|||
|
{
|
|||
|
*pjDst++ = (BYTE) pulXlate[jSrc & 0xf];
|
|||
|
jSrc = *(++pjSrc);
|
|||
|
*pjDst++ = (BYTE) pulXlate[jSrc >> 4];
|
|||
|
}
|
|||
|
|
|||
|
if (cxThis & 1)
|
|||
|
*pjDst = (BYTE) pulXlate[jSrc & 0xf];
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
iLoop = (cxThis + 1) >> 1; // Each loop handles 2 pels
|
|||
|
do {
|
|||
|
jSrc = *pjSrc++;
|
|||
|
|
|||
|
*pjDst++ = (BYTE) pulXlate[jSrc >> 4];
|
|||
|
*pjDst++ = (BYTE) pulXlate[jSrc & 0xf];
|
|||
|
|
|||
|
} while (--iLoop != 0);
|
|||
|
}
|
|||
|
|
|||
|
// The number of bytes we'll transfer is equal to the number
|
|||
|
// of pels we've processed in the batch. Since we're
|
|||
|
// transferring words, we have to round up to get the word
|
|||
|
// count:
|
|||
|
|
|||
|
cdwThis = (cxThis + 3) >> 2;
|
|||
|
pjBuf = ajBuf;
|
|||
|
|
|||
|
TRANSFER_DWORD_ALIGNED(ppdev, pulXfer, pjBuf, cdwThis);
|
|||
|
|
|||
|
} while (cxToGo > 0);
|
|||
|
|
|||
|
pjScan += lSrcDelta; // Advance to next source scan. Note
|
|||
|
// that we could have computed the
|
|||
|
// value to advance 'pjSrc' directly,
|
|||
|
// but this method is less
|
|||
|
// error-prone.
|
|||
|
|
|||
|
} while (--cy != 0);
|
|||
|
|
|||
|
if (--c == 0)
|
|||
|
return;
|
|||
|
|
|||
|
prcl++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************Public*Routine******************************\
|
|||
|
* VOID vMmXferNative
|
|||
|
*
|
|||
|
* Transfers a bitmap that is the same color depth as the display to
|
|||
|
* the screen via the data transfer register, with no translation.
|
|||
|
*
|
|||
|
\**************************************************************************/
|
|||
|
|
|||
|
VOID vMmXferNative(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c, // Count of rectangles, can't be zero
|
|||
|
RECTL* prcl, // Array of relative coordinates destination rectangles
|
|||
|
ULONG rop4, // rop4
|
|||
|
SURFOBJ* psoSrc, // Source surface
|
|||
|
POINTL* pptlSrc, // Original unclipped source point
|
|||
|
RECTL* prclDst, // Original unclipped destination rectangle
|
|||
|
XLATEOBJ* pxlo) // Not used
|
|||
|
{
|
|||
|
ULONG ulDstAddr;
|
|||
|
LONG dx;
|
|||
|
LONG dy;
|
|||
|
LONG cx;
|
|||
|
LONG cy;
|
|||
|
LONG lSrcDelta;
|
|||
|
BYTE* pjSrcScan0;
|
|||
|
BYTE* pjSrc;
|
|||
|
LONG cjSrc;
|
|||
|
|
|||
|
ULONG* pulXfer = ppdev->pulXfer;
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
|
|||
|
ASSERTDD((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL),
|
|||
|
"Can handle trivial xlate only");
|
|||
|
ASSERTDD(psoSrc->iBitmapFormat == ppdev->iBitmapFormat,
|
|||
|
"Source must be same color depth as screen");
|
|||
|
ASSERTDD(c > 0, "Can't handle zero rectangles");
|
|||
|
ASSERTDD(((rop4 & 0xff00) >> 8) == (rop4 & 0xff),
|
|||
|
"Expect only a rop2");
|
|||
|
|
|||
|
dx = pptlSrc->x - prclDst->left;
|
|||
|
dy = pptlSrc->y - prclDst->top; // Add to destination to get source
|
|||
|
|
|||
|
lSrcDelta = psoSrc->lDelta;
|
|||
|
pjSrcScan0 = psoSrc->pvScan0;
|
|||
|
|
|||
|
#if BANKING //bank#1
|
|||
|
ppdev->pfnBankMap(ppdev, ppdev->lXferBank);
|
|||
|
#endif
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
#if 1 // D5480
|
|||
|
CP_MM_BLT_MODE_PACKED(ppdev, pjBase, gajHwPackedMixFromRop2[rop4 & 0xf] | SRC_CPU_DATA);
|
|||
|
#else
|
|||
|
CP_MM_ROP(ppdev, pjBase, gajHwMixFromRop2[rop4 & 0xf]);
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, SRC_CPU_DATA);
|
|||
|
#endif
|
|||
|
|
|||
|
while(TRUE)
|
|||
|
{
|
|||
|
ulDstAddr = (prcl->top * lDelta) + PELS_TO_BYTES(prcl->left);
|
|||
|
cx = prcl->right - prcl->left;
|
|||
|
cy = prcl->bottom - prcl->top;
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(cx) - 1);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, cy - 1);
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstAddr);
|
|||
|
|
|||
|
cjSrc = PELS_TO_BYTES(cx);
|
|||
|
pjSrc = pjSrcScan0 + (prcl->top + dy) * lSrcDelta
|
|||
|
+ (PELS_TO_BYTES(prcl->left + dx));
|
|||
|
|
|||
|
CP_MM_START_BLT(ppdev, pjBase);
|
|||
|
vImageTransfer(ppdev, pjSrc, lSrcDelta, cjSrc, cy);
|
|||
|
|
|||
|
if (--c == 0)
|
|||
|
return;
|
|||
|
|
|||
|
prcl++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// N E W B L T R O U T I N E S F O R B R U S H C A C H E //
|
|||
|
// //
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
VOID vMmFillSolid36(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c,
|
|||
|
RECTL* prcl,
|
|||
|
ROP4 rop4,
|
|||
|
RBRUSH_COLOR rbc,
|
|||
|
POINTL* pptlBrush)
|
|||
|
{
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
BYTE jHwRop = gajHwMixFromRop2[(rop4 >> 2) & 0x0F];
|
|||
|
BYTE jMode = ppdev->jModeColor
|
|||
|
| ENABLE_8x8_PATTERN_COPY
|
|||
|
| ENABLE_COLOR_EXPAND;
|
|||
|
|
|||
|
while (c-- > 0)
|
|||
|
{
|
|||
|
ULONG ulDstOffset;
|
|||
|
SIZEL sizlDst;
|
|||
|
|
|||
|
// Calculate the destination address and size.
|
|||
|
ulDstOffset = (prcl->top * lDelta) + PELS_TO_BYTES(prcl->left);
|
|||
|
sizlDst.cx = PELS_TO_BYTES(prcl->right - prcl->left) - 1;
|
|||
|
sizlDst.cy = (prcl->bottom - prcl->top) - 1;
|
|||
|
|
|||
|
// Wait for the bitblt engine.
|
|||
|
WAIT_BUSY_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
// Setup the bitblt registers.
|
|||
|
CP_MM_FG_COLOR(ppdev, pjBase, rbc.iSolidColor);
|
|||
|
CP_MM_XCNT(ppdev, pjBase, sizlDst.cx);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, sizlDst.cy);
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
CP_MM_DST_WRITE_MASK(ppdev, pjBase, 0); // Disable clipping.
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, jMode);
|
|||
|
CP_MM_ROP(ppdev, pjBase, jHwRop);
|
|||
|
CP_MM_BLT_EXT_MODE(ppdev, pjBase, ENABLE_SOLID_FILL);
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
|
|||
|
|
|||
|
// Next rectangle.
|
|||
|
prcl++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID vMmFillPat36(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c,
|
|||
|
RECTL* prcl,
|
|||
|
ROP4 rop4,
|
|||
|
RBRUSH_COLOR rbc,
|
|||
|
POINTL* pptlBrush)
|
|||
|
{
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
BYTE jHwRop = gajHwMixFromRop2[(rop4 >> 2) & 0x0F];
|
|||
|
|
|||
|
CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0) ; // chu01
|
|||
|
|
|||
|
// Dithered brush...
|
|||
|
if (rbc.prb->fl == RBRUSH_DITHER)
|
|||
|
{
|
|||
|
DITHERCACHE* pdc;
|
|||
|
|
|||
|
pdc = (DITHERCACHE*) ((ULONG_PTR)ppdev + rbc.prb->ulSlot);
|
|||
|
if (pdc->ulColor != rbc.prb->ulUniq)
|
|||
|
{
|
|||
|
// Cache entry is invalid, realize the brush again.
|
|||
|
bCacheDither(ppdev, rbc.prb);
|
|||
|
}
|
|||
|
|
|||
|
while (c-- > 0)
|
|||
|
{
|
|||
|
ULONG ulDstOffset, ulSrcOffset;
|
|||
|
SIZEL sizlDst;
|
|||
|
LONG xOffset, yOffset;
|
|||
|
LONG x;
|
|||
|
|
|||
|
// Calculate the brush rotation.
|
|||
|
xOffset = (prcl->left - pptlBrush->x) & 7;
|
|||
|
yOffset = (prcl->top - pptlBrush->y) & 7;
|
|||
|
ulSrcOffset = rbc.prb->ulBrush | yOffset;
|
|||
|
|
|||
|
// Calculate the destination and size.
|
|||
|
x = prcl->left - xOffset;
|
|||
|
ulDstOffset = (prcl->top * lDelta) + x;
|
|||
|
sizlDst.cx = (prcl->right - x) - 1;
|
|||
|
sizlDst.cy = (prcl->bottom - prcl->top) - 1;
|
|||
|
|
|||
|
// Wait for the bitblt engine.
|
|||
|
WAIT_BUSY_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
// Setup the bitblt registers.
|
|||
|
CP_MM_XCNT(ppdev, pjBase, sizlDst.cx);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, sizlDst.cy);
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
|
|||
|
CP_MM_DST_WRITE_MASK(ppdev, pjBase, xOffset);
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, ENABLE_8x8_PATTERN_COPY);
|
|||
|
CP_MM_ROP(ppdev, pjBase, jHwRop);
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
|
|||
|
|
|||
|
// Next rectangle.
|
|||
|
prcl++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Monochrome brush...
|
|||
|
else if (rbc.prb->fl == RBRUSH_MONOCHROME)
|
|||
|
{
|
|||
|
MONOCACHE* pmc;
|
|||
|
BYTE jMode;
|
|||
|
ULONG ulBgColor, ulFgColor;
|
|||
|
|
|||
|
pmc = (MONOCACHE*) ((ULONG_PTR)ppdev + rbc.prb->ulSlot);
|
|||
|
if (pmc->ulUniq != rbc.prb->ulUniq)
|
|||
|
{
|
|||
|
// Cache entry is invalid, realize the brush again.
|
|||
|
bCacheMonochrome(ppdev, rbc.prb);
|
|||
|
}
|
|||
|
|
|||
|
// Setup the common parameters.
|
|||
|
jMode = ppdev->jModeColor
|
|||
|
| ENABLE_8x8_PATTERN_COPY
|
|||
|
| ENABLE_COLOR_EXPAND;
|
|||
|
ulBgColor = rbc.prb->ulBackColor;
|
|||
|
ulFgColor = rbc.prb->ulForeColor;
|
|||
|
|
|||
|
// Monochrome brushes in 24-bpp are already cached expanded.
|
|||
|
if (ppdev->cBpp == 3)
|
|||
|
{
|
|||
|
jMode = ppdev->jModeColor
|
|||
|
| ENABLE_8x8_PATTERN_COPY;
|
|||
|
}
|
|||
|
|
|||
|
// Walk through all rectangles.
|
|||
|
while (c-- > 0)
|
|||
|
{
|
|||
|
ULONG ulDstOffset, ulSrcOffset;
|
|||
|
SIZEL sizlDst;
|
|||
|
LONG xOffset, yOffset;
|
|||
|
LONG x;
|
|||
|
|
|||
|
// Calculate the brush rotation.
|
|||
|
xOffset = (prcl->left - pptlBrush->x) & 7;
|
|||
|
yOffset = (prcl->top - pptlBrush->y) & 7;
|
|||
|
ulSrcOffset = rbc.prb->ulBrush | yOffset;
|
|||
|
|
|||
|
// Calculate the destination and size.
|
|||
|
x = prcl->left - xOffset;
|
|||
|
ulDstOffset = (prcl->top * lDelta) + PELS_TO_BYTES(x);
|
|||
|
sizlDst.cx = PELS_TO_BYTES(prcl->right - x) - 1;
|
|||
|
sizlDst.cy = (prcl->bottom - prcl->top) - 1;
|
|||
|
if (ppdev->cBpp == 3)
|
|||
|
{
|
|||
|
xOffset *= 3;
|
|||
|
}
|
|||
|
|
|||
|
// Wait for the bitblt engine.
|
|||
|
WAIT_BUSY_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
// Setup the bitblt registers.
|
|||
|
CP_MM_BG_COLOR(ppdev, pjBase, ulBgColor);
|
|||
|
CP_MM_FG_COLOR(ppdev, pjBase, ulFgColor);
|
|||
|
CP_MM_XCNT(ppdev, pjBase, sizlDst.cx);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, sizlDst.cy);
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
|
|||
|
CP_MM_DST_WRITE_MASK(ppdev, pjBase, xOffset);
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, jMode);
|
|||
|
CP_MM_ROP(ppdev, pjBase, jHwRop);
|
|||
|
CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
|
|||
|
|
|||
|
// Next rectangle.
|
|||
|
prcl++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Patterned brush...
|
|||
|
else if (ppdev->flStatus & STAT_PATTERN_CACHE)
|
|||
|
{
|
|||
|
PATTERNCACHE* ppc;
|
|||
|
|
|||
|
BYTE jMode = ppdev->jModeColor
|
|||
|
| ENABLE_8x8_PATTERN_COPY;
|
|||
|
|
|||
|
ppc = (PATTERNCACHE*) ((ULONG_PTR)ppdev + rbc.prb->ulSlot);
|
|||
|
if (ppc->prbUniq != rbc.prb)
|
|||
|
{
|
|||
|
// Cache entry is invalid, realize the brush again.
|
|||
|
bCachePattern(ppdev, rbc.prb);
|
|||
|
}
|
|||
|
|
|||
|
while (c-- > 0)
|
|||
|
{
|
|||
|
ULONG ulDstOffset, ulSrcOffset;
|
|||
|
SIZEL sizlDst;
|
|||
|
LONG xOffset, yOffset;
|
|||
|
LONG x;
|
|||
|
|
|||
|
// Calculate the brush rotation.
|
|||
|
xOffset = (prcl->left - pptlBrush->x) & 7;
|
|||
|
yOffset = (prcl->top - pptlBrush->y) & 7;
|
|||
|
ulSrcOffset = rbc.prb->ulBrush | yOffset;
|
|||
|
|
|||
|
// Calculate the destination and size.
|
|||
|
x = prcl->left - xOffset;
|
|||
|
ulDstOffset = (prcl->top * lDelta) + PELS_TO_BYTES(x);
|
|||
|
sizlDst.cx = PELS_TO_BYTES(prcl->right - x) - 1;
|
|||
|
sizlDst.cy = (prcl->bottom - prcl->top) - 1;
|
|||
|
if (ppdev->cBpp == 3)
|
|||
|
{
|
|||
|
xOffset *= 3;
|
|||
|
}
|
|||
|
|
|||
|
// Wait for the bitblt engine.
|
|||
|
WAIT_BUSY_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
// Setup the bitblt registers.
|
|||
|
CP_MM_XCNT(ppdev, pjBase, sizlDst.cx);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, sizlDst.cy);
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
|
|||
|
CP_MM_DST_WRITE_MASK(ppdev, pjBase, xOffset);
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, jMode);
|
|||
|
CP_MM_ROP(ppdev, pjBase, jHwRop);
|
|||
|
CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
|
|||
|
|
|||
|
// Next rectangle.
|
|||
|
prcl++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Old-style brush cache.
|
|||
|
else
|
|||
|
{
|
|||
|
vMmFillPat(ppdev, c, prcl, rop4, rbc, pptlBrush);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID vMmCopyBlt36(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c,
|
|||
|
RECTL* prcl,
|
|||
|
ROP4 rop4,
|
|||
|
POINTL* pptlSrc,
|
|||
|
RECTL* prclDst)
|
|||
|
{
|
|||
|
LONG xy;
|
|||
|
LONG cx, cy;
|
|||
|
ULONG ulSrc, ulDst;
|
|||
|
|
|||
|
BYTE jHwRop = gajHwMixFromRop2[rop4 & 0x0F];
|
|||
|
LONG xyOffset = ppdev->xyOffset;
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
|
|||
|
DISPDBG((10, "vMmCopyBlt36 called"));
|
|||
|
|
|||
|
// The src-dst delta will be the same for all rectangles.
|
|||
|
xy = ((pptlSrc->y - prclDst->top) * lDelta)
|
|||
|
+ PELS_TO_BYTES(pptlSrc->x - prclDst->left);
|
|||
|
|
|||
|
// Determine the direction of the blit.
|
|||
|
if ((xy >= 0) || !OVERLAP(prclDst, pptlSrc))
|
|||
|
{
|
|||
|
DISPDBG((12, "Top to Bottom - Left to Right"));
|
|||
|
|
|||
|
while (c-- > 0)
|
|||
|
{
|
|||
|
// Calculate the blit size and offsets.
|
|||
|
cx = PELS_TO_BYTES(prcl->right - prcl->left) - 1;
|
|||
|
cy = (prcl->bottom - prcl->top) - 1;
|
|||
|
ulDst = xyOffset + (prcl->top * lDelta) + PELS_TO_BYTES(prcl->left);
|
|||
|
ulSrc = ulDst + xy;
|
|||
|
|
|||
|
// Wait for the bitblt engine.
|
|||
|
WAIT_BUSY_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
// Perform the move.
|
|||
|
CP_MM_XCNT(ppdev, pjBase, cx);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, cy);
|
|||
|
CP_MM_SRC_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, ulSrc);
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, DIR_TBLR);
|
|||
|
CP_MM_ROP(ppdev, pjBase, jHwRop);
|
|||
|
CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDst);
|
|||
|
|
|||
|
// Next rectangle.
|
|||
|
prcl++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
DISPDBG((12, "Bottom to Top - Right to Left"));
|
|||
|
|
|||
|
while (c-- > 0)
|
|||
|
{
|
|||
|
// Calculate the blit size and offsets.
|
|||
|
cx = PELS_TO_BYTES(prcl->right - prcl->left) - 1;
|
|||
|
cy = (prcl->bottom - prcl->top) - 1;
|
|||
|
ulDst = xyOffset + ((prcl->bottom - 1) * lDelta)
|
|||
|
+ (PELS_TO_BYTES(prcl->right) - 1);
|
|||
|
ulSrc = ulDst + xy;
|
|||
|
|
|||
|
// Wait for the bitblt engine.
|
|||
|
WAIT_BUSY_BLT(ppdev, pjBase);
|
|||
|
|
|||
|
// Perform the move.
|
|||
|
CP_MM_XCNT(ppdev, pjBase, cx);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, cy);
|
|||
|
CP_MM_SRC_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, ulSrc);
|
|||
|
CP_MM_BLT_MODE(ppdev, pjBase, DIR_BTRL);
|
|||
|
CP_MM_ROP(ppdev, pjBase, jHwRop);
|
|||
|
CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDst);
|
|||
|
|
|||
|
// Next rectangle.
|
|||
|
prcl++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#if 1 // D5480
|
|||
|
VOID vMmFillSolid80(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c,
|
|||
|
RECTL* prcl,
|
|||
|
ROP4 rop4,
|
|||
|
RBRUSH_COLOR rbc,
|
|||
|
POINTL* pptlBrush)
|
|||
|
{
|
|||
|
ULONG_PTR* ulCLStart;
|
|||
|
ULONG ulWidthHeight;
|
|||
|
ULONG xCLOffset;
|
|||
|
ULONG ulDstOffset = 0;
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
DWORD jHwRop = gajHwPackedMixFromRop2[(rop4 >> 2) & 0x0F];
|
|||
|
DWORD jExtMode = ENABLE_SOLID_FILL_PACKED
|
|||
|
| ENABLE_XY_POSITION_PACKED
|
|||
|
| ppdev->jModeColor
|
|||
|
| ENABLE_8x8_PATTERN_COPY
|
|||
|
| ENABLE_COLOR_EXPAND;
|
|||
|
|
|||
|
//
|
|||
|
// Make sure we can write to the video registers.
|
|||
|
//
|
|||
|
// We need to change to wait for buffer ready
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
// Setup the bitblt registers.
|
|||
|
CP_MM_FG_COLOR(ppdev, pjBase, rbc.iSolidColor);
|
|||
|
// Do we really need to set it every time?
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
|
|||
|
// Do we need to clear Source XY?
|
|||
|
CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
|
|||
|
CP_MM_DST_WRITE_MASK(ppdev, pjBase, 0); // Disable clipping.
|
|||
|
|
|||
|
// Setup first set registers
|
|||
|
xCLOffset = prcl->left;
|
|||
|
CP_MM_DST_Y(ppdev, pjBase, prcl->top);
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (prcl->right - prcl->left) - 1);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top) - 1);
|
|||
|
|
|||
|
if (--c)
|
|||
|
{
|
|||
|
// There are more than one rectangle
|
|||
|
prcl++;
|
|||
|
jExtMode |= ENABLE_COMMAND_LIST_PACKED;
|
|||
|
ulCLStart = ppdev->pCommandList;
|
|||
|
ulDstOffset |= ((ULONG)((ULONG_PTR)ulCLStart
|
|||
|
- (ULONG_PTR)ppdev->pjScreen) << 14);
|
|||
|
CP_MM_CL_SWITCH(ppdev);
|
|||
|
while (TRUE)
|
|||
|
{
|
|||
|
// Command List
|
|||
|
|
|||
|
// Calculate the destination address and size.
|
|||
|
ulWidthHeight = PACKXY_FAST((prcl->right - prcl->left) - 1,
|
|||
|
(prcl->bottom - prcl->top) - 1);
|
|||
|
ulWidthHeight |= COMMAND_NOSRC_NOTHING;
|
|||
|
// XY
|
|||
|
*(ulCLStart + 1) = PACKXY_FAST(prcl->left, prcl->top);
|
|||
|
|
|||
|
// Source Start address
|
|||
|
*(ulCLStart + 2) = 0;
|
|||
|
|
|||
|
if (c == 1)
|
|||
|
{
|
|||
|
ulWidthHeight |= COMMAND_LAST_PACKET;
|
|||
|
*ulCLStart = ulWidthHeight;
|
|||
|
// Last Command
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
*ulCLStart = ulWidthHeight;
|
|||
|
// Next rectangle.
|
|||
|
prcl++;
|
|||
|
c--;
|
|||
|
ulCLStart += 4;
|
|||
|
}
|
|||
|
}
|
|||
|
CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode | jHwRop );
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
|
|||
|
CP_MM_DST_X(ppdev, pjBase, xCLOffset);
|
|||
|
}
|
|||
|
|
|||
|
VOID vMmFillPat80(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c,
|
|||
|
RECTL* prcl,
|
|||
|
ROP4 rop4,
|
|||
|
RBRUSH_COLOR rbc,
|
|||
|
POINTL* pptlBrush)
|
|||
|
{
|
|||
|
ULONG xOffset, yOffset;
|
|||
|
ULONG ulSrcOffset;
|
|||
|
ULONG_PTR* ulCLStart;
|
|||
|
ULONG ulWidthHeight;
|
|||
|
ULONG xCLOffset;
|
|||
|
ULONG ulDstOffset = 0;
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
DWORD jHwRop = gajHwPackedMixFromRop2[(rop4 >> 2) & 0x0F];
|
|||
|
DWORD jExtMode = ENABLE_XY_POSITION_PACKED
|
|||
|
| ENABLE_8x8_PATTERN_COPY;
|
|||
|
|
|||
|
// Dithered brush...
|
|||
|
if (rbc.prb->fl == RBRUSH_DITHER)
|
|||
|
{
|
|||
|
DITHERCACHE* pdc;
|
|||
|
|
|||
|
pdc = (DITHERCACHE*) ((ULONG_PTR)ppdev + rbc.prb->ulSlot);
|
|||
|
if (pdc->ulColor != rbc.prb->ulUniq)
|
|||
|
{
|
|||
|
// Cache entry is invalid, realize the brush again.
|
|||
|
bCacheDither(ppdev, rbc.prb);
|
|||
|
}
|
|||
|
|
|||
|
// Calculate the brush rotation.
|
|||
|
xOffset = (prcl->left - pptlBrush->x) & 7;
|
|||
|
yOffset = (prcl->top - pptlBrush->y) & 7;
|
|||
|
ulSrcOffset = rbc.prb->ulBrush | yOffset | (xOffset << 24);
|
|||
|
|
|||
|
// Calculate the destination and size.
|
|||
|
xCLOffset = prcl->left - xOffset;
|
|||
|
|
|||
|
//
|
|||
|
// Make sure we can write to the video registers.
|
|||
|
//
|
|||
|
// We need to change to wait for buffer ready
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
// Do we really need to set it every time?
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
|
|||
|
// Do we need to clear Source XY?
|
|||
|
CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
|
|||
|
|
|||
|
// Setup first set registers
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
|
|||
|
CP_MM_DST_Y(ppdev, pjBase, prcl->top);
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (prcl->right - xCLOffset) - 1);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top) - 1);
|
|||
|
|
|||
|
if (--c)
|
|||
|
{
|
|||
|
// There are more than one rectangle
|
|||
|
prcl++;
|
|||
|
jExtMode |= ENABLE_COMMAND_LIST_PACKED;
|
|||
|
ulCLStart = ppdev->pCommandList;
|
|||
|
ulDstOffset |= ((ULONG)((ULONG_PTR)ulCLStart
|
|||
|
- (ULONG_PTR)ppdev->pjScreen) << 14);
|
|||
|
CP_MM_CL_SWITCH(ppdev);
|
|||
|
while (TRUE)
|
|||
|
{
|
|||
|
// Command List
|
|||
|
|
|||
|
// Calculate the brush rotation.
|
|||
|
xOffset = (prcl->left - pptlBrush->x) & 7;
|
|||
|
yOffset = (prcl->top - pptlBrush->y) & 7;
|
|||
|
|
|||
|
// Calculate the destination address and size.
|
|||
|
ulWidthHeight = PACKXY_FAST((prcl->right - prcl->left + xOffset ) - 1,
|
|||
|
(prcl->bottom - prcl->top) - 1);
|
|||
|
ulWidthHeight |= COMMAND_FOURTH_NOTHING;
|
|||
|
// XY
|
|||
|
*(ulCLStart + 1) = PACKXY_FAST(prcl->left - xOffset, prcl->top);
|
|||
|
|
|||
|
// Source Start address
|
|||
|
*(ulCLStart + 2) = rbc.prb->ulBrush | yOffset | (xOffset << 24);
|
|||
|
|
|||
|
if (c == 1)
|
|||
|
{
|
|||
|
ulWidthHeight |= COMMAND_LAST_PACKET;
|
|||
|
*ulCLStart = ulWidthHeight;
|
|||
|
// Last Command
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
*ulCLStart = ulWidthHeight;
|
|||
|
// Next rectangle.
|
|||
|
prcl++;
|
|||
|
c--;
|
|||
|
ulCLStart += 4;
|
|||
|
}
|
|||
|
}
|
|||
|
CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode | jHwRop );
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
|
|||
|
CP_MM_DST_X(ppdev, pjBase, xCLOffset);
|
|||
|
}
|
|||
|
|
|||
|
// Monochrome brush...
|
|||
|
else if (rbc.prb->fl == RBRUSH_MONOCHROME)
|
|||
|
{
|
|||
|
MONOCACHE* pmc;
|
|||
|
BYTE jMode;
|
|||
|
ULONG ulBgColor, ulFgColor;
|
|||
|
|
|||
|
pmc = (MONOCACHE*) ((ULONG_PTR) ppdev + rbc.prb->ulSlot);
|
|||
|
if (pmc->ulUniq != rbc.prb->ulUniq)
|
|||
|
{
|
|||
|
// Cache entry is invalid, realize the brush again.
|
|||
|
bCacheMonochrome(ppdev, rbc.prb);
|
|||
|
}
|
|||
|
|
|||
|
ulBgColor = rbc.prb->ulBackColor;
|
|||
|
ulFgColor = rbc.prb->ulForeColor;
|
|||
|
// Calculate the brush rotation.
|
|||
|
xOffset = (prcl->left - pptlBrush->x) & 7;
|
|||
|
yOffset = (prcl->top - pptlBrush->y) & 7;
|
|||
|
// Monochrome brushes in 24-bpp are already cached expanded.
|
|||
|
if (ppdev->cBpp == 3)
|
|||
|
{
|
|||
|
jExtMode |= ppdev->jModeColor;
|
|||
|
ulSrcOffset = rbc.prb->ulBrush | yOffset | ((xOffset * 3) << 24);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
jExtMode |= (ppdev->jModeColor | ENABLE_COLOR_EXPAND);
|
|||
|
ulSrcOffset = rbc.prb->ulBrush | yOffset | (xOffset << 24);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// Calculate the destination and size.
|
|||
|
xCLOffset = prcl->left - xOffset;
|
|||
|
//
|
|||
|
// Make sure we can write to the video registers.
|
|||
|
//
|
|||
|
// We need to change to wait for buffer ready
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
// Do we really need to set it every time?
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
|
|||
|
// Do we need to clear Source XY?
|
|||
|
CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
|
|||
|
|
|||
|
// Setup first set registers
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
|
|||
|
CP_MM_DST_Y(ppdev, pjBase, prcl->top);
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (prcl->right - xCLOffset) - 1);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top) - 1);
|
|||
|
CP_MM_BG_COLOR(ppdev, pjBase, ulBgColor);
|
|||
|
CP_MM_FG_COLOR(ppdev, pjBase, ulFgColor);
|
|||
|
|
|||
|
if (--c)
|
|||
|
{
|
|||
|
// There are more than one rectangle
|
|||
|
prcl++;
|
|||
|
jExtMode |= ENABLE_COMMAND_LIST_PACKED;
|
|||
|
ulCLStart = ppdev->pCommandList;
|
|||
|
ulDstOffset
|
|||
|
|= (ULONG)(((ULONG_PTR)ulCLStart - (ULONG_PTR)ppdev->pjScreen)<<14);
|
|||
|
CP_MM_CL_SWITCH(ppdev);
|
|||
|
while (TRUE)
|
|||
|
{
|
|||
|
// Command List
|
|||
|
|
|||
|
// Calculate the brush rotation.
|
|||
|
xOffset = (prcl->left - pptlBrush->x) & 7;
|
|||
|
yOffset = (prcl->top - pptlBrush->y) & 7;
|
|||
|
|
|||
|
// Calculate the destination address and size.
|
|||
|
ulWidthHeight = PACKXY_FAST((prcl->right - prcl->left + xOffset ) - 1,
|
|||
|
(prcl->bottom - prcl->top) - 1);
|
|||
|
ulWidthHeight |= COMMAND_FOURTH_NOTHING;
|
|||
|
// XY
|
|||
|
*(ulCLStart + 1) = PACKXY_FAST(prcl->left - xOffset, prcl->top);
|
|||
|
|
|||
|
// Source Start address
|
|||
|
if(ppdev->cBpp == 3)
|
|||
|
*(ulCLStart + 2) = rbc.prb->ulBrush | yOffset | ((xOffset * 3) << 24);
|
|||
|
else
|
|||
|
*(ulCLStart + 2) = rbc.prb->ulBrush | yOffset | (xOffset << 24);
|
|||
|
|
|||
|
if (c == 1)
|
|||
|
{
|
|||
|
ulWidthHeight |= COMMAND_LAST_PACKET;
|
|||
|
*ulCLStart = ulWidthHeight;
|
|||
|
// Last Command
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
*ulCLStart = ulWidthHeight;
|
|||
|
// Next rectangle.
|
|||
|
prcl++;
|
|||
|
c--;
|
|||
|
ulCLStart += 4;
|
|||
|
}
|
|||
|
}
|
|||
|
CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode | jHwRop );
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
|
|||
|
CP_MM_DST_X(ppdev, pjBase, xCLOffset);
|
|||
|
}
|
|||
|
|
|||
|
// Patterned brush...
|
|||
|
else if (ppdev->flStatus & STAT_PATTERN_CACHE)
|
|||
|
{
|
|||
|
PATTERNCACHE* ppc;
|
|||
|
|
|||
|
ppc = (PATTERNCACHE*) ((ULONG_PTR) ppdev + rbc.prb->ulSlot);
|
|||
|
if (ppc->prbUniq != rbc.prb)
|
|||
|
{
|
|||
|
// Cache entry is invalid, realize the brush again.
|
|||
|
bCachePattern(ppdev, rbc.prb);
|
|||
|
}
|
|||
|
|
|||
|
// Calculate the brush rotation.
|
|||
|
xOffset = (prcl->left - pptlBrush->x) & 7;
|
|||
|
yOffset = (prcl->top - pptlBrush->y) & 7;
|
|||
|
// Monochrome brushes in 24-bpp are already cached expanded.
|
|||
|
jExtMode |= ppdev->jModeColor;
|
|||
|
if (ppdev->cBpp == 3)
|
|||
|
{
|
|||
|
ulSrcOffset = rbc.prb->ulBrush | yOffset | ((xOffset * 3) << 24);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ulSrcOffset = rbc.prb->ulBrush | yOffset | (xOffset << 24);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// Calculate the destination and size.
|
|||
|
xCLOffset = prcl->left - xOffset;
|
|||
|
//
|
|||
|
// Make sure we can write to the video registers.
|
|||
|
//
|
|||
|
// We need to change to wait for buffer ready
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
// Do we really need to set it every time?
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
|
|||
|
// Do we need to clear Source XY?
|
|||
|
CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
|
|||
|
|
|||
|
// Setup first set registers
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
|
|||
|
CP_MM_DST_Y(ppdev, pjBase, prcl->top);
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (prcl->right - xCLOffset) - 1);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top) - 1);
|
|||
|
|
|||
|
if (--c)
|
|||
|
{
|
|||
|
// There are more than one rectangle
|
|||
|
prcl++;
|
|||
|
jExtMode |= ENABLE_COMMAND_LIST_PACKED;
|
|||
|
ulCLStart = ppdev->pCommandList;
|
|||
|
ulDstOffset
|
|||
|
|= (ULONG)(((ULONG_PTR)ulCLStart-(ULONG_PTR)ppdev->pjScreen)<<14);
|
|||
|
CP_MM_CL_SWITCH(ppdev);
|
|||
|
while (TRUE)
|
|||
|
{
|
|||
|
// Command List
|
|||
|
|
|||
|
// Calculate the brush rotation.
|
|||
|
xOffset = (prcl->left - pptlBrush->x) & 7;
|
|||
|
yOffset = (prcl->top - pptlBrush->y) & 7;
|
|||
|
|
|||
|
// Calculate the destination address and size.
|
|||
|
ulWidthHeight = PACKXY_FAST((prcl->right - prcl->left + xOffset ) - 1,
|
|||
|
(prcl->bottom - prcl->top) - 1);
|
|||
|
ulWidthHeight |= COMMAND_FOURTH_NOTHING;
|
|||
|
// XY
|
|||
|
*(ulCLStart + 1) = PACKXY_FAST(prcl->left - xOffset, prcl->top);
|
|||
|
|
|||
|
// Source Start address
|
|||
|
if(ppdev->cBpp == 3)
|
|||
|
*(ulCLStart + 2) = rbc.prb->ulBrush | yOffset | ((xOffset * 3) << 24);
|
|||
|
else
|
|||
|
*(ulCLStart + 2) = rbc.prb->ulBrush | yOffset | (xOffset << 24);
|
|||
|
|
|||
|
if (c == 1)
|
|||
|
{
|
|||
|
ulWidthHeight |= COMMAND_LAST_PACKET;
|
|||
|
*ulCLStart = ulWidthHeight;
|
|||
|
// Last Command
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
*ulCLStart = ulWidthHeight;
|
|||
|
// Next rectangle.
|
|||
|
prcl++;
|
|||
|
c--;
|
|||
|
ulCLStart += 4;
|
|||
|
}
|
|||
|
}
|
|||
|
CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode | jHwRop );
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
|
|||
|
CP_MM_DST_X(ppdev, pjBase, xCLOffset);
|
|||
|
}
|
|||
|
|
|||
|
// Old-style brush cache.
|
|||
|
else
|
|||
|
{
|
|||
|
vMmFillPat(ppdev, c, prcl, rop4, rbc, pptlBrush);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID vMmCopyBlt80(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c, // Can't be zero
|
|||
|
RECTL* prcl, // Array of relative coordinates destination rectangles
|
|||
|
ROP4 rop4, // Obvious?
|
|||
|
POINTL* pptlSrc, // Original unclipped source point
|
|||
|
RECTL* prclDst) // Original unclipped destination rectangle
|
|||
|
{
|
|||
|
LONG dx;
|
|||
|
LONG dy; // Add delta to destination to get source
|
|||
|
|
|||
|
ULONG jHwRop;
|
|||
|
ULONG_PTR* ulCLStart;
|
|||
|
ULONG ulWidthHeight;
|
|||
|
ULONG xCLOffset;
|
|||
|
ULONG ulDstOffset = 0;
|
|||
|
LONG xyOffset = ppdev->xyOffset;
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
DWORD jExtMode = ENABLE_XY_POSITION_PACKED |
|
|||
|
ppdev->jModeColor;
|
|||
|
|
|||
|
DISPDBG((10,"vCopyBlt called"));
|
|||
|
|
|||
|
ASSERTDD(c > 0, "Can't handle zero rectangles");
|
|||
|
|
|||
|
//
|
|||
|
// The src-dst delta will be the same for all rectangles
|
|||
|
//
|
|||
|
|
|||
|
dx = pptlSrc->x - prclDst->left;
|
|||
|
dy = pptlSrc->y - prclDst->top;
|
|||
|
|
|||
|
//
|
|||
|
// Make sure we can write to the video registers.
|
|||
|
//
|
|||
|
// We need to change to wait for buffer ready
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
jHwRop = gajHwPackedMixFromRop2[rop4 & 0xf];
|
|||
|
|
|||
|
CP_MM_SRC_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
// Do we really need to set it every time?
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
|
|||
|
//
|
|||
|
// The accelerator may not be as fast at doing right-to-left copies, so
|
|||
|
// only do them when the rectangles truly overlap:
|
|||
|
//
|
|||
|
|
|||
|
if (!OVERLAP(prclDst, pptlSrc) ||
|
|||
|
(prclDst->top < pptlSrc->y) ||
|
|||
|
((prclDst->top == pptlSrc->y) && (prclDst->left <= pptlSrc->x))
|
|||
|
)
|
|||
|
{
|
|||
|
//
|
|||
|
// Top to Bottom - Left to Right
|
|||
|
//
|
|||
|
|
|||
|
DISPDBG((12,"Top to Bottom - Left to Right"));
|
|||
|
|
|||
|
// Setup first set registers
|
|||
|
xCLOffset = prcl->left;
|
|||
|
CP_MM_DST_Y(ppdev, pjBase, prcl->top);
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (prcl->right - prcl->left) - 1);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top) - 1);
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, (xyOffset + ((prcl->top + dy) * lDelta) + PELS_TO_BYTES(prcl->left + dx)));
|
|||
|
CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
|
|||
|
|
|||
|
if (--c)
|
|||
|
{
|
|||
|
// There are more than one rectangle
|
|||
|
prcl++;
|
|||
|
jExtMode |= ENABLE_COMMAND_LIST_PACKED;
|
|||
|
ulCLStart = ppdev->pCommandList;
|
|||
|
ulDstOffset
|
|||
|
|= (ULONG)(((ULONG_PTR)ulCLStart - (ULONG_PTR)ppdev->pjScreen)<<14);
|
|||
|
CP_MM_CL_SWITCH(ppdev);
|
|||
|
while (TRUE)
|
|||
|
{
|
|||
|
// Command List
|
|||
|
|
|||
|
// Calculate the destination address and size.
|
|||
|
ulWidthHeight = PACKXY_FAST((prcl->right - prcl->left) - 1,
|
|||
|
(prcl->bottom - prcl->top) - 1);
|
|||
|
ulWidthHeight |= COMMAND_FOURTH_NOTHING;
|
|||
|
// XY
|
|||
|
*(ulCLStart + 1) = PACKXY_FAST(prcl->left, prcl->top);
|
|||
|
// Source Start address
|
|||
|
*(ulCLStart + 2) = xyOffset + (prcl->top + dy) * lDelta + PELS_TO_BYTES(prcl->left + dx);
|
|||
|
|
|||
|
if (c == 1)
|
|||
|
{
|
|||
|
ulWidthHeight |= COMMAND_LAST_PACKET;
|
|||
|
*ulCLStart = ulWidthHeight;
|
|||
|
// Last Command
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
*ulCLStart = ulWidthHeight;
|
|||
|
// Next rectangle.
|
|||
|
prcl++;
|
|||
|
c--;
|
|||
|
ulCLStart += 4;
|
|||
|
}
|
|||
|
}
|
|||
|
CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode | jHwRop);
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
|
|||
|
CP_MM_DST_X(ppdev, pjBase, xCLOffset);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//
|
|||
|
// Bottom to Top - Right to Left
|
|||
|
//
|
|||
|
|
|||
|
DISPDBG((12,"Bottom to Top - Right to Left"));
|
|||
|
|
|||
|
// Setup first set registers
|
|||
|
xCLOffset = prcl->right - 1;
|
|||
|
CP_MM_DST_Y(ppdev, pjBase, prcl->bottom - 1);
|
|||
|
CP_MM_XCNT(ppdev, pjBase, (prcl->right - prcl->left) - 1);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, (prcl->bottom - prcl->top) - 1);
|
|||
|
CP_MM_SRC_ADDR(ppdev, pjBase, (xyOffset + ((prcl->bottom - 1 + dy) * lDelta) + PELS_TO_BYTES(prcl->right + dx - 1)));
|
|||
|
CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
|
|||
|
|
|||
|
if (--c)
|
|||
|
{
|
|||
|
// There are more than one rectangle
|
|||
|
prcl++;
|
|||
|
jExtMode |= ENABLE_COMMAND_LIST_PACKED;
|
|||
|
ulCLStart = ppdev->pCommandList;
|
|||
|
ulDstOffset
|
|||
|
|=(ULONG)(((ULONG_PTR)ulCLStart - (ULONG_PTR)ppdev->pjScreen) << 14);
|
|||
|
CP_MM_CL_SWITCH(ppdev);
|
|||
|
while (TRUE)
|
|||
|
{
|
|||
|
// Command List
|
|||
|
|
|||
|
// Calculate the destination address and size.
|
|||
|
ulWidthHeight = PACKXY_FAST((prcl->right - prcl->left) - 1,
|
|||
|
(prcl->bottom - prcl->top) - 1);
|
|||
|
ulWidthHeight |= COMMAND_FOURTH_NOTHING;
|
|||
|
// XY
|
|||
|
*(ulCLStart + 1) = PACKXY_FAST(prcl->right - 1, prcl->bottom - 1);
|
|||
|
// Source Start address
|
|||
|
*(ulCLStart + 2) = xyOffset + (prcl->bottom - 1 + dy) * lDelta + PELS_TO_BYTES(prcl->right + dx - 1);
|
|||
|
|
|||
|
if (c == 1)
|
|||
|
{
|
|||
|
ulWidthHeight |= COMMAND_LAST_PACKET;
|
|||
|
*ulCLStart = ulWidthHeight;
|
|||
|
// Last Command
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
*ulCLStart = ulWidthHeight;
|
|||
|
// Next rectangle.
|
|||
|
prcl++;
|
|||
|
c--;
|
|||
|
ulCLStart += 4;
|
|||
|
}
|
|||
|
}
|
|||
|
CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode | jHwRop | DIR_BTRL);
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
|
|||
|
CP_MM_DST_X(ppdev, pjBase, xCLOffset);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************Public*Routine******************************\
|
|||
|
* VOID vMmXfer1bpp80
|
|||
|
*
|
|||
|
* Low-level routine used to transfer monochrome data to the screen using
|
|||
|
* DWORD writes to the blt engine.
|
|||
|
*
|
|||
|
* This can handle opaque or transparent expansions. It does opaque
|
|||
|
* expansions by drawing the opaque rectangle first and then transparently
|
|||
|
* expands the foreground bits.
|
|||
|
*
|
|||
|
\**************************************************************************/
|
|||
|
|
|||
|
VOID vMmXfer1bpp80(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c, // Count of rectangles, can't be zero
|
|||
|
RECTL* prcl, // List of destination rectangles, in relative
|
|||
|
// coordinates
|
|||
|
ROP4 rop4, // Actually had better be a rop3
|
|||
|
SURFOBJ* psoSrc, // Source surface
|
|||
|
POINTL* pptlSrc, // Original unclipped source point
|
|||
|
RECTL* prclDst, // Original unclipped destination rectangle
|
|||
|
XLATEOBJ* pxlo) // Translate that provides color-expansion information
|
|||
|
{
|
|||
|
ULONG* pulXfer;
|
|||
|
ULONG* pul;
|
|||
|
LONG ix;
|
|||
|
LONG iy;
|
|||
|
LONG cxWidthInBytes;
|
|||
|
BYTE* pjBits;
|
|||
|
POINTL ptlDst;
|
|||
|
POINTL ptlSrc;
|
|||
|
SIZEL sizlDst;
|
|||
|
LONG cxLeftMask;
|
|||
|
LONG cxRightMask;
|
|||
|
ULONG ulDstAddr;
|
|||
|
INT nDwords;
|
|||
|
ULONG ulLeftMask;
|
|||
|
ULONG ulRightMask;
|
|||
|
LONG dx;
|
|||
|
LONG dy;
|
|||
|
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
LONG lDeltaSrc = psoSrc->lDelta;
|
|||
|
LONG cBpp = ppdev->cBpp;
|
|||
|
ULONG ulFgColor = pxlo->pulXlate[1];
|
|||
|
ULONG ulBgColor = pxlo->pulXlate[0];
|
|||
|
|
|||
|
// Since the hardware clipping on some of the Cirrus chips is broken, we
|
|||
|
// do the clipping by rounding out the edges to dword boundaries and then
|
|||
|
// doing the blt transparently. In the event that we want the expansion
|
|||
|
// to be opaque, we do the opaquing blt in advance. One side effect of
|
|||
|
// this is that the destination bits are no longer valid for processing
|
|||
|
// the rop. This could probably be optimized by doing the edges seperately
|
|||
|
// and then doing the middle section in one pass. However, this is
|
|||
|
// complicated by a 5434 bug that breaks blts less than 10 pixels wide.
|
|||
|
|
|||
|
ASSERTDD(c > 0, "Can't handle zero rectangles");
|
|||
|
ASSERTDD(((rop4 & 0xff00) == 0xcc00), "Expected foreground rop of 0xcc");
|
|||
|
|
|||
|
//
|
|||
|
// The src-dst delta will be the same for all rectangles
|
|||
|
//
|
|||
|
|
|||
|
dx = pptlSrc->x - prclDst->left;
|
|||
|
dy = pptlSrc->y - prclDst->top;
|
|||
|
|
|||
|
#if 0
|
|||
|
if (cBpp == 1)
|
|||
|
{
|
|||
|
ulFgColor = (ulFgColor << 8) | (ulFgColor & 0xff);
|
|||
|
ulBgColor = (ulBgColor << 8) | (ulBgColor & 0xff);
|
|||
|
ulFgColor = (ulFgColor << 16) | (ulFgColor & 0xffff);
|
|||
|
ulBgColor = (ulBgColor << 16) | (ulBgColor & 0xffff);
|
|||
|
}
|
|||
|
else if (cBpp == 2)
|
|||
|
{
|
|||
|
ulFgColor = (ulFgColor << 16) | (ulFgColor & 0xffff);
|
|||
|
ulBgColor = (ulBgColor << 16) | (ulBgColor & 0xffff);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
pulXfer = ppdev->pulXfer;
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
|
|||
|
|
|||
|
if (rop4 != 0xCCAA)
|
|||
|
{
|
|||
|
LONG lCnt = c;
|
|||
|
RECTL* prclTmp = prcl;
|
|||
|
DWORD jHwBgRop = gajHwPackedMixFromRop2[rop4 & 0xf];
|
|||
|
|
|||
|
CP_MM_FG_COLOR(ppdev, pjBase, ulBgColor);
|
|||
|
CP_MM_BLT_MODE_PACKED(ppdev, pjBase, ENABLE_XY_POSITION_PACKED |
|
|||
|
ENABLE_SOLID_FILL_PACKED |
|
|||
|
jHwBgRop |
|
|||
|
ppdev->jModeColor |
|
|||
|
ENABLE_COLOR_EXPAND |
|
|||
|
ENABLE_8x8_PATTERN_COPY);
|
|||
|
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, 0);
|
|||
|
do
|
|||
|
{
|
|||
|
// calculate the size of the blt
|
|||
|
|
|||
|
ptlDst.x = prclTmp->left;
|
|||
|
ptlDst.y = prclTmp->top;
|
|||
|
|
|||
|
//
|
|||
|
// Fill the background rectangle with the background color
|
|||
|
//
|
|||
|
|
|||
|
// Set the dest addresses
|
|||
|
|
|||
|
ulDstAddr = (ptlDst.y * lDelta) + PELS_TO_BYTES(ptlDst.x);
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_XCNT(ppdev, pjBase, prclTmp->right - ptlDst.x - 1);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, prclTmp->bottom - ptlDst.y - 1);
|
|||
|
CP_MM_DST_Y(ppdev, pjBase, ptlDst.y);
|
|||
|
CP_MM_DST_X(ppdev, pjBase, ptlDst.x);
|
|||
|
prclTmp++;
|
|||
|
} while (--lCnt != 0);
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
}
|
|||
|
|
|||
|
CP_MM_FG_COLOR(ppdev, pjBase, ulFgColor);
|
|||
|
CP_MM_BG_COLOR(ppdev, pjBase, ~ulFgColor);
|
|||
|
// CP_IO_XPAR_COLOR(ppdev, pjBase, ~ulFgColor);
|
|||
|
CP_MM_BLT_MODE_PACKED(ppdev, pjBase, ENABLE_XY_POSITION_PACKED |
|
|||
|
ENABLE_CLIP_RECT_PACKED |
|
|||
|
CL_PACKED_SRC_COPY |
|
|||
|
ppdev->jModeColor |
|
|||
|
ENABLE_COLOR_EXPAND |
|
|||
|
ENABLE_TRANSPARENCY_COMPARE |
|
|||
|
SRC_CPU_DATA |
|
|||
|
SOURCE_GRANULARITY_PACKED);
|
|||
|
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, 0);
|
|||
|
do
|
|||
|
{
|
|||
|
// calculate the size of the blt
|
|||
|
|
|||
|
ptlDst.x = prcl->left;
|
|||
|
ptlDst.y = prcl->top;
|
|||
|
sizlDst.cx = prcl->right - ptlDst.x;
|
|||
|
sizlDst.cy = prcl->bottom - ptlDst.y;
|
|||
|
|
|||
|
// calculate the number of dwords per scan line
|
|||
|
|
|||
|
ptlSrc.x = prcl->left + dx;
|
|||
|
ptlSrc.y = prcl->top + dy;
|
|||
|
|
|||
|
// Floor the source.
|
|||
|
// Extend the width by the amount required to floor to a dword boundary.
|
|||
|
// Set the size of the left mask.
|
|||
|
// Floor the dest, so it aligns with the floored source.
|
|||
|
|
|||
|
if ((cxLeftMask = (ptlSrc.x & 31)))
|
|||
|
{
|
|||
|
sizlDst.cx += cxLeftMask;
|
|||
|
ptlSrc.x &= ~31;
|
|||
|
ptlDst.x -= cxLeftMask;
|
|||
|
}
|
|||
|
|
|||
|
// Calculate the width in Bytes
|
|||
|
|
|||
|
cxWidthInBytes = (sizlDst.cx + 7) >> 3;
|
|||
|
|
|||
|
// Calculate the address of the source bitmap
|
|||
|
// This is to a byte boundary.
|
|||
|
|
|||
|
pjBits = (PBYTE) psoSrc->pvScan0;
|
|||
|
pjBits += ptlSrc.y * lDeltaSrc;
|
|||
|
pjBits += ptlSrc.x >> 3;
|
|||
|
|
|||
|
ASSERTDD((((ULONG_PTR)pjBits & 0x03) == 0),
|
|||
|
"pjBits not DWORD aligned like it should be");
|
|||
|
|
|||
|
//
|
|||
|
// Blt the 1 bpp bitmap
|
|||
|
//
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
// set clipping register
|
|||
|
CP_MM_CLIP_ULXY(ppdev, pjBase, prcl->left, prcl->top);
|
|||
|
CP_MM_CLIP_LRXY(ppdev, pjBase, prcl->right - 1, prcl->bottom - 1);
|
|||
|
|
|||
|
CP_MM_DST_Y(ppdev, pjBase, ptlDst.y);
|
|||
|
CP_MM_XCNT(ppdev, pjBase, sizlDst.cx - 1);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, sizlDst.cy - 1);
|
|||
|
CP_MM_DST_X(ppdev, pjBase, ptlDst.x);
|
|||
|
|
|||
|
//
|
|||
|
// Transfer the host bitmap.
|
|||
|
//
|
|||
|
vImageTransfer(ppdev, pjBits, lDeltaSrc, cxWidthInBytes, sizlDst.cy);
|
|||
|
prcl++;
|
|||
|
} while (--c != 0);
|
|||
|
}
|
|||
|
|
|||
|
/******************************Public*Routine******************************\
|
|||
|
* VOID vMmXferNative80
|
|||
|
*
|
|||
|
* Transfers a bitmap that is the same color depth as the display to
|
|||
|
* the screen via the data transfer register, with no translation.
|
|||
|
*
|
|||
|
\**************************************************************************/
|
|||
|
|
|||
|
VOID vMmXferNative80(
|
|||
|
PDEV* ppdev,
|
|||
|
LONG c, // Count of rectangles, can't be zero
|
|||
|
RECTL* prcl, // Array of relative coordinates destination rectangles
|
|||
|
ULONG rop4, // rop4
|
|||
|
SURFOBJ* psoSrc, // Source surface
|
|||
|
POINTL* pptlSrc, // Original unclipped source point
|
|||
|
RECTL* prclDst, // Original unclipped destination rectangle
|
|||
|
XLATEOBJ* pxlo) // Not used
|
|||
|
{
|
|||
|
LONG dx;
|
|||
|
LONG dy;
|
|||
|
LONG cx;
|
|||
|
LONG cy;
|
|||
|
LONG lSrcDelta;
|
|||
|
BYTE* pjSrcScan0;
|
|||
|
BYTE* pjSrc;
|
|||
|
LONG cjSrc;
|
|||
|
|
|||
|
BYTE* pjBase = ppdev->pjBase;
|
|||
|
LONG lDelta = ppdev->lDelta;
|
|||
|
DWORD jHwRop = gajHwPackedMixFromRop2[rop4 & 0x0F];
|
|||
|
DWORD jExtMode= ENABLE_XY_POSITION_PACKED |
|
|||
|
SRC_CPU_DATA |
|
|||
|
ppdev->jModeColor;
|
|||
|
|
|||
|
ASSERTDD((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL),
|
|||
|
"Can handle trivial xlate only");
|
|||
|
ASSERTDD(psoSrc->iBitmapFormat == ppdev->iBitmapFormat,
|
|||
|
"Source must be same color depth as screen");
|
|||
|
ASSERTDD(c > 0, "Can't handle zero rectangles");
|
|||
|
ASSERTDD(((rop4 & 0xff00) >> 8) == (rop4 & 0xff),
|
|||
|
"Expect only a rop2");
|
|||
|
|
|||
|
dx = pptlSrc->x - prclDst->left;
|
|||
|
dy = pptlSrc->y - prclDst->top; // Add to destination to get source
|
|||
|
|
|||
|
lSrcDelta = psoSrc->lDelta;
|
|||
|
pjSrcScan0 = psoSrc->pvScan0;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Make sure we can write to the video registers.
|
|||
|
//
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
|
|||
|
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
|||
|
CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jHwRop | jExtMode);
|
|||
|
CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
|
|||
|
|
|||
|
|
|||
|
while(TRUE)
|
|||
|
{
|
|||
|
|
|||
|
cx = prcl->right - prcl->left;
|
|||
|
cy = prcl->bottom - prcl->top;
|
|||
|
|
|||
|
cjSrc = PELS_TO_BYTES(cx);
|
|||
|
pjSrc = pjSrcScan0 + (prcl->top + dy) * lSrcDelta
|
|||
|
+ (PELS_TO_BYTES(prcl->left + dx));
|
|||
|
|
|||
|
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
|||
|
CP_MM_XCNT(ppdev, pjBase, cx - 1);
|
|||
|
CP_MM_YCNT(ppdev, pjBase, cy - 1);
|
|||
|
|
|||
|
CP_MM_DST_Y(ppdev, pjBase, prcl->top);
|
|||
|
CP_MM_DST_ADDR(ppdev, pjBase, 0);
|
|||
|
CP_MM_DST_X(ppdev, pjBase, prcl->left);
|
|||
|
vImageTransfer(ppdev, pjSrc, lSrcDelta, cjSrc, cy);
|
|||
|
|
|||
|
if (--c == 0)
|
|||
|
break;
|
|||
|
|
|||
|
prcl++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endif // endif D5480
|