/******************************Module*Header*******************************\ * Module Name: rxtri.c * * Contains the low-level (rasterization) triangle-rendering routines for the * Millenium MCD driver. * * Copyright (c) 1995 Microsoft Corporation \**************************************************************************/ #include "precomp.h" #include "mcdhw.h" #include "mcdutil.h" #include "mcdmath.h" //#undef CHECK_FIFO_FREE //#define CHECK_FIFO_FREE static MCDFLOAT fixScale = __MCDFIXSCALE; VOID FASTCALL __MCDCalcDeltaRGBZ(DEVRC *pRc, MCDVERTEX *a, MCDVERTEX *b, MCDVERTEX *c) { MCDFLOAT oneOverArea, t1, t2, t3, t4; LARGE_INTEGER temp; /* ** t1-4 are delta values for unit changes in x or y for each ** parameter. */ #if !(_X86_ && ASM_ACCEL) if (pRc->privateEnables & (__MCDENABLE_SMOOTH | __MCDENABLE_Z)) { __MCD_FLOAT_BEGIN_DIVIDE(__MCDONE, pRc->halfArea, &oneOverArea); } #endif if (pRc->privateEnables & __MCDENABLE_SMOOTH) { MCDFLOAT drAC, dgAC, dbAC, daAC; MCDFLOAT drBC, dgBC, dbBC, daBC; MCDCOLOR *ac, *bc, *cc; #if _X86_ && ASM_ACCEL __asm{ mov edx, pRc fstp oneOverArea // finish divide fld DWORD PTR [OFFSET(DEVRC.dyAC)][edx] fmul oneOverArea fld DWORD PTR [OFFSET(DEVRC.dyBC)][edx] fmul oneOverArea // dyBC dyAC fld DWORD PTR [OFFSET(DEVRC.dxAC)][edx] fmul oneOverArea // dxAC dyBC dyAC fxch ST(1) // dyBC dxAC dyAC fld DWORD PTR [OFFSET(DEVRC.dxBC)][edx] fmul oneOverArea // dxBC dyBC dxAC dyAC fxch ST(3) // dyAC dyBC dxAC dxBC fstp t1 fstp t2 fstp t3 fstp t4 // Now, calculate deltas: mov eax, a mov ecx, c mov ebx, b lea eax, [OFFSET(MCDVERTEX.colors) + eax] lea ecx, [OFFSET(MCDVERTEX.colors) + ecx] lea ebx, [OFFSET(MCDVERTEX.colors) + ebx] fld DWORD PTR [OFFSET(MCDCOLOR.r)][ecx] fsub DWORD PTR [OFFSET(MCDCOLOR.r)][eax] fld DWORD PTR [OFFSET(MCDCOLOR.r)][ecx] fsub DWORD PTR [OFFSET(MCDCOLOR.r)][ebx] // drBC drAC fld ST(1) // drAC drBC drAC fmul t2 // drACt2 drBC drAC fld ST(1) // drBC drACt2 drBC drAC fmul t1 // drBCt1 drACt2 drBC drAC fxch ST(2) // drBC drACt2 drBCt1 drAC fmul t3 // drBCt3 drACt2 drBCt1 drAC fxch ST(3) // drAC drACt2 drBCt1 drBCt3 fmul t4 // drACt4 drACt2 drBCt1 drBCt3 fxch ST(2) // drBCt1 drACt2 drACt4 drBCt3 fsubp ST(1), ST // drACBC drACt4 drBCt3 fld DWORD PTR [OFFSET(MCDCOLOR.g)][ecx] fsub DWORD PTR [OFFSET(MCDCOLOR.g)][ebx] // dgBC drACBC drACt4 drBCt3 fxch ST(2) // drACt4 drACBC dgBC drBCt3 fsubp ST(3), ST // drACBC dgBC drBCAC fmul DWORD PTR [OFFSET(DEVRC.rScale)][edx] // DRACBC dgBC drBCAC fxch ST(2) // drBCAC dgBC DRACBC fmul DWORD PTR [OFFSET(DEVRC.rScale)][edx] // DRBCAC dgBC DRACBC fld DWORD PTR [OFFSET(MCDCOLOR.g)][ecx] fsub DWORD PTR [OFFSET(MCDCOLOR.g)][eax] // dgAC DRBCAC dgBC DRACBC fxch ST(3) // DRACBC DRBCAC dgBC dgAC fst DWORD PTR [OFFSET(DEVRC.drdx)][edx] fistp DWORD PTR [OFFSET(DEVRC.fxdrdx)][edx] fst DWORD PTR [OFFSET(DEVRC.drdy)][edx] fistp DWORD PTR [OFFSET(DEVRC.fxdrdy)][edx] // dgBC dgAC fld ST(1) // dgAC dgBC dgAC fmul t2 // dgACt2 dgBC dgAC fld ST(1) // dgBC dgACt2 dgBC dgAC fmul t1 // dgBCt1 dgACt2 dgBC dgAC fxch ST(2) // dgBC dgACt2 dgBCt1 dgAC fmul t3 // dgBCt3 dgACt2 dgBCt1 dgAC fxch ST(3) // dgAC dgACt2 dgBCt1 dgBCt3 fmul t4 // dgACt4 dgACt2 dgBCt1 dgBCt3 fxch ST(2) // dgBCt1 dgACt2 dgACt4 dgBCt3 fsubp ST(1), ST // dgACBC dgACt4 dgBCt3 fld DWORD PTR [OFFSET(MCDCOLOR.b)][ecx] fsub DWORD PTR [OFFSET(MCDCOLOR.b)][ebx] // dbBC dgACBC dgACt4 dgBCt3 fxch ST(2) // dgACt4 dgACBC dbBC dgBCt3 fsubp ST(3), ST // dgACBC dbBC dgBCAC fmul DWORD PTR [OFFSET(DEVRC.gScale)][edx] // DGACBC dbBC dgBCAC fxch ST(2) // dgBCAC dbBC DGACBC fmul DWORD PTR [OFFSET(DEVRC.gScale)][edx] // DGBCAC dbBC DGACBC fld DWORD PTR [OFFSET(MCDCOLOR.b)][ecx] fsub DWORD PTR [OFFSET(MCDCOLOR.b)][eax] // dbAC DGBCAC dbBC DGACBC fxch ST(3) // DGACBC DGBCAC dbBC dbAC fst DWORD PTR [OFFSET(DEVRC.dgdx)][edx] fistp DWORD PTR [OFFSET(DEVRC.fxdgdx)][edx] fst DWORD PTR [OFFSET(DEVRC.dgdy)][edx] fistp DWORD PTR [OFFSET(DEVRC.fxdgdy)][edx] // dbBC dbAC fld ST(1) // dbAC dbBC dbAC fmul t2 // dbACt2 dbBC dbAC fld ST(1) // dbBC dbACt2 dbBC dbAC fmul t1 // dbBCt1 dbACt2 dbBC dbAC fxch ST(2) // dbBC dbACt2 dbBCt1 dbAC fmul t3 // dbBCt3 dbACt2 dbBCt1 dbAC fxch ST(3) // dbAC dbACt2 dbBCt1 dbBCt3 fmul t4 // dbACt4 dbACt2 dbBCt1 dbBCt3 fxch ST(2) // dbBCt1 dbACt2 dbACt4 dbBCt3 fsubp ST(1), ST // dbACBC dbACt4 dbBCt3 fxch ST(1) // dbACt4 dbACBC dbBCt3 fsubp ST(2), ST // dbACBC dbBCAC (+1) fmul DWORD PTR [OFFSET(DEVRC.bScale)][edx] // DBACBC dbBCAC fxch ST(1) // dbBCAC DBACBC fmul DWORD PTR [OFFSET(DEVRC.bScale)][edx] // DBBCAC DBACBC fxch ST(1) // DBACBC DBBCAC fst DWORD PTR [OFFSET(DEVRC.dbdx)][edx] //(+1) fistp DWORD PTR [OFFSET(DEVRC.fxdbdx)][edx] fst DWORD PTR [OFFSET(DEVRC.dbdy)][edx] fistp DWORD PTR [OFFSET(DEVRC.fxdbdy)][edx] } #else ac = &a->colors[0]; bc = &b->colors[0]; cc = &c->colors[0]; drAC = cc->r - ac->r; drBC = cc->r - bc->r; dgAC = cc->g - ac->g; dgBC = cc->g - bc->g; dbAC = cc->b - ac->b; dbBC = cc->b - bc->b; __MCD_FLOAT_SIMPLE_END_DIVIDE(oneOverArea); t1 = pRc->dyAC * oneOverArea; t2 = pRc->dyBC * oneOverArea; t3 = pRc->dxAC * oneOverArea; t4 = pRc->dxBC * oneOverArea; pRc->drdx = (drAC * t2 - drBC * t1) * pRc->rScale; pRc->drdy = (drBC * t3 - drAC * t4) * pRc->rScale; pRc->dgdx = (dgAC * t2 - dgBC * t1) * pRc->gScale; pRc->dgdy = (dgBC * t3 - dgAC * t4) * pRc->gScale; pRc->dbdx = (dbAC * t2 - dbBC * t1) * pRc->bScale; pRc->dbdy = (dbBC * t3 - dbAC * t4) * pRc->bScale; pRc->fxdrdx = FTOL(pRc->drdx); pRc->fxdrdy = FTOL(pRc->drdy); pRc->fxdgdx = FTOL(pRc->dgdx); pRc->fxdgdy = FTOL(pRc->dgdy); pRc->fxdbdx = FTOL(pRc->dbdx); pRc->fxdbdy = FTOL(pRc->dbdy); #endif } else { // In this case, we're not smooth shading, but we still need // to set up the color registers: BYTE *pjBase; #if _X86_ && ASM_ACCEL LONG rTemp, gTemp, bTemp; _asm{ mov ebx, pRc mov eax, [OFFSET(DEVRC.pvProvoking)][ebx] // AGI lea eax, [OFFSET(MCDVERTEX.colors) + eax] fld DWORD PTR [OFFSET(DEVRC.rScale)][ebx] fmul DWORD PTR [OFFSET(MCDCOLOR.r)][eax] fld DWORD PTR [OFFSET(DEVRC.gScale)][ebx] fmul DWORD PTR [OFFSET(MCDCOLOR.g)][eax] fld DWORD PTR [OFFSET(DEVRC.bScale)][ebx] // B G R fmul DWORD PTR [OFFSET(MCDCOLOR.b)][eax] fxch ST(2) // R G B fistp rTemp // G B fistp gTemp fistp bTemp } pjBase = pRc->ppdev->pjBase; CHECK_FIFO_FREE(pjBase, pRc->cFifo, 3); CP_WRITE(pjBase, DWG_DR4, rTemp); CP_WRITE(pjBase, DWG_DR8, gTemp); CP_WRITE(pjBase, DWG_DR12, bTemp); #else MCDCOLOR *pColor = &pRc->pvProvoking->colors[0]; pjBase = pRc->ppdev->pjBase; CHECK_FIFO_FREE(pjBase, pRc->cFifo, 3); CP_WRITE(pjBase, DWG_DR4, FTOL(pColor->r * pRc->rScale)); CP_WRITE(pjBase, DWG_DR8, FTOL(pColor->g * pRc->gScale)); CP_WRITE(pjBase, DWG_DR12, FTOL(pColor->b * pRc->bScale)); #endif } if (pRc->privateEnables & __MCDENABLE_Z) { MCDFLOAT dzAC, dzBC; if (!(pRc->privateEnables & __MCDENABLE_SMOOTH)) { #if _X86_ && ASM_ACCEL _asm { mov eax, pRc fstp oneOverArea // finish divide fld DWORD PTR [OFFSET(DEVRC.dyAC)][eax] fmul oneOverArea fld DWORD PTR [OFFSET(DEVRC.dyBC)][eax] fmul oneOverArea // dyBC dyAC fld DWORD PTR [OFFSET(DEVRC.dxAC)][eax] fmul oneOverArea // dxAC dyBC dyAC fxch ST(1) // dyBC dxAC dyAC fld DWORD PTR [OFFSET(DEVRC.dxBC)][eax] fmul oneOverArea // dxBC dyBC dxAC dyAC fxch ST(3) // dyAC dyBC dxAC dxBC fstp t1 fstp t2 fstp t3 fstp t4 } #else __MCD_FLOAT_SIMPLE_END_DIVIDE(oneOverArea); t1 = pRc->dyAC * oneOverArea; t2 = pRc->dyBC * oneOverArea; t3 = pRc->dxAC * oneOverArea; t4 = pRc->dxBC * oneOverArea; #endif } #if _X86_ && ASM_ACCEL _asm { mov ecx, c mov eax, a mov ebx, b mov edx, pRc fld DWORD PTR [OFFSET(MCDVERTEX.windowCoord.z)][ecx] fsub DWORD PTR [OFFSET(MCDVERTEX.windowCoord.z)][eax] fld DWORD PTR [OFFSET(MCDVERTEX.windowCoord.z)][ecx] fsub DWORD PTR [OFFSET(MCDVERTEX.windowCoord.z)][ebx] // dzBC dzAC fld ST(1) // dzAC dzBC dzAC fmul t2 // ACt2 dzBC dzAC fld ST(1) // dzBC ACt2 dzBC dzAC fmul t1 // BCt1 ACt2 dzBC dzAC fxch ST(3) // dzAC ACt2 dzBC BCt1 fmul t4 // ACt4 ACt2 dzBC BCt1 fxch ST(2) // dzBC ACt2 ACt4 BCt1 fmul t3 // BCt3 ACt2 ACt4 BCt1 fsubrp ST(2),ST // ACt2 BCAC BCt1 fsubrp ST(2),ST // BCAC ACBC fxch ST(1) // ACBC BCAC fmul DWORD PTR [OFFSET(DEVRC.zScale)][edx] // dzdx BCAC (1 cycle hit!) fxch ST(1) // BCAC dzdx fmul DWORD PTR [OFFSET(DEVRC.zScale)][edx] // dzdy dzdx fxch ST(1) // dzdx dzdy fst DWORD PTR [OFFSET(DEVRC.dzdx)][edx] // (1 cycle hit!) fistp temp mov ebx, DWORD PTR temp fst DWORD PTR [OFFSET(DEVRC.dzdy)][edx] mov [OFFSET(DEVRC.fxdzdx)][edx], ebx fistp temp mov ebx, DWORD PTR temp mov [OFFSET(DEVRC.fxdzdy)][edx], ebx } #else dzAC = c->windowCoord.z - a->windowCoord.z; dzBC = c->windowCoord.z - b->windowCoord.z; pRc->dzdx = (dzAC * t2 - dzBC * t1) * pRc->zScale; pRc->dzdy = (dzBC * t3 - dzAC * t4) * pRc->zScale; pRc->fxdzdx = FTOL(pRc->dzdx); pRc->fxdzdy = FTOL(pRc->dzdy); #endif } } VOID FASTCALL __HWSetupDeltas(DEVRC *pRc) { BYTE *pjBase = pRc->ppdev->pjBase; if (pRc->privateEnables & __MCDENABLE_SMOOTH) { CHECK_FIFO_FREE(pjBase, pRc->cFifo, 9); CP_WRITE(pjBase, DWG_DWGCTL, pRc->hwTrapFunc); CP_WRITE(pjBase, DWG_DR2, pRc->fxdzdx); CP_WRITE(pjBase, DWG_DR3, pRc->fxdzdy); CP_WRITE(pjBase, DWG_DR6, pRc->fxdrdx); CP_WRITE(pjBase, DWG_DR7, pRc->fxdrdy); CP_WRITE(pjBase, DWG_DR10, pRc->fxdgdx); CP_WRITE(pjBase, DWG_DR11, pRc->fxdgdy); CP_WRITE(pjBase, DWG_DR14, pRc->fxdbdx); CP_WRITE(pjBase, DWG_DR15, pRc->fxdbdy); } else { CHECK_FIFO_FREE(pjBase, pRc->cFifo, 3); CP_WRITE(pjBase, DWG_DWGCTL, pRc->hwTrapFunc); CP_WRITE(pjBase, DWG_DR2, pRc->fxdzdx); CP_WRITE(pjBase, DWG_DR3, pRc->fxdzdy); } } #define SNAPCOORD(value, intValue)\ intValue = __MCD_VERTEX_FIXED_TO_INT(__MCD_VERTEX_FLOAT_TO_FIXED(value)+\ __MCD_VERTEX_FRAC_HALF); void FASTCALL __HWDrawTrap(DEVRC *pRc, MCDFLOAT dxLeft, MCDFLOAT dxRight, LONG y, LONG dy) { BYTE *pjBase = pRc->ppdev->pjBase; ULONG signs = 0; if (*((ULONG *)&dxLeft) & 0x80000000) { signs |= sdxl_SUB; } if (*((ULONG *)&dxRight) & 0x80000000) { signs |= sdxr_DEC; } CHECK_FIFO_FREE(pjBase, pRc->cFifo, 3); CP_WRITE(pjBase, DWG_SGN, (scanleft_RIGHT | sdy_ADD | signs)); CP_WRITE(pjBase, DWG_LEN, dy); CP_START(pjBase, DWG_YDST, y + pRc->yOffset); } VOID FASTCALL __HWAdjustLeftEdgeRGBZ(DEVRC *pRc, MCDVERTEX *p, MCDFLOAT fdxLeft, MCDFLOAT fdyLeft, MCDFLOAT xFrac, MCDFLOAT yFrac, MCDFLOAT xErr) { BYTE *pjBase = pRc->ppdev->pjBase; LONG dxLeft, dyLeft, dyLeftErr; MCDCOLOR *pColor; #if _X86_ && ASM_ACCEL _asm { fld fdxLeft fmul fixScale fld fdyLeft fmul fixScale // leave these on the stack... } #else dxLeft = FLT_TO_FIX(fdxLeft); dyLeft = FLT_TO_FIX(fdyLeft); #endif CHECK_FIFO_FREE(pjBase, pRc->cFifo, 8); // Adjust the color and z values for the first pixel drawn on the left // edge to be on the pixel center. This is especially important to // perform accurate z-buffering. // We will need to set up the hardware color interpolators: if (pRc->privateEnables & __MCDENABLE_SMOOTH) { #if _X86_ && ASM_ACCEL LONG rTemp, gTemp, bTemp; // Compute the following in assembly: // // rTemp = (r * rScale) + (drdx * xFrac) + (drdy * yFrac); // gTemp = (g * gScale) + (dgdx * xFrac) + (dgdy * yFrac); // bTemp = (b * bScale) + (dbdx * xFrac) + (dbdy * yFrac); _asm{ mov eax, p mov ebx, pRc fld xFrac fmul DWORD PTR [OFFSET(DEVRC.drdx)][ebx] lea eax, [OFFSET(MCDVERTEX.colors) + eax] fld yFrac fmul DWORD PTR [OFFSET(DEVRC.drdy)][ebx] fld DWORD PTR [OFFSET(MCDCOLOR.r)][eax] fmul DWORD PTR [OFFSET(DEVRC.rScale)][ebx] fxch ST(2) faddp ST(1), ST // R R fld xFrac fmul DWORD PTR [OFFSET(DEVRC.dgdx)][ebx] fld yFrac fmul DWORD PTR [OFFSET(DEVRC.dgdy)][ebx] fld DWORD PTR [OFFSET(MCDCOLOR.g)][eax] fmul DWORD PTR [OFFSET(DEVRC.gScale)][ebx] fxch ST(2) // G G G R R faddp ST(1), ST // G G R R fxch ST(2) // R G G R faddp ST(3), ST // G G R fld xFrac fmul DWORD PTR [OFFSET(DEVRC.dbdx)][ebx] fld yFrac fmul DWORD PTR [OFFSET(DEVRC.dbdy)][ebx] fld DWORD PTR [OFFSET(MCDCOLOR.b)][eax] fmul DWORD PTR [OFFSET(DEVRC.bScale)][ebx] fxch ST(2) faddp ST(1), ST // B B G G R fxch ST(2) // G B B G R faddp ST(3), ST // B B G R fxch ST(2) // G B B R fistp gTemp // B B R faddp ST(1), ST // B R fxch ST(1) // R B fistp rTemp // B fistp bTemp // not quite empty, still have dy, dx } CP_WRITE(pjBase, DWG_DR4, rTemp + 0x0800); CP_WRITE(pjBase, DWG_DR8, gTemp + 0x0800); CP_WRITE(pjBase, DWG_DR12, bTemp + 0x0800); #else pColor = &p->colors[0]; CP_WRITE(pjBase, DWG_DR4, FTOL((pColor->r * pRc->rScale) + (pRc->drdx * xFrac) + (pRc->drdy * yFrac)) + 0x0800); CP_WRITE(pjBase, DWG_DR8, FTOL((pColor->g * pRc->gScale) + (pRc->dgdx * xFrac) + (pRc->dgdy * yFrac)) + 0x0800); CP_WRITE(pjBase, DWG_DR12, FTOL((pColor->b * pRc->bScale) + (pRc->dbdx * xFrac) + (pRc->dbdy * yFrac)) + 0x0800); #endif } // Now, sub-pixel correct the z-buffer: if (pRc->privateEnables & __MCDENABLE_Z) { #if _X86_ && ASM_ACCEL LARGE_INTEGER zTemp; if (pRc->MCDState.enables & MCD_POLYGON_OFFSET_FILL_ENABLE) { MCDFLOAT zOffset; zOffset = __MCDGetZOffsetDelta(pRc) + (pRc->MCDState.zOffsetUnits * pRc->zScale); // zTemp = (z * zScale) + (dzdx * xFrac) + (dzdy * yFrac) + zOffset; _asm{ mov eax, p mov ebx, pRc fld xFrac fmul DWORD PTR [OFFSET(DEVRC.dzdx)][ebx] fld yFrac fmul DWORD PTR [OFFSET(DEVRC.dzdy)][ebx] fxch ST(1) fadd zOffset fld DWORD PTR [OFFSET(MCDVERTEX.windowCoord.z)][eax] fmul DWORD PTR [OFFSET(DEVRC.zScale)][ebx] fxch ST(2) faddp ST(1), ST // OUCH!! faddp ST(1), ST fistp zTemp // OUCH!!! } CP_WRITE(pjBase, DWG_DR0, zTemp.LowPart); } else { // zTemp = (z * zScale) + (dzdx * xFrac) + (dzdy * yFrac); _asm{ mov eax, p mov ebx, pRc fld xFrac fmul DWORD PTR [OFFSET(DEVRC.dzdx)][ebx] fld yFrac fmul DWORD PTR [OFFSET(DEVRC.dzdy)][ebx] fld DWORD PTR [OFFSET(MCDVERTEX.windowCoord.z)][eax] fmul DWORD PTR [OFFSET(DEVRC.zScale)][ebx] fxch ST(2) faddp ST(1), ST faddp ST(1), ST // OUCH!!! fistp zTemp // OUCH!!! } CP_WRITE(pjBase, DWG_DR0, zTemp.LowPart); } #else if (pRc->MCDState.enables & MCD_POLYGON_OFFSET_FILL_ENABLE) { MCDFLOAT zOffset; zOffset = __MCDGetZOffsetDelta(pRc) + (pRc->MCDState.zOffsetUnits * pRc->zScale); CP_WRITE(pjBase, DWG_DR0, FTOL((p->windowCoord.z * pRc->zScale) + zOffset + (pRc->dzdx * xFrac) + (pRc->dzdy * yFrac))); } else { CP_WRITE(pjBase, DWG_DR0, FTOL((p->windowCoord.z * pRc->zScale) + (pRc->dzdx * xFrac) + (pRc->dzdy * yFrac))); } #endif } // We've handled the color and z setup. Now, take care of the actual // DDA. #if _X86_ && ASM_ACCEL // convert dxLeft and dyLeft to integer: _asm{ fistp dyLeft fistp dxLeft } #endif if (dxLeft >= 0) { ULONG size = (dxLeft | dyLeft) >> 16; if (size <= 0xff) { dxLeft >>= (8 + 1); dyLeft >>= (8 + 1); } else if (size <= 0xfff) { dxLeft >>= (12 + 1); dyLeft >>= (12 + 1); } else { dxLeft >>= (16 + 1); dyLeft >>= (16 + 1); } dyLeftErr = FTOL(xErr * (MCDFLOAT)dyLeft); CP_WRITE(pjBase, DWG_AR1, -dxLeft + dyLeftErr); CP_WRITE(pjBase, DWG_AR2, -dxLeft); } else { ULONG size = (-dxLeft | dyLeft) >> 16; if (size <= 0xff) { dxLeft >>= (8 + 1); dyLeft >>= (8 + 1); } else if (size <= 0xfff) { dxLeft >>= (12 + 1); dyLeft >>= (12 + 1); } else { dxLeft >>= (16 + 1); dyLeft >>= (16 + 1); } dyLeftErr = FTOL(xErr * (MCDFLOAT)dyLeft); CP_WRITE(pjBase, DWG_AR1, dxLeft + dyLeft - 1 - dyLeftErr); CP_WRITE(pjBase, DWG_AR2, dxLeft); } if (!dyLeft) dyLeft++; //MCDBG_PRINT("LeftEdge: dxLeft = %x, dyLeft = %x, dyLeftErr = %x", dxLeft, dyLeft, dyLeftErr); CP_WRITE(pjBase, DWG_AR0, dyLeft); CP_WRITE(pjBase, DWG_FXLEFT, pRc->ixLeft + pRc->xOffset); } VOID FASTCALL __HWAdjustRightEdge(DEVRC *pRc, MCDVERTEX *p, MCDFLOAT fdxRight, MCDFLOAT fdyRight, MCDFLOAT xErr) { PDEV *ppdev = pRc->ppdev; BYTE *pjBase = ppdev->pjBase; LONG dxRight, dyRight, dyRightErr; #if _X86_ && ASM_ACCEL _asm { fld fdxRight fmul fixScale fld fdyRight fmul fixScale // leave these on the stack... } #else dxRight = FLT_TO_FIX(fdxRight); dyRight = FLT_TO_FIX(fdyRight); #endif CHECK_FIFO_FREE(pjBase, pRc->cFifo, 4); #if _X86_ && ASM_ACCEL _asm{ fistp dyRight fistp dxRight } #endif if (dxRight >= 0) { ULONG size = (dxRight | dyRight) >> 16; if (size <= 0xff) { dxRight >>= (8 + 1); dyRight >>= (8 + 1); } else if (size <= 0xfff) { dxRight >>= (12 + 1); dyRight >>= (12 + 1); } else { dxRight >>= (16 + 1); dyRight >>= (16 + 1); } #if _X86_ && ASM_ACCEL _asm{ fild dyRight fmul xErr } #else dyRightErr = FTOL(xErr * (MCDFLOAT)dyRight); #endif CP_WRITE(pjBase, DWG_AR5, -dxRight); #if _X86_ && ASM_ACCEL _asm{ fistp dyRightErr } #endif CP_WRITE(pjBase, DWG_AR4, -dxRight + dyRightErr); } else { ULONG size = (-dxRight | dyRight) >> 16; if (size <= 0xff) { dxRight >>= (8 + 1); dyRight >>= (8 + 1); } else if (size <= 0xfff) { dxRight >>= (12 + 1); dyRight >>= (12 + 1); } else { dxRight >>= (16 + 1); dyRight >>= (16 + 1); } #if _X86_ && ASM_ACCEL _asm{ fild dyRight fmul xErr } #else dyRightErr = FTOL(xErr * (MCDFLOAT)dyRight); #endif CP_WRITE(pjBase, DWG_AR5, dxRight); #if _X86_ && ASM_ACCEL _asm{ fistp dyRightErr } #endif CP_WRITE(pjBase, DWG_AR4, dxRight + dyRight - 1 - dyRightErr); } if (!dyRight) dyRight++; CP_WRITE(pjBase, DWG_AR6, dyRight); CP_WRITE(pjBase, DWG_FXRIGHT, pRc->ixRight + pRc->xOffset); } VOID FASTCALL __MCDFillTriangle(DEVRC *pRc, MCDVERTEX *a, MCDVERTEX *b, MCDVERTEX *c, BOOL bCCW) { LONG aIY, bIY, cIY; MCDFLOAT dxdyAC, dxdyBC, dxdyAB; MCDFLOAT dx, dy, errX; MCDFLOAT xLeft, xRight; MCDFLOAT xLeftRound; #if _X86_ && ASM_ACCEL if (pRc->privateEnables & (__MCDENABLE_SMOOTH | __MCDENABLE_Z)) { // Pre-compute one over polygon half-area __MCD_FLOAT_BEGIN_DIVIDE(__MCDONE, pRc->halfArea, &pRc->invHalfArea); } #endif // // Snap each y coordinate to its pixel center // SNAPCOORD(a->windowCoord.y, aIY); SNAPCOORD(b->windowCoord.y, bIY); SNAPCOORD(c->windowCoord.y, cIY); // // Calculate delta values for unit changes in x or y // (*pRc->calcDeltas)(pRc, a, b, c); __MCD_FLOAT_BEGIN_DIVIDE(pRc->dxAC, pRc->dyAC, &dxdyAC); (*pRc->HWSetupDeltas)(pRc); // // Fill the two triangle halves. Note that the edge parameters // don't need to be recomputed for counter-clockwise triangles, // making them slightly faster... // if (bCCW) { __MCD_FLOAT_SIMPLE_END_DIVIDE(dxdyAC); dy = (aIY + __MCDHALF) - a->windowCoord.y; xLeft = a->windowCoord.x + dy*dxdyAC; SNAPCOORD(xLeft, pRc->ixLeft); xLeftRound = pRc->ixLeft + __MCDHALF; dx = xLeftRound - a->windowCoord.x; errX = xLeftRound - xLeft; (*pRc->adjustLeftEdge)(pRc, a, pRc->dxAC, pRc->dyAC, dx, dy, errX); if (aIY != bIY) { dxdyAB = pRc->dxAB / pRc->dyAB; xRight = a->windowCoord.x + dy*dxdyAB; SNAPCOORD(xRight, pRc->ixRight); errX = (pRc->ixRight + __MCDHALF) - xRight; (*pRc->adjustRightEdge)(pRc, a, pRc->dxAB, pRc->dyAB, errX); if (bIY != cIY) { __MCD_FLOAT_BEGIN_DIVIDE(pRc->dxBC, pRc->dyBC, &dxdyBC); } (*pRc->HWDrawTrap)(pRc, pRc->dxAC, pRc->dxAB, aIY, bIY - aIY); } else if (bIY != cIY) { __MCD_FLOAT_BEGIN_DIVIDE(pRc->dxBC, pRc->dyBC, &dxdyBC); } if (bIY != cIY) { __MCD_FLOAT_SIMPLE_END_DIVIDE(dxdyBC); dy = (bIY + __MCDHALF) - b->windowCoord.y; xRight = b->windowCoord.x + dy*dxdyBC; SNAPCOORD(xRight, pRc->ixRight); errX = (pRc->ixRight + __MCDHALF) - xRight; (*pRc->adjustRightEdge)(pRc, b, pRc->dxBC, pRc->dyBC, errX); (*pRc->HWDrawTrap)(pRc, pRc->dxAC, pRc->dxBC, bIY, cIY - bIY); } } else { __MCD_FLOAT_SIMPLE_END_DIVIDE(dxdyAC); dy = (aIY + __MCDHALF) - a->windowCoord.y; xRight = a->windowCoord.x + dy*dxdyAC; SNAPCOORD(xRight, pRc->ixRight); errX = (pRc->ixRight + __MCDHALF) - xRight; (*pRc->adjustRightEdge)(pRc, a, pRc->dxAC, pRc->dyAC, errX); if (aIY != bIY) { dxdyAB = pRc->dxAB / pRc->dyAB; xLeft = a->windowCoord.x + dy*dxdyAB; SNAPCOORD(xLeft, pRc->ixLeft); xLeftRound = pRc->ixLeft + __MCDHALF; dx = xLeftRound - a->windowCoord.x; errX = xLeftRound - xLeft; (*pRc->adjustLeftEdge)(pRc, a, pRc->dxAB, pRc->dyAB, dx, dy, errX); if (bIY != cIY) { __MCD_FLOAT_BEGIN_DIVIDE(pRc->dxBC, pRc->dyBC, &dxdyBC); } (*pRc->HWDrawTrap)(pRc, pRc->dxAB, pRc->dxAC, aIY, bIY - aIY); } else if (bIY != cIY) { __MCD_FLOAT_BEGIN_DIVIDE(pRc->dxBC, pRc->dyBC, &dxdyBC); } if (bIY != cIY) { __MCD_FLOAT_SIMPLE_END_DIVIDE(dxdyBC); dy = (bIY + __MCDHALF) - b->windowCoord.y; xLeft = b->windowCoord.x + dy*dxdyBC; SNAPCOORD(xLeft, pRc->ixLeft); xLeftRound = pRc->ixLeft + __MCDHALF; dx = xLeftRound - b->windowCoord.x; errX = xLeftRound - xLeft; (*pRc->adjustLeftEdge)(pRc, b, pRc->dxBC, pRc->dyBC, dx, dy, errX); (*pRc->HWDrawTrap)(pRc, pRc->dxBC, pRc->dxAC, bIY, cIY - bIY); } } }