windows-nt/Source/XPSP1/NT/drivers/video/matrox/mga/disp/bltmil24.c
2020-09-26 16:20:57 +08:00

271 lines
9.9 KiB
C

/******************************Module*Header*******************************\
* Module Name: bltmil24.c
*
* Contains the low-level blt functions for the Millenium at 24bpp.
*
* 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-1996 Microsoft Corporation
* Copyright (c) 1993-1996 Matrox Electronic Systems, Ltd.
\**************************************************************************/
#include "precomp.h"
/******************************Public*Routine******************************\
* VOID vMilPatRealize24bpp
*
* Download the Color Brush to the Color brush cache in the Storm offscreen
* memory. We download a 16x8 brush. We'll use direct frame buffer access.
*
* There are some hardware restrictions concerning the way that a pattern
* must be stored in memory:
* - the first pixel of the pattern must be stored so that the first pixel
* address mod 256 is 0 or 16;
* - each line of 16 pixels is stored continuously, but there must be a
* difference of 32 in the pixel addresses of successive pattern lines.
* This means that we will store patterns in the following way:
*
* +----+---------------+---------------+---------------+---------------+
* | | Pattern 0 | Pattern 1 |
* |Line| | |1 1 1 1 1 1 1 1|1 1 1 1 1 1 1 1|
* | |0 1 2 3 4 5 6 7|8 9 a b c d e f|0 1 2 3 4 5 6 7|8 9 a b c d e f|
* +----+---------------+---------------+---------------+---------------+
* | 0 |* * * * * * * * | o o o o|
* | 1 | * * * * * * * *| o o o o |
* | 2 |* * * * * * * * | o o o o |
* | 3 | * * * * * * * *|o o o o |
* | 4 |* * * * * * * * | o o o o|
* | 5 | * * * * * * * *| o o o o |
* | 6 |* * * * * * * * | o o o o |
* | 7 | * * * * * * * *|o o o o |
* +----+---------------+---------------+---------------+---------------+
*
* where a given pixel address is
* FirstPixelAddress + Line*0x20 + Pattern*0x10 + xPat.
*
\**************************************************************************/
VOID vMilPatRealize24bpp(
PDEV* ppdev,
RBRUSH* prb)
{
BYTE* pjBase;
BRUSHENTRY* pbe;
LONG iBrushCache;
ULONG i;
ULONG j;
ULONG* pulBrush;
ULONG* pulDst;
ULONG lDeltaPat;
pjBase = ppdev->pjBase;
// Allocate a new off-screen cache brush entry for the brush.
iBrushCache = ppdev->iBrushCache;
pbe = &ppdev->pbe[iBrushCache];
iBrushCache++;
if (iBrushCache >= ppdev->cBrushCache)
iBrushCache = 0;
ppdev->iBrushCache = iBrushCache;
// Update our links.
pbe->prbVerify = prb;
prb->apbe[IBOARD(ppdev)] = pbe;
// Point to the pattern bits.
pulBrush = prb->aulPattern;
pulDst = (ULONG*) (pbe->pvScan0);
pulDst = (ULONG*) (ppdev->pjScreen + (pbe->ulLinear * 3));
DISPDBG((1,"pulBrush = %x", pulBrush));
DISPDBG((1,"pulDst = %x", pulDst));
{
ULONG y;
for (y = 0; y < 8; y++)
{
DISPDBG((2, "%02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x",
((BYTE*)pulBrush)[y*48 + 0],
((BYTE*)pulBrush)[y*48 + 1],
((BYTE*)pulBrush)[y*48 + 2],
((BYTE*)pulBrush)[y*48 + 3],
((BYTE*)pulBrush)[y*48 + 4],
((BYTE*)pulBrush)[y*48 + 5],
((BYTE*)pulBrush)[y*48 + 6],
((BYTE*)pulBrush)[y*48 + 7],
((BYTE*)pulBrush)[y*48 + 8],
((BYTE*)pulBrush)[y*48 + 9],
((BYTE*)pulBrush)[y*48 + 10],
((BYTE*)pulBrush)[y*48 + 11],
((BYTE*)pulBrush)[y*48 + 12],
((BYTE*)pulBrush)[y*48 + 13],
((BYTE*)pulBrush)[y*48 + 14],
((BYTE*)pulBrush)[y*48 + 15],
((BYTE*)pulBrush)[y*48 + 16],
((BYTE*)pulBrush)[y*48 + 17],
((BYTE*)pulBrush)[y*48 + 18],
((BYTE*)pulBrush)[y*48 + 19],
((BYTE*)pulBrush)[y*48 + 20],
((BYTE*)pulBrush)[y*48 + 21],
((BYTE*)pulBrush)[y*48 + 22],
((BYTE*)pulBrush)[y*48 + 23],
((BYTE*)pulBrush)[y*48 + 24],
((BYTE*)pulBrush)[y*48 + 25],
((BYTE*)pulBrush)[y*48 + 26],
((BYTE*)pulBrush)[y*48 + 27],
((BYTE*)pulBrush)[y*48 + 28],
((BYTE*)pulBrush)[y*48 + 29],
((BYTE*)pulBrush)[y*48 + 30],
((BYTE*)pulBrush)[y*48 + 31],
((BYTE*)pulBrush)[y*48 + 32],
((BYTE*)pulBrush)[y*48 + 33],
((BYTE*)pulBrush)[y*48 + 34],
((BYTE*)pulBrush)[y*48 + 35],
((BYTE*)pulBrush)[y*48 + 36],
((BYTE*)pulBrush)[y*48 + 37],
((BYTE*)pulBrush)[y*48 + 38],
((BYTE*)pulBrush)[y*48 + 39],
((BYTE*)pulBrush)[y*48 + 40],
((BYTE*)pulBrush)[y*48 + 41],
((BYTE*)pulBrush)[y*48 + 42],
((BYTE*)pulBrush)[y*48 + 43],
((BYTE*)pulBrush)[y*48 + 44],
((BYTE*)pulBrush)[y*48 + 45],
((BYTE*)pulBrush)[y*48 + 46],
((BYTE*)pulBrush)[y*48 + 47]
));
}
}
START_DIRECT_ACCESS_STORM(ppdev, pjBase);
for (i = 8; i != 0 ; i--)
{
for (j = 0; j < 12; j++)
{
pulDst[j] = *pulBrush++;
}
pulDst += (8 * 3); // dwords!
}
END_DIRECT_ACCESS_STORM(ppdev, pjBase);
}
/*****************************************************************************
* VOID vMilFillPat24bpp
*
* 24bpp patterned color fills for Storm.
****************************************************************************/
VOID vMilFillPat24bpp(
PDEV* ppdev,
LONG c, // Can't be zero
RECTL* prcl, // List of rectangles to be filled, in relative
// coordinates
ULONG rop4, // Rop4
RBRUSH_COLOR rbc, // rbc.prb points to brush realization structure
POINTL* pptlBrush) // Pattern alignment
{
BRUSHENTRY* pbe;
LONG xOffset;
LONG yOffset;
LONG xLeft;
LONG yTop;
LONG xBrush;
LONG yBrush;
LONG lSrcAdd;
ULONG ulLinear;
BYTE* pjBase;
ULONG ulHwMix;
ASSERTDD(!(rbc.prb->fl & RBRUSH_2COLOR), "Can't do 2 colour brushes here");
// We have to ensure that no other brush took our spot in off-screen
// memory, or we might have to realize the brush for the first time.
pbe = rbc.prb->apbe[IBOARD(ppdev)];
if (pbe->prbVerify != rbc.prb)
{
vMilPatRealize24bpp(ppdev, rbc.prb);
pbe = rbc.prb->apbe[IBOARD(ppdev)];
}
pjBase = ppdev->pjBase;
xOffset = ppdev->xOffset;
yOffset = ppdev->yOffset;
lSrcAdd = ppdev->lPatSrcAdd;
CHECK_FIFO_SPACE(pjBase, 6);
CP_WRITE(pjBase, DWG_AR5, 32); // Source (pattern) pitch.
ppdev->HopeFlags = SIGN_CACHE;
if ((rop4 & 0x000000FF) == 0x000000F0)
{
// The rop is PATCOPY.
CP_WRITE(pjBase, DWG_DWGCTL, (opcode_BITBLT + atype_RPL + sgnzero_ZERO +
shftzero_ZERO + bop_SRCCOPY +
bltmod_BFCOL + pattern_ON +
transc_BG_OPAQUE));
}
else
{
ulHwMix = (rop4 & 0x03) + ((rop4 & 0x30) >> 2);
CP_WRITE(pjBase, DWG_DWGCTL, (opcode_BITBLT + atype_RSTR + sgnzero_ZERO +
shftzero_ZERO + bltmod_BFCOL + pattern_ON +
transc_BG_OPAQUE +
(ulHwMix << 16)));
}
// The pattern setup is complete.
while(TRUE)
{
// Take into account the brush origin. The upper left pel of the
// brush should be aligned here in the destination surface.
yTop = prcl->top;
xLeft = prcl->left;
xBrush = (xLeft - pptlBrush->x) & 7;
yBrush = (yTop - pptlBrush->y) & 7;
ulLinear = pbe->ulLinear + (yBrush << 5) + xBrush;
CP_WRITE(pjBase, DWG_AR3, ulLinear);
CP_WRITE(pjBase, DWG_AR0, (ulLinear +7));
CP_WRITE(pjBase, DWG_FXBNDRY,
(((prcl->right + xOffset - 1) << bfxright_SHIFT) |
((xLeft + xOffset) & bfxleft_MASK)));
// ylength_MASK not is needed since coordinates are within range
CP_START(pjBase, DWG_YDSTLEN,
(((yTop + yOffset ) << yval_SHIFT) |
((prcl->bottom - yTop))));
if (--c == 0)
return;
CHECK_FIFO_SPACE(pjBase, 4);
prcl++;
}
}