windows-nt/Source/XPSP1/NT/drivers/video/ms/w32/disp/stroke.c
2020-09-26 16:20:57 +08:00

508 lines
14 KiB
C

/******************************Module*Header*******************************\
* Module Name: Stroke.c
*
* DrvStrokePath for the display driver
*
* Copyright (c) 1992-1995 Microsoft Corporation
\**************************************************************************/
#include "precomp.h"
// Note: the following table has 17 entries
BYTE aMixToRop3[] = {
0xFF, /* 0 1 */
0x00, /* 1 0 */
0x05, /* 2 DPon */
0x0A, /* 3 DPna */
0x0F, /* 4 PN */
0x50, /* 5 PDna */
0x55, /* 6 Dn */
0x5a, /* 7 DPx */
0x5f, /* 8 DPan */
0xA0, /* 9 DPa */
0xA5, /* 10 DPxn */
0xAA, /* 11 D */
0xAF, /* 12 DPno */
0xF0, /* 13 P */
0xF5, /* 14 PDno */
0xFA, /* 15 DPo */
0xFF /* 16 1 */
};
VOID (*gapfnStripI[])(PDEV*, STRIP*, LINESTATE*) = {
vrlSolidHorizontal,
vrlSolidVertical,
vrlSolidDiagonalHorizontal,
vrlSolidDiagonalVertical,
// Should be NUM_STRIP_DRAW_DIRECTIONS = 4 strip drawers in every group
vssSolidHorizontal,
vssSolidVertical,
vssSolidDiagonalHorizontal,
vssSolidDiagonalVertical,
// Should be NUM_STRIP_DRAW_STYLES = 8 strip drawers in total for doing
// solid lines, and the same number for non-solid lines:
vStripStyledHorizontal,
vStripStyledVertical,
vStripStyledVertical, // Diagonal goes here
vStripStyledVertical, // Diagonal goes here
vStripStyledHorizontal,
vStripStyledVertical,
vStripStyledVertical, // Diagonal goes here
vStripStyledVertical, // Diagonal goes here
};
VOID (*gapfnStripP[])(PDEV*, STRIP*, LINESTATE*) = {
vrlSolidHorizontalP,
vrlSolidVerticalP,
vrlSolidDiagonalHorizontalP,
vrlSolidDiagonalVerticalP,
// Should be NUM_STRIP_DRAW_DIRECTIONS = 4 strip drawers in every group
vrlSolidHorizontalP,
vrlSolidVerticalP,
vrlSolidDiagonalHorizontalP,
vrlSolidDiagonalVerticalP,
// Should be NUM_STRIP_DRAW_STYLES = 8 strip drawers in total for doing
// solid lines, and the same number for non-solid lines:
vStripStyledHorizontalP,
vStripStyledVerticalP,
vStripStyledVerticalP, // Diagonal goes here
vStripStyledVerticalP, // Diagonal goes here
vStripStyledHorizontalP,
vStripStyledVerticalP,
vStripStyledVerticalP, // Diagonal goes here
vStripStyledVerticalP, // Diagonal goes here
};
// Style array for alternate style (alternates one pixel on, one pixel off):
STYLEPOS gaspAlternateStyle[] = { 1 };
/******************************Public*Routine******************************\
* BOOL DrvStrokePath(pso, ppo, pco, pxo, pbo, pptlBrush, pla, mix)
*
* Strokes the path.
*
\**************************************************************************/
BOOL DrvStrokePath(
SURFOBJ* pso,
PATHOBJ* ppo,
CLIPOBJ* pco,
XFORMOBJ* pxo,
BRUSHOBJ* pbo,
POINTL* pptlBrush,
LINEATTRS* pla,
MIX mix)
{
PDEV *ppdev = (PDEV*) pso->dhpdev;
DSURF *pdsurf;
OH* poh;
BYTE* pjBase;
LONG cBpp;
STYLEPOS aspLtoR[STYLE_MAX_COUNT];
STYLEPOS aspRtoL[STYLE_MAX_COUNT];
LINESTATE ls;
PFNSTRIP* apfn;
FLONG fl;
RECTL arclClip[4]; // For rectangular clipping
if ((mix & 0xf) != 0x0d) DISPDBG((3,"Line with mix(%x)", mix));
// Pass the surface off to GDI if it's a device bitmap that we've
// converted to a DIB:
pdsurf = (DSURF*) pso->dhsurf;
if (pdsurf->dt == DT_DIB)
{
return(EngStrokePath(pdsurf->pso, ppo, pco, pxo, pbo, pptlBrush,
pla, mix));
}
// We'll be drawing to the screen or an off-screen DFB; copy the surface's
// offset now so that we won't need to refer to the DSURF again:
poh = pdsurf->poh;
cBpp = ppdev->cBpp;
ppdev->xOffset = poh->x;
ppdev->yOffset = poh->y;
ppdev->xyOffset = (poh->x * cBpp) +
(poh->y * ppdev->lDelta);
if (DRIVER_PUNT_ALL ||
(pla->fl & LA_ALTERNATE) ||
(pla->pstyle != (FLOAT_LONG*) NULL) ||
((cBpp == 3) && (ppdev->ulChipID != W32P) && (ppdev->ulChipID != ET6000)))
{
if (ppdev->bAutoBanking)
{
PVOID pvScan0;
BOOL bRet;
BYTE* pjBase = ppdev->pjBase;
pvScan0 = ppdev->psoFrameBuffer->pvScan0;
(BYTE*)ppdev->psoFrameBuffer->pvScan0 += ppdev->xyOffset;
WAIT_FOR_IDLE_ACL(ppdev, pjBase);
bRet = EngStrokePath(ppdev->psoFrameBuffer,ppo,pco,pxo,pbo,
pptlBrush,pla,mix);
ppdev->psoFrameBuffer->pvScan0 = pvScan0;
return(bRet);
}
//
// Bank and punt call to the engine (line was styled)
//
{
BANK bnk;
BOOL b;
RECTL rclDraw;
RECTL *prclDst = &pco->rclBounds;
FLOAT_LONG elSavedStyleState = pla->elStyleState;
{
DISPDBG((110,"Simulating StrokePath\n"));
// The bank manager requires that the 'draw' rectangle be
// well-ordered:
rclDraw = *prclDst;
if (rclDraw.left > rclDraw.right)
{
rclDraw.left = prclDst->right;
rclDraw.right = prclDst->left;
}
if (rclDraw.top > rclDraw.bottom)
{
rclDraw.top = prclDst->bottom;
rclDraw.bottom = prclDst->top;
}
vBankStart(ppdev, &rclDraw, pco, &bnk);
b = TRUE;
do {
pla->elStyleState = elSavedStyleState;
b &= EngStrokePath(bnk.pso,
ppo,
bnk.pco,
pxo,
pbo,
pptlBrush,
pla,
mix);
} while (bBankEnum(&bnk));
return(b);
}
}
}
// Get the device ready:
pjBase = ppdev->pjBase;
WAIT_FOR_EMPTY_ACL_QUEUE(ppdev, pjBase);
CP_FG_ROP(ppdev, pjBase, (aMixToRop3[mix & 0xf]));
CP_PAT_WRAP(ppdev, pjBase, (SOLID_COLOR_PATTERN_WRAP));
CP_PAT_Y_OFFSET(ppdev, pjBase, (SOLID_COLOR_PATTERN_OFFSET - 1));
CP_PAT_ADDR(ppdev, pjBase, (ppdev->ulSolidColorOffset));
{
ULONG ulSolidColor = pbo->iSolidColor;
if (cBpp == 1)
{
ulSolidColor &= 0x000000FF; // We may get some extraneous data in the
ulSolidColor |= ulSolidColor << 8;
}
if (cBpp <= 2)
{
ulSolidColor &= 0x0000FFFF;
ulSolidColor |= ulSolidColor << 16;
}
WAIT_FOR_IDLE_ACL(ppdev, pjBase);
// Set the color in offscreen memory
if (ppdev->bAutoBanking)
{
*(PULONG)(ppdev->pjScreen + ppdev->ulSolidColorOffset) = ulSolidColor;
}
else
{
CP_MMU_BP0(ppdev, pjBase, ppdev->ulSolidColorOffset);
CP_WRITE_MMU_DWORD(ppdev, 0, 0, ulSolidColor);
}
}
fl = 0;
// Look after styling initialization:
if (pla->fl & LA_ALTERNATE)
{
ls.cStyle = 1;
ls.spTotal = 1;
ls.spTotal2 = 2;
ls.spRemaining = 1;
ls.aspRtoL = &gaspAlternateStyle[0];
ls.aspLtoR = &gaspAlternateStyle[0];
ls.spNext = HIWORD(pla->elStyleState.l);
ls.xyDensity = 1;
fl |= FL_STYLED;
ls.ulStartMask = 0L;
}
else if (pla->pstyle != (FLOAT_LONG*) NULL)
{
PFLOAT_LONG pstyle;
STYLEPOS* pspDown;
STYLEPOS* pspUp;
pstyle = &pla->pstyle[pla->cstyle];
ls.xyDensity = STYLE_DENSITY;
ls.spTotal = 0;
while (pstyle-- > pla->pstyle)
{
ls.spTotal += pstyle->l;
}
ls.spTotal *= STYLE_DENSITY;
ls.spTotal2 = 2 * ls.spTotal;
// Compute starting style position (this is guaranteed not to overflow):
ls.spNext = HIWORD(pla->elStyleState.l) * STYLE_DENSITY +
LOWORD(pla->elStyleState.l);
fl |= FL_STYLED;
ls.cStyle = pla->cstyle;
ls.aspRtoL = aspRtoL;
ls.aspLtoR = aspLtoR;
if (pla->fl & LA_STARTGAP)
ls.ulStartMask = 0xffffffffL;
else
ls.ulStartMask = 0L;
pstyle = pla->pstyle;
pspDown = &ls.aspRtoL[ls.cStyle - 1];
pspUp = &ls.aspLtoR[0];
while (pspDown >= &ls.aspRtoL[0])
{
*pspDown = pstyle->l * STYLE_DENSITY;
*pspUp = *pspDown;
pspUp++;
pspDown--;
pstyle++;
}
}
if ((ppdev->ulChipID == W32P) || (ppdev->ulChipID == ET6000))
{
apfn = &gapfnStripP[NUM_STRIP_DRAW_STYLES *
((fl & FL_STYLE_MASK) >> FL_STYLE_SHIFT)];
CP_PEL_DEPTH(ppdev, pjBase, ((cBpp - 1) << 4));
}
else
{
apfn = &gapfnStripI[NUM_STRIP_DRAW_STYLES *
((fl & FL_STYLE_MASK) >> FL_STYLE_SHIFT)];
}
// Set up to enumerate the path:
if (pco->iDComplexity != DC_COMPLEX)
{
PATHDATA pd;
RECTL* prclClip = (RECTL*) NULL;
BOOL bMore;
ULONG cptfx;
POINTFIX ptfxStartFigure;
POINTFIX ptfxLast;
POINTFIX* pptfxFirst;
POINTFIX* pptfxBuf;
if (pco->iDComplexity == DC_RECT)
{
fl |= FL_SIMPLE_CLIP;
arclClip[0] = pco->rclBounds;
// FL_FLIP_D:
arclClip[1].top = pco->rclBounds.left;
arclClip[1].left = pco->rclBounds.top;
arclClip[1].bottom = pco->rclBounds.right;
arclClip[1].right = pco->rclBounds.bottom;
// FL_FLIP_V:
arclClip[2].top = -pco->rclBounds.bottom + 1;
arclClip[2].left = pco->rclBounds.left;
arclClip[2].bottom = -pco->rclBounds.top + 1;
arclClip[2].right = pco->rclBounds.right;
// FL_FLIP_V | FL_FLIP_D:
arclClip[3].top = pco->rclBounds.left;
arclClip[3].left = -pco->rclBounds.bottom + 1;
arclClip[3].bottom = pco->rclBounds.right;
arclClip[3].right = -pco->rclBounds.top + 1;
prclClip = arclClip;
}
pd.flags = 0;
do {
bMore = PATHOBJ_bEnum(ppo, &pd);
cptfx = pd.count;
if (cptfx == 0)
{
break;
}
if (pd.flags & PD_BEGINSUBPATH)
{
ptfxStartFigure = *pd.pptfx;
pptfxFirst = pd.pptfx;
pptfxBuf = pd.pptfx + 1;
cptfx--;
}
else
{
pptfxFirst = &ptfxLast;
pptfxBuf = pd.pptfx;
}
if (pd.flags & PD_RESETSTYLE)
ls.spNext = 0;
if (cptfx > 0)
{
if (!bLines(ppdev,
pptfxFirst,
pptfxBuf,
(RUN*) NULL,
cptfx,
&ls,
prclClip,
apfn,
fl))
goto ReturnFalse;
}
ptfxLast = pd.pptfx[pd.count - 1];
if (pd.flags & PD_CLOSEFIGURE)
{
if (!bLines(ppdev,
&ptfxLast,
&ptfxStartFigure,
(RUN*) NULL,
1,
&ls,
prclClip,
apfn,
fl))
goto ReturnFalse;
}
} while (bMore);
if (fl & FL_STYLED)
{
// Save the style state:
ULONG ulHigh;
ULONG ulLow;
// Masked styles don't normalize the style state. It's a good
// thing to do, so let's do it now:
if ((ULONG) ls.spNext >= (ULONG) ls.spTotal2)
ls.spNext = (ULONG) ls.spNext % (ULONG) ls.spTotal2;
ulHigh = ls.spNext / ls.xyDensity;
ulLow = ls.spNext % ls.xyDensity;
pla->elStyleState.l = MAKELONG(ulLow, ulHigh);
}
}
else
{
// Local state for path enumeration:
BOOL bMore;
union {
BYTE aj[offsetof(CLIPLINE, arun) + RUN_MAX * sizeof(RUN)];
CLIPLINE cl;
} cl;
fl |= FL_COMPLEX_CLIP;
// We use the clip object when non-simple clipping is involved:
PATHOBJ_vEnumStartClipLines(ppo, pco, pso, pla);
do {
bMore = PATHOBJ_bEnumClipLines(ppo, sizeof(cl), &cl.cl);
if (cl.cl.c != 0)
{
if (fl & FL_STYLED)
{
ls.spComplex = HIWORD(cl.cl.lStyleState) * ls.xyDensity
+ LOWORD(cl.cl.lStyleState);
}
if (!bLines(ppdev,
&cl.cl.ptfxA,
&cl.cl.ptfxB,
&cl.cl.arun[0],
cl.cl.c,
&ls,
(RECTL*) NULL,
apfn,
fl))
goto ReturnFalse;
}
} while (bMore);
}
CP_PEL_DEPTH(ppdev, pjBase, 0);
return(TRUE);
ReturnFalse:
CP_PEL_DEPTH(ppdev, pjBase, 0);
return(FALSE);
}