|
|
/******************************Module*Header*******************************\
* Module Name: Lineto.c * * DrvLineTo for the driver. * * Copyright (c) 1995-1996 Microsoft Corporation \**************************************************************************/
#include "precomp.h"
// The MGA's hardware coordinates are limited to 16-bit signed values:
#define MIN_INTEGER_BOUND (-32767)
#define MAX_INTEGER_BOUND (32767)
/**************************************************************************
* Line Rasterization * * The 3D DDI's line rasterization rules are not as strict as are GDI's. * In particular, the 3D DDI doesn't care how we handle 'tie-breakers,' * where the true line falls exactly mid-way between two pixels, as long * as we're consistent, particularly between unclipped and clipped lines. * * For this implementation, I've chosen to match GDI's convention so that * I can share clipping code with the GDI line drawing routines. * * For integer lines, GDI's rule is that when a line falls exactly mid-way * between two pixels, the upper or left pixel should be left. For * standard Bresenham, this means that we should bias the error term down * by an infinitesimal amount in the following octants: * * \ 0 | 1 / * \ | / * 0 \ | / 0 * ------------- 1 - Indicates the quadrants in which * 1 / | \ 1 the error term should be biased * / | \ * / 0 | 1 \ * * The MGA's convention for numbering the qudrants is as follows, where * 'sdydxl_MAJOR_X' = 1, 'sdxl_SUB' = 2, 'sdy_SUB' = 4: * * \ 2 | 0 / * \ | / * 3 \ | / 1 * ------------- * 7 / | \ 5 * / | \ * / 6 | 4 \ * **************************************************************************/
LONG gaiLineBias[] = { 1, 1, 0, 1, 1, 0, 0, 0 };
/******************************Public*Routine******************************\
* VOID vLineToTrivial * * Draws a single solid integer-only unclipped cosmetic line. * * We can't use the point-to-point capabilities of the MGA because its * tie-breaker convention doesn't match that of NT's in two octants, * and would cause us to fail HCTs. * \**************************************************************************/
VOID vLineToTrivial( PDEV* ppdev, LONG x, // Passed in x1
LONG y, // Passed in y1
LONG dx, // Passed in x2
LONG dy, // Passed in y2
ULONG iSolidColor, MIX mix) { BYTE* pjBase; FLONG flQuadrant; ULONG ulHwMix;
pjBase = ppdev->pjBase;
CHECK_FIFO_SPACE(pjBase, 13);
if (mix == 0x0d0d) // R2_COPYPEN
{ CP_WRITE(pjBase, DWG_DWGCTL, blockm_OFF + pattern_OFF + bltmod_BFCOL + transc_BG_TRANSP + atype_RPL + bop_SRCCOPY); } else { ulHwMix = (mix & 0xff) - 1;
CP_WRITE(pjBase, DWG_DWGCTL, blockm_OFF + pattern_OFF + bltmod_BFCOL + transc_BG_TRANSP + atype_RSTR + (ulHwMix << 16)); }
CP_WRITE(pjBase, DWG_FCOL, COLOR_REPLICATE(ppdev, iSolidColor));
if (!(GET_CACHE_FLAGS(ppdev, PATTERN_CACHE))) { CP_WRITE(pjBase, DWG_SRC0, 0xFFFFFFFF); CP_WRITE(pjBase, DWG_SRC1, 0xFFFFFFFF); CP_WRITE(pjBase, DWG_SRC2, 0xFFFFFFFF); CP_WRITE(pjBase, DWG_SRC3, 0xFFFFFFFF); }
ppdev->HopeFlags = PATTERN_CACHE;
CP_START(pjBase, DWG_XDST, x); CP_START(pjBase, DWG_YDST, y);
flQuadrant = sdydxl_MAJOR_X;
dx -= x; if (dx < 0) { dx = -dx; flQuadrant |= sdxl_SUB; }
dy -= y; if (dy < 0) { dy = -dy; flQuadrant |= sdy_SUB; }
if (dy > dx) { register LONG l;
l = dy; dy = dx; dx = l; // Swap 'dx' and 'dy'
flQuadrant &= ~sdydxl_MAJOR_X; }
CP_WRITE(pjBase, DWG_SGN, flQuadrant); CP_WRITE(pjBase, DWG_LEN, dx); CP_WRITE(pjBase, DWG_AR0, dy); CP_WRITE(pjBase, DWG_AR2, dy - dx); CP_START(pjBase, DWG_AR1, (dy + dy - dx - gaiLineBias[flQuadrant]) >> 1); }
/******************************Public*Routine******************************\
* VOID vLineToClipped * * Draws a single solid integer-only clipped cosmetic line using * 'New MM I/O'. * \**************************************************************************/
VOID vLineToClipped( PDEV* ppdev, LONG x1, LONG y1, LONG x2, LONG y2, ULONG iSolidColor, MIX mix, RECTL* prclClip) { vSetClipping(ppdev, prclClip); vLineToTrivial(ppdev, x1, y1, x2, y2, iSolidColor, mix); vResetClipping(ppdev); }
/******************************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; 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) { vLineToTrivial(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)) { ppdev->xOffset = xOffset; ppdev->yOffset = yOffset;
vLineToClipped(ppdev, x1, y1, x2, y2, pbo->iSolidColor, mix, &pco->rclBounds); } else { bRet = FALSE; }
return(bRet); }
|