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

456 lines
12 KiB
C

/******************************Module*Header*******************************\
*
* *******************
* * GDI SAMPLE CODE *
* *******************
*
* Module Name: Lineto.c
*
* DrvLineTo for S3 driver
*
* Copyright (c) 1995-1998 Microsoft Corporation
\**************************************************************************/
#include "precomp.h"
// For the S3, we use the following flags to denote the quadrant, and
// we use this as an index into 'gaiLineBias' to determine the Bresenham
// error bias:
#define QUAD_PLUS_X 1
#define QUAD_MAJOR_Y 2
#define QUAD_PLUS_Y 4
LONG gaiLineBias[] = { 0, 0, 0, 1, 1, 1, 0, 1 };
// We shift these flags by 'QUADRANT_SHIFT' to send the actual
// command to the S3:
#define QUADRANT_SHIFT 5
/******************************Public*Routine******************************\
* VOID vNwLineToTrivial
*
* Draws a single solid integer-only unclipped cosmetic line using
* 'New MM I/O'.
*
* We can't use the point-to-point capabilities of the S3 because its
* tie-breaker convention doesn't match that of NT's in two octants,
* and would cause us to fail HCTs.
*
\**************************************************************************/
VOID vNwLineToTrivial(
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)
{
BYTE* pjMmBase;
FLONG flQuadrant;
pjMmBase = ppdev->pjMmBase;
NW_FIFO_WAIT(ppdev, pjMmBase, 8);
if (iSolidColor != (ULONG) -1)
{
NW_FRGD_COLOR(ppdev, pjMmBase, iSolidColor);
NW_ALT_MIX(ppdev, pjMmBase, FOREGROUND_COLOR |
gajHwMixFromMix[mix & 0xf], 0);
MM_PIX_CNTL(ppdev, pjMmBase, ALL_ONES);
}
NW_ABS_CURXY(ppdev, pjMmBase, x, y);
flQuadrant = (QUAD_PLUS_X | QUAD_PLUS_Y);
dx -= x;
if (dx < 0)
{
dx = -dx;
flQuadrant &= ~QUAD_PLUS_X;
}
dy -= y;
if (dy < 0)
{
dy = -dy;
flQuadrant &= ~QUAD_PLUS_Y;
}
if (dy > dx)
{
register LONG l;
l = dy;
dy = dx;
dx = l; // Swap 'dx' and 'dy'
flQuadrant |= QUAD_MAJOR_Y;
}
NW_ALT_PCNT(ppdev, pjMmBase, dx, 0);
NW_ALT_STEP(ppdev, pjMmBase, dy - dx, dy);
NW_ALT_ERR(ppdev, pjMmBase, 0,
(dy + dy - dx - gaiLineBias[flQuadrant]) >> 1);
NW_ALT_CMD(ppdev, pjMmBase, (flQuadrant << QUADRANT_SHIFT) |
(DRAW_LINE | DRAW | DIR_TYPE_XY |
MULTIPLE_PIXELS | WRITE | LAST_PIXEL_OFF));
}
/******************************Public*Routine******************************\
* VOID vNwLineToClipped
*
* Draws a single solid integer-only clipped cosmetic line using
* 'New MM I/O'.
*
\**************************************************************************/
VOID vNwLineToClipped(
PDEV* ppdev,
LONG x1,
LONG y1,
LONG x2,
LONG y2,
ULONG iSolidColor,
MIX mix,
RECTL* prclClip)
{
BYTE* pjMmBase;
LONG xOffset;
LONG yOffset;
pjMmBase = ppdev->pjMmBase;
xOffset = ppdev->xOffset;
yOffset = ppdev->yOffset;
NW_FIFO_WAIT(ppdev, pjMmBase, 2);
NW_ABS_SCISSORS_LT(ppdev, pjMmBase,
prclClip->left + xOffset,
prclClip->top + yOffset);
NW_ABS_SCISSORS_RB(ppdev, pjMmBase,
prclClip->right + xOffset - 1,
prclClip->bottom + yOffset - 1);
vNwLineToTrivial(ppdev, x1, y1, x2, y2, iSolidColor, mix);
NW_FIFO_WAIT(ppdev, pjMmBase, 2);
NW_ABS_SCISSORS_LT(ppdev, pjMmBase, 0, 0);
NW_ABS_SCISSORS_RB(ppdev, pjMmBase,
ppdev->cxMemory - 1,
ppdev->cyMemory - 1);
}
/******************************Public*Routine******************************\
* VOID vMmLineToTrivial
*
* Draws a single solid integer-only unclipped cosmetic line using
* 'Old MM I/O'.
*
\**************************************************************************/
VOID vMmLineToTrivial(
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)
{
BYTE* pjMmBase;
FLONG flQuadrant;
pjMmBase = ppdev->pjMmBase;
if (iSolidColor != (ULONG) -1)
{
IO_FIFO_WAIT(ppdev, 3);
MM_FRGD_COLOR(ppdev, pjMmBase, iSolidColor);
MM_FRGD_MIX(ppdev, pjMmBase, FOREGROUND_COLOR | gajHwMixFromMix[mix & 0xf]);
MM_PIX_CNTL(ppdev, pjMmBase, ALL_ONES);
}
IO_FIFO_WAIT(ppdev, 7);
MM_ABS_CUR_X(ppdev, pjMmBase, x);
MM_ABS_CUR_Y(ppdev, pjMmBase, y);
flQuadrant = (QUAD_PLUS_X | QUAD_PLUS_Y);
dx -= x;
if (dx < 0)
{
dx = -dx;
flQuadrant &= ~QUAD_PLUS_X;
}
dy -= y;
if (dy < 0)
{
dy = -dy;
flQuadrant &= ~QUAD_PLUS_Y;
}
if (dy > dx)
{
register LONG l;
l = dy;
dy = dx;
dx = l; // Swap 'dx' and 'dy'
flQuadrant |= QUAD_MAJOR_Y;
}
MM_MAJ_AXIS_PCNT(ppdev, pjMmBase, dx);
MM_AXSTP(ppdev, pjMmBase, dy);
MM_DIASTP(ppdev, pjMmBase, dy - dx);
MM_ERR_TERM(ppdev, pjMmBase,
(dy + dy - dx - gaiLineBias[flQuadrant]) >> 1);
MM_CMD(ppdev, pjMmBase, (flQuadrant << QUADRANT_SHIFT) |
(DRAW_LINE | DRAW | DIR_TYPE_XY |
MULTIPLE_PIXELS | WRITE | LAST_PIXEL_OFF));
}
/******************************Public*Routine******************************\
* VOID vMmLineToClipped
*
* Draws a single solid integer-only clipped cosmetic line using
* 'Old MM I/O'.
*
\**************************************************************************/
VOID vMmLineToClipped(
PDEV* ppdev,
LONG x1,
LONG y1,
LONG x2,
LONG y2,
ULONG iSolidColor,
MIX mix,
RECTL* prclClip)
{
BYTE* pjMmBase;
LONG xOffset;
LONG yOffset;
pjMmBase = ppdev->pjMmBase;
xOffset = ppdev->xOffset;
yOffset = ppdev->yOffset;
IO_FIFO_WAIT(ppdev, 4);
MM_ABS_SCISSORS_L(ppdev, pjMmBase, prclClip->left + xOffset);
MM_ABS_SCISSORS_R(ppdev, pjMmBase, prclClip->right + xOffset - 1);
MM_ABS_SCISSORS_T(ppdev, pjMmBase, prclClip->top + yOffset);
MM_ABS_SCISSORS_B(ppdev, pjMmBase, prclClip->bottom + yOffset - 1);
vMmLineToTrivial(ppdev, x1, y1, x2, y2, iSolidColor, mix);
IO_FIFO_WAIT(ppdev, 4);
MM_ABS_SCISSORS_L(ppdev, pjMmBase, 0);
MM_ABS_SCISSORS_T(ppdev, pjMmBase, 0);
MM_ABS_SCISSORS_R(ppdev, pjMmBase, ppdev->cxMemory - 1);
MM_ABS_SCISSORS_B(ppdev, pjMmBase, ppdev->cyMemory - 1);
}
/******************************Public*Routine******************************\
* VOID vIoLineToTrivial
*
* Draws a single solid integer-only unclipped cosmetic line using
* 'Old I/O'.
*
\**************************************************************************/
VOID vIoLineToTrivial(
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)
{
BYTE* pjMmBase;
FLONG flQuadrant;
pjMmBase = ppdev->pjMmBase;
if (iSolidColor != (ULONG) -1)
{
IO_FIFO_WAIT(ppdev, 4);
if (DEPTH32(ppdev))
{
IO_FRGD_COLOR32(ppdev, iSolidColor);
}
else
{
IO_FRGD_COLOR(ppdev, iSolidColor);
}
IO_FRGD_MIX(ppdev, FOREGROUND_COLOR | gajHwMixFromMix[mix & 0xf]);
IO_PIX_CNTL(ppdev, ALL_ONES);
}
IO_FIFO_WAIT(ppdev, 7);
IO_ABS_CUR_X(ppdev, x);
IO_ABS_CUR_Y(ppdev, y);
flQuadrant = (QUAD_PLUS_X | QUAD_PLUS_Y);
dx -= x;
if (dx < 0)
{
dx = -dx;
flQuadrant &= ~QUAD_PLUS_X;
}
dy -= y;
if (dy < 0)
{
dy = -dy;
flQuadrant &= ~QUAD_PLUS_Y;
}
if (dy > dx)
{
register LONG l;
l = dy;
dy = dx;
dx = l; // Swap 'dx' and 'dy'
flQuadrant |= QUAD_MAJOR_Y;
}
IO_MAJ_AXIS_PCNT(ppdev, dx);
IO_AXSTP(ppdev, dy);
IO_DIASTP(ppdev, dy - dx);
IO_ERR_TERM(ppdev, (dy + dy - dx - gaiLineBias[flQuadrant]) >> 1);
IO_CMD(ppdev, (flQuadrant << QUADRANT_SHIFT) |
(DRAW_LINE | DRAW | DIR_TYPE_XY |
MULTIPLE_PIXELS | WRITE | LAST_PIXEL_OFF));
}
/******************************Public*Routine******************************\
* VOID vIoLineToClipped
*
* Draws a single solid integer-only clipped cosmetic line using
* 'Old I/O'.
*
\**************************************************************************/
VOID vIoLineToClipped(
PDEV* ppdev,
LONG x1,
LONG y1,
LONG x2,
LONG y2,
ULONG iSolidColor,
MIX mix,
RECTL* prclClip)
{
BYTE* pjMmBase;
LONG xOffset;
LONG yOffset;
pjMmBase = ppdev->pjMmBase;
xOffset = ppdev->xOffset;
yOffset = ppdev->yOffset;
IO_FIFO_WAIT(ppdev, 4);
IO_ABS_SCISSORS_L(ppdev, prclClip->left + xOffset);
IO_ABS_SCISSORS_R(ppdev, prclClip->right + xOffset - 1);
IO_ABS_SCISSORS_T(ppdev, prclClip->top + yOffset);
IO_ABS_SCISSORS_B(ppdev, prclClip->bottom + yOffset - 1);
vIoLineToTrivial(ppdev, x1, y1, x2, y2, iSolidColor, mix);
IO_FIFO_WAIT(ppdev, 4);
IO_ABS_SCISSORS_L(ppdev, 0);
IO_ABS_SCISSORS_T(ppdev, 0);
IO_ABS_SCISSORS_R(ppdev, ppdev->cxMemory - 1);
IO_ABS_SCISSORS_B(ppdev, ppdev->cyMemory - 1);
}
/******************************Public*Routine******************************\
* BOOL DrvLineTo(pso, pco, pbo, x1, y1, x2, y2, prclBounds, mix)
*
* Draws a single solid integer-only cosmetic line.
*
\**************************************************************************/
BOOL DrvLineTo(
SURFOBJ* pso,
CLIPOBJ* pco,
BRUSHOBJ* pbo,
LONG x1,
LONG y1,
LONG x2,
LONG y2,
RECTL* prclBounds,
MIX mix)
{
PDEV* ppdev;
DSURF* pdsurf;
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;
ASSERTDD(!(pdsurf->dt & DT_DIB), "Didn't expect DT_DIB");
// 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:
ppdev = (PDEV*) pso->dhpdev;
xOffset = pdsurf->x;
yOffset = pdsurf->y;
x1 += xOffset;
x2 += xOffset;
y1 += yOffset;
y2 += yOffset;
bRet = TRUE;
if (pco == NULL)
{
ppdev->pfnLineToTrivial(ppdev, x1, y1, x2, y2, pbo->iSolidColor, mix);
}
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))
{
// s3 diamond 968 doesn't like negative x coordinates.
if ((ppdev->iBitmapFormat == BMF_24BPP) && (prclBounds->left < 0))
return FALSE;
ppdev->xOffset = xOffset;
ppdev->yOffset = yOffset;
ppdev->pfnLineToClipped(ppdev, x1, y1, x2, y2, pbo->iSolidColor, mix,
&pco->rclBounds);
}
else
{
bRet = FALSE;
}
return(bRet);
}