/*
** Copyright 1991, 1992, 1993, Silicon Graphics, Inc.
** All Rights Reserved.
**
** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
** the contents of this file may not be disclosed to third parties, copied or
** duplicated in any form, in whole or in part, without the prior written
** permission of Silicon Graphics, Inc.
**
** RESTRICTED RIGHTS LEGEND:
** Use, duplication or disclosure by the Government is subject to restrictions
** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
** rights reserved under the Copyright Laws of the United States.
*/

#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stddef.h>
#include <windows.h>
#include <winddi.h>

#include "render.h"
#include "context.h"
#include "global.h"
#include "gencx.h"
#include "..\inc\wglp.h"

#define FLT_TO_FIX(value) \
    *((GLint *)&value) = (GLint)(*((__GLfloat *)&(value)) * (__GLfloat)65536.0)

/* This routine sets gc->polygon.shader.cfb to gc->drawBuffer */

void __fastTriangleSetup(__GLcontext *gc)
{
    SPANREC deltaRec;

    if (gc->polygon.shader.modeFlags & __GL_SHADE_RGB) {
        if (gc->polygon.shader.modeFlags & __GL_SHADE_DITHER) {
            __fastRGBSmoothSpanSetup(gc);
            __fastRGBFlatSpanSetup(gc);
        } else {
            __fastRGBNDSmoothSpanSetup(gc);
            __fastRGBNDFlatSpanSetup(gc);
        }
    } else {
        if (gc->polygon.shader.modeFlags & __GL_SHADE_DITHER) {
            __fastCISmoothSpanSetup(gc);
            __fastCIFlatSpanSetup(gc);
        } else {
            __fastCINDSmoothSpanSetup(gc);
            __fastCINDFlatSpanSetup(gc);
        }
    }

    deltaRec.r = 0;
    deltaRec.g = 0;
    deltaRec.b = 0;
    deltaRec.a = 0;
    deltaRec.z = 0;

    __fastDeltaSpan(gc, &deltaRec);     // Set up initial delta values
}

/*static*/ void fastFillSubTriangle(__GLcontext *gc, GLint iyBottom, GLint iyTop)
{
    GLint ixLeft, ixRight;
    GLint ixLeftFrac, ixRightFrac;
    GLint dxLeftFrac, dxRightFrac;
    GLint dxLeftLittle, dxRightLittle;
    GLint dxLeftBig, dxRightBig;
    GLint spanWidth, clipY0, clipY1;
    GLuint modeFlags;
    __GLGENcontext  *gengc = (__GLGENcontext *)gc;
#ifdef NT
    __GLstippleWord stackWords[__GL_MAX_STACK_STIPPLE_WORDS];
    __GLstippleWord *words;
    GLuint maxWidth;
#else
    __GLstippleWord words[__GL_MAX_STIPPLE_WORDS];
#endif
    __GLspanFunc spanFunc = 
        ((FASTFUNCS *)(*((VOID **)(gengc->pPrivateArea))))->__fastSpanFuncPtr;

#ifdef NT
    maxWidth = (gc->transform.clipX1 - gc->transform.clipX0) + 31;
    if (maxWidth > __GL_MAX_STACK_STIPPLE_BITS)
    {
        words = __wglTempAlloc(gc, (maxWidth+__GL_STIPPLE_BITS-1)/8);
        if (words == NULL)
        {
            return;
        }
    }
    else
    {
        words = stackWords;
    }
#endif
    
    ixLeft = gc->polygon.shader.ixLeft;
    ixLeftFrac = gc->polygon.shader.ixLeftFrac;
    ixRight = gc->polygon.shader.ixRight;
    ixRightFrac = gc->polygon.shader.ixRightFrac;
    clipY0 = gc->transform.clipY0;
    clipY1 = gc->transform.clipY1;
    dxLeftFrac = gc->polygon.shader.dxLeftFrac;
    dxLeftBig = gc->polygon.shader.dxLeftBig;
    dxLeftLittle = gc->polygon.shader.dxLeftLittle;
    dxRightFrac = gc->polygon.shader.dxRightFrac;
    dxRightBig = gc->polygon.shader.dxRightBig;
    dxRightLittle = gc->polygon.shader.dxRightLittle;
    modeFlags = gc->polygon.shader.modeFlags;
    gc->polygon.shader.stipplePat = words;

    if (modeFlags & __GL_SHADE_DEPTH_TEST) {
	gc->polygon.shader.zbuf =
	    __GL_DEPTH_ADDR(&gc->depthBuffer, (__GLzValue*),
			    ixLeft, iyBottom);
    }
    gc->polygon.shader.cfb = gc->drawBuffer;
    while (iyBottom < iyTop) {
	spanWidth = ixRight - ixLeft;
	/*
	** Only render spans that have non-zero width and which are
	** not scissored out vertically.
	*/
	if ((spanWidth > 0) && (iyBottom >= clipY0) && (iyBottom < clipY1)) {
	    gc->polygon.shader.frag.x = ixLeft;
	    gc->polygon.shader.frag.y = iyBottom;
	    gc->polygon.shader.length = spanWidth;

            if (gc->state.raster.drawBuffer == GL_FRONT_AND_BACK) {
                gc->polygon.shader.cfb = &gc->frontBuffer;
                (*spanFunc)(gc);

                if (!((GLint)gc->polygon.shader.cfb->buf.other & DIB_FORMAT))
                    wglCopyBits(gengc->pdco, gengc->pwo, gengc->ColorsBitmap,
                                __GL_UNBIAS_X(gc, ixLeft) + 
                                              gc->drawBuffer->buf.xOrigin,
                                __GL_UNBIAS_Y(gc, iyBottom) + 
                                              gc->drawBuffer->buf.yOrigin,
                                spanWidth, TRUE);


                gc->polygon.shader.cfb = &gc->backBuffer;
                (*spanFunc)(gc);
            } else {

                (*spanFunc)(gc);

                if (!((GLint)gc->drawBuffer->buf.other & DIB_FORMAT))
                    wglCopyBits(gengc->pdco, gengc->pwo, gengc->ColorsBitmap,
                                __GL_UNBIAS_X(gc, ixLeft) + 
                                              gc->drawBuffer->buf.xOrigin,
                                __GL_UNBIAS_Y(gc, iyBottom) + 
                                              gc->drawBuffer->buf.yOrigin,
                                spanWidth, TRUE);
            }
	}

	/* Advance right edge fixed point, adjusting for carry */
	ixRightFrac += dxRightFrac;
	if (ixRightFrac < 0) {
	    /* Carry/Borrow'd. Use large step */
	    ixRight += dxRightBig;
	    ixRightFrac &= ~0x80000000;
	} else {
	    ixRight += dxRightLittle;
	}

	iyBottom++;
	ixLeftFrac += dxLeftFrac;
	if (ixLeftFrac < 0) {
	    /* Carry/Borrow'd.  Use large step */
	    ixLeft += dxLeftBig;
	    ixLeftFrac &= ~0x80000000;

	    if (modeFlags & __GL_SHADE_RGB) {
		if (modeFlags & __GL_SHADE_SMOOTH) {
		    *((GLint *)&gc->polygon.shader.frag.color.r) += 
                        *((GLint *)&gc->polygon.shader.rBig);
		    *((GLint *)&gc->polygon.shader.frag.color.g) += 
                        *((GLint *)&gc->polygon.shader.gBig);
		    *((GLint *)&gc->polygon.shader.frag.color.b) += 
                        *((GLint *)&gc->polygon.shader.bBig);
		    *((GLint *)&gc->polygon.shader.frag.color.a) += 
                        *((GLint *)&gc->polygon.shader.aBig);
		}
	    } else {
		if (modeFlags & __GL_SHADE_SMOOTH) {
		    *((GLint *)&gc->polygon.shader.frag.color.r) += 
                        *((GLint *)&gc->polygon.shader.rBig);
		}
	    }
	    if (modeFlags & __GL_SHADE_DEPTH_ITER) {
		gc->polygon.shader.frag.z += gc->polygon.shader.zBig;
	    }

	    if (modeFlags & __GL_SHADE_DEPTH_TEST) {
		/* The implicit multiply is taken out of the loop */
		gc->polygon.shader.zbuf = (__GLzValue*)
		    ((GLubyte*) gc->polygon.shader.zbuf
		     + gc->polygon.shader.zbufBig);
	    }
	} else {
	    /* Use small step */
	    ixLeft += dxLeftLittle;
	    if (modeFlags & __GL_SHADE_RGB) {
		if (modeFlags & __GL_SHADE_SMOOTH) {
		    *((GLint *)&gc->polygon.shader.frag.color.r) += 
                        *((GLint *)&gc->polygon.shader.rLittle);
		    *((GLint *)&gc->polygon.shader.frag.color.g) += 
                        *((GLint *)&gc->polygon.shader.gLittle);
		    *((GLint *)&gc->polygon.shader.frag.color.b) += 
                        *((GLint *)&gc->polygon.shader.bLittle);
		    *((GLint *)&gc->polygon.shader.frag.color.a) += 
                        *((GLint *)&gc->polygon.shader.aLittle);
		}
	    } else {
		if (modeFlags & __GL_SHADE_SMOOTH) {
		    *((GLint *)&gc->polygon.shader.frag.color.r) += 
                        *((GLint *)&gc->polygon.shader.rLittle);
		}
            }
	    if (modeFlags & __GL_SHADE_DEPTH_ITER) {
		gc->polygon.shader.frag.z += gc->polygon.shader.zLittle;
	    }
	    if (modeFlags & __GL_SHADE_DEPTH_TEST) {
		/* The implicit multiply is taken out of the loop */
		gc->polygon.shader.zbuf = (__GLzValue*)
		    ((GLubyte*) gc->polygon.shader.zbuf
		     + gc->polygon.shader.zbufLittle);
	    }
	}
    }
    gc->polygon.shader.ixLeft = ixLeft;
    gc->polygon.shader.ixLeftFrac = ixLeftFrac;
    gc->polygon.shader.ixRight = ixRight;
    gc->polygon.shader.ixRightFrac = ixRightFrac;

#ifdef NT
    if (maxWidth > __GL_MAX_STACK_STIPPLE_BITS)
    {
        __wglTempFree(gc, words);
    }
#endif
}

#define __TWO_31 ((__GLfloat) 2147483648.0)

#define __FRACTION(result,f) \
    result = (GLint) ((f) * __TWO_31)

static void SnapXLeft(__GLcontext *gc, __GLfloat xLeft, __GLfloat dxdyLeft)
{
    __GLfloat little, dx;
    GLint ixLeft, ixLeftFrac, frac, lineBytes, elementSize, ilittle, ibig;

    ixLeft = (GLint) xLeft;
    dx = xLeft - ixLeft;
    __FRACTION(ixLeftFrac,dx);

    /* Pre-add .5 to allow truncation in spanWidth calculation */
    ixLeftFrac += 0x40000000;
    gc->polygon.shader.ixLeft = ixLeft + (((GLuint) ixLeftFrac) >> 31);
    gc->polygon.shader.ixLeftFrac = ixLeftFrac & ~0x80000000;

    /* Compute big and little steps */
    ilittle = (GLint) dxdyLeft;
    little = (__GLfloat) ilittle;
    if (dxdyLeft < 0) {
	ibig = ilittle - 1;
	dx = little - dxdyLeft;
	__FRACTION(frac,dx);
	gc->polygon.shader.dxLeftFrac = -frac;
    } else {
	ibig = ilittle + 1;
	dx = dxdyLeft - little;
	__FRACTION(frac,dx);
	gc->polygon.shader.dxLeftFrac = frac;
    }
    if (gc->polygon.shader.modeFlags & __GL_SHADE_DEPTH_TEST) {
	/*
	** Compute the big and little depth buffer steps.  We walk the
	** memory pointers for the depth buffer along the edge of the
	** triangle as we walk the edge.  This way we don't have to
	** recompute the buffer address as we go.
	*/
	elementSize = gc->depthBuffer.buf.elementSize;
	lineBytes = elementSize * gc->depthBuffer.buf.outerWidth;
	gc->polygon.shader.zbufLittle = lineBytes + ilittle * elementSize;
	gc->polygon.shader.zbufBig = lineBytes + ibig * elementSize;
    }
    gc->polygon.shader.dxLeftLittle = ilittle;
    gc->polygon.shader.dxLeftBig = ibig;
}

static void SnapXRight(__GLshade *sh, __GLfloat xRight, __GLfloat dxdyRight)
{
    __GLfloat little, big, dx;
    GLint ixRight, ixRightFrac, frac;

    ixRight = (GLint) xRight;
    dx = xRight - ixRight;
    __FRACTION(ixRightFrac,dx);

    /* Pre-add .5 to allow truncation in spanWidth calculation */
    ixRightFrac += 0x40000000;
    sh->ixRight = ixRight + (((GLuint) ixRightFrac) >> 31);
    sh->ixRightFrac = ixRightFrac & ~0x80000000;

    /* Compute big and little steps */
    little = (__GLfloat) ((GLint) dxdyRight);
    if (dxdyRight < 0) {
	big = little - 1;
	dx = little - dxdyRight;
	__FRACTION(frac,dx);
	sh->dxRightFrac = -frac;
    } else {
	big = little + 1;
	dx = dxdyRight - little;
	__FRACTION(frac,dx);
	sh->dxRightFrac = frac;
    }
    sh->dxRightLittle = (GLint) little;
    sh->dxRightBig = (GLint) big;
}

static void SetInitialParameters(__GLshade *sh, const __GLvertex *a,
				 const __GLcolor *ac, __GLfloat aFog,
				 __GLfloat dx, __GLfloat dy)
{
    __GLfloat little = sh->dxLeftLittle;
    __GLfloat big = sh->dxLeftBig;
    GLuint modeFlags = sh->modeFlags;

    if (big > little) {
	if (modeFlags & __GL_SHADE_RGB) {
	    if (modeFlags & __GL_SHADE_SMOOTH) {
		sh->frag.color.r = ac->r + dx*sh->drdx + dy*sh->drdy;
		sh->rLittle = sh->drdy + little * sh->drdx;
		sh->rBig = sh->rLittle + sh->drdx;

		sh->frag.color.g = ac->g + dx*sh->dgdx + dy*sh->dgdy;
		sh->gLittle = sh->dgdy + little * sh->dgdx;
		sh->gBig = sh->gLittle + sh->dgdx;

		sh->frag.color.b = ac->b + dx*sh->dbdx + dy*sh->dbdy;
		sh->bLittle = sh->dbdy + little * sh->dbdx;
		sh->bBig = sh->bLittle + sh->dbdx;

		sh->frag.color.a = ac->a + dx*sh->dadx + dy*sh->dady;
		sh->aLittle = sh->dady + little * sh->dadx;
		sh->aBig =sh->aLittle + sh->dadx;

                FLT_TO_FIX(sh->frag.color.r);
                FLT_TO_FIX(sh->frag.color.g);
                FLT_TO_FIX(sh->frag.color.b);
                FLT_TO_FIX(sh->frag.color.a);

                FLT_TO_FIX(sh->rLittle);
                FLT_TO_FIX(sh->gLittle);
                FLT_TO_FIX(sh->bLittle);
                FLT_TO_FIX(sh->aLittle);

                FLT_TO_FIX(sh->rBig);
                FLT_TO_FIX(sh->gBig);
                FLT_TO_FIX(sh->bBig);
                FLT_TO_FIX(sh->aBig);

	    }
	} else {
	    if (modeFlags & __GL_SHADE_SMOOTH) {
		sh->frag.color.r = ac->r + dx*sh->drdx + dy*sh->drdy;
		sh->rLittle = sh->drdy + little * sh->drdx;
		sh->rBig = sh->rLittle + sh->drdx;

                FLT_TO_FIX(sh->frag.color.r);
                FLT_TO_FIX(sh->rLittle);
                FLT_TO_FIX(sh->rBig);
            }
	}
	if (modeFlags & __GL_SHADE_DEPTH_ITER) {
	    __GLfloat zLittle;

	    sh->frag.z = (__GLzValue)
		(a->window.z + dx*sh->dzdxf + dy*sh->dzdyf);
	    zLittle = sh->dzdyf + little * sh->dzdxf;
	    sh->zLittle = (GLint)zLittle;
	    sh->zBig = (GLint)(zLittle + sh->dzdxf);
	}
	if (modeFlags & __GL_SHADE_SLOW_FOG) {
	    sh->frag.f = aFog + dx*sh->dfdx + dy*sh->dfdy;
	    sh->fLittle = sh->dfdy + little * sh->dfdx;
	    sh->fBig = sh->fLittle + sh->dfdx;

            FLT_TO_FIX(sh->frag.f);
            FLT_TO_FIX(sh->fLittle);
            FLT_TO_FIX(sh->fBig);
	}
    } else {	
	if (modeFlags & __GL_SHADE_RGB) {
	    if (modeFlags & __GL_SHADE_SMOOTH) {
		sh->frag.color.r = ac->r + dx*sh->drdx + dy*sh->drdy;
		sh->rLittle = sh->drdy + little * sh->drdx;
		sh->rBig = sh->rLittle - sh->drdx;

		sh->frag.color.g = ac->g + dx*sh->dgdx + dy*sh->dgdy;
		sh->gLittle = sh->dgdy + little * sh->dgdx;
		sh->gBig = sh->gLittle - sh->dgdx;

		sh->frag.color.b = ac->b + dx*sh->dbdx + dy*sh->dbdy;
		sh->bLittle = sh->dbdy + little * sh->dbdx;
		sh->bBig = sh->bLittle - sh->dbdx;

		sh->frag.color.a = ac->a + dx*sh->dadx + dy*sh->dady;
		sh->aLittle = sh->dady + little * sh->dadx;
		sh->aBig =sh->aLittle - sh->dadx;

                FLT_TO_FIX(sh->frag.color.r);
                FLT_TO_FIX(sh->frag.color.g);
                FLT_TO_FIX(sh->frag.color.b);
                FLT_TO_FIX(sh->frag.color.a);

                FLT_TO_FIX(sh->rLittle);
                FLT_TO_FIX(sh->gLittle);
                FLT_TO_FIX(sh->bLittle);
                FLT_TO_FIX(sh->aLittle);

                FLT_TO_FIX(sh->rBig);
                FLT_TO_FIX(sh->gBig);
                FLT_TO_FIX(sh->bBig);
                FLT_TO_FIX(sh->aBig);
	    }
	} else {
	    if (modeFlags & __GL_SHADE_SMOOTH) {
		sh->frag.color.r = ac->r + dx*sh->drdx + dy*sh->drdy;
		sh->rLittle = sh->drdy + little * sh->drdx;
		sh->rBig = sh->rLittle - sh->drdx;

                FLT_TO_FIX(sh->frag.color.r);
                FLT_TO_FIX(sh->rLittle);
                FLT_TO_FIX(sh->rBig);
	    }
	}
	if (modeFlags & __GL_SHADE_DEPTH_ITER) {
	    __GLfloat zLittle;
	    sh->frag.z = (__GLzValue)
		(a->window.z + dx*sh->dzdxf + dy*sh->dzdyf);
	    zLittle = sh->dzdyf + little * sh->dzdxf;
	    sh->zLittle = (GLint)zLittle;
	    sh->zBig = (GLint)(zLittle - sh->dzdxf);
	}
	if (modeFlags & __GL_SHADE_SLOW_FOG) {
	    sh->frag.f = aFog + dx*sh->dfdx + dy*sh->dfdy;
	    sh->fLittle = sh->dfdy + little * sh->dfdx;
	    sh->fBig = sh->fLittle - sh->dfdx;

            FLT_TO_FIX(sh->frag.f);
            FLT_TO_FIX(sh->fLittle);
            FLT_TO_FIX(sh->fBig);
	}
    }
}


void __fastFillTriangle(__GLcontext *gc, __GLvertex *a, __GLvertex *b,
                        __GLvertex *c, GLboolean ccw)

{
    __GLfloat oneOverArea, t1, t2, t3, t4;
    __GLfloat dxAC, dxBC, dyAC, dyBC;
    __GLfloat aFog, bFog;
    __GLfloat dxAB, dyAB;
    __GLfloat dx, dy, dxdyLeft, dxdyRight;
    __GLcolor *ac, *bc;
    GLint aIY, bIY, cIY;
    GLuint modeFlags;
    SPANREC deltaRec;


    /* Pre-compute one over polygon area */

    oneOverArea = __glOne / gc->polygon.shader.area;

    /* Fetch some stuff we are going to reuse */
    modeFlags = gc->polygon.shader.modeFlags;
    dxAC = gc->polygon.shader.dxAC;
    dxBC = gc->polygon.shader.dxBC;
    dyAC = gc->polygon.shader.dyAC;
    dyBC = gc->polygon.shader.dyBC;
    ac = a->color;
    bc = b->color;

    /*
    ** Compute delta values for unit changes in x or y for each
    ** parameter.
    */
    t1 = dyAC * oneOverArea;
    t2 = dyBC * oneOverArea;
    t3 = dxAC * oneOverArea;
    t4 = dxBC * oneOverArea;
    if (modeFlags & __GL_SHADE_RGB) {
	if (modeFlags & __GL_SHADE_SMOOTH) {
	    __GLfloat drAC, dgAC, dbAC, daAC;
	    __GLfloat drBC, dgBC, dbBC, daBC;
	    __GLcolor *cc;

	    cc = c->color;
	    drAC = ac->r - cc->r;
	    drBC = bc->r - cc->r;
	    gc->polygon.shader.drdx = drAC * t2 - drBC * t1;
	    gc->polygon.shader.drdy = drBC * t3 - drAC * t4;
	    dgAC = ac->g - cc->g;
	    dgBC = bc->g - cc->g;
	    gc->polygon.shader.dgdx = dgAC * t2 - dgBC * t1;
	    gc->polygon.shader.dgdy = dgBC * t3 - dgAC * t4;
	    dbAC = ac->b - cc->b;
	    dbBC = bc->b - cc->b;
	    gc->polygon.shader.dbdx = dbAC * t2 - dbBC * t1;
	    gc->polygon.shader.dbdy = dbBC * t3 - dbAC * t4;
	    daAC = ac->a - cc->a;
	    daBC = bc->a - cc->a;
	    gc->polygon.shader.dadx = daAC * t2 - daBC * t1;
	    gc->polygon.shader.dady = daBC * t3 - daAC * t4;

            RtlCopyMemory(&deltaRec.r, &gc->polygon.shader.drdx, 
                          4 * sizeof(__GLfloat));

            FLT_TO_FIX(deltaRec.r);
            FLT_TO_FIX(deltaRec.g);
            FLT_TO_FIX(deltaRec.b);
            FLT_TO_FIX(deltaRec.a);
	} else {
	    __GLcolor *flatColor = gc->vertex.provoking->color;
	    gc->polygon.shader.frag.color.r = flatColor->r;
	    gc->polygon.shader.frag.color.g = flatColor->g;
	    gc->polygon.shader.frag.color.b = flatColor->b;
	    gc->polygon.shader.frag.color.a = flatColor->a;

            FLT_TO_FIX(gc->polygon.shader.frag.color.r);
            FLT_TO_FIX(gc->polygon.shader.frag.color.g);
            FLT_TO_FIX(gc->polygon.shader.frag.color.b);
            FLT_TO_FIX(gc->polygon.shader.frag.color.a);
	}
    } else {
	if (modeFlags & __GL_SHADE_SMOOTH) {
	    __GLfloat drAC;
	    __GLfloat drBC;
	    __GLcolor *cc;

	    cc = c->color;
	    drAC = ac->r - cc->r;
	    drBC = bc->r - cc->r;
	    gc->polygon.shader.drdx = drAC * t2 - drBC * t1;
	    gc->polygon.shader.drdy = drBC * t3 - drAC * t4;

            deltaRec.r = *((GLint *)&gc->polygon.shader.drdx);
            FLT_TO_FIX(deltaRec.r);
	} else {
	    __GLcolor *flatColor = gc->vertex.provoking->color;
	    gc->polygon.shader.frag.color.r = flatColor->r;
            FLT_TO_FIX(gc->polygon.shader.frag.color.r);
	}
    }
    if (modeFlags & __GL_SHADE_DEPTH_ITER) {
	__GLfloat dzAC, dzBC;

	dzAC = a->window.z - c->window.z;
	dzBC = b->window.z - c->window.z;
	gc->polygon.shader.dzdxf = dzAC * t2 - dzBC * t1;
	gc->polygon.shader.dzdyf = dzBC * t3 - dzAC * t4;
	deltaRec.z = gc->polygon.shader.dzdx = (GLint) gc->polygon.shader.dzdxf;
    }

    __fastDeltaSpan(gc, &deltaRec);     // Set up span delta values


    /* Snap each y coordinate to its pixel center */
    aIY = (GLint) (a->window.y + __glHalf);
    bIY = (GLint) (b->window.y + __glHalf);
    cIY = (GLint) (c->window.y + __glHalf);

    /*
    ** This algorithim always fills from bottom to top, left to right.
    ** Because of this, ccw triangles are inherently faster because
    ** the parameter values need not be recomputed.
    */
    dxAB = a->window.x - b->window.x;
    dyAB = a->window.y - b->window.y;
    if (ccw) {
	dxdyLeft = dxAC / dyAC;
	dy = (aIY + __glHalf) - a->window.y;
	SnapXLeft(gc, a->window.x + dy*dxdyLeft, dxdyLeft);
	dx = (gc->polygon.shader.ixLeft + __glHalf) - a->window.x;
	SetInitialParameters(&gc->polygon.shader, a, ac, aFog, dx, dy);
	if (aIY != bIY) {
	    dxdyRight = dxAB / dyAB;
	    SnapXRight(&gc->polygon.shader, a->window.x + dy*dxdyRight,
		       dxdyRight);
	    fastFillSubTriangle(gc, aIY, bIY);
	}

	if (bIY != cIY) {
	    dxdyRight = dxBC / dyBC;
	    dy = (bIY + __glHalf) - b->window.y;
	    SnapXRight(&gc->polygon.shader, b->window.x + dy*dxdyRight,
		       dxdyRight);
	    fastFillSubTriangle(gc, bIY, cIY);
	}
    } else {
	dxdyRight = dxAC / dyAC;
	dy = (aIY + __glHalf) - a->window.y;
	SnapXRight(&gc->polygon.shader, a->window.x + dy*dxdyRight, dxdyRight);
	if (aIY != bIY) {
	    dxdyLeft = dxAB / dyAB;
	    SnapXLeft(gc, a->window.x + dy*dxdyLeft, dxdyLeft);
	    dx = (gc->polygon.shader.ixLeft + __glHalf) - a->window.x;
	    SetInitialParameters(&gc->polygon.shader, a, ac, aFog, dx, dy);
	    fastFillSubTriangle(gc, aIY, bIY);
	}

	if (bIY != cIY) {
	    dxdyLeft = dxBC / dyBC;
	    dy = (bIY + __glHalf) - b->window.y;
	    SnapXLeft(gc, b->window.x + dy*dxdyLeft, dxdyLeft);
	    dx = (gc->polygon.shader.ixLeft + __glHalf) - b->window.x;
	    SetInitialParameters(&gc->polygon.shader, b, bc, bFog, dx, dy);
	    fastFillSubTriangle(gc, bIY, cIY);
	}
    }
}