|
|
/******************************Module*Header*******************************\
* Module Name: Lineto.c * * Implements DrvLineTo. * * Copyright (c) 1995 Microsoft Corporation \**************************************************************************/
#include "precomp.h"
LONG gai32LineBias[] = { 0, 0, 0, 1, 1, 1, 0, 1 }; LONG gai64LineBias[] = { 0, 0, 1, 1, 0, 1, 0, 1 };
/******************************Public*Routine******************************\
* VOID vM64LineToTrivial * * Draws a single solid integer-only unclipped cosmetic line for the mach64. * \**************************************************************************/
VOID vM64LineToTrivial( PDEV* ppdev, LONG x, // Passed in x1
LONG y, // Passed in y1
LONG dx, // Passed in x2
LONG dy, // Passed in y2
ULONG iSolidColor, // -1 means hardware is already set up
MIX mix, RECTL* prclClip) // not used
{ BYTE* pjMmBase; FLONG flQuadrant;
pjMmBase = ppdev->pjMmBase;
if (iSolidColor == (ULONG) -1) { M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 7); } else { M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 10);
M64_OD(pjMmBase, DP_MIX, gaul64HwMixFromMix[mix & 0xf]); M64_OD(pjMmBase, DP_FRGD_CLR, iSolidColor); M64_OD(pjMmBase, DP_SRC, DP_SRC_Always1 | DP_SRC_FrgdClr << 8); }
M64_OD(pjMmBase, DST_Y_X, PACKXY(x, y));
flQuadrant = (DST_CNTL_XDir | DST_CNTL_YDir);
dx -= x; if (dx < 0) { dx = -dx; flQuadrant &= ~DST_CNTL_XDir; }
dy -= y; if (dy < 0) { dy = -dy; flQuadrant &= ~DST_CNTL_YDir; }
if (dy > dx) { register LONG l;
l = dy; dy = dx; dx = l; // Swap 'dx' and 'dy'
flQuadrant |= DST_CNTL_YMajor; }
M64_OD(pjMmBase, DST_CNTL, flQuadrant | DST_CNTL_LastPel); M64_OD(pjMmBase, DST_BRES_ERR, (dy + dy - dx - gai64LineBias[flQuadrant]) >> 1); M64_OD(pjMmBase, DST_BRES_INC, dy); M64_OD(pjMmBase, DST_BRES_DEC, dy - dx); M64_OD(pjMmBase, DST_BRES_LNTH, dx);
// Since we don't use a default context, we must restore registers:
M64_OD(pjMmBase, DST_CNTL, DST_CNTL_XDir | DST_CNTL_YDir); }
VOID vM64LineToTrivial24( PDEV* ppdev, LONG x, // Passed in x1
LONG y, // Passed in y1
LONG dx, // Passed in x2
LONG dy, // Passed in y2
ULONG iSolidColor, // -1 means hardware is already set up
MIX mix, RECTL* prclClip) // required for Bresenham algorithm
{ BYTE* pjMmBase = ppdev->pjMmBase; FLONG flQuadrant; LONG x2 = dx, y2 = dy;
if (iSolidColor != (ULONG) -1) { M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 3);
M64_OD(pjMmBase, DP_MIX, gaul64HwMixFromMix[mix & 0xf]); M64_OD(pjMmBase, DP_FRGD_CLR, iSolidColor); M64_OD(pjMmBase, DP_SRC, DP_SRC_Always1 | DP_SRC_FrgdClr << 8); }
flQuadrant = (DST_CNTL_XDir | DST_CNTL_YDir);
dx -= x; if (dx < 0) { dx = -dx; flQuadrant &= ~DST_CNTL_XDir; }
dy -= y; if (dy < 0) { dy = -dy; flQuadrant &= ~DST_CNTL_YDir; }
if (dy > dx) { register LONG l;
l = dy; dy = dx; dx = l; // Swap 'dx' and 'dy'
flQuadrant |= DST_CNTL_YMajor; }
if (y == y2) // Horizontal line
{ x *= 3; dx *= 3;
if (! (flQuadrant & DST_CNTL_XDir)) x += 2; // From right to left, start with the Blue byte.
M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 5);
M64_OD(pjMmBase, DP_SRC, DP_SRC_FrgdClr << 8 ); M64_OD(pjMmBase, DST_CNTL, flQuadrant | DST_CNTL_24_RotEna | ((x/4 % 6) << 8) );
M64_OD(pjMmBase, DST_Y_X, PACKXY(x, y) ); M64_OD(pjMmBase, DST_HEIGHT_WIDTH, PACKPAIR(1, dx) );
// Since we don't use a default context, we must restore registers:
M64_OD(pjMmBase, DST_CNTL, DST_CNTL_XDir | DST_CNTL_YDir); } else if (x == x2) // Vertical line
{ x *= 3;
M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 5);
M64_OD(pjMmBase, DP_SRC, DP_SRC_FrgdClr << 8 ); M64_OD(pjMmBase, DST_CNTL, flQuadrant | DST_CNTL_24_RotEna | ((x/4 % 6) << 8) );
M64_OD(pjMmBase, DST_Y_X, PACKXY(x, y) ); M64_OD(pjMmBase, DST_HEIGHT_WIDTH, PACKPAIR(dx, 3) );
// Since we don't use a default context, we must restore registers:
M64_OD(pjMmBase, DST_CNTL, DST_CNTL_XDir | DST_CNTL_YDir); } else { BYTE *pjDest, *pjScreen = ppdev->pjScreen; BYTE red, green, blue; LONG bres_err, bres_inc, bres_dec, bres_len; LONG lDelta = ppdev->lDelta; MIX hw_mix;
hw_mix = gaul64HwMixFromMix[mix & 0xf] >> 16;
bres_err = (dy + dy - dx - gai64LineBias[flQuadrant]) >> 1; bres_inc = dy; bres_dec = dy - dx; bres_len = dx;
// Separate into color bytes.
red = (BYTE) ((iSolidColor & ppdev->flRed) >> REDSHIFT); green = (BYTE) ((iSolidColor & ppdev->flGreen) >> GREENSHIFT); blue = (BYTE) ((iSolidColor & ppdev->flBlue) >> BLUESHIFT);
vM64QuietDown(ppdev, pjMmBase);
// Execute 24bpp Bresenham algorithm.
while (bres_len-- > 0) { // Write pel. Check for clipping. Last pel enabled.
if (prclClip == NULL || x >= prclClip->left && x < prclClip->right && y >= prclClip->top && y < prclClip->bottom ) { pjDest = pjScreen + y*lDelta + x*3; switch (hw_mix) { case 0: // NOT dst
*pjDest = ~*pjDest++; *pjDest = ~*pjDest++; *pjDest = ~*pjDest; break; case 1: // "0"
*pjDest++ = 0; *pjDest++ = 0; *pjDest = 0; break; case 2: // "1"
*pjDest++ = 0xFF; *pjDest++ = 0xFF; *pjDest = 0xFF; break; case 3: // dst
break; case 4: // NOT src
*pjDest++ = ~blue; *pjDest++ = ~green; *pjDest = ~red; break; case 5: // dst XOR src
*pjDest++ ^= blue; *pjDest++ ^= green; *pjDest ^= red; break; case 6: // NOT dst XOR src
*pjDest = ~*pjDest++ ^ blue; *pjDest = ~*pjDest++ ^ green; *pjDest = ~*pjDest ^ red; break; case 7: // src
*pjDest++ = blue; *pjDest++ = green; *pjDest = red; break; case 8: // NOT dst OR NOT src
*pjDest = ~*pjDest++ | ~blue; *pjDest = ~*pjDest++ | ~green; *pjDest = ~*pjDest | ~red; break; case 9: // dst OR NOT src
*pjDest++ |= ~blue; *pjDest++ |= ~green; *pjDest |= ~red; break; case 0xA: // NOT dst OR src
*pjDest = ~*pjDest++ | blue; *pjDest = ~*pjDest++ | green; *pjDest = ~*pjDest | red; break; case 0xB: // dst OR src
*pjDest++ |= blue; *pjDest++ |= green; *pjDest |= red; break; case 0xC: // dst AND src
*pjDest++ &= blue; *pjDest++ &= green; *pjDest &= red; break; case 0xD: // NOT dst AND src
*pjDest = ~*pjDest++ & blue; *pjDest = ~*pjDest++ & green; *pjDest = ~*pjDest & red; break; case 0xE: // dst AND NOT src
*pjDest++ &= ~blue; *pjDest++ &= ~green; *pjDest &= ~red; break; case 0xF: // NOT dst AND NOT src
*pjDest = ~*pjDest++ & ~blue; *pjDest = ~*pjDest++ & ~green; *pjDest = ~*pjDest & ~red; break; case 0x17: *pjDest = ((*pjDest++) + blue)/2; *pjDest = ((*pjDest++) + green)/2; *pjDest = (*pjDest + red)/2; break; } }
if (flQuadrant & DST_CNTL_YMajor) { if (flQuadrant & DST_CNTL_YDir) y++; else y--;
if (bres_err >= 0) { bres_err += bres_dec; if (flQuadrant & DST_CNTL_XDir) x++; else x--; } else bres_err += bres_inc; } else { if (flQuadrant & DST_CNTL_XDir) x++; else x--;
if (bres_err >= 0) { bres_err += bres_dec; if (flQuadrant & DST_CNTL_YDir) y++; else y--; } else bres_err += bres_inc; } } } }
/******************************Public*Routine******************************\
* VOID vM32LineToTrivial * * Draws a single solid integer-only unclipped cosmetic line for the mach32 * using memory-mapped I/O. * * See vSetStrips and bIntgerLine_M8 from the old driver. * \**************************************************************************/
VOID vM32LineToTrivial( PDEV* ppdev, LONG x, // Passed in x1
LONG y, // Passed in y1
LONG dx, // Passed in x2
LONG dy, // Passed in y2
ULONG iSolidColor, // -1 means hardware is already set up
MIX mix, RECTL* prclClip) // not used
{ BYTE* pjMmBase; FLONG flQuadrant;
pjMmBase = ppdev->pjMmBase;
if (iSolidColor == (ULONG) -1) { M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 7); } else { M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 11);
M32_OW(pjMmBase, DP_CONFIG, FG_COLOR_SRC_FG | DRAW | WRITE); M32_OW(pjMmBase, FRGD_MIX, FOREGROUND_COLOR | gaul32HwMixFromMix[mix & 0xf]); M32_OW(pjMmBase, FRGD_COLOR, iSolidColor); M32_OW(pjMmBase, MULTIFUNC_CNTL, DATA_EXTENSION | ALL_ONES); }
M32_OW(pjMmBase, CUR_X, x); M32_OW(pjMmBase, CUR_Y, y);
flQuadrant = (XPOSITIVE | YPOSITIVE);
dx -= x; if (dx < 0) { dx = -dx; flQuadrant &= ~XPOSITIVE; }
dy -= y; if (dy < 0) { dy = -dy; flQuadrant &= ~YPOSITIVE; }
if (dy > dx) { register LONG l;
l = dy; dy = dx; dx = l; // Swap 'dx' and 'dy'
flQuadrant |= YMAJOR; }
M32_OW(pjMmBase, LINEDRAW_OPT, flQuadrant | LAST_PEL_OFF); M32_OW(pjMmBase, ERR_TERM, (dy + dy - dx - gai32LineBias[flQuadrant >> 5]) >> 1); M32_OW(pjMmBase, AXSTP, dy); M32_OW(pjMmBase, DIASTP, dy - dx); M32_OW(pjMmBase, BRES_COUNT, dx); }
/******************************Public*Routine******************************\
* VOID vI32LineToTrivial * * Draws a single solid integer-only unclipped cosmetic line for the mach32 * using I/O-mapped registers. * * See vSetStrips and bIntgerLine_M8 from the old driver. * \**************************************************************************/
VOID vI32LineToTrivial( PDEV* ppdev, LONG x, // Passed in x1
LONG y, // Passed in y1
LONG dx, // Passed in x2
LONG dy, // Passed in y2
ULONG iSolidColor, // -1 means hardware is already set up
MIX mix, RECTL* prclClip) // not used
{ BYTE* pjIoBase; FLONG flQuadrant;
pjIoBase = ppdev->pjIoBase;
if (iSolidColor == (ULONG) -1) { I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 7); } else { I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 11);
I32_OW(pjIoBase, DP_CONFIG, FG_COLOR_SRC_FG | DRAW | WRITE); I32_OW(pjIoBase, FRGD_MIX, FOREGROUND_COLOR | gaul32HwMixFromMix[mix & 0xf]); I32_OW(pjIoBase, FRGD_COLOR, iSolidColor); I32_OW(pjIoBase, MULTIFUNC_CNTL, DATA_EXTENSION | ALL_ONES); }
I32_OW(pjIoBase, CUR_X, x); I32_OW(pjIoBase, CUR_Y, y);
flQuadrant = (XPOSITIVE | YPOSITIVE);
dx -= x; if (dx < 0) { dx = -dx; flQuadrant &= ~XPOSITIVE; }
dy -= y; if (dy < 0) { dy = -dy; flQuadrant &= ~YPOSITIVE; }
if (dy > dx) { register LONG l;
l = dy; dy = dx; dx = l; // Swap 'dx' and 'dy'
flQuadrant |= YMAJOR; }
I32_OW(pjIoBase, LINEDRAW_OPT, flQuadrant | LAST_PEL_OFF); I32_OW(pjIoBase, ERR_TERM, (dy + dy - dx - gai32LineBias[flQuadrant >> 5]) >> 1); I32_OW(pjIoBase, AXSTP, dy); I32_OW(pjIoBase, DIASTP, dy - dx); I32_OW(pjIoBase, BRES_COUNT, dx); }
/******************************Public*Routine******************************\
* BOOL DrvLineTo(pso, pco, pbo, x1, y1, x2, y2, prclBounds, mix) * * Draws a single solid integer-only cosmetic line. * \**************************************************************************/
#if TARGET_BUILD > 351
BOOL DrvLineTo( SURFOBJ* pso, CLIPOBJ* pco, BRUSHOBJ* pbo, LONG x1, LONG y1, LONG x2, LONG y2, RECTL* prclBounds, MIX mix) { PDEV* ppdev; DSURF* pdsurf; OH* poh; LONG xOffset; LONG yOffset; BOOL bRet;
// 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(EngLineTo(pdsurf->pso, pco, pbo, x1, y1, x2, y2, prclBounds, 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; ppdev = (PDEV*) pso->dhpdev;
xOffset = poh->x; yOffset = poh->y;
x1 += xOffset; x2 += xOffset; y1 += yOffset; y2 += yOffset;
bRet = TRUE;
if (pco == NULL) { ppdev->pfnLineToTrivial(ppdev, x1, y1, x2, y2, pbo->iSolidColor, mix, NULL); } else if ((pco->iDComplexity <= DC_RECT) && (prclBounds->left >= MIN_INTEGER_BOUND) && (prclBounds->top >= MIN_INTEGER_BOUND) && (prclBounds->right <= MAX_INTEGER_BOUND) && (prclBounds->bottom <= MAX_INTEGER_BOUND)) { ppdev->xOffset = xOffset; ppdev->yOffset = yOffset;
vSetClipping(ppdev, &pco->rclBounds); // may need rclBounds for clipping in 24bpp:
ppdev->pfnLineToTrivial(ppdev, x1, y1, x2, y2, pbo->iSolidColor, mix, &pco->rclBounds); vResetClipping(ppdev); } else { bRet = FALSE; }
return(bRet); } #endif
|