You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
783 lines
26 KiB
783 lines
26 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: misc.c
|
|
*
|
|
* Miscellaneous common routines.
|
|
*
|
|
* Copyright (c) 1992-1995 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
|
|
/******************************Public*Table********************************\
|
|
* ULONG gaul32HwMixFromRop2[]
|
|
*
|
|
* Table to convert from a Source and Destination Rop2 to the Mach32's
|
|
* hardware mix.
|
|
\**************************************************************************/
|
|
|
|
ULONG gaul32HwMixFromRop2[] = {
|
|
LOGICAL_0, // 00 -- 0 BLACKNESS
|
|
NOT_SCREEN_AND_NOT_NEW, // 11 -- DSon NOTSRCERASE
|
|
SCREEN_AND_NOT_NEW, // 22 -- DSna
|
|
NOT_NEW, // 33 -- Sn NOSRCCOPY
|
|
NOT_SCREEN_AND_NEW, // 44 -- SDna SRCERASE
|
|
NOT_SCREEN, // 55 -- Dn DSTINVERT
|
|
SCREEN_XOR_NEW, // 66 -- DSx SRCINVERT
|
|
NOT_SCREEN_OR_NOT_NEW, // 77 -- DSan
|
|
SCREEN_AND_NEW, // 88 -- DSa SRCAND
|
|
NOT_SCREEN_XOR_NEW, // 99 -- DSxn
|
|
LEAVE_ALONE, // AA -- D
|
|
SCREEN_OR_NOT_NEW, // BB -- DSno MERGEPAINT
|
|
OVERPAINT, // CC -- S SRCCOPY
|
|
NOT_SCREEN_OR_NEW, // DD -- SDno
|
|
SCREEN_OR_NEW, // EE -- DSo SRCPAINT
|
|
LOGICAL_1 // FF -- 1 WHITENESS
|
|
};
|
|
|
|
/******************************Public*Table********************************\
|
|
* ULONG gaul32HwMixFromMix[]
|
|
*
|
|
* Table to convert from a GDI mix value to the Mach32's hardware mix.
|
|
*
|
|
* Ordered so that the mix may be calculated from gaul32HwMixFromMix[mix & 0xf]
|
|
* or gaul32HwMixFromMix[mix & 0xff].
|
|
\**************************************************************************/
|
|
|
|
ULONG gaul32HwMixFromMix[] = {
|
|
LOGICAL_1, // 0 -- 1
|
|
LOGICAL_0, // 1 -- 0
|
|
NOT_SCREEN_AND_NOT_NEW, // 2 -- DPon
|
|
SCREEN_AND_NOT_NEW, // 3 -- DPna
|
|
NOT_NEW, // 4 -- Pn
|
|
NOT_SCREEN_AND_NEW, // 5 -- PDna
|
|
NOT_SCREEN, // 6 -- Dn
|
|
SCREEN_XOR_NEW, // 7 -- DPx
|
|
NOT_SCREEN_OR_NOT_NEW, // 8 -- DPan
|
|
SCREEN_AND_NEW, // 9 -- DPa
|
|
NOT_SCREEN_XOR_NEW, // 10 -- DPxn
|
|
LEAVE_ALONE, // 11 -- D
|
|
SCREEN_OR_NOT_NEW, // 12 -- DPno
|
|
OVERPAINT, // 13 -- P
|
|
NOT_SCREEN_OR_NEW, // 14 -- PDno
|
|
SCREEN_OR_NEW, // 15 -- DPo
|
|
LOGICAL_1 // 16 -- 1
|
|
};
|
|
|
|
/******************************Public*Table********************************\
|
|
* ULONG gaul64HwMixFromRop2[]
|
|
*
|
|
* Table to convert from a Source and Destination Rop2 to the Mach64's
|
|
* foreground hardware mix.
|
|
\**************************************************************************/
|
|
|
|
ULONG gaul64HwMixFromRop2[] = {
|
|
LOGICAL_0 << 16, // 00 -- 0 BLACKNESS
|
|
NOT_SCREEN_AND_NOT_NEW << 16, // 11 -- DSon NOTSRCERASE
|
|
SCREEN_AND_NOT_NEW << 16, // 22 -- DSna
|
|
NOT_NEW << 16, // 33 -- Sn NOSRCCOPY
|
|
NOT_SCREEN_AND_NEW << 16, // 44 -- SDna SRCERASE
|
|
NOT_SCREEN << 16, // 55 -- Dn DSTINVERT
|
|
SCREEN_XOR_NEW << 16, // 66 -- DSx SRCINVERT
|
|
NOT_SCREEN_OR_NOT_NEW << 16, // 77 -- DSan
|
|
SCREEN_AND_NEW << 16, // 88 -- DSa SRCAND
|
|
NOT_SCREEN_XOR_NEW << 16, // 99 -- DSxn
|
|
LEAVE_ALONE << 16, // AA -- D
|
|
SCREEN_OR_NOT_NEW << 16, // BB -- DSno MERGEPAINT
|
|
OVERPAINT << 16, // CC -- S SRCCOPY
|
|
NOT_SCREEN_OR_NEW << 16, // DD -- SDno
|
|
SCREEN_OR_NEW << 16, // EE -- DSo SRCPAINT
|
|
LOGICAL_1 << 16 // FF -- 1 WHITENESS
|
|
};
|
|
|
|
/******************************Public*Table********************************\
|
|
* ULONG gaul64HwMixFromMix[]
|
|
*
|
|
* Table to convert from a GDI mix value to the Mach64's foreground hardware
|
|
* mix.
|
|
*
|
|
* Ordered so that the mix may be calculated from gaul64HwMixFromMix[mix & 0xf]
|
|
* or gaul64HwMixFromMix[mix & 0xff].
|
|
\**************************************************************************/
|
|
|
|
ULONG gaul64HwMixFromMix[] = {
|
|
LOGICAL_1 << 16, // 0 -- 1
|
|
LOGICAL_0 << 16, // 1 -- 0
|
|
NOT_SCREEN_AND_NOT_NEW << 16, // 2 -- DPon
|
|
SCREEN_AND_NOT_NEW << 16, // 3 -- DPna
|
|
NOT_NEW << 16, // 4 -- Pn
|
|
NOT_SCREEN_AND_NEW << 16, // 5 -- PDna
|
|
NOT_SCREEN << 16, // 6 -- Dn
|
|
SCREEN_XOR_NEW << 16, // 7 -- DPx
|
|
NOT_SCREEN_OR_NOT_NEW << 16, // 8 -- DPan
|
|
SCREEN_AND_NEW << 16, // 9 -- DPa
|
|
NOT_SCREEN_XOR_NEW << 16, // 10 -- DPxn
|
|
LEAVE_ALONE << 16, // 11 -- D
|
|
SCREEN_OR_NOT_NEW << 16, // 12 -- DPno
|
|
OVERPAINT << 16, // 13 -- P
|
|
NOT_SCREEN_OR_NEW << 16, // 14 -- PDno
|
|
SCREEN_OR_NEW << 16, // 15 -- DPo
|
|
LOGICAL_1 << 16 // 16 -- 1
|
|
};
|
|
|
|
/******************************Public*Data*********************************\
|
|
* MIX translation table
|
|
*
|
|
* Translates a mix 1-16, into an old style Rop 0-255.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BYTE gaRop3FromMix[] =
|
|
{
|
|
0xFF, // R2_WHITE - Allow rop = gaRop3FromMix[mix & 0x0F]
|
|
0x00, // R2_BLACK
|
|
0x05, // R2_NOTMERGEPEN
|
|
0x0A, // R2_MASKNOTPEN
|
|
0x0F, // R2_NOTCOPYPEN
|
|
0x50, // R2_MASKPENNOT
|
|
0x55, // R2_NOT
|
|
0x5A, // R2_XORPEN
|
|
0x5F, // R2_NOTMASKPEN
|
|
0xA0, // R2_MASKPEN
|
|
0xA5, // R2_NOTXORPEN
|
|
0xAA, // R2_NOP
|
|
0xAF, // R2_MERGENOTPEN
|
|
0xF0, // R2_COPYPEN
|
|
0xF5, // R2_MERGEPENNOT
|
|
0xFA, // R2_MERGEPEN
|
|
0xFF // R2_WHITE - Allow rop = gaRop3FromMix[mix & 0xFF]
|
|
};
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL bIntersect
|
|
*
|
|
* If 'prcl1' and 'prcl2' intersect, has a return value of TRUE and returns
|
|
* the intersection in 'prclResult'. If they don't intersect, has a return
|
|
* value of FALSE, and 'prclResult' is undefined.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL bIntersect(
|
|
RECTL* prcl1,
|
|
RECTL* prcl2,
|
|
RECTL* prclResult)
|
|
{
|
|
prclResult->left = max(prcl1->left, prcl2->left);
|
|
prclResult->right = min(prcl1->right, prcl2->right);
|
|
|
|
if (prclResult->left < prclResult->right)
|
|
{
|
|
prclResult->top = max(prcl1->top, prcl2->top);
|
|
prclResult->bottom = min(prcl1->bottom, prcl2->bottom);
|
|
|
|
if (prclResult->top < prclResult->bottom)
|
|
{
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* LONG cIntersect
|
|
*
|
|
* This routine takes a list of rectangles from 'prclIn' and clips them
|
|
* in-place to the rectangle 'prclClip'. The input rectangles don't
|
|
* have to intersect 'prclClip'; the return value will reflect the
|
|
* number of input rectangles that did intersect, and the intersecting
|
|
* rectangles will be densely packed.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
LONG cIntersect(
|
|
RECTL* prclClip,
|
|
RECTL* prclIn, // List of rectangles
|
|
LONG c) // Can be zero
|
|
{
|
|
LONG cIntersections;
|
|
RECTL* prclOut;
|
|
|
|
cIntersections = 0;
|
|
prclOut = prclIn;
|
|
|
|
for (; c != 0; prclIn++, c--)
|
|
{
|
|
prclOut->left = max(prclIn->left, prclClip->left);
|
|
prclOut->right = min(prclIn->right, prclClip->right);
|
|
|
|
if (prclOut->left < prclOut->right)
|
|
{
|
|
prclOut->top = max(prclIn->top, prclClip->top);
|
|
prclOut->bottom = min(prclIn->bottom, prclClip->bottom);
|
|
|
|
if (prclOut->top < prclOut->bottom)
|
|
{
|
|
prclOut++;
|
|
cIntersections++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(cIntersections);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vResetClipping
|
|
\**************************************************************************/
|
|
|
|
VOID vResetClipping(
|
|
PDEV* ppdev)
|
|
{
|
|
BYTE* pjMmBase;
|
|
BYTE* pjIoBase;
|
|
|
|
if (ppdev->iMachType == MACH_MM_64)
|
|
{
|
|
pjMmBase = ppdev->pjMmBase;
|
|
|
|
M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 2);
|
|
M64_OD(pjMmBase, SC_LEFT_RIGHT, PACKPAIR(0, M64_MAX_SCISSOR_R));
|
|
M64_OD(pjMmBase, SC_TOP_BOTTOM, PACKPAIR(0, ppdev->cyMemory));
|
|
}
|
|
else if (ppdev->iMachType == MACH_MM_32)
|
|
{
|
|
pjMmBase = ppdev->pjMmBase;
|
|
|
|
M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
|
|
M32_OW(pjMmBase, EXT_SCISSOR_L, 0);
|
|
M32_OW(pjMmBase, EXT_SCISSOR_R, M32_MAX_SCISSOR);
|
|
M32_OW(pjMmBase, EXT_SCISSOR_T, 0);
|
|
M32_OW(pjMmBase, EXT_SCISSOR_B, M32_MAX_SCISSOR);
|
|
}
|
|
else
|
|
{
|
|
pjIoBase = ppdev->pjIoBase;
|
|
|
|
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 4);
|
|
I32_OW(pjIoBase, EXT_SCISSOR_L, 0);
|
|
I32_OW(pjIoBase, EXT_SCISSOR_R, M32_MAX_SCISSOR);
|
|
I32_OW(pjIoBase, EXT_SCISSOR_T, 0);
|
|
I32_OW(pjIoBase, EXT_SCISSOR_B, M32_MAX_SCISSOR);
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vSetClipping
|
|
\**************************************************************************/
|
|
|
|
VOID vSetClipping(
|
|
PDEV* ppdev,
|
|
RECTL* prclClip) // In relative coordinates
|
|
{
|
|
LONG xOffset;
|
|
LONG yOffset;
|
|
BYTE* pjMmBase;
|
|
BYTE* pjIoBase;
|
|
|
|
xOffset = ppdev->xOffset;
|
|
yOffset = ppdev->yOffset;
|
|
|
|
if (ppdev->iMachType == MACH_MM_64)
|
|
{
|
|
pjMmBase = ppdev->pjMmBase;
|
|
|
|
M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 2);
|
|
if (ppdev->iBitmapFormat != BMF_24BPP)
|
|
{
|
|
M64_OD(pjMmBase, SC_LEFT_RIGHT, PACKPAIR(xOffset + prclClip->left,
|
|
xOffset + prclClip->right - 1));
|
|
}
|
|
else
|
|
{
|
|
M64_OD(pjMmBase, SC_LEFT_RIGHT, PACKPAIR((xOffset + prclClip->left) * 3,
|
|
(xOffset + prclClip->right) * 3 - 1));
|
|
}
|
|
M64_OD(pjMmBase, SC_TOP_BOTTOM, PACKPAIR(yOffset + prclClip->top,
|
|
yOffset + prclClip->bottom - 1));
|
|
}
|
|
else if (ppdev->iMachType == MACH_MM_32)
|
|
{
|
|
pjMmBase = ppdev->pjMmBase;
|
|
|
|
M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
|
|
M32_OW(pjMmBase, EXT_SCISSOR_L, xOffset + prclClip->left);
|
|
M32_OW(pjMmBase, EXT_SCISSOR_R, xOffset + prclClip->right - 1);
|
|
M32_OW(pjMmBase, EXT_SCISSOR_T, yOffset + prclClip->top);
|
|
M32_OW(pjMmBase, EXT_SCISSOR_B, yOffset + prclClip->bottom - 1);
|
|
}
|
|
else
|
|
{
|
|
pjIoBase = ppdev->pjIoBase;
|
|
|
|
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 4);
|
|
I32_OW(pjIoBase, EXT_SCISSOR_L, xOffset + prclClip->left);
|
|
I32_OW(pjIoBase, EXT_SCISSOR_R, xOffset + prclClip->right - 1);
|
|
I32_OW(pjIoBase, EXT_SCISSOR_T, yOffset + prclClip->top);
|
|
I32_OW(pjIoBase, EXT_SCISSOR_B, yOffset + prclClip->bottom - 1);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// For mach8 cards only...
|
|
//
|
|
|
|
VOID vI32DataPortIn(PDEV *ppdev, WORD *pw, UINT count)
|
|
{
|
|
BYTE *pjIoBase = ppdev->pjIoBase;
|
|
UINT i;
|
|
|
|
for (i=0; i < count; i++)
|
|
{
|
|
*((USHORT UNALIGNED *)pw)++ = I32_IW(pjIoBase, PIX_TRANS);
|
|
}
|
|
|
|
}
|
|
|
|
VOID vI32GetBits( PDEV *ppdev,
|
|
SURFOBJ *psoDst,
|
|
RECTL *prclDst,
|
|
POINTL *pptlSrc
|
|
)
|
|
{
|
|
LONG xPunt, yPunt,
|
|
cxPunt, cyPunt, nwords;
|
|
LONG lDeltaDst = psoDst->lDelta;
|
|
PBYTE pjPunt, pjIoBase = ppdev->pjIoBase;
|
|
PWORD pw;
|
|
WORD Cmd;
|
|
|
|
|
|
// pptlSrc gives the starting point on the screen.
|
|
xPunt = pptlSrc->x;
|
|
yPunt = pptlSrc->y;
|
|
|
|
// prclDst gives the region size.
|
|
cxPunt = prclDst->right - prclDst->left;
|
|
cyPunt = prclDst->bottom - prclDst->top;
|
|
|
|
// Do not optimize for word alignment if prclDst points to beginning of scan.
|
|
if ((prclDst->left) && (xPunt & 0x1))
|
|
{
|
|
xPunt--;
|
|
cxPunt++;
|
|
pjPunt = (PBYTE) psoDst->pvScan0 + (prclDst->top * lDeltaDst) + prclDst->left - 1;
|
|
}
|
|
else
|
|
pjPunt = (PBYTE) psoDst->pvScan0 + (prclDst->top * lDeltaDst) + prclDst->left;
|
|
|
|
// Make sure the cx is an even number of words.
|
|
if (cxPunt & 0x1)
|
|
{
|
|
cxPunt++;
|
|
}
|
|
|
|
// Set the engine up for the copy.
|
|
|
|
Cmd = READ | FG_COLOR_SRC_HOST | DATA_WIDTH | DATA_ORDER | DRAW;
|
|
|
|
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 7);
|
|
|
|
I32_OW(pjIoBase, DP_CONFIG, Cmd );
|
|
I32_OW(pjIoBase, WRT_MASK, 0xffff );
|
|
I32_OW(pjIoBase, CUR_X, (SHORT) xPunt );
|
|
I32_OW(pjIoBase, CUR_Y, (SHORT) yPunt );
|
|
I32_OW(pjIoBase, DEST_X_START, (SHORT) xPunt );
|
|
I32_OW(pjIoBase, DEST_X_END, (SHORT) (xPunt + cxPunt) );
|
|
I32_OW(pjIoBase, DEST_Y_END, (SHORT) (yPunt + cyPunt) );
|
|
|
|
// Wait for the Data Available.
|
|
|
|
while (!(I32_IW(pjIoBase, GE_STAT) & 0x100));
|
|
|
|
// Now transfer the data from the screen to the host memory bitmap.
|
|
|
|
pw = (PWORD) pjPunt;
|
|
|
|
nwords = (cxPunt + 1)/2;
|
|
|
|
while (cyPunt-- > 0)
|
|
{
|
|
vI32DataPortIn(ppdev, pw, nwords);
|
|
((PBYTE) pw) += lDeltaDst;
|
|
}
|
|
}
|
|
|
|
VOID vI32DataPortOut(PDEV *ppdev, WORD *pw, UINT count)
|
|
{
|
|
BYTE *pjIoBase = ppdev->pjIoBase;
|
|
UINT i;
|
|
|
|
for (i=0; i < count; i++)
|
|
{
|
|
if (i % 8 == 0)
|
|
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 10);
|
|
|
|
I32_OW(pjIoBase, PIX_TRANS, *((USHORT UNALIGNED *)pw)++);
|
|
}
|
|
}
|
|
|
|
VOID vI32PutBits( PDEV *ppdev,
|
|
SURFOBJ *psoSrc,
|
|
RECTL *prclDst,
|
|
POINTL *pptlSrc
|
|
)
|
|
{
|
|
BOOL leftScissor = FALSE, rightScissor = FALSE;
|
|
LONG xPunt, yPunt,
|
|
cxPunt, cyPunt, nwords;
|
|
LONG lDeltaSrc = psoSrc->lDelta;
|
|
PBYTE pjPunt, pjIoBase = ppdev->pjIoBase;
|
|
PWORD pw;
|
|
WORD Cmd;
|
|
|
|
|
|
// prclDst gives the starting point on the screen.
|
|
xPunt = prclDst->left;
|
|
yPunt = prclDst->top;
|
|
|
|
// prclDst gives the region size.
|
|
cxPunt = min( prclDst->right, (LONG) ppdev->cxMemory ) - xPunt;
|
|
cyPunt = prclDst->bottom - yPunt;
|
|
|
|
// Do not optimize for word alignment if pptlSrc points to beginning of scan.
|
|
if ((pptlSrc->x) && (xPunt & 0x1))
|
|
{
|
|
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 1);
|
|
I32_OW(pjIoBase, EXT_SCISSOR_L, (SHORT) xPunt );
|
|
xPunt--;
|
|
cxPunt++;
|
|
leftScissor = TRUE;
|
|
pjPunt = (PBYTE) psoSrc->pvScan0 + (pptlSrc->y * lDeltaSrc) + pptlSrc->x - 1;
|
|
}
|
|
else
|
|
pjPunt = (PBYTE) psoSrc->pvScan0 + (pptlSrc->y * lDeltaSrc) + pptlSrc->x;
|
|
|
|
// Make sure the cx is an even number of words.
|
|
if (cxPunt & 0x1)
|
|
{
|
|
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 1);
|
|
I32_OW(pjIoBase, EXT_SCISSOR_R, (SHORT) (xPunt + cxPunt - 1) );
|
|
cxPunt++;
|
|
rightScissor = TRUE;
|
|
}
|
|
|
|
// Set the engine up for the copy.
|
|
|
|
Cmd = FG_COLOR_SRC_HOST | DATA_ORDER | DATA_WIDTH | DRAW | WRITE;
|
|
|
|
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 9);
|
|
|
|
I32_OW(pjIoBase, DP_CONFIG, Cmd );
|
|
I32_OW(pjIoBase, WRT_MASK, 0xffff );
|
|
I32_OW(pjIoBase, ALU_FG_FN, OVERPAINT );
|
|
I32_OW(pjIoBase, ALU_BG_FN, OVERPAINT );
|
|
|
|
I32_OW(pjIoBase, CUR_X, (SHORT) xPunt );
|
|
I32_OW(pjIoBase, CUR_Y, (SHORT) yPunt );
|
|
I32_OW(pjIoBase, DEST_X_START, (SHORT) xPunt );
|
|
I32_OW(pjIoBase, DEST_X_END, (SHORT) (xPunt + cxPunt) );
|
|
I32_OW(pjIoBase, DEST_Y_END, (SHORT) (yPunt + cyPunt) );
|
|
|
|
// Now transfer the data, from the host memory bitmap to the screen.
|
|
|
|
pw = (PWORD) pjPunt;
|
|
|
|
nwords = (cxPunt + 1)/2;
|
|
|
|
while (cyPunt-- > 0)
|
|
{
|
|
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 1);
|
|
vI32DataPortOut(ppdev, pw, nwords);
|
|
((PBYTE) pw) += lDeltaSrc;
|
|
}
|
|
|
|
if (leftScissor)
|
|
{
|
|
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 1);
|
|
I32_OW(pjIoBase, EXT_SCISSOR_L, 0 );
|
|
}
|
|
if (rightScissor)
|
|
{
|
|
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 1);
|
|
I32_OW(pjIoBase, EXT_SCISSOR_R, (SHORT) M32_MAX_SCISSOR );
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Context Stuff
|
|
//
|
|
|
|
#define _bit(x) (1 << (x))
|
|
#define CONTEXT_ADDR(ppdev,p) (ppdev->pjContextBase - (((p)+1) * 0x100))
|
|
|
|
#define cxtCONTEXT_MASK 0
|
|
|
|
#define cxtDST_OFF_PITCH 2
|
|
#define cxtDST_Y_X 3
|
|
#define cxtDST_HEIGHT_WIDTH 4
|
|
#define cxtDST_BRES_ERR 5
|
|
#define cxtDST_BRES_INC 6
|
|
#define cxtDST_BRES_DEC 7
|
|
|
|
#define cxtSRC_OFF_PITCH 8
|
|
#define cxtSRC_Y_X 9
|
|
#define cxtSRC_HEIGHT1_WIDTH1 10
|
|
#define cxtSRC_Y_X_START 11
|
|
#define cxtSRC_HEIGHT2_WIDTH2 12
|
|
#define cxtPAT_REG0 13
|
|
#define cxtPAT_REG1 14
|
|
#define cxtSC_LEFT_RIGHT 15
|
|
|
|
#define cxtSC_TOP_BOTTOM 16
|
|
#define cxtDP_BKGD_CLR 17
|
|
#define cxtDP_FRGD_CLR 18
|
|
#define cxtDP_WRITE_MASK 19
|
|
#define cxtDP_CHAIN_MASK 20
|
|
#define cxtDP_PIX_WIDTH 21
|
|
#define cxtDP_MIX 22
|
|
#define cxtDP_SRC 23
|
|
|
|
#define cxtCLR_CMP_CLR 24
|
|
#define cxtCLR_CMP_MASK 25
|
|
#define cxtCLR_CMP_CNTL 26
|
|
#define cxtGUI_TRAJ_CNTL 27
|
|
#define cxtCONTEXT_LOAD_CNTL 28
|
|
|
|
|
|
BYTE *ContextBaseAddress(PDEV *ppdev)
|
|
{
|
|
ULONG context_addr = 0;
|
|
DWORD mem_cntl;
|
|
|
|
mem_cntl = M64_ID(ppdev->pjMmBase, M64_MEM_CNTL);
|
|
|
|
switch (mem_cntl & 7)
|
|
{
|
|
case 0:
|
|
context_addr = 0x80000; // 512 K
|
|
break;
|
|
case 1:
|
|
context_addr = 0x100000; // 1 M
|
|
break;
|
|
case 2:
|
|
context_addr = 0x200000;
|
|
break;
|
|
case 3:
|
|
context_addr = 0x400000;
|
|
break;
|
|
case 4:
|
|
context_addr = 0x600000;
|
|
break;
|
|
case 5:
|
|
context_addr = 0x800000;
|
|
break;
|
|
}
|
|
return (BYTE *) context_addr;
|
|
}
|
|
|
|
VOID SetContextWorkspace( PDEV *ppdev, DWORD *context_regs,
|
|
DWORD context_mask, DWORD context_load_cntl )
|
|
{
|
|
BYTE* pjMmBase = ppdev->pjMmBase;
|
|
INT i;
|
|
|
|
for (i = 0; i < 64; i++)
|
|
context_regs[i] = 0;
|
|
|
|
context_regs[ 0] = context_mask;
|
|
if (context_mask & 0x00000004)
|
|
*(context_regs+ 2) = M64_ID(pjMmBase, DST_OFF_PITCH);
|
|
if (context_mask & 0x00000008)
|
|
*(context_regs+ 3) = M64_ID(pjMmBase, DST_Y_X);
|
|
if (context_mask & 0x00000010)
|
|
*(context_regs+ 4) = M64_ID(pjMmBase, DST_HEIGHT_WIDTH);
|
|
if (context_mask & 0x00000020)
|
|
*(context_regs+ 5) = M64_ID(pjMmBase, DST_BRES_ERR);
|
|
if (context_mask & 0x00000040)
|
|
*(context_regs+ 6) = M64_ID(pjMmBase, DST_BRES_INC);
|
|
if (context_mask & 0x00000080)
|
|
*(context_regs+ 7) = M64_ID(pjMmBase, DST_BRES_DEC);
|
|
if (context_mask & 0x00000100)
|
|
*(context_regs+ 8) = M64_ID(pjMmBase, SRC_OFF_PITCH);
|
|
if (context_mask & 0x00000200)
|
|
*(context_regs+ 9) = M64_ID(pjMmBase, SRC_Y_X);
|
|
if (context_mask & 0x00000400)
|
|
*(context_regs+10) = M64_ID(pjMmBase, SRC_HEIGHT1_WIDTH1);
|
|
if (context_mask & 0x00000800)
|
|
*(context_regs+11) = M64_ID(pjMmBase, SRC_Y_X_START);
|
|
if (context_mask & 0x00001000)
|
|
*(context_regs+12) = M64_ID(pjMmBase, SRC_HEIGHT2_WIDTH2);
|
|
if (context_mask & 0x00002000)
|
|
*(context_regs+13) = M64_ID(pjMmBase, PAT_REG0);
|
|
if (context_mask & 0x00004000)
|
|
*(context_regs+14) = M64_ID(pjMmBase, PAT_REG1);
|
|
if (context_mask & 0x00008000)
|
|
*(context_regs+15) = M64_ID(pjMmBase, SC_LEFT_RIGHT);
|
|
if (context_mask & 0x00010000)
|
|
*(context_regs+16) = M64_ID(pjMmBase, SC_TOP_BOTTOM);
|
|
if (context_mask & 0x00020000)
|
|
*(context_regs+17) = M64_ID(pjMmBase, DP_BKGD_CLR);
|
|
if (context_mask & 0x00040000)
|
|
*(context_regs+18) = M64_ID(pjMmBase, DP_FRGD_CLR);
|
|
if (context_mask & 0x00080000)
|
|
*(context_regs+19) = M64_ID(pjMmBase, DP_WRITE_MASK);
|
|
if (context_mask & 0x00100000)
|
|
*(context_regs+20) = M64_ID(pjMmBase, DP_CHAIN_MASK);
|
|
if (context_mask & 0x00200000)
|
|
*(context_regs+21) = M64_ID(pjMmBase, DP_PIX_WIDTH);
|
|
if (context_mask & 0x00400000)
|
|
*(context_regs+22) = M64_ID(pjMmBase, DP_MIX);
|
|
if (context_mask & 0x00800000)
|
|
*(context_regs+23) = M64_ID(pjMmBase, DP_SRC);
|
|
if (context_mask & 0x01000000)
|
|
*(context_regs+24) = M64_ID(pjMmBase, CLR_CMP_CLR);
|
|
if (context_mask & 0x02000000)
|
|
*(context_regs+25) = M64_ID(pjMmBase, CLR_CMP_MSK);
|
|
if (context_mask & 0x04000000)
|
|
*(context_regs+26) = M64_ID(pjMmBase, CLR_CMP_CNTL);
|
|
if (context_mask & 0x08000000)
|
|
*(context_regs+27) = M64_ID(pjMmBase, GUI_TRAJ_CNTL);
|
|
context_regs[28] = context_load_cntl;
|
|
|
|
}
|
|
|
|
VOID UploadContext( PDEV *ppdev, DWORD *context_regs, BYTE *context_addr )
|
|
{
|
|
BYTE* pjMmBase = ppdev->pjMmBase;
|
|
|
|
M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 10);
|
|
M64_OD(pjMmBase, CLR_CMP_CNTL, 0 );
|
|
M64_OD(pjMmBase, SC_LEFT_RIGHT, (255) << 16 );
|
|
M64_OD(pjMmBase, SC_TOP_BOTTOM, 0 );
|
|
M64_OD(pjMmBase, DP_SRC, DP_SRC_Host << 8 );
|
|
M64_OD(pjMmBase, DST_CNTL, DST_CNTL_XDir | DST_CNTL_YDir );
|
|
M64_OD(pjMmBase, DP_MIX, OVERPAINT << 16 );
|
|
M64_OD(pjMmBase, DP_PIX_WIDTH, DP_PIX_WIDTH_8bpp | (DP_PIX_WIDTH_8bpp << 16) );
|
|
M64_OD(pjMmBase, DST_OFF_PITCH,
|
|
(ULONG)((ULONG_PTR) context_addr/8 | (256 << 19) ));
|
|
M64_OD(pjMmBase, DST_Y_X, 0 );
|
|
M64_OD(pjMmBase, DST_HEIGHT_WIDTH, 0x01000001 ); // 256x1
|
|
|
|
vM64DataPortOutB(ppdev, (BYTE *)context_regs, 256);
|
|
|
|
M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
|
|
M64_OD(pjMmBase, DST_OFF_PITCH, ppdev->ulScreenOffsetAndPitch );
|
|
M64_OD(pjMmBase, DP_PIX_WIDTH, ppdev->ulMonoPixelWidth );
|
|
M64_OD(pjMmBase, SC_LEFT_RIGHT, M64_MAX_SCISSOR_R << 16 );
|
|
M64_OD(pjMmBase, SC_TOP_BOTTOM, ppdev->cyMemory << 16 );
|
|
}
|
|
|
|
VOID vSetDefaultContext(PDEV * ppdev)
|
|
{
|
|
DWORD work_context [64];
|
|
|
|
SetContextWorkspace( ppdev, work_context,
|
|
_bit(cxtCONTEXT_MASK) |
|
|
_bit(cxtDP_WRITE_MASK) |
|
|
_bit(cxtCLR_CMP_CNTL) |
|
|
_bit(cxtGUI_TRAJ_CNTL),
|
|
0);
|
|
// Fix vanishing text and fills, as well as other color problems:
|
|
work_context[cxtDP_WRITE_MASK] = 0xFFFFFFFF;
|
|
work_context[cxtCLR_CMP_CNTL] = 0;
|
|
// Fix frizzy text and RGB ordering problems:
|
|
work_context[cxtGUI_TRAJ_CNTL] = DST_CNTL_XDir | DST_CNTL_YDir;
|
|
UploadContext( ppdev, work_context, CONTEXT_ADDR(ppdev,ppdev->iDefContext) );
|
|
}
|
|
|
|
VOID vEnableContexts(PDEV * ppdev)
|
|
{
|
|
ppdev->pjContextBase = ContextBaseAddress(ppdev);
|
|
if (ppdev->cjBank == (LONG)((ULONG_PTR)ppdev->pjContextBase))
|
|
ppdev->ulContextCeiling =(ULONG)((ULONG_PTR)ppdev->pjContextBase - 1024);
|
|
else
|
|
ppdev->ulContextCeiling = (ULONG)((ULONG_PTR) ppdev->pjContextBase);
|
|
|
|
// Compute ALL context pointers needed in the driver.
|
|
ppdev->iDefContext = (ULONG)((ULONG_PTR)ppdev->pjContextBase
|
|
- (ULONG_PTR)ppdev->ulContextCeiling)/256;
|
|
ppdev->ulContextCeiling -= 256;
|
|
|
|
// In general, you need to check whether a context allocation will decrease
|
|
// cyMemory. Here, we only have the one and FIRST allocation, so decrement cyMemory.
|
|
ppdev->cyMemory--;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// DataPortOutB routine for the mach64
|
|
//
|
|
|
|
VOID vM64DataPortOutB(PDEV *ppdev, PBYTE pb, UINT count)
|
|
{
|
|
PBYTE pjMmBase = ppdev->pjMmBase;
|
|
UINT i, DWLeft, LastBytes;
|
|
DWORD UNALIGNED *pdw;
|
|
PBYTE Byte_in_Dword;
|
|
DWORD Buffer;
|
|
|
|
#define THRESH 14
|
|
|
|
pdw = (DWORD*)pb;
|
|
DWLeft = (count + 3)/4;
|
|
LastBytes = count % 4;
|
|
|
|
while ( DWLeft > 0 )
|
|
{
|
|
if (DWLeft < THRESH || (DWLeft == THRESH && LastBytes != 0))
|
|
{
|
|
M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, DWLeft);
|
|
|
|
if (LastBytes > 0)
|
|
{
|
|
for (i=0; i< DWLeft-1 ; i++)
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+i));
|
|
|
|
Byte_in_Dword = (PBYTE) (pdw+i);
|
|
Buffer = 0;
|
|
for (i=0; i < LastBytes; i++)
|
|
{
|
|
Buffer |= (*Byte_in_Dword) << (i*8);
|
|
Byte_in_Dword++;
|
|
}
|
|
|
|
M64_OD(pjMmBase, HOST_DATA0, Buffer);
|
|
}
|
|
else
|
|
{
|
|
for (i=0; i< DWLeft ; i++)
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+i));
|
|
}
|
|
|
|
pdw += DWLeft;
|
|
DWLeft = 0;
|
|
}
|
|
else
|
|
{
|
|
M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
|
|
|
|
/* Inline coded for greater performance */
|
|
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw)); // 1 Word
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+1)); // 2 Words
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+2)); // 3 Words
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+3)); // 4 Words
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+4)); // 5 Words
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+5)); // 6 Words
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+6)); // 7 Words
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+7)); // 8 Words
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+8)); // 9 Words
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+9)); // 10 Words
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+10)); // 11 Words
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+11)); // 12 Words
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+12)); // 13 Words
|
|
M64_OD(pjMmBase, HOST_DATA0, *(pdw+13)); // 14 Words
|
|
|
|
pdw += 14;
|
|
DWLeft -= THRESH;
|
|
} /*if*/
|
|
} /* while */
|
|
|
|
#undef THRESH
|
|
|
|
}
|