//=================================================================
//
// Copyright (c) Microsoft Corporation 1999 - All Rights Reserved.
//
//=================================================================

//-----------------------------------------------------------------------------
//
// _CREATEEDGE_FN_NAME_     Name of the create edge function
// _GOURAUD_                Define this to interpolate the intensity along the edge.
// _AFFINE_                 Define this to use affine texture mapping along the edge.
// _PERSPECTIVE_            Define this to use perspective texture mapping along the edge.
// _ZBUFFER_                Define this to interpolate the z-values along the edge.
// _FOG_                    Define this to interpolate fog intensity along the edge.
//
//-----------------------------------------------------------------------------

void _CREATEEDGE_FN_NAME_(int iTop, int iBottom)
{
    assert(g_grdRenderData.gvVertices[iBottom].y >= g_grdRenderData.gvVertices[iTop].y);

	g_grdRenderData.geEdge.y  = Ceil28_4NonNeg(g_grdRenderData.gvVertices[iTop].y);
	long yEnd = Ceil28_4NonNeg(g_grdRenderData.gvVertices[iBottom].y);

	g_grdRenderData.geEdge.cy = yEnd - g_grdRenderData.geEdge.y;

	if(g_grdRenderData.geEdge.cy)
	{
		long dN = g_grdRenderData.gvVertices[iBottom].y - g_grdRenderData.gvVertices[iTop].y;
		long dM = g_grdRenderData.gvVertices[iBottom].x - g_grdRenderData.gvVertices[iTop].x;
	
		long InitialNum = dM*((g_grdRenderData.geEdge.y<<intSHIFT28_4) -
                              g_grdRenderData.gvVertices[iTop].y) +
                          dN*g_grdRenderData.gvVertices[iTop].x -
                          1 +
                          (dN<<intSHIFT28_4);

		FloorQuoRem(InitialNum,
                    (dN<<intSHIFT28_4),
                    g_grdRenderData.geEdge.x,
                    g_grdRenderData.geEdge.xError);

#if defined(_AFFINE_) || defined(_PERSPECTIVE_) || defined(_ZBUFFER_)
		float yPrestep = Fixed28_4ToFloat((g_grdRenderData.geEdge.y<<intSHIFT28_4) - g_grdRenderData.gvVertices[iTop].y);
		float xPrestep = Fixed28_4ToFloat((g_grdRenderData.geEdge.x<<intSHIFT28_4) - g_grdRenderData.gvVertices[iTop].x);
#endif

#if defined(_GOURAUD_)
        // bump up 1/16 step to avoid jitter below 0 to FF (1/16, not 1/2, because this ends up getting used as a 5-bit value)
		g_grdRenderData.geEdge.f16Blue = FloatToFixed16_16((float)BLUE(g_grdRenderData.gvVertices[iTop].color) + yPrestep * Fixed16_16ToFloat(g_grdRenderData.f16dBdy) + xPrestep * Fixed16_16ToFloat(g_grdRenderData.f16dBdx)) + 0x8000;

        if (!(g_grdRenderData.dwState & STATE_SHADEI))
        {
            // bump up 1/16 step to avoid jitter below 0 to FF (1/16, not 1/2, because this ends up getting used as a 5-bit value)
            g_grdRenderData.geEdge.f16Green = FloatToFixed16_16((float)GREEN(g_grdRenderData.gvVertices[iTop].color) + yPrestep * Fixed16_16ToFloat(g_grdRenderData.f16dGdy) + xPrestep * Fixed16_16ToFloat(g_grdRenderData.f16dGdx)) + 0x8000;
            // bump up 1/16 step to avoid jitter below 0 to FF
		    g_grdRenderData.geEdge.f16Red = FloatToFixed16_16((float)RED(g_grdRenderData.gvVertices[iTop].color) + yPrestep * Fixed16_16ToFloat(g_grdRenderData.f16dRdy) + xPrestep * Fixed16_16ToFloat(g_grdRenderData.f16dRdx)) + 0x8000;
        }

        if (g_grdRenderData.dwState & STATE_SHADEALPHA)
        {
            // bump up 1/16 step to avoid jitter below 0 to FF (1/16, not 1/2, because this ends up getting used as a 5-bit value)
		    g_grdRenderData.geEdge.f16Alpha = FloatToFixed16_16((float)ALPHA(g_grdRenderData.gvVertices[iTop].color) + yPrestep * Fixed16_16ToFloat(g_grdRenderData.f16dAdy) + xPrestep * Fixed16_16ToFloat(g_grdRenderData.f16dAdx)) + 0x8000;
        }
#endif

#if defined(_FOG_)
        if (!g_grdRenderData.fFogIsFlat)
        {
            // bump up 1/16 step to avoid jitter below 0 to FF (1/16, not 1/2, because this ends up getting used as a 5-bit value)
		    g_grdRenderData.geEdge.f16Fog = FloatToFixed16_16((float)FOG(g_grdRenderData.gvVertices[iTop].specular) + yPrestep * Fixed16_16ToFloat(g_grdRenderData.f16dFdy) + xPrestep * Fixed16_16ToFloat(g_grdRenderData.f16dFdx)) + 0x8000;
        }
#endif

#if defined(_AFFINE_)
		g_grdRenderData.geEdge.u = g_grdRenderData.gvVertices[iTop].tu + yPrestep * g_grdRenderData.dudy + xPrestep * g_grdRenderData.dudx;
		g_grdRenderData.geEdge.v = g_grdRenderData.gvVertices[iTop].tv + yPrestep * g_grdRenderData.dvdy + xPrestep * g_grdRenderData.dvdx;
#endif
	
#if defined(_ZBUFFER_)
		g_grdRenderData.geEdge.Z = g_grdRenderData.gvVertices[iTop].z + yPrestep * g_grdRenderData.dZdy + xPrestep * g_grdRenderData.dZdx;
#endif
	
#if defined(_PERSPECTIVE_)
		g_grdRenderData.geEdge.oow = g_grdRenderData.gvVertices[iTop].rhw + yPrestep * g_grdRenderData.doowdy + xPrestep * g_grdRenderData.doowdx;
		g_grdRenderData.geEdge.uow = g_grdRenderData.rguow[iTop] + yPrestep * g_grdRenderData.duowdy + xPrestep * g_grdRenderData.duowdx;
		g_grdRenderData.geEdge.vow = g_grdRenderData.rgvow[iTop] + yPrestep * g_grdRenderData.dvowdy + xPrestep * g_grdRenderData.dvowdx;
#endif

	    if(g_grdRenderData.geEdge.cy > 1)
	    {
            if (dM >= 0)
            {
                if (dM < dN)
                {
                    g_grdRenderData.geEdge.xStep = 0;
                    g_grdRenderData.geEdge.xNum = dM << intSHIFT28_4;
                    goto Done;
                }
                else if (dM < (dN << 1))
                {
                    g_grdRenderData.geEdge.xStep = 1;
                    g_grdRenderData.geEdge.xNum = (dM - dN) << intSHIFT28_4;
                    goto Done;
                }
            }
            else
            {
                if ((dM + dN) >= 0)
                {
                    g_grdRenderData.geEdge.xStep = -1;
                    g_grdRenderData.geEdge.xNum = (dM + dN) << intSHIFT28_4;
                    goto Done;
                }
                else if ((dM + (dN << 1)) >= 0)
                {
                    g_grdRenderData.geEdge.xStep = -2;
                    g_grdRenderData.geEdge.xNum = (dM + (dN << 1)) << intSHIFT28_4;
                    goto Done;
                }
            }

		    FloorQuoRem((dM<<intSHIFT28_4),
                        (dN<<intSHIFT28_4),
                        g_grdRenderData.geEdge.xStep,
                        g_grdRenderData.geEdge.xNum);
Done:
		    g_grdRenderData.geEdge.xDenom = dN<<intSHIFT28_4;

            // bias so we can test for 0
            g_grdRenderData.geEdge.xError -= g_grdRenderData.geEdge.xDenom;

#if defined(_GOURAUD_)
		    g_grdRenderData.geEdge.f16BlueStep = g_grdRenderData.geEdge.xStep * g_grdRenderData.f16dBdx + g_grdRenderData.f16dBdy;
		    g_grdRenderData.geEdge.f16BlueStepExtra = g_grdRenderData.geEdge.f16BlueStep + g_grdRenderData.f16dBdx;

            if (!(g_grdRenderData.dwState & STATE_SHADEI))
            {
		        g_grdRenderData.geEdge.f16GreenStep = g_grdRenderData.geEdge.xStep * g_grdRenderData.f16dGdx + g_grdRenderData.f16dGdy;
		        g_grdRenderData.geEdge.f16GreenStepExtra = g_grdRenderData.geEdge.f16GreenStep + g_grdRenderData.f16dGdx;

		        g_grdRenderData.geEdge.f16RedStep = g_grdRenderData.geEdge.xStep * g_grdRenderData.f16dRdx + g_grdRenderData.f16dRdy;
		        g_grdRenderData.geEdge.f16RedStepExtra = g_grdRenderData.geEdge.f16RedStep + g_grdRenderData.f16dRdx;
            }

            if (g_grdRenderData.dwState & STATE_SHADEALPHA)
            {
		        g_grdRenderData.geEdge.f16AlphaStep = g_grdRenderData.geEdge.xStep * g_grdRenderData.f16dAdx + g_grdRenderData.f16dAdy;
		        g_grdRenderData.geEdge.f16AlphaStepExtra = g_grdRenderData.geEdge.f16AlphaStep + g_grdRenderData.f16dAdx;
            }
#endif

#if defined(_FOG_)
            if (!g_grdRenderData.fFogIsFlat)
            {
		        g_grdRenderData.geEdge.f16FogStep = g_grdRenderData.geEdge.xStep * g_grdRenderData.f16dFdx + g_grdRenderData.f16dFdy;
		        g_grdRenderData.geEdge.f16FogStepExtra = g_grdRenderData.geEdge.f16FogStep + g_grdRenderData.f16dFdx;
            }
#endif

#if defined(_AFFINE_)
		    g_grdRenderData.geEdge.uStep = g_grdRenderData.geEdge.xStep * g_grdRenderData.dudx + g_grdRenderData.dudy;
		    g_grdRenderData.geEdge.uStepExtra = g_grdRenderData.geEdge.uStep + g_grdRenderData.dudx;
	    
		    g_grdRenderData.geEdge.vStep = g_grdRenderData.geEdge.xStep * g_grdRenderData.dvdx + g_grdRenderData.dvdy;
            g_grdRenderData.geEdge.vStepExtra = g_grdRenderData.geEdge.vStep + g_grdRenderData.dvdx;
#endif
	
#if defined(_ZBUFFER_)
		    g_grdRenderData.geEdge.ZStep = g_grdRenderData.geEdge.xStep * g_grdRenderData.dZdx + g_grdRenderData.dZdy;
		    g_grdRenderData.geEdge.ZStepExtra = g_grdRenderData.geEdge.ZStep + g_grdRenderData.dZdx;
#endif
	
#if defined(_PERSPECTIVE_)
		    g_grdRenderData.geEdge.oowStep = g_grdRenderData.geEdge.xStep * g_grdRenderData.doowdx + g_grdRenderData.doowdy;
		    g_grdRenderData.geEdge.oowStepExtra = g_grdRenderData.geEdge.oowStep + g_grdRenderData.doowdx;

		    g_grdRenderData.geEdge.uowStep = g_grdRenderData.geEdge.xStep * g_grdRenderData.duowdx + g_grdRenderData.duowdy;
		    g_grdRenderData.geEdge.uowStepExtra = g_grdRenderData.geEdge.uowStep + g_grdRenderData.duowdx;
	    
		    g_grdRenderData.geEdge.vowStep = g_grdRenderData.geEdge.xStep * g_grdRenderData.dvowdx + g_grdRenderData.dvowdy;
            g_grdRenderData.geEdge.vowStepExtra = g_grdRenderData.geEdge.vowStep + g_grdRenderData.dvowdx;
#endif
        }
    }
}

