PageRenderTime 136ms CodeModel.GetById 18ms app.highlight 110ms RepoModel.GetById 1ms app.codeStats 0ms

/opengles/src/RasterizerTriangles.inc

http://ftk.googlecode.com/
Pascal | 1132 lines | 232 code | 112 blank | 788 comment | 36 complexity | 557db63d3e597d20535e24c8e17c4cae MD5 | raw file
   1// ==========================================================================
   2//
   3// RasterizerTriangles.inc	Rasterizer Class for 3D Rendering Library
   4//
   5// The rasterizer converts transformed and lit primitives and creates a 
   6// raster image in the current rendering surface.
   7//
   8// This files contains the triangle rasterization code, which was
   9// previously in the Rasterizer.cpp source file.
  10//
  11// --------------------------------------------------------------------------
  12//
  13// 05-22-2004		Hans-Martin Will	initial version
  14//
  15// --------------------------------------------------------------------------
  16//
  17// Copyright (c) 2004, Hans-Martin Will. All rights reserved.
  18// 
  19// Redistribution and use in source and binary forms, with or without 
  20// modification, are permitted provided that the following conditions are 
  21// met:
  22// 
  23//	 *  Redistributions of source code must retain the above copyright
  24// 		notice, this list of conditions and the following disclaimer. 
  25//   *	Redistributions in binary form must reproduce the above copyright
  26// 		notice, this list of conditions and the following disclaimer in the 
  27// 		documentation and/or other materials provided with the distribution. 
  28// 
  29// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  30// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  31// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  32// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
  33// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
  34// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
  35// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  36// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
  37// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  38// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
  39// THE POSSIBILITY OF SUCH DAMAGE.
  40//
  41// ==========================================================================
  42
  43
  44// The following macros need to be defined for this include file:
  45//
  46// InitScanlineStart
  47// InitScanlineDeltas
  48// RasterTriangle
  49//
  50// HasFog
  51// HasDepth
  52// HasColor
  53// HasTexture
  54// HasStencil
  55// HasScissor
  56
  57
  58#ifndef InitScanlineStart
  59#error "InitScanlineStart is not defined"
  60#endif
  61
  62#ifndef InitScanlineDeltas
  63#error "InitScanlineDeltas is not defined"
  64#endif
  65
  66#ifndef RasterTriangle
  67#error "RasterTriangle is not defined"
  68#endif
  69
  70#ifndef HasFog
  71#error "HasFog is not defined"
  72#endif
  73
  74#ifndef HasDepth
  75#error "HasDepth is not defined"
  76#endif
  77
  78#ifndef HasColor
  79#error "HasColor is not defined"
  80#endif
  81
  82#ifndef HasTexture
  83#error "HasTexture is not defined"
  84#endif
  85
  86#ifndef HasStencil
  87#error "HasStencil is not defined"
  88#endif
  89
  90#ifndef HasScissor
  91#error "HasScissor is not defined"
  92#endif
  93
  94
  95namespace {
  96	inline void InitScanlineStart(const RasterInfo & rasterInfo, EdgePos & start, const Gradients & grad,
  97		EGL_Fixed xPreStep, EGL_Fixed yPreStep,
  98		const FractionalColor& color, EGL_Fixed fog, EGL_Fixed depth, EGL_Fixed invZ, EGL_Fixed tuOverZ[], EGL_Fixed tvOverZ[]) {
  99#if HasDepth
 100		start.m_WindowCoords.depth = 
 101			depth		+ EGL_Mul(grad.dx.m_WindowCoords.depth, xPreStep)	
 102						+ EGL_Mul(grad.dy.m_WindowCoords.depth, yPreStep); 
 103#endif
 104
 105#if HasColor
 106		start.m_Color.r	= 
 107			color.r		+ EGL_Mul(grad.dx.m_Color.r, xPreStep)				
 108						+ EGL_Mul(grad.dy.m_Color.r, yPreStep);
 109
 110		start.m_Color.g	= 
 111			color.g		+ EGL_Mul(grad.dx.m_Color.g, xPreStep)				
 112						+ EGL_Mul(grad.dy.m_Color.g, yPreStep);
 113
 114		start.m_Color.b	= 
 115			color.b		+ EGL_Mul(grad.dx.m_Color.b, xPreStep)				
 116						+ EGL_Mul(grad.dy.m_Color.b, yPreStep);
 117
 118		start.m_Color.a	= 
 119			color.a		+ EGL_Mul(grad.dx.m_Color.a, xPreStep)				
 120						+ EGL_Mul(grad.dy.m_Color.a, yPreStep);
 121#endif
 122
 123#if HasTexture		
 124		start.m_WindowCoords.invZ = 
 125			invZ		+ EGL_Mul(grad.dx.m_WindowCoords.invZ, xPreStep)	
 126						+ EGL_Mul(grad.dy.m_WindowCoords.invZ, yPreStep); 
 127
 128		for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
 129			if (!rasterInfo.Textures[index])
 130				continue;
 131
 132			start.m_TextureCoords[index].tu = 
 133				tuOverZ[index]		
 134					+ EGL_Mul(grad.dx.m_TextureCoords[index].tu, xPreStep)		
 135					+ EGL_Mul(grad.dy.m_TextureCoords[index].tu, yPreStep);
 136
 137			start.m_TextureCoords[index].tv = 
 138				tvOverZ[index]		
 139					+ EGL_Mul(grad.dx.m_TextureCoords[index].tv, xPreStep)		
 140					+ EGL_Mul(grad.dy.m_TextureCoords[index].tv, yPreStep);
 141
 142#if EGL_MIPMAP_PER_TEXEL
 143
 144			// ------------------------------------------------------------------
 145			// Determine partial derivatives of texture functions, 
 146			// see eq. (2) and (3) in
 147			// J. P. Ewins et al (1998), 
 148			// "MIP-Map Level Selection for Texture Mapping",
 149			// IEEE Transactions on Visualization and Computer Graphics, 
 150			// Vol 4, No. 4
 151			// ------------------------------------------------------------------
 152
 153			start.m_TextureCoords[index].dtudx = 
 154				Det2x2(grad.dx.m_TextureCoords[index].tu, tuOverZ[index], grad.dx.m_WindowCoords.invZ, invZ) 
 155					+ EGL_Mul(grad.dy.m_TextureCoords[index].dtudx, yPreStep);
 156
 157			// Swap the following two assignments as reported by user
 158			start.m_TextureCoords[index].dtvdx = 
 159				Det2x2(grad.dx.m_TextureCoords[index].tv, tvOverZ[index], grad.dx.m_WindowCoords.invZ, invZ)
 160					+ EGL_Mul(grad.dx.m_TextureCoords[index].dtudy, xPreStep);
 161
 162			start.m_TextureCoords[index].dtudy = 
 163				Det2x2(grad.dy.m_TextureCoords[index].tu, tuOverZ[index], grad.dy.m_WindowCoords.invZ, invZ)
 164					+ EGL_Mul(grad.dy.m_TextureCoords[index].dtvdx, yPreStep);
 165
 166			start.m_TextureCoords[index].dtvdy = 
 167				Det2x2(grad.dy.m_TextureCoords[index].tv, tvOverZ[index], grad.dy.m_WindowCoords.invZ, invZ)
 168					+ EGL_Mul(grad.dx.m_TextureCoords[index].dtvdy, xPreStep);
 169#endif
 170		}
 171#endif
 172
 173#if HasFog
 174		start.m_FogDensity = 
 175			fog			+ EGL_Mul(grad.dx.m_FogDensity, xPreStep)			
 176						+ EGL_Mul(grad.dy.m_FogDensity, yPreStep);
 177#endif
 178	}
 179
 180
 181	inline void InitScanlineDeltas(const RasterInfo & rasterInfo, EdgePos & deltaSmall, EdgePos & deltaBig,
 182								   const Gradients & gradients, 
 183								   EGL_Fixed dxdy, I32 dXdYStepInt) {
 184
 185		deltaSmall.m_WindowCoords.x		= dxdy;	// x offset is stepped for each line (could consider removing fractional part from scanline function)
 186
 187#if HasDepth
 188		deltaSmall.m_WindowCoords.depth	= gradients.dx.m_WindowCoords.depth * dXdYStepInt	+ gradients.dy.m_WindowCoords.depth; 
 189#endif
 190
 191#if HasColor
 192		deltaSmall.m_Color.r			= gradients.dx.m_Color.r * dXdYStepInt		+ gradients.dy.m_Color.r;
 193		deltaSmall.m_Color.g			= gradients.dx.m_Color.g * dXdYStepInt		+ gradients.dy.m_Color.g;
 194		deltaSmall.m_Color.b			= gradients.dx.m_Color.b * dXdYStepInt		+ gradients.dy.m_Color.b;
 195		deltaSmall.m_Color.a			= gradients.dx.m_Color.a * dXdYStepInt		+ gradients.dy.m_Color.a;
 196#endif
 197
 198#if HasTexture		
 199		deltaSmall.m_WindowCoords.invZ	= gradients.dx.m_WindowCoords.invZ * dXdYStepInt	+ gradients.dy.m_WindowCoords.invZ; 
 200
 201		for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
 202			if (!rasterInfo.Textures[index])
 203				continue;
 204
 205			deltaSmall.m_TextureCoords[index].tu	= 
 206				gradients.dx.m_TextureCoords[index].tu * dXdYStepInt		
 207					+ gradients.dy.m_TextureCoords[index].tu;
 208			deltaSmall.m_TextureCoords[index].tv	= 
 209				gradients.dx.m_TextureCoords[index].tv * dXdYStepInt		
 210					+ gradients.dy.m_TextureCoords[index].tv;
 211
 212#if EGL_MIPMAP_PER_TEXEL
 213
 214			deltaSmall.m_TextureCoords[index].dtudx =													  
 215				gradients.dy.m_TextureCoords[index].dtudx;
 216			deltaSmall.m_TextureCoords[index].dtudy = 
 217				gradients.dx.m_TextureCoords[index].dtudy * dXdYStepInt;
 218			deltaSmall.m_TextureCoords[index].dtvdx =													  
 219				gradients.dy.m_TextureCoords[index].dtvdx;
 220			deltaSmall.m_TextureCoords[index].dtvdy = 
 221				gradients.dx.m_TextureCoords[index].dtvdy * dXdYStepInt;
 222#endif
 223		}
 224#endif
 225
 226#if HasFog
 227		deltaSmall.m_FogDensity			= gradients.dx.m_FogDensity * dXdYStepInt	+ gradients.dy.m_FogDensity;
 228#endif
 229
 230		deltaBig.m_WindowCoords.x		= dxdy;
 231
 232		if (dxdy >= 0) {
 233#if HasDepth
 234			deltaBig.m_WindowCoords.depth	= deltaSmall.m_WindowCoords.depth	+ gradients.dx.m_WindowCoords.depth; 
 235#endif
 236
 237#if HasColor
 238			deltaBig.m_Color.r				= deltaSmall.m_Color.r				+ gradients.dx.m_Color.r;
 239			deltaBig.m_Color.g				= deltaSmall.m_Color.g				+ gradients.dx.m_Color.g;
 240			deltaBig.m_Color.b				= deltaSmall.m_Color.b				+ gradients.dx.m_Color.b;
 241			deltaBig.m_Color.a				= deltaSmall.m_Color.a				+ gradients.dx.m_Color.a;
 242#endif
 243
 244#if HasTexture			
 245			deltaBig.m_WindowCoords.invZ	= deltaSmall.m_WindowCoords.invZ	+ gradients.dx.m_WindowCoords.invZ; 
 246
 247			for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
 248				if (!rasterInfo.Textures[index])
 249					continue;
 250
 251				deltaBig.m_TextureCoords[index].tu		= deltaSmall.m_TextureCoords[index].tu		+ gradients.dx.m_TextureCoords[index].tu;
 252				deltaBig.m_TextureCoords[index].tv		= deltaSmall.m_TextureCoords[index].tv		+ gradients.dx.m_TextureCoords[index].tv;
 253
 254#if EGL_MIPMAP_PER_TEXEL
 255				deltaBig.m_TextureCoords[index].dtudx	= deltaSmall.m_TextureCoords[index].dtudx;
 256				deltaBig.m_TextureCoords[index].dtudy	= deltaSmall.m_TextureCoords[index].dtudy	+ gradients.dx.m_TextureCoords[index].dtudy;
 257				deltaBig.m_TextureCoords[index].dtvdx	= deltaSmall.m_TextureCoords[index].dtvdx;
 258				deltaBig.m_TextureCoords[index].dtvdy	= deltaSmall.m_TextureCoords[index].dtvdy	+ gradients.dx.m_TextureCoords[index].dtvdy;
 259#endif
 260			}
 261#endif
 262
 263#if HasFog
 264			deltaBig.m_FogDensity			= deltaSmall.m_FogDensity			+ gradients.dx.m_FogDensity;
 265#endif
 266		} else {
 267#if HasDepth
 268			deltaBig.m_WindowCoords.depth	= deltaSmall.m_WindowCoords.depth	- gradients.dx.m_WindowCoords.depth; 
 269#endif
 270
 271#if HasColor
 272			deltaBig.m_Color.r				= deltaSmall.m_Color.r				- gradients.dx.m_Color.r;
 273			deltaBig.m_Color.g				= deltaSmall.m_Color.g				- gradients.dx.m_Color.g;
 274			deltaBig.m_Color.b				= deltaSmall.m_Color.b				- gradients.dx.m_Color.b;
 275			deltaBig.m_Color.a				= deltaSmall.m_Color.a				- gradients.dx.m_Color.a;
 276#endif
 277
 278#if HasTexture			
 279			deltaBig.m_WindowCoords.invZ	= deltaSmall.m_WindowCoords.invZ	- gradients.dx.m_WindowCoords.invZ; 
 280
 281			for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
 282				if (!rasterInfo.Textures[index])
 283					continue;
 284
 285				deltaBig.m_TextureCoords[index].tu		= deltaSmall.m_TextureCoords[index].tu		- gradients.dx.m_TextureCoords[index].tu;
 286				deltaBig.m_TextureCoords[index].tv		= deltaSmall.m_TextureCoords[index].tv		- gradients.dx.m_TextureCoords[index].tv;
 287
 288#if EGL_MIPMAP_PER_TEXEL
 289				deltaBig.m_TextureCoords[index].dtudx	= deltaSmall.m_TextureCoords[index].dtudx;
 290				deltaBig.m_TextureCoords[index].dtudy	= deltaSmall.m_TextureCoords[index].dtudy	- gradients.dx.m_TextureCoords[index].dtudy;
 291				deltaBig.m_TextureCoords[index].dtvdx	= deltaSmall.m_TextureCoords[index].dtvdx;
 292				deltaBig.m_TextureCoords[index].dtvdy	= deltaSmall.m_TextureCoords[index].dtvdy	+ gradients.dx.m_TextureCoords[index].dtvdy;
 293#endif
 294			}
 295#endif
 296
 297#if HasFog
 298			deltaBig.m_FogDensity			= deltaSmall.m_FogDensity			- gradients.dx.m_FogDensity;
 299#endif
 300		}
 301	}
 302
 303// --------------------------------------------------------------------------
 304// Scanline to scanline increment
 305// --------------------------------------------------------------------------
 306
 307#if HasFog
 308#define ScanlineDeltaFogBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
 309			start.m_FogDensity			+= deltaBig.m_FogDensity;				
 310
 311#define ScanlineDeltaFogSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
 312			start.m_FogDensity			+= deltaSmall.m_FogDensity;				\
 313
 314#else
 315#define ScanlineDeltaFogBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
 316#define ScanlineDeltaFogSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
 317#endif
 318
 319
 320#if HasDepth
 321#define ScanlineDeltaDepthBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
 322			start.m_WindowCoords.depth	+= deltaBig.m_WindowCoords.depth;		
 323
 324#define ScanlineDeltaDepthSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
 325			start.m_WindowCoords.depth	+= deltaSmall.m_WindowCoords.depth;		
 326
 327#define ScanlineDeltaDepth(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
 328		rasterInfo.DepthBuffer			+= rasterInfo.SurfaceWidth;				\
 329
 330#else
 331#define ScanlineDeltaDepthBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
 332#define ScanlineDeltaDepthSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
 333#define ScanlineDeltaDepth(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
 334#endif
 335
 336
 337#if HasTexture
 338#if EGL_MIPMAP_PER_TEXEL
 339#define ScanlineDeltaTextureBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
 340		start.m_WindowCoords.invZ	+= deltaBig.m_WindowCoords.invZ;			\
 341		for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {		\
 342			if (!m_RasterInfo.Textures[index]) continue;														\
 343			start.m_TextureCoords[index].tu	+= deltaBig.m_TextureCoords[index].tu;			\
 344			start.m_TextureCoords[index].tv	+= deltaBig.m_TextureCoords[index].tv;			\
 345			start.m_TextureCoords[index].dtudx	+= deltaBig.m_TextureCoords[index].dtudx;		\
 346			start.m_TextureCoords[index].dtudy	+= deltaBig.m_TextureCoords[index].dtudy;		\
 347			start.m_TextureCoords[index].dtvdx	+= deltaBig.m_TextureCoords[index].dtvdx;		\
 348			start.m_TextureCoords[index].dtvdy	+= deltaBig.m_TextureCoords[index].dtvdy;		\
 349		}
 350
 351#define ScanlineDeltaTextureSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
 352			start.m_WindowCoords.invZ	+= deltaSmall.m_WindowCoords.invZ;		\
 353		for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {		\
 354			if (!m_RasterInfo.Textures[index]) continue;						\
 355			start.m_TextureCoords[index].tu	+= deltaSmall.m_TextureCoords[index].tu;		\
 356			start.m_TextureCoords[index].tv	+= deltaSmall.m_TextureCoords[index].tv;		\
 357			start.m_TextureCoords[index].dtudx	+= deltaSmall.m_TextureCoords[index].dtudx;	\
 358			start.m_TextureCoords[index].dtudy	+= deltaSmall.m_TextureCoords[index].dtudy;	\
 359			start.m_TextureCoords[index].dtvdx	+= deltaSmall.m_TextureCoords[index].dtvdx;	\
 360			start.m_TextureCoords[index].dtvdy	+= deltaSmall.m_TextureCoords[index].dtvdy;	\
 361		}
 362#else
 363#define ScanlineDeltaTextureBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
 364		start.m_WindowCoords.invZ	+= deltaBig.m_WindowCoords.invZ;			\
 365		for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {		\
 366			if (!m_RasterInfo.Textures[index]) continue;														\
 367			start.m_TextureCoords[index].tu	+= deltaBig.m_TextureCoords[index].tu;			\
 368			start.m_TextureCoords[index].tv	+= deltaBig.m_TextureCoords[index].tv;			\
 369		}
 370
 371#define ScanlineDeltaTextureSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
 372			start.m_WindowCoords.invZ	+= deltaSmall.m_WindowCoords.invZ;		\
 373		for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {		\
 374			if (!m_RasterInfo.Textures[index]) continue;						\
 375			start.m_TextureCoords[index].tu	+= deltaSmall.m_TextureCoords[index].tu;		\
 376			start.m_TextureCoords[index].tv	+= deltaSmall.m_TextureCoords[index].tv;		\
 377		}
 378
 379#endif // EGL_MIPMAP_PER_TEXEL
 380
 381#else
 382#define ScanlineDeltaTextureBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
 383#define ScanlineDeltaTextureSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
 384#endif
 385
 386
 387#if HasColor
 388#define ScanlineDeltaColorBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
 389			start.m_Color				+= deltaBig.m_Color;					
 390
 391#define ScanlineDeltaColorSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
 392			start.m_Color				+= deltaSmall.m_Color;					
 393
 394#else
 395#define ScanlineDeltaColorBig(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
 396#define ScanlineDeltaColorSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
 397#endif
 398
 399
 400#if HasStencil
 401#define ScanlineDeltaStencil(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
 402		rasterInfo.StencilBuffer		+= rasterInfo.SurfaceWidth;				
 403
 404#else
 405#define ScanlineDeltaStencil(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)
 406#endif
 407
 408#define ScanlineDelta(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy) \
 409		xError += xStepError;													\
 410		if (xError >= EGL_ONE) {												\
 411			xError -= EGL_ONE;													\
 412			start.m_WindowCoords.x		+= deltaBig.m_WindowCoords.x;			\
 413			ScanlineDeltaColorBig	(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)	\
 414			ScanlineDeltaTextureBig	(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)	\
 415			ScanlineDeltaFogBig		(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)	\
 416			ScanlineDeltaDepthBig	(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)	\
 417		} else {																\
 418			start.m_WindowCoords.x		+= deltaSmall.m_WindowCoords.x;			\
 419			ScanlineDeltaColorSmall	(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)	\
 420			ScanlineDeltaTextureSmall(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)	\
 421			ScanlineDeltaFogSmall	(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)	\
 422			ScanlineDeltaDepthSmall	(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)	\
 423		}																		\
 424		delta.m_WindowCoords.x			+= dxdy;								\
 425		ScanlineDeltaDepth	(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)	\
 426		ScanlineDeltaStencil(rasterInfo, start, delta, deltaSmall, deltaBig, xError, xStepError, dxdy)	\
 427		rasterInfo.ColorBuffer			+= rasterInfo.SurfaceWidth;				\
 428		rasterInfo.AlphaBuffer			+= rasterInfo.SurfaceWidth;
 429}
 430
 431
 432// ---------------------------------------------------------------------------
 433// Ultimately, we have the following variantions on rastering a triangle:
 434//
 435//	- With or without color
 436//  - With or without texture
 437//  - With or without depth
 438//  - With or without fog
 439//  - With or without alpha buffer
 440//  - With or without stencil buffer
 441//  - With or without scissor test
 442//
 443// ---------------------------------------------------------------------------
 444
 445
 446// ---------------------------------------------------------------------------
 447// Render the triangle specified by the three transformed and lit vertices
 448// passed as arguments. 
 449//
 450// Parameters:
 451//		a, b, c		The three vertices of the triangle
 452//
 453// Returns:
 454//		N/A
 455// --------------------------------------------------------------------------
 456void Rasterizer :: RasterTriangle(const RasterPos& a, const RasterPos& b,
 457								  const RasterPos& c) {
 458	
 459	// ----------------------------------------------------------------------
 460	// sort vertices by y
 461	// ----------------------------------------------------------------------
 462
 463	const RasterPos * pos[3];
 464	pos[0] = &a;
 465	pos[1] = &b;
 466	pos[2] = &c;
 467
 468	const I8 * permutation = SortPermutation(a.m_WindowCoords.y, b.m_WindowCoords.y, c.m_WindowCoords.y);
 469	const RasterPos &pos1 = *pos[permutation[0]];
 470	const RasterPos &pos2 = *pos[permutation[1]];
 471	const RasterPos &pos3 = *pos[permutation[2]];
 472
 473	// ----------------------------------------------------------------------
 474	// Calculate the screen area of the triangle
 475	// ----------------------------------------------------------------------
 476
 477	EGL_Fixed denominator = 
 478		Det2x2(
 479			pos2.m_WindowCoords.x - pos1.m_WindowCoords.x, pos2.m_WindowCoords.y - pos1.m_WindowCoords.y,
 480			pos3.m_WindowCoords.x - pos1.m_WindowCoords.x, pos3.m_WindowCoords.y - pos1.m_WindowCoords.y);
 481
 482	// ----------------------------------------------------------------------
 483	// calculate all gradients for interpolation 
 484	// ----------------------------------------------------------------------
 485
 486	EGL_Fixed invDenominator = 0;
 487
 488	Gradients grad;
 489
 490	EGL_Fixed tuOverZ1[EGL_NUM_TEXTURE_UNITS], 
 491			  tuOverZ2[EGL_NUM_TEXTURE_UNITS], 
 492			  tuOverZ3[EGL_NUM_TEXTURE_UNITS], 
 493			  tvOverZ1[EGL_NUM_TEXTURE_UNITS], 
 494			  tvOverZ2[EGL_NUM_TEXTURE_UNITS], 
 495			  tvOverZ3[EGL_NUM_TEXTURE_UNITS];
 496
 497	if (!denominator) {
 498		memset(&grad, 0, sizeof grad);
 499	} else {
 500		invDenominator = EGL_Inverse(denominator);
 501
 502#if HasColor
 503		SOLVE_XY(m_Color.r, invDenominator);
 504		SOLVE_XY(m_Color.g, invDenominator);
 505		SOLVE_XY(m_Color.b, invDenominator);
 506		SOLVE_XY(m_Color.a, invDenominator);
 507#endif
 508
 509#if HasFog
 510		SOLVE_XY(m_FogDensity, invDenominator);
 511#endif
 512
 513#if HasDepth
 514		SOLVE_XY(m_WindowCoords.depth, invDenominator);
 515#endif
 516
 517
 518#if HasTexture
 519		SOLVE_XY(m_WindowCoords.invZ, invDenominator);
 520
 521		for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
 522
 523			if (!m_RasterInfo.Textures[index])
 524				continue;
 525
 526			tuOverZ1[index] = EGL_Mul(pos1.m_TextureCoords[index].tu, pos1.m_WindowCoords.invZ);
 527			tuOverZ2[index] = EGL_Mul(pos2.m_TextureCoords[index].tu, pos2.m_WindowCoords.invZ);
 528			tuOverZ3[index] = EGL_Mul(pos3.m_TextureCoords[index].tu, pos3.m_WindowCoords.invZ);
 529
 530			tvOverZ1[index] = EGL_Mul(pos1.m_TextureCoords[index].tv, pos1.m_WindowCoords.invZ);
 531			tvOverZ2[index] = EGL_Mul(pos2.m_TextureCoords[index].tv, pos2.m_WindowCoords.invZ);
 532			tvOverZ3[index] = EGL_Mul(pos3.m_TextureCoords[index].tv, pos3.m_WindowCoords.invZ);
 533
 534			SOLVE_PARAM_XY(m_TextureCoords[index].tu, tuOverZ1[index], tuOverZ2[index], tuOverZ3[index], invDenominator);
 535			SOLVE_PARAM_XY(m_TextureCoords[index].tv, tvOverZ1[index], tvOverZ2[index], tvOverZ3[index], invDenominator);
 536
 537#if EGL_MIPMAP_PER_TEXEL
 538
 539			// ------------------------------------------------------------------
 540			// Determine partial derivatives of texture functions, 
 541			// see eq. (2) and (3) in
 542			// J. P. Ewins et al (1998), 
 543			// "MIP-Map Level Selection for Texture Mapping",
 544			// IEEE Transactions on Visualization and Computer Graphics, 
 545			// Vol 4, No. 4
 546			// ------------------------------------------------------------------
 547
 548			EGL_Fixed A = grad.dx.m_TextureCoords[index].tu;
 549			EGL_Fixed B = grad.dy.m_TextureCoords[index].tu;
 550			EGL_Fixed D = grad.dx.m_WindowCoords.invZ;
 551			EGL_Fixed E = grad.dy.m_WindowCoords.invZ;
 552			EGL_Fixed F = pos1.m_WindowCoords.invZ;
 553			EGL_Fixed G = grad.dx.m_TextureCoords[index].tv;
 554			EGL_Fixed H = grad.dy.m_TextureCoords[index].tv;
 555
 556			EGL_Fixed K1 = Det2x2(A, B, D, E);
 557			EGL_Fixed K2 = Det2x2(G, H, D, E);
 558
 559			grad.dy.m_TextureCoords[index].dtudx = K1;
 560			grad.dy.m_TextureCoords[index].dtudy = 0;
 561			grad.dy.m_TextureCoords[index].dtvdx = K2;
 562			grad.dy.m_TextureCoords[index].dtvdy = 0;
 563
 564			grad.dx.m_TextureCoords[index].dtudx = 0;
 565			grad.dx.m_TextureCoords[index].dtudy = -K1;
 566			grad.dx.m_TextureCoords[index].dtvdx = 0;
 567			grad.dx.m_TextureCoords[index].dtvdy = -K2;
 568#endif
 569		}
 570#endif
 571	}
 572
 573	// ----------------------------------------------------------------------
 574	// Constants to determine partial derivatives, see eq. (2) and (3) in
 575	// J. P. Ewins et al (1998), "MIP-Map Level Selection for Texture Mapping",
 576	// IEEE Transactions on Visualization and Computer Graphics, Vol 4, No. 4
 577	// ----------------------------------------------------------------------
 578
 579	// Share the gradient in x direction for scanline function
 580
 581	EdgePos& delta = grad.dx;
 582
 583	// ----------------------------------------------------------------------
 584	// determine if the depth coordinate needs to be adjusted to
 585	// support polygon-offset
 586	// ----------------------------------------------------------------------
 587
 588//#if HasDepth
 589	EGL_Fixed depth1 = pos1.m_WindowCoords.depth;
 590	EGL_Fixed depth2 = pos2.m_WindowCoords.depth;
 591	EGL_Fixed depth3 = pos3.m_WindowCoords.depth;
 592//#endif
 593
 594#if HasDepth
 595
 596	if (m_State->m_Polygon.OffsetFillEnabled) {
 597
 598		EGL_Fixed factor = m_State->m_Polygon.OffsetFactor;
 599		EGL_Fixed units = m_State->m_Polygon.OffsetUnits;
 600
 601		// calculation here
 602
 603		EGL_Fixed gradX = EGL_Abs(grad.dx.m_WindowCoords.depth);
 604		EGL_Fixed gradY = EGL_Abs(grad.dy.m_WindowCoords.depth);
 605
 606		EGL_Fixed depthSlope = gradX > gradY ? gradX : gradY;
 607
 608		I32 offset = EGL_Mul(factor, depthSlope) + EGL_IntFromFixed(units * PolygonOffsetUnitSize);
 609
 610		if (offset > 0) {
 611			depth1 = depth1 < DepthRangeMax - offset ? depth1 + offset : DepthRangeMax;
 612			depth2 = depth2 < DepthRangeMax - offset ? depth2 + offset : DepthRangeMax;
 613			depth3 = depth3 < DepthRangeMax - offset ? depth3 + offset : DepthRangeMax;
 614		} else {
 615			depth1 = depth1 > -offset ? depth1 + offset : 0;
 616			depth2 = depth2 > -offset ? depth2 + offset : 0;
 617			depth3 = depth3 > -offset ? depth3 + offset : 0;
 618		}
 619	}
 620#endif
 621
 622	// ----------------------------------------------------------------------
 623	// determine the appropriate mipmapping level
 624	// ----------------------------------------------------------------------
 625
 626//#if HasTexture
 627	EGL_Fixed invZ1 = pos1.m_WindowCoords.invZ;
 628	EGL_Fixed invZ2 = pos2.m_WindowCoords.invZ;
 629	EGL_Fixed invZ3 = pos3.m_WindowCoords.invZ;
 630//#endif
 631
 632#if !EGL_MIPMAP_PER_TEXEL && HasTexture
 633
 634	for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
 635
 636		if (!m_RasterInfo.Textures[index])
 637			continue;
 638	
 639		if (m_UseMipmap[index]) {
 640
 641			int logWidth = Log2(m_Texture[index]->GetTexture(0)->GetWidth());
 642			int logHeight = Log2(m_Texture[index]->GetTexture(0)->GetHeight());
 643			int maxLevel = m_RasterInfo.MaxMipmapLevel[index];
 644
 645			if (invDenominator) {
 646
 647				EGL_Fixed textureArea = 
 648					Det2x2(
 649						(pos2.m_TextureCoords[index].tu - pos1.m_TextureCoords[index].tu) << logWidth, 
 650						(pos2.m_TextureCoords[index].tv - pos1.m_TextureCoords[index].tv) << logHeight,
 651						(pos3.m_TextureCoords[index].tu - pos1.m_TextureCoords[index].tu) << logWidth,
 652						(pos3.m_TextureCoords[index].tv - pos1.m_TextureCoords[index].tv) << logHeight);
 653				
 654				EGL_Fixed ratio = EGL_Mul(textureArea, invDenominator) >> EGL_PRECISION;
 655				
 656				int logRatio = Log2(ratio);
 657
 658				if (logRatio <= 0) {
 659					m_RasterInfo.MipmapLevel[index] = 0;
 660				} else {
 661					m_RasterInfo.MipmapLevel[index] = logRatio / 2;
 662
 663					if (m_RasterInfo.MipmapLevel[index] > maxLevel) {
 664						m_RasterInfo.MipmapLevel[index] = maxLevel;
 665					}
 666				}
 667			} else {
 668				m_RasterInfo.MipmapLevel[index] = maxLevel;
 669			}
 670		} else {
 671			m_RasterInfo.MipmapLevel[index] = 0;
 672		}
 673	}
 674
 675#endif	
 676
 677	// ----------------------------------------------------------------------
 678	//
 679	// - Raster top part of triangle
 680	//		determine integer (i.e. each line) and fractional increments per edgebuffer
 681	//		determine y-pre step and x-pre step for first pixel of first scanline
 682	//		determine error for x-stepping.
 683	//
 684	// - Raster bottom part of triangle
 685	// ----------------------------------------------------------------------
 686
 687	EGL_Fixed yRounded1 = EGL_NearestInt(pos1.m_WindowCoords.y);
 688	EGL_Fixed yPreStep1 = yRounded1 + (EGL_ONE/2) - pos1.m_WindowCoords.y;
 689	I32 y = EGL_IntFromFixed(yRounded1);
 690
 691	EGL_Fixed yRounded2 = EGL_NearestInt(pos2.m_WindowCoords.y);
 692	EGL_Fixed yPreStep2 = yRounded2 + (EGL_ONE/2) - pos2.m_WindowCoords.y;
 693	I32 y2 = EGL_IntFromFixed(yRounded2);
 694
 695	EGL_Fixed yRounded3 = EGL_NearestInt(pos3.m_WindowCoords.y);
 696	I32 y3 = EGL_IntFromFixed(yRounded3);
 697
 698	m_RasterInfo.Init(m_Surface, y);
 699
 700	I32 yScissorStart = m_State->m_ScissorTest.Y;
 701	I32 yScissorEnd = yScissorStart + m_State->m_ScissorTest.Height;
 702
 703	// ----------------------------------------------------------------------
 704	// Determine edge increments and scanline starting point
 705	// ----------------------------------------------------------------------
 706
 707	EGL_Fixed deltaY2	= pos2.m_WindowCoords.y - pos1.m_WindowCoords.y;
 708	EGL_Fixed deltaY3	= pos3.m_WindowCoords.y - pos1.m_WindowCoords.y;
 709	EGL_Fixed deltaY23	= pos3.m_WindowCoords.y - pos2.m_WindowCoords.y;
 710
 711	if (y >= y3) {
 712		// Always, the triangle is empty
 713		return;
 714	}
 715
 716	if (y == y2) {
 717		// do special case here
 718
 719		EGL_Fixed invDeltaY3 = EGL_Inverse(deltaY3);	// deltaY3 == 0 should not occur, triangle would already have been skipped
 720		EGL_Fixed invDeltaY23 = EGL_Inverse(deltaY23);
 721
 722		EGL_Fixed deltaX3	= pos3.m_WindowCoords.x - pos1.m_WindowCoords.x;
 723		EGL_Fixed deltaX23	= pos3.m_WindowCoords.x - pos2.m_WindowCoords.x;
 724
 725		EGL_Fixed dXdY3		= EGL_Mul(deltaX3, invDeltaY3);
 726		EGL_Fixed dXdY23	= EGL_Mul(deltaX23, invDeltaY23);
 727
 728		if (dXdY23 < dXdY3) {
 729			// move beginning of scanline along p1->p3
 730
 731			// ------------------------------------------------------------------
 732			// initialize start onto first pixel right off line p1->p3
 733			// ------------------------------------------------------------------
 734
 735			EGL_Fixed xStepped1L = pos1.m_WindowCoords.x + EGL_Mul(yPreStep1, dXdY3);
 736			EGL_Fixed xRounded1 = EGL_NearestInt(xStepped1L);
 737			EGL_Fixed xPreStep1 = xRounded1 + (EGL_ONE/2) - pos1.m_WindowCoords.x;
 738
 739			EdgePos start;
 740			start.m_WindowCoords.x = 
 741				xStepped1L + ((EGL_ONE/2) - 1);	// added offset so round down will be round to nearest
 742
 743			InitScanlineStart(m_RasterInfo, start, grad, xPreStep1, yPreStep1,
 744							  pos1.m_Color, pos1.m_FogDensity, depth1, invZ1, tuOverZ1, tvOverZ1);
 745
 746			// ------------------------------------------------------------------
 747			// initialize edge buffer delta2Int & delta2Frac
 748			// ------------------------------------------------------------------
 749
 750			// determine integer x step/y
 751			I32 dXdYStep1Int = dXdY3 >= 0 ? EGL_IntFromFixed(dXdY3) : -EGL_IntFromFixed(-dXdY3);
 752
 753			EdgePos delta3Small, delta3Big;
 754			InitScanlineDeltas(m_RasterInfo, delta3Small, delta3Big, grad, dXdY3, dXdYStep1Int);
 755
 756			// ------------------------------------------------------------------
 757			// Stepping for right edge
 758			// ------------------------------------------------------------------
 759
 760			EGL_Fixed xStepped1R = pos2.m_WindowCoords.x + EGL_Mul(pos1.m_WindowCoords.y - pos2.m_WindowCoords.y + yPreStep1, dXdY23);
 761
 762			delta.m_WindowCoords.x = 
 763				xStepped1R + ((EGL_ONE/2) - 1);	// added offset so round down will be round to nearest
 764
 765			// ------------------------------------------------------------------
 766			// initialize the x-step error
 767			// ------------------------------------------------------------------
 768
 769			EGL_Fixed xStepError, xError;
 770
 771			if (dXdY3 >= 0) {
 772				xStepError = dXdY3 - EGL_FixedFromInt(dXdYStep1Int);
 773				assert(xStepError >= 0 && xStepError < EGL_ONE);
 774				xError = EGL_FractionFromFixed(xStepped1L + EGL_ONE/2);
 775			} else {
 776				xStepError = -dXdY3 + EGL_FixedFromInt(dXdYStep1Int);
 777				assert(xStepError >= 0 && xStepError < EGL_ONE);
 778				xError = (EGL_ONE-1) - EGL_FractionFromFixed(xStepped1L + EGL_ONE/2);
 779			}
 780
 781			// ------------------------------------------------------------------
 782			// Raster the top part of the triangle
 783			// ------------------------------------------------------------------
 784
 785			for (; y < y3; ++y) {
 786
 787#if HasScissor
 788				if (!m_State->m_ScissorTest.Enabled || (y >= yScissorStart && y < yScissorEnd))
 789#endif
 790					RasterScanLine(m_RasterInfo, start, delta);												
 791
 792				ScanlineDelta(m_RasterInfo, start, delta, delta3Small, delta3Big,
 793							  xError, xStepError, dXdY23);
 794			}
 795
 796		} else {
 797			// move beginning of scanline along p2->p3
 798
 799			// ------------------------------------------------------------------
 800			// now do second part of triangle
 801			//
 802			// ------------------------------------------------------------------
 803			//
 804			// initialize start onto first pixel right off line p2->p3
 805			// ------------------------------------------------------------------
 806
 807			EGL_Fixed xStepped2L = pos2.m_WindowCoords.x + EGL_Mul(yPreStep2, dXdY23);
 808			EGL_Fixed xRounded2 = EGL_NearestInt(xStepped2L);
 809			EGL_Fixed xPreStep2 = xRounded2 + (EGL_ONE/2) - pos2.m_WindowCoords.x;
 810
 811			EdgePos start;
 812			start.m_WindowCoords.x = 
 813				xStepped2L + ((EGL_ONE/2) - 1);	// added offset so round down will be round to nearest
 814
 815			InitScanlineStart(m_RasterInfo, start, grad, xPreStep2, yPreStep1,
 816							  pos2.m_Color, pos2.m_FogDensity, depth2, invZ2, tuOverZ2, tvOverZ2);
 817
 818			// ------------------------------------------------------------------
 819			// initialize edge buffer delta2Int & delta2Frac
 820			// ------------------------------------------------------------------
 821
 822			// determine integer x step/y
 823			I32 dXdYStep2Int = dXdY23 >= 0 ? EGL_IntFromFixed(dXdY23) : -EGL_IntFromFixed(-dXdY23);
 824
 825			EdgePos delta23Small, delta23Big;
 826			InitScanlineDeltas(m_RasterInfo, delta23Small, delta23Big, grad, dXdY23, dXdYStep2Int);
 827
 828			// ------------------------------------------------------------------
 829			// initialize the x coordinate for right edge
 830			// ------------------------------------------------------------------
 831
 832			EGL_Fixed xStepped1R = pos1.m_WindowCoords.x + EGL_Mul(pos2.m_WindowCoords.y - pos1.m_WindowCoords.y + yPreStep2, dXdY3);
 833			delta.m_WindowCoords.x = 
 834				xStepped1R + ((EGL_ONE/2) - 1);	// added offset so round down will be round to nearest
 835
 836			// ------------------------------------------------------------------
 837			// initialize the x-step error
 838			// ------------------------------------------------------------------
 839
 840			EGL_Fixed xStepError, xError;
 841
 842			if (dXdY23 >= 0) {
 843				xStepError = dXdY23 - EGL_FixedFromInt(dXdYStep2Int);
 844				assert(xStepError >= 0 && xStepError < EGL_ONE);
 845				xError = EGL_FractionFromFixed(xStepped2L + EGL_ONE/2);
 846			} else {
 847				xStepError = -dXdY23 + EGL_FixedFromInt(dXdYStep2Int);
 848				assert(xStepError >= 0 && xStepError < EGL_ONE);
 849				xError = (EGL_ONE-1) - EGL_FractionFromFixed(xStepped2L + EGL_ONE/2);
 850			}
 851
 852			// ------------------------------------------------------------------
 853			// Raster the triangle
 854			// ------------------------------------------------------------------
 855
 856			for (; y < y3; ++y) {
 857#if HasScissor
 858				if (!m_State->m_ScissorTest.Enabled || (y >= yScissorStart && y < yScissorEnd))
 859#endif
 860					RasterScanLine(m_RasterInfo, start, delta);												
 861
 862				ScanlineDelta(m_RasterInfo, start, delta, delta23Small, delta23Big,
 863							  xError, xStepError, dXdY3);
 864			}
 865
 866		}
 867
 868		return;
 869	}
 870
 871	EGL_Fixed invDeltaY2 = EGL_Inverse(deltaY2);	
 872	EGL_Fixed invDeltaY3 = EGL_Inverse(deltaY3);	// deltaY3 == 0 should not occur, triangle would already have been skipped
 873
 874	EGL_Fixed deltaX2	= pos2.m_WindowCoords.x - pos1.m_WindowCoords.x;
 875	EGL_Fixed deltaX3	= pos3.m_WindowCoords.x - pos1.m_WindowCoords.x;
 876
 877	EGL_Fixed dXdY2		= EGL_Mul(deltaX2, invDeltaY2);
 878	EGL_Fixed dXdY3		= EGL_Mul(deltaX3, invDeltaY3);
 879
 880	if (dXdY2 < dXdY3) {
 881
 882		// ------------------------------------------------------------------
 883		// initialize start onto first pixel right off line p1->p2
 884		// ------------------------------------------------------------------
 885
 886		EGL_Fixed xStepped1L = pos1.m_WindowCoords.x + EGL_Mul(yPreStep1, dXdY2);
 887		EGL_Fixed xStepped1R = pos1.m_WindowCoords.x + EGL_Mul(yPreStep1, dXdY3);
 888		EGL_Fixed xRounded1 = EGL_NearestInt(xStepped1L);
 889		EGL_Fixed xPreStep1 = xRounded1 + (EGL_ONE/2) - pos1.m_WindowCoords.x;
 890
 891		EdgePos start;
 892		start.m_WindowCoords.x = 
 893			xStepped1L + ((EGL_ONE/2) - 1);	// added offset so round down will be round to nearest
 894
 895		InitScanlineStart(m_RasterInfo, start, grad, xPreStep1, yPreStep1,
 896						  pos1.m_Color, pos1.m_FogDensity, depth1, invZ1, tuOverZ1, tvOverZ1);
 897
 898		// ------------------------------------------------------------------
 899		// initialize edge buffer delta2Int & delta2Frac
 900		// ------------------------------------------------------------------
 901
 902		// determine integer x step/y
 903		I32 dXdYStep1Int = dXdY2 >= 0 ? EGL_IntFromFixed(dXdY2) : -EGL_IntFromFixed(-dXdY2);
 904
 905		EdgePos delta2Small, delta2Big;
 906		InitScanlineDeltas(m_RasterInfo, delta2Small, delta2Big, grad, dXdY2, dXdYStep1Int);
 907
 908		// ------------------------------------------------------------------
 909		// initialize the x coordinate for right edge
 910		// ------------------------------------------------------------------
 911
 912		delta.m_WindowCoords.x = 
 913			xStepped1R + ((EGL_ONE/2) - 1);	// added offset so round down will be round to nearest
 914
 915
 916		// ------------------------------------------------------------------
 917		// initialize the x-step error
 918		// ------------------------------------------------------------------
 919
 920		EGL_Fixed xStepError, xError;
 921
 922		if (dXdY2 >= 0) {
 923			xStepError = dXdY2 - EGL_FixedFromInt(dXdYStep1Int);
 924			assert(xStepError >= 0 && xStepError < EGL_ONE);
 925			xError = EGL_FractionFromFixed(xStepped1L + EGL_ONE/2);
 926			assert(xError >= 0 && xError < EGL_ONE);
 927		} else {
 928			xStepError = -dXdY2 + EGL_FixedFromInt(dXdYStep1Int);
 929			assert(xStepError >= 0 && xStepError < EGL_ONE);
 930			xError = (EGL_ONE-1) - EGL_FractionFromFixed(xStepped1L + EGL_ONE/2);
 931			assert(xError >= 0 && xError < EGL_ONE);
 932		}
 933
 934		// ------------------------------------------------------------------
 935		// Raster the top part of the triangle
 936		// ------------------------------------------------------------------
 937
 938		for (; y < y2; ++y) {
 939#if HasScissor
 940			if (!m_State->m_ScissorTest.Enabled || (y >= yScissorStart && y < yScissorEnd))
 941#endif
 942				RasterScanLine(m_RasterInfo, start, delta);												
 943
 944			ScanlineDelta(m_RasterInfo, start, delta, delta2Small, delta2Big,
 945						  xError, xStepError, dXdY3);
 946		}
 947
 948		if (y >= y3)
 949			return;
 950
 951		EGL_Fixed invDeltaY23 = EGL_Inverse(deltaY23);
 952		EGL_Fixed deltaX23	= pos3.m_WindowCoords.x - pos2.m_WindowCoords.x;
 953		EGL_Fixed dXdY23	= EGL_Mul(deltaX23, invDeltaY23);
 954
 955		// ------------------------------------------------------------------
 956		// now do second part of triangle
 957		//
 958		// ------------------------------------------------------------------
 959		//
 960		// initialize start onto first pixel right off line p2->p3
 961		// ------------------------------------------------------------------
 962
 963		EGL_Fixed xStepped2L = pos2.m_WindowCoords.x + EGL_Mul(yPreStep2, dXdY23);
 964		EGL_Fixed xRounded2 = EGL_NearestInt(xStepped2L);
 965		EGL_Fixed xPreStep2 = xRounded2 + (EGL_ONE/2) - pos2.m_WindowCoords.x;
 966
 967		start.m_WindowCoords.x = 
 968			xStepped2L + ((EGL_ONE/2) - 1);	// added offset so round down will be round to nearest
 969
 970		InitScanlineStart(m_RasterInfo, start, grad, xPreStep2, yPreStep2,
 971						  pos2.m_Color, pos2.m_FogDensity, depth2, invZ2, tuOverZ2, tvOverZ2);
 972
 973		// ------------------------------------------------------------------
 974		// initialize edge buffer delta2Int & delta2Frac
 975		// ------------------------------------------------------------------
 976
 977		// determine integer x step/y
 978		I32 dXdYStep2Int = dXdY23 >= 0 ? EGL_IntFromFixed(dXdY23) : -EGL_IntFromFixed(-dXdY23);
 979
 980		EdgePos delta23Small, delta23Big;
 981		InitScanlineDeltas(m_RasterInfo, delta23Small, delta23Big, grad, dXdY23, dXdYStep2Int);
 982
 983		// ------------------------------------------------------------------
 984		// initialize the x-step error
 985		// ------------------------------------------------------------------
 986
 987		if (dXdY23 >= 0) {
 988			xStepError = dXdY23 - EGL_FixedFromInt(dXdYStep2Int);
 989			assert(xStepError >= 0 && xStepError < EGL_ONE);
 990			xError = EGL_FractionFromFixed(xStepped2L + EGL_ONE/2);
 991		} else {
 992			xStepError = -dXdY23 + EGL_FixedFromInt(dXdYStep2Int);
 993			assert(xStepError >= 0 && xStepError < EGL_ONE);
 994			xError = (EGL_ONE-1) - EGL_FractionFromFixed(xStepped2L + EGL_ONE/2);
 995		}
 996
 997
 998		// ------------------------------------------------------------------
 999		// Raster the bottom part of the triangle
1000		// ------------------------------------------------------------------
1001
1002		for (; y < y3; ++y) {
1003#if HasScissor
1004			if (!m_State->m_ScissorTest.Enabled || (y >= yScissorStart && y < yScissorEnd))
1005#endif
1006				RasterScanLine(m_RasterInfo, start, delta);												
1007
1008			ScanlineDelta(m_RasterInfo, start, delta, delta23Small, delta23Big,
1009						  xError, xStepError, dXdY3);
1010		}
1011
1012	} else /* dXdY2 >= dXdY3) */ {
1013
1014		// ------------------------------------------------------------------
1015		// initialize start onto first pixel right off line p1->p3
1016		// ------------------------------------------------------------------
1017
1018		EGL_Fixed xStepped1L = pos1.m_WindowCoords.x + EGL_Mul(yPreStep1, dXdY3);
1019		EGL_Fixed xRounded1 = EGL_NearestInt(xStepped1L);
1020		EGL_Fixed xPreStep1 = xRounded1 + (EGL_ONE/2) - pos1.m_WindowCoords.x;
1021
1022		EdgePos start;
1023
1024		start.m_WindowCoords.x		= xStepped1L + ((EGL_ONE/2) - 1);	// added offset so round down will be round to nearest
1025
1026		InitScanlineStart(m_RasterInfo, start, grad, xPreStep1, yPreStep1,
1027						  pos1.m_Color, pos1.m_FogDensity, depth1, invZ1, tuOverZ1, tvOverZ1);
1028
1029		// ------------------------------------------------------------------
1030		// initialize edge buffer delta2Int & delta2Frac
1031		// ------------------------------------------------------------------
1032
1033		// determine integer x step/y
1034		I32 dXdYStep1Int = dXdY3 >= 0 ? EGL_IntFromFixed(dXdY3) : -EGL_IntFromFixed(-dXdY3);
1035
1036		EdgePos delta3Small, delta3Big;
1037		InitScanlineDeltas(m_RasterInfo, delta3Small, delta3Big, grad, dXdY3, dXdYStep1Int);
1038
1039		// ------------------------------------------------------------------
1040		// initialize the x coordinate for right edge
1041		// ------------------------------------------------------------------
1042
1043		EGL_Fixed xStepped1R = pos1.m_WindowCoords.x + EGL_Mul(yPreStep1, dXdY2);
1044		delta.m_WindowCoords.x = 
1045			xStepped1R + ((EGL_ONE/2) - 1);	// added offset so round down will be round to nearest
1046
1047		// ------------------------------------------------------------------
1048		// initialize the x-step error
1049		// ------------------------------------------------------------------
1050
1051		EGL_Fixed xStepError, xError;
1052
1053		if (dXdY3 >= 0) {
1054			xStepError = dXdY3 - EGL_FixedFromInt(dXdYStep1Int);
1055			assert(xStepError >= 0 && xStepError < EGL_ONE);
1056			xError = EGL_FractionFromFixed(xStepped1L + EGL_ONE/2);
1057		} else {
1058			xStepError = -dXdY3 + EGL_FixedFromInt(dXdYStep1Int);
1059			assert(xStepError >= 0 && xStepError < EGL_ONE);
1060			xError = (EGL_ONE-1) - EGL_FractionFromFixed(xStepped1L + EGL_ONE/2);
1061		}
1062
1063		// ------------------------------------------------------------------
1064		// Raster the top part of the triangle
1065		// ------------------------------------------------------------------
1066
1067		for (; y < y2; ++y) {
1068#if HasScissor
1069			if (!m_State->m_ScissorTest.Enabled || (y >= yScissorStart && y < yScissorEnd))
1070#endif
1071				RasterScanLine(m_RasterInfo, start, delta);												
1072
1073			ScanlineDelta(m_RasterInfo, start, delta, delta3Small, delta3Big,
1074						  xError, xStepError, dXdY2);
1075		}
1076
1077		if (y >= y3)
1078			return;
1079
1080		EGL_Fixed invDeltaY23 = EGL_Inverse(deltaY23);
1081		EGL_Fixed deltaX23	= pos3.m_WindowCoords.x - pos2.m_WindowCoords.x;
1082		EGL_Fixed dXdY23	= EGL_Mul(deltaX23, invDeltaY23);
1083
1084		// ------------------------------------------------------------------
1085		// now do second part of triangle
1086		//
1087		// ------------------------------------------------------------------
1088		//
1089		// initialize end behind first pixel right off line p2->p3
1090		// ------------------------------------------------------------------
1091
1092		EGL_Fixed xStepped2R = pos2.m_WindowCoords.x + EGL_Mul(yPreStep2, dXdY23);
1093
1094		delta.m_WindowCoords.x = 
1095			xStepped2R + ((EGL_ONE/2) - 1);	// added offset so round down will be round to nearest
1096
1097		for (; y < y3; ++y) {
1098#if HasScissor
1099			if (!m_State->m_ScissorTest.Enabled || (y >= yScissorStart && y < yScissorEnd))
1100#endif
1101				RasterScanLine(m_RasterInfo, start, delta);												
1102
1103			ScanlineDelta(m_RasterInfo, start, delta, delta3Small, delta3Big,
1104						  xError, xStepError, dXdY23);
1105		}
1106	}
1107}
1108
1109
1110#undef ScanlineDelta
1111#undef ScanlineDeltaFogBig
1112#undef ScanlineDeltaFogSmall
1113#undef ScanlineDeltaDepthBig
1114#undef ScanlineDeltaDepthSmall
1115#undef ScanlineDeltaColorBig
1116#undef ScanlineDeltaColorSmall
1117#undef ScanlineDeltaTextureBig
1118#undef ScanlineDeltaTextureSmall
1119#undef ScanlineDeltaStencil
1120#undef ScanlineDeltaDepth
1121
1122
1123#undef InitScanlineStart
1124#undef InitScanlineDeltas
1125#undef RasterTriangle
1126
1127#undef HasFog
1128#undef HasDepth
1129#undef HasColor
1130#undef HasTexture
1131#undef HasStencil
1132#undef HasScissor