/******************************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); }