PageRenderTime 1164ms CodeModel.GetById 101ms app.highlight 827ms RepoModel.GetById 119ms app.codeStats 1ms

/opengles/src/Rasterizer.cpp

http://ftk.googlecode.com/
C++ | 1616 lines | 1189 code | 340 blank | 87 comment | 145 complexity | 8a504c41d557be294f9b30db1e35cb9c MD5 | raw file
   1// ==========================================================================
   2//
   3// Rasterizer.cpp	Rasterizer Class for 3D Rendering Library
   4//
   5//					The rasterizer converts transformed and lit
   6//					primitives and creates a raster image in the
   7//					current rendering surface.
   8//
   9// --------------------------------------------------------------------------
  10//
  11// 10-06-2003		Hans-Martin Will	initial version
  12//
  13// --------------------------------------------------------------------------
  14//
  15// Copyright (c) 2004, Hans-Martin Will. All rights reserved.
  16//
  17// Redistribution and use in source and binary forms, with or without
  18// modification, are permitted provided that the following conditions are
  19// met:
  20//
  21//	 *  Redistributions of source code must retain the above copyright
  22// 		notice, this list of conditions and the following disclaimer.
  23//   *	Redistributions in binary form must reproduce the above copyright
  24// 		notice, this list of conditions and the following disclaimer in the
  25// 		documentation and/or other materials provided with the distribution.
  26//
  27// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  28// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  31// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  32// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  33// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  35// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  36// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  37// THE POSSIBILITY OF SUCH DAMAGE.
  38//
  39// ==========================================================================
  40
  41
  42#include "stdafx.h"
  43#include "Rasterizer.h"
  44#include "Surface.h"
  45#include "Texture.h"
  46#include "arm/FunctionCache.h"
  47
  48using namespace EGL;
  49
  50
  51// --------------------------------------------------------------------------
  52// Local helper functions
  53// --------------------------------------------------------------------------
  54
  55namespace {
  56
  57	inline U8 MulU8(U8 a, U8 b) {
  58		U16 prod = a * b;
  59		return (((prod + (prod >> 6)) >> 7) + 1) >> 1;
  60	}
  61
  62	inline U8 ClampU8(U16 value) {
  63		return (value > 0xff) ? (U8) 0xff : (U8) value;
  64	}
  65
  66	inline U8 AddU8(U8 arg0, U8 arg1) {
  67		return ClampU8(arg0 + arg1);
  68	}
  69
  70	inline U8 SubU8(U8 arg0, U8 arg1) {
  71		return arg0 > arg1 ? arg0 - arg1 : 0;
  72	}
  73
  74	inline U8 AddSignedU8(U8 arg0, U8 arg1) {
  75		U16 value = (U16) arg0 + arg1;
  76
  77		if (value >= 0x80)
  78			return ClampU8(value - 0x80);
  79		else
  80			return 0;
  81	}
  82
  83	inline U8 InterpolateU8(U8 arg0, U8 arg1, U8 arg2) {
  84		return MulU8(arg0, arg2) + MulU8(arg1, 0xff - arg2);
  85	}
  86
  87	// bring 0 .. 255 -> -128 .. 128
  88	inline I16 SignedVal(U8 in) {
  89		if (in <= 0x80)
  90			return (I16) in - 0x80;
  91		else {
  92			I16 inter = (I16) in - 0x80;
  93			return inter + (inter >> 6);
  94		}
  95	}
  96
  97	inline U8 Dot3U8(const Color& arg0, const Color& arg1) {
  98		
  99		// each product is in the range of -2^14 .. +2^14
 100		I32 prodR = SignedVal(arg0.r) * SignedVal(arg1.r);
 101		I32 prodG = SignedVal(arg0.g) * SignedVal(arg1.g);
 102		I32 prodB = SignedVal(arg0.b) * SignedVal(arg1.b);
 103
 104		I32 sum = (prodR + prodG + prodB) * 4;
 105
 106		if (sum <= 0)
 107			return 0;
 108		else if (sum >= 0x10000) 
 109			return 0xff;
 110		else
 111			return (sum >> 8) - (sum >> 15);
 112	}
 113
 114	inline U8 MulU8(U8 a, U8 b, EGL_Fixed scale) {
 115		U16 prod = a * b;
 116		return ClampU8((U16) EGL_Mul((prod + (prod >> 7)) >> 8, scale));
 117	}
 118
 119	inline U8 AddU8(U8 arg0, U8 arg1, EGL_Fixed scale) {
 120		return ClampU8((U16) EGL_Mul((U16) arg0 + (U16) arg1, scale));
 121	}
 122
 123	inline U8 SubU8(U8 arg0, U8 arg1, EGL_Fixed scale) {
 124		return arg0 > arg1 ? ClampU8((U16) EGL_Mul(arg0 - arg1, scale)) : 0;
 125	}
 126
 127	inline U8 AddSignedU8(U8 arg0, U8 arg1, EGL_Fixed scale) {
 128		U16 value = (U16) arg0 + arg1;
 129
 130		if (value >= 0x80)
 131			return ClampU8((U16) EGL_Mul(value - 0x80, scale));
 132		else
 133			return 0;
 134	}
 135
 136	inline U8 InterpolateU8(U8 arg0, U8 arg1, U8 arg2, EGL_Fixed scale) {
 137		return ClampU8((U16) MulU8(arg0, arg2, scale) + MulU8(arg1, 0xff - arg2, scale));
 138	}
 139
 140	inline U8 Dot3U8(const Color& arg0, const Color& arg1, EGL_Fixed scale) {
 141		// each product is in the range of -2^14 .. +2^14
 142		I32 prodR = SignedVal(arg0.r) * SignedVal(arg1.r);
 143		I32 prodG = SignedVal(arg0.g) * SignedVal(arg1.g);
 144		I32 prodB = SignedVal(arg0.b) * SignedVal(arg1.b);
 145
 146		I32 sum = (prodR + prodG + prodB) * 4;
 147		I32 scaledSum = ((sum >> 7) - (sum >> 14) + 1) >> 1;
 148
 149		if (sum <= 0xff)
 150			return 0;
 151		else
 152			return ClampU8(EGL_Mul(scaledSum, scale));
 153	}
 154
 155    const I32 InversionTable[32] = {
 156	    0,
 157	    EGL_FixedFromFloat(1.0f / 1.0f),
 158	    EGL_FixedFromFloat(1.0f / 2.0f),
 159	    EGL_FixedFromFloat(1.0f / 3.0f),
 160	    EGL_FixedFromFloat(1.0f / 4.0f),
 161	    EGL_FixedFromFloat(1.0f / 5.0f),
 162	    EGL_FixedFromFloat(1.0f / 6.0f),
 163	    EGL_FixedFromFloat(1.0f / 7.0f),
 164	    EGL_FixedFromFloat(1.0f / 8.0f),
 165	    EGL_FixedFromFloat(1.0f / 9.0f),
 166	    EGL_FixedFromFloat(1.0f / 10.0f),
 167	    EGL_FixedFromFloat(1.0f / 11.0f),
 168	    EGL_FixedFromFloat(1.0f / 12.0f),
 169	    EGL_FixedFromFloat(1.0f / 13.0f),
 170	    EGL_FixedFromFloat(1.0f / 14.0f),
 171	    EGL_FixedFromFloat(1.0f / 15.0f),
 172    };
 173}
 174
 175void RasterInfo::Init(Surface * surface, I32 y) {
 176	size_t offset = y * surface->GetWidth();
 177	
 178	SurfaceWidth = surface->GetWidth();
 179	SurfaceHeight = surface->GetHeight();
 180	DepthBuffer = surface->GetDepthBuffer() + offset;
 181	ColorBuffer = surface->GetColorBuffer() + offset;
 182	StencilBuffer = surface->GetStencilBuffer() + offset;
 183	AlphaBuffer = surface->GetAlphaBuffer() + offset;
 184	InversionTablePtr = InversionTable;
 185}
 186
 187// --------------------------------------------------------------------------
 188// Class Rasterizer
 189// --------------------------------------------------------------------------
 190
 191
 192Rasterizer :: Rasterizer(RasterizerState * state):
 193	m_State(state)
 194{
 195	m_FunctionCache = new FunctionCache();
 196
 197	memset(m_RasterTriangleFunctions, 0, sizeof m_RasterTriangleFunctions);
 198
 199    m_RasterTriangleFunctions[(1 << RasterTriangleTexture)	] = &Rasterizer::RasterTriangle_cTdfs;
 200	m_RasterTriangleFunctions[(1 << RasterTriangleTexture)  |
 201							  (1 << RasterTriangleFog)		] = &Rasterizer::RasterTriangle_cTdFs;
 202	m_RasterTriangleFunctions[(1 << RasterTriangleTexture)  |
 203							  (1 << RasterTriangleDepth)	] = &Rasterizer::RasterTriangle_cTDfs;
 204	m_RasterTriangleFunctions[(1 << RasterTriangleTexture)  |
 205							  (1 << RasterTriangleDepth)	|
 206							  (1 << RasterTriangleFog)		] = &Rasterizer::RasterTriangle_cTDFs;
 207
 208	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	] = &Rasterizer::RasterTriangle_Ctdfs;
 209	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 210							  (1 << RasterTriangleFog)		] = &Rasterizer::RasterTriangle_CtdFs;
 211	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 212							  (1 << RasterTriangleDepth)	] = &Rasterizer::RasterTriangle_CtDfs;
 213	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 214							  (1 << RasterTriangleDepth)	|
 215							  (1 << RasterTriangleFog)		] = &Rasterizer::RasterTriangle_CtDFs;
 216
 217	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 218							  (1 << RasterTriangleTexture)	] = &Rasterizer::RasterTriangle_CTdfs;
 219	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 220							  (1 << RasterTriangleTexture)	|
 221							  (1 << RasterTriangleFog)		] = &Rasterizer::RasterTriangle_CTdFs;
 222	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 223							  (1 << RasterTriangleTexture)	|
 224							  (1 << RasterTriangleDepth)	] = &Rasterizer::RasterTriangle_CTDfs;
 225	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 226							  (1 << RasterTriangleTexture)	|
 227							  (1 << RasterTriangleDepth)	|
 228							  (1 << RasterTriangleFog)		] = &Rasterizer::RasterTriangle_CTDFs;
 229
 230	m_RasterTriangleFunctions[(1 << RasterTriangleTexture)	|
 231							  (1 << RasterTriangleScissor)	] = &Rasterizer::RasterTriangle_cTdfS;
 232	m_RasterTriangleFunctions[(1 << RasterTriangleTexture)  |
 233							  (1 << RasterTriangleFog)		|
 234							  (1 << RasterTriangleScissor)	] = &Rasterizer::RasterTriangle_cTdFS;
 235	m_RasterTriangleFunctions[(1 << RasterTriangleTexture)  |
 236							  (1 << RasterTriangleDepth)	|
 237							  (1 << RasterTriangleScissor)	] = &Rasterizer::RasterTriangle_cTDfS;
 238	m_RasterTriangleFunctions[(1 << RasterTriangleTexture)  |
 239							  (1 << RasterTriangleDepth)	|
 240							  (1 << RasterTriangleFog)		|
 241							  (1 << RasterTriangleScissor)	] = &Rasterizer::RasterTriangle_cTDFS;
 242
 243	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 244							  (1 << RasterTriangleScissor)	] = &Rasterizer::RasterTriangle_CtdfS;
 245	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 246							  (1 << RasterTriangleFog)		|
 247							  (1 << RasterTriangleScissor)	] = &Rasterizer::RasterTriangle_CtdFS;
 248	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 249							  (1 << RasterTriangleDepth)	|
 250							  (1 << RasterTriangleScissor)	] = &Rasterizer::RasterTriangle_CtDfS;
 251	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 252							  (1 << RasterTriangleDepth)	|
 253							  (1 << RasterTriangleFog)		|
 254							  (1 << RasterTriangleScissor)	] = &Rasterizer::RasterTriangle_CtDFS;
 255
 256	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 257							  (1 << RasterTriangleTexture)	|
 258							  (1 << RasterTriangleScissor)	] = &Rasterizer::RasterTriangle_CTdfS;
 259	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 260							  (1 << RasterTriangleTexture)	|
 261							  (1 << RasterTriangleFog)		|
 262							  (1 << RasterTriangleScissor)	] = &Rasterizer::RasterTriangle_CTdFS;
 263	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 264							  (1 << RasterTriangleTexture)	|
 265							  (1 << RasterTriangleDepth)	|
 266							  (1 << RasterTriangleScissor)	] = &Rasterizer::RasterTriangle_CTDfS;
 267	m_RasterTriangleFunctions[(1 << RasterTriangleColor)	|
 268							  (1 << RasterTriangleTexture)	|
 269							  (1 << RasterTriangleDepth)	|
 270							  (1 << RasterTriangleFog)		|
 271							  (1 << RasterTriangleScissor)	] = &Rasterizer::RasterTriangle_CTDFS;
 272}
 273
 274
 275Rasterizer :: ~Rasterizer() {
 276	if (m_FunctionCache) {
 277		delete m_FunctionCache;
 278	}
 279}
 280
 281
 282void Rasterizer :: SetState(RasterizerState * state) {
 283	m_State = state;
 284
 285	for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 286		m_Texture[unit] = 0;
 287	}
 288}
 289
 290
 291RasterizerState * Rasterizer :: GetState() const {
 292	return m_State;
 293}
 294
 295
 296void Rasterizer :: SetTexture(size_t unit, MultiTexture * texture) {
 297	m_Texture[unit] = texture;
 298}
 299
 300
 301void Rasterizer :: PrepareTexture() {
 302	if (m_State) {
 303		for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 304			if (m_State->m_Texture[unit].Enabled && m_Texture[unit]) {
 305				m_State->SetWrappingModeS(unit, m_Texture[unit]->GetWrappingModeS());
 306				m_State->SetWrappingModeT(unit, m_Texture[unit]->GetWrappingModeT());
 307				m_State->SetMinFilterMode(unit, m_Texture[unit]->GetMinFilterMode());
 308				m_State->SetMagFilterMode(unit, m_Texture[unit]->GetMagFilterMode());
 309				m_State->SetMipmapFilterMode(unit, m_Texture[unit]->GetMipmapFilterMode());
 310				m_State->SetInternalFormat(unit, m_Texture[unit]->GetInternalFormat());
 311
 312				m_RasterInfo.Textures[unit] = m_Texture[unit]->m_TextureLevels;
 313
 314				m_UseMipmap[unit] = m_Texture[unit]->IsMipMap() && m_Texture[unit]->IsComplete();
 315				m_RasterInfo.MaxMipmapLevel[unit] = EGL_Max(m_Texture[unit]->GetTexture(0)->GetLogWidth(), m_Texture[unit]->GetTexture(0)->GetLogHeight());
 316			} else {
 317				m_RasterInfo.Textures[unit] = 0;
 318				m_UseMipmap[unit] = false;
 319			}
 320		}
 321	}
 322}
 323
 324
 325#if !EGL_USE_JIT
 326
 327inline void Rasterizer :: Fragment(I32 x, I32 y, EGL_Fixed depth, EGL_Fixed tu[], EGL_Fixed tv[],
 328								   EGL_Fixed fogDensity, const Color& baseColor) {
 329
 330	// pixel ownership test
 331	if (x < 0 || x >= m_Surface->GetWidth() ||
 332		y < 0 || y >= m_Surface->GetHeight()) {
 333		return;
 334	}
 335
 336	// fragment level clipping (for now)
 337	if (m_State->m_ScissorTest.Enabled) {
 338		if (x < m_State->m_ScissorTest.X || x - m_State->m_ScissorTest.X >= m_State->m_ScissorTest.Width ||
 339			y < m_State->m_ScissorTest.Y || y - m_State->m_ScissorTest.Y >= m_State->m_ScissorTest.Height) {
 340			return;
 341		}
 342	}
 343
 344	m_RasterInfo.Init(m_Surface, y);
 345
 346	Fragment(&m_RasterInfo, x, depth, tu, tv, baseColor, fogDensity);
 347}
 348
 349
 350Color Rasterizer :: GetRawTexColor(const RasterizerState::TextureState * state, const Texture * texture, EGL_Fixed tu, EGL_Fixed tv) {
 351	// retrieve the texture color from a texture plane
 352
 353	EGL_Fixed tu0;
 354	EGL_Fixed tv0;
 355
 356	// for nearest texel
 357
 358	switch (state->WrappingModeS) {
 359		case RasterizerState::WrappingModeClampToEdge:
 360			if (tu < 0)
 361				tu0 = 0;
 362			else if (tu >= EGL_ONE)
 363				tu0 = EGL_ONE - 1;
 364			else
 365				tu0 = tu;
 366
 367			break;
 368
 369		default:
 370		case RasterizerState::WrappingModeRepeat:
 371			tu0 = tu & 0xffff;
 372			break;
 373	}
 374
 375	switch (state->WrappingModeT) {
 376		case RasterizerState::WrappingModeClampToEdge:
 377			if (tv < 0)
 378				tv0 = 0;
 379			else if (tv >= EGL_ONE)
 380				tv0 = EGL_ONE - 1;
 381			else tv0 = tv;
 382
 383			break;
 384
 385		default:
 386		case RasterizerState::WrappingModeRepeat:
 387			tv0 = tv & 0xffff;
 388			break;
 389	}
 390
 391	// get the pixel color
 392	I32 texX = EGL_IntFromFixed(texture->GetWidth() * tu0);		// can become a shift
 393	I32 texY = EGL_IntFromFixed(texture->GetHeight() * tv0);	// can become a shift
 394
 395	// do wrapping mode here
 396	I32 texOffset = texX + (texY << texture->GetLogWidth());
 397
 398	void * data = texture->GetData();
 399
 400	switch (state->InternalFormat) {
 401		default:
 402		case RasterizerState::TextureFormatAlpha:
 403			//return Color(0xff, 0xff, 0xff, reinterpret_cast<const U8 *>(data)[texOffset]);
 404			return Color(0, 0, 0, reinterpret_cast<const U8 *>(data)[texOffset]);
 405
 406		case RasterizerState::TextureFormatLuminance:
 407			{
 408			U8 luminance = reinterpret_cast<const U8 *>(data)[texOffset];
 409			return Color (luminance, luminance, luminance, 0xff);
 410			}
 411
 412		case RasterizerState::TextureFormatRGB565:
 413			return Color::From565(reinterpret_cast<const U16 *>(data)[texOffset]);
 414
 415		case RasterizerState::TextureFormatRGB8:
 416			{
 417			texOffset = (texOffset << 1) + texOffset;
 418			const U8 * ptr = reinterpret_cast<const U8 *>(data) + texOffset;
 419			return Color(ptr[0], ptr[1], ptr[2], 0xff);
 420			}
 421
 422		case RasterizerState::TextureFormatLuminanceAlpha:
 423			{
 424			U8 luminance = reinterpret_cast<const U8 *>(data)[texOffset * 2];
 425			U8 alpha = reinterpret_cast<const U8 *>(data)[texOffset * 2 + 1];
 426			return Color (luminance, luminance, luminance, alpha);
 427			}
 428
 429		case RasterizerState::TextureFormatRGBA8:
 430			//texColor = Color::FromRGBA(reinterpret_cast<const U32 *>(data)[texOffset]);
 431			{
 432			texOffset = texOffset << 2;
 433			const U8 * ptr = reinterpret_cast<const U8 *>(data) + texOffset;
 434			return Color(ptr[0], ptr[1], ptr[2], ptr[3]);
 435			}
 436
 437		case RasterizerState::TextureFormatRGBA4444:
 438			return Color::From4444(reinterpret_cast<const U16 *>(data)[texOffset]);
 439
 440		case RasterizerState::TextureFormatRGBA5551:
 441			return Color::From5551(reinterpret_cast<const U16 *>(data)[texOffset]);
 442	}
 443}
 444
 445
 446inline Color Rasterizer :: GetTexColor(const RasterizerState::TextureState * state, const Texture * texture, EGL_Fixed tu, EGL_Fixed tv,
 447								RasterizerState::FilterMode filterMode) {
 448	// retrieve the texture color from a texture plane
 449
 450	if (filterMode == RasterizerState::FilterModeNearest) {
 451		return GetRawTexColor(state, texture, tu, tv);
 452	} else if (filterMode == RasterizerState::FilterModeLinear) {
 453		I32 logWidth = texture->GetLogWidth();
 454		I32 logHeight = texture->GetLogHeight();
 455
 456		EGL_Fixed tu0 = tu - (0x8000 >> logWidth);
 457		EGL_Fixed tu1 = tu + (0x7fff >> logWidth);
 458		EGL_Fixed tv0 = tv - (0x8000 >> logHeight);
 459		EGL_Fixed tv1 = tv + (0x7fff >> logHeight);
 460
 461		U32 alpha = EGL_FractionFromFixed(tu0 << logWidth) >> 8;
 462		U32 beta = EGL_FractionFromFixed(tv0 << logHeight) >> 8;
 463
 464		return Color::BlendAlpha(Color::BlendAlpha(GetRawTexColor(state, texture, tu1, tv1),
 465												   GetRawTexColor(state, texture, tu0, tv1), alpha),
 466								 Color::BlendAlpha(GetRawTexColor(state, texture, tu1, tv0),
 467												   GetRawTexColor(state, texture, tu0, tv0), alpha),
 468								 beta);
 469	} else {
 470		return Color(0, 0, 0, 0xff);
 471	}
 472}
 473
 474
 475void Rasterizer :: Fragment(const RasterInfo * rasterInfo, I32 x, EGL_Fixed depth, EGL_Fixed tu[], EGL_Fixed tv[],
 476			  const Color& baseColor, EGL_Fixed fogDensity) {
 477	// fragment rendering with signature corresponding to function fragment
 478	// generated by code generator
 479
 480	bool depthTest;
 481
 482	// fragment level clipping (for now)
 483	if (m_State->m_ScissorTest.Enabled) {
 484		if (x < m_State->m_ScissorTest.X || x - m_State->m_ScissorTest.X >= m_State->m_ScissorTest.Width) {
 485			return;
 486		}
 487	}
 488
 489	I32 offset = x;
 490
 491	depth = EGL_CLAMP(depth, 0, 0xffff);
 492	assert(depth >= 0 && depth <= 0xffff);
 493	I32 zBufferValue = rasterInfo->DepthBuffer[offset];
 494
 495	switch (m_State->m_DepthTest.Func) {
 496		default:
 497		case RasterizerState::CompFuncNever:	depthTest = false;						break;
 498		case RasterizerState::CompFuncLess:		depthTest = depth < zBufferValue;		break;
 499		case RasterizerState::CompFuncEqual:	depthTest = depth == zBufferValue;		break;
 500		case RasterizerState::CompFuncLEqual:	depthTest = depth <= zBufferValue;		break;
 501		case RasterizerState::CompFuncGreater:	depthTest = depth > zBufferValue;		break;
 502		case RasterizerState::CompFuncNotEqual:	depthTest = depth != zBufferValue;		break;
 503		case RasterizerState::CompFuncGEqual:	depthTest = depth >= zBufferValue;		break;
 504		case RasterizerState::CompFuncAlways:	depthTest = true;						break;
 505	}
 506
 507	if (!m_State->m_Stencil.Enabled && m_State->m_DepthTest.Enabled && !depthTest) {
 508		return;
 509	}
 510
 511	Color color(baseColor);
 512
 513	// have offset, color, texOffset, texture
 514
 515	for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 516		if (m_State->m_Texture[unit].Enabled) {
 517
 518			Texture * texture = rasterInfo->Textures[unit] + rasterInfo->MipmapLevel[unit];
 519			Color texColor = GetTexColor(&m_State->m_Texture[unit], texture, tu[unit], tv[unit], m_State->GetMinFilterMode(unit));
 520
 521			if (m_State->m_Texture[unit].Mode == RasterizerState::TextureModeCombine) {
 522				Color arg[3];
 523
 524				for (size_t idx = 0; idx < 3; ++idx) {
 525					Color rgbIn;
 526					U8 alphaIn;
 527
 528					switch (m_State->m_Texture[unit].CombineSrcRGB[idx]) {
 529					case RasterizerState::TextureCombineSrcTexture:
 530						rgbIn = texColor;
 531						break;
 532
 533					case RasterizerState::TextureCombineSrcConstant:
 534						rgbIn = m_State->m_Texture[unit].EnvColor;
 535						break;
 536
 537					case RasterizerState::TextureCombineSrcPrimaryColor:
 538						rgbIn = baseColor;
 539						break;
 540
 541					case RasterizerState::TextureCombineSrcPrevious:
 542						rgbIn = color;
 543						break;
 544					}
 545
 546					switch (m_State->m_Texture[unit].CombineSrcAlpha[idx]) {
 547					case RasterizerState::TextureCombineSrcTexture:
 548						alphaIn = texColor.a;
 549						break;
 550
 551					case RasterizerState::TextureCombineSrcConstant:
 552						alphaIn = m_State->m_Texture[unit].EnvColor.a;
 553						break;
 554
 555					case RasterizerState::TextureCombineSrcPrimaryColor:
 556						alphaIn = baseColor.a;
 557						break;
 558
 559					case RasterizerState::TextureCombineSrcPrevious:
 560						alphaIn = color.a;
 561						break;
 562					}
 563
 564					U8 alphaOut;
 565
 566					if (m_State->m_Texture[unit].CombineOpAlpha[idx] == RasterizerState::TextureCombineOpSrcAlpha) {
 567						alphaOut = alphaIn;
 568					} else {
 569						alphaOut = 0xFF - alphaIn;
 570					}
 571
 572					switch (m_State->m_Texture[unit].CombineOpRGB[idx]) {
 573					case RasterizerState::TextureCombineOpSrcColor:
 574						arg[idx] = Color(rgbIn.r, rgbIn.g, rgbIn.b, alphaOut);
 575						break;
 576
 577					case RasterizerState::TextureCombineOpOneMinusSrcColor:
 578						arg[idx] = Color(0xFF - rgbIn.r, 0xFF - rgbIn.g, 0xFF - rgbIn.b, alphaOut);
 579						break;
 580
 581					case RasterizerState::TextureCombineOpSrcAlpha:
 582						arg[idx] = Color(rgbIn.a, rgbIn.a, rgbIn.a, alphaOut);
 583						break;
 584
 585					case RasterizerState::TextureCombineOpOneMinusSrcAlpha:
 586						arg[idx] = Color(0xFF - rgbIn.a, 0xFF - rgbIn.a, 0xFF - rgbIn.a, alphaOut);
 587						break;
 588					}
 589				}
 590
 591				U8 combineAlpha;
 592				EGL_Fixed scaleAlpha = m_State->m_Texture[unit].ScaleAlpha;
 593
 594				switch (m_State->m_Texture[unit].CombineFuncAlpha) {
 595				case RasterizerState::TextureModeCombineReplace:
 596					combineAlpha = MulU8(arg[0].a, 0xFF, scaleAlpha);
 597					break;
 598
 599				case RasterizerState::TextureModeCombineModulate:
 600					combineAlpha = MulU8(arg[0].a, arg[1].a, scaleAlpha);
 601					break;
 602
 603				case RasterizerState::TextureModeCombineAdd:
 604					combineAlpha = AddU8(arg[0].a, arg[1].a, scaleAlpha);
 605					break;
 606
 607				case RasterizerState::TextureModeCombineAddSigned:
 608					combineAlpha = AddSignedU8(arg[0].a, arg[1].a, scaleAlpha);
 609					break;
 610
 611				case RasterizerState::TextureModeCombineInterpolate:
 612					combineAlpha = InterpolateU8(arg[0].a, arg[1].a, arg[2].a, scaleAlpha);
 613					break;
 614
 615				case RasterizerState::TextureModeCombineSubtract:
 616					combineAlpha = SubU8(arg[0].a, arg[1].a, scaleAlpha);
 617					break;
 618				}
 619
 620				EGL_Fixed scaleRGB = m_State->m_Texture[unit].ScaleRGB;
 621
 622				switch (m_State->m_Texture[unit].CombineFuncRGB) {
 623				case RasterizerState::TextureModeCombineReplace:
 624					color = Color(
 625							MulU8(arg[0].r, 0xFF, scaleRGB), 
 626							MulU8(arg[0].g, 0xFF, scaleRGB), 
 627							MulU8(arg[0].b, 0xFF, scaleRGB), 
 628							combineAlpha); 
 629					break;
 630
 631				case RasterizerState::TextureModeCombineModulate:
 632					color = 
 633						Color(
 634							MulU8(arg[0].r, arg[1].r, scaleRGB), 
 635							MulU8(arg[0].g, arg[1].g, scaleRGB), 
 636							MulU8(arg[0].b, arg[1].b, scaleRGB), 
 637							combineAlpha); 
 638					break;
 639
 640				case RasterizerState::TextureModeCombineAdd:
 641					color = 
 642						Color(
 643							AddU8(arg[0].r, arg[1].r, scaleRGB), 
 644							AddU8(arg[0].g, arg[1].g, scaleRGB), 
 645							AddU8(arg[0].b, arg[1].b, scaleRGB), 
 646							combineAlpha); 
 647					break;
 648
 649				case RasterizerState::TextureModeCombineAddSigned:
 650					color = 
 651						Color(
 652							AddSignedU8(arg[0].r, arg[1].r, scaleRGB), 
 653							AddSignedU8(arg[0].g, arg[1].g, scaleRGB), 
 654							AddSignedU8(arg[0].b, arg[1].b, scaleRGB), 
 655							combineAlpha); 
 656					break;
 657
 658				case RasterizerState::TextureModeCombineInterpolate:
 659					color =
 660						Color(
 661							InterpolateU8(arg[0].r, arg[1].r, arg[2].r, scaleRGB),
 662							InterpolateU8(arg[0].g, arg[1].g, arg[2].g, scaleRGB),
 663							InterpolateU8(arg[0].b, arg[1].b, arg[2].b, scaleRGB),
 664							combineAlpha); 
 665					break;
 666
 667				case RasterizerState::TextureModeCombineSubtract:
 668					color = 
 669						Color(
 670							SubU8(arg[0].r, arg[1].r, scaleRGB), 
 671							SubU8(arg[0].g, arg[1].g, scaleRGB), 
 672							SubU8(arg[0].b, arg[1].b, scaleRGB), 
 673							combineAlpha); 
 674					break;
 675
 676				case RasterizerState::TextureModeCombineDot3RGB:
 677					{
 678						U8 dotRGB = Dot3U8(arg[0], arg[1], scaleRGB);
 679						color = Color(dotRGB, dotRGB, dotRGB, combineAlpha);
 680					}
 681
 682					break;
 683
 684				case RasterizerState::TextureModeCombineDot3RGBA:
 685					{
 686						U8 dotRGB = Dot3U8(arg[0], arg[1], scaleRGB);
 687						U8 dotAlpha = Dot3U8(arg[0], arg[1], scaleAlpha);
 688						color = Color(dotRGB, dotRGB, dotRGB, dotAlpha);
 689					}
 690
 691					break;
 692				}
 693			} else {
 694				switch (m_Texture[unit]->GetInternalFormat()) {
 695					default:
 696					case RasterizerState::TextureFormatAlpha:
 697						switch (m_State->m_Texture[unit].Mode) {
 698							case RasterizerState::TextureModeReplace:
 699								color = Color(color.r, color.g, color.b, texColor.a);
 700								break;
 701
 702							case RasterizerState::TextureModeModulate:
 703							case RasterizerState::TextureModeBlend:
 704							case RasterizerState::TextureModeAdd:
 705								color = Color(color.r, color.g, color.b, MulU8(color.a, texColor.a));
 706								break;
 707						}
 708						break;
 709
 710					case RasterizerState::TextureFormatLuminance:
 711						switch (m_State->m_Texture[unit].Mode) {
 712							case RasterizerState::TextureModeDecal:
 713							case RasterizerState::TextureModeReplace:
 714								color = Color(texColor.r, texColor.g, texColor.b, color.a);
 715								break;
 716
 717							case RasterizerState::TextureModeModulate:
 718								color = Color(MulU8(color.r, texColor.r),
 719									MulU8(color.g, texColor.g), MulU8(color.b, texColor.b), color.a);
 720								break;
 721
 722							case RasterizerState::TextureModeBlend:
 723								color =
 724									Color(
 725										MulU8(color.r, 0xff - texColor.r) + MulU8(m_State->m_Texture[unit].EnvColor.r, texColor.r),
 726										MulU8(color.g, 0xff - texColor.g) + MulU8(m_State->m_Texture[unit].EnvColor.g, texColor.g),
 727										MulU8(color.b, 0xff - texColor.b) + MulU8(m_State->m_Texture[unit].EnvColor.b, texColor.b),
 728										color.a);
 729								break;
 730
 731							case RasterizerState::TextureModeAdd:
 732								color =
 733									Color(
 734										ClampU8(color.r + texColor.r),
 735										ClampU8(color.g + texColor.g),
 736										ClampU8(color.b + texColor.b),
 737										color.a);
 738								break;
 739						}
 740						break;
 741
 742					case RasterizerState::TextureFormatRGB565:
 743					case RasterizerState::TextureFormatRGB8:
 744						switch (m_State->m_Texture[unit].Mode) {
 745							case RasterizerState::TextureModeDecal:
 746							case RasterizerState::TextureModeReplace:
 747								color = Color(texColor.r, texColor.g, texColor.b, color.a);
 748								break;
 749
 750							case RasterizerState::TextureModeModulate:
 751								color = Color(MulU8(color.r, texColor.r),
 752									MulU8(color.g, texColor.g), MulU8(color.b, texColor.b), color.a);
 753								break;
 754
 755							case RasterizerState::TextureModeBlend:
 756								color =
 757									Color(
 758										MulU8(color.r, 0xff - texColor.r) + MulU8(m_State->m_Texture[unit].EnvColor.r, texColor.r),
 759										MulU8(color.g, 0xff - texColor.g) + MulU8(m_State->m_Texture[unit].EnvColor.g, texColor.g),
 760										MulU8(color.b, 0xff - texColor.b) + MulU8(m_State->m_Texture[unit].EnvColor.b, texColor.b),
 761										color.a);
 762								break;
 763
 764							case RasterizerState::TextureModeAdd:
 765								color =
 766									Color(
 767										ClampU8(color.r + texColor.r),
 768										ClampU8(color.g + texColor.g),
 769										ClampU8(color.b + texColor.b),
 770										color.a);
 771								break;
 772						}
 773						break;
 774
 775					case RasterizerState::TextureFormatLuminanceAlpha:
 776						switch (m_State->m_Texture[unit].Mode) {
 777							case RasterizerState::TextureModeReplace:
 778								color = texColor;
 779								break;
 780
 781							case RasterizerState::TextureModeModulate:
 782								color = color * texColor;
 783								break;
 784
 785							case RasterizerState::TextureModeDecal:
 786								color =
 787									Color(
 788										MulU8(color.r, 0xff - texColor.a) + MulU8(texColor.r, texColor.a),
 789										MulU8(color.g, 0xff - texColor.a) + MulU8(texColor.g, texColor.a),
 790										MulU8(color.b, 0xff - texColor.a) + MulU8(texColor.b, texColor.a),
 791										color.a);
 792								break;
 793
 794							case RasterizerState::TextureModeBlend:
 795								color =
 796									Color(
 797										MulU8(color.r, 0xff - texColor.r) + MulU8(m_State->m_Texture[unit].EnvColor.r, texColor.r),
 798										MulU8(color.g, 0xff - texColor.g) + MulU8(m_State->m_Texture[unit].EnvColor.g, texColor.g),
 799										MulU8(color.b, 0xff - texColor.b) + MulU8(m_State->m_Texture[unit].EnvColor.b, texColor.b),
 800										MulU8(color.a, texColor.a));
 801								break;
 802
 803							case RasterizerState::TextureModeAdd:
 804								color =
 805									Color(
 806										ClampU8(color.r + texColor.r),
 807										ClampU8(color.g + texColor.g),
 808										ClampU8(color.b + texColor.b),
 809										MulU8(color.a, texColor.a));
 810								break;
 811						}
 812						break;
 813
 814					case RasterizerState::TextureFormatRGBA5551:
 815					case RasterizerState::TextureFormatRGBA4444:
 816					case RasterizerState::TextureFormatRGBA8:
 817						switch (m_State->m_Texture[unit].Mode) {
 818							case RasterizerState::TextureModeReplace:
 819								color = texColor;
 820								break;
 821
 822							case RasterizerState::TextureModeModulate:
 823								color = color * texColor;
 824								break;
 825
 826							case RasterizerState::TextureModeDecal:
 827								color =
 828									Color(
 829										MulU8(color.r, 0xff - texColor.a) + MulU8(texColor.r, texColor.a),
 830										MulU8(color.g, 0xff - texColor.a) + MulU8(texColor.g, texColor.a),
 831										MulU8(color.b, 0xff - texColor.a) + MulU8(texColor.b, texColor.a),
 832										color.a);
 833								break;
 834
 835							case RasterizerState::TextureModeBlend:
 836								color =
 837									Color(
 838										MulU8(color.r, 0xff - texColor.r) + MulU8(m_State->m_Texture[unit].EnvColor.r, texColor.r),
 839										MulU8(color.g, 0xff - texColor.g) + MulU8(m_State->m_Texture[unit].EnvColor.g, texColor.g),
 840										MulU8(color.b, 0xff - texColor.b) + MulU8(m_State->m_Texture[unit].EnvColor.b, texColor.b),
 841										MulU8(color.a, texColor.a));
 842								break;
 843
 844							case RasterizerState::TextureModeAdd:
 845								color =
 846									Color(
 847										ClampU8(color.r + texColor.r),
 848										ClampU8(color.g + texColor.g),
 849										ClampU8(color.b + texColor.b),
 850										MulU8(color.a, texColor.a));
 851								break;
 852						}
 853						break;
 854				}
 855			}
 856		}
 857	}
 858
 859	// fog
 860	if (m_State->m_Fog.Enabled) {
 861		color = Color::Blend(color, m_State->m_Fog.Color, fogDensity >> 8);
 862	}
 863
 864	// have color
 865
 866	if (m_State->m_Alpha.Enabled) {
 867		bool alphaTest;
 868		U8 alpha = color.A();
 869		U8 alphaRef = EGL_IntFromFixed(m_State->m_Alpha.Reference * 255);
 870
 871		switch (m_State->m_Alpha.Func) {
 872			default:
 873			case RasterizerState::CompFuncNever:	alphaTest = false;					break;
 874			case RasterizerState::CompFuncLess:		alphaTest = alpha < alphaRef;		break;
 875			case RasterizerState::CompFuncEqual:	alphaTest = alpha == alphaRef;		break;
 876			case RasterizerState::CompFuncLEqual:	alphaTest = alpha <= alphaRef;		break;
 877			case RasterizerState::CompFuncGreater:	alphaTest = alpha > alphaRef;		break;
 878			case RasterizerState::CompFuncNotEqual:	alphaTest = alpha != alphaRef;		break;
 879			case RasterizerState::CompFuncGEqual:	alphaTest = alpha >= alphaRef;		break;
 880			case RasterizerState::CompFuncAlways:	alphaTest = true;					break;
 881		}
 882
 883		if (!alphaTest) {
 884			return;
 885		}
 886	}
 887
 888	// have offset, depth
 889
 890	if (m_State->m_Stencil.Enabled) {
 891
 892		bool stencilTest;
 893		U32 stencilRef = m_State->m_Stencil.Reference & m_State->m_Stencil.ComparisonMask;
 894		U32 stencilValue = rasterInfo->StencilBuffer[offset];
 895		U32 stencil = stencilValue & m_State->m_Stencil.ComparisonMask;
 896
 897		switch (m_State->m_Stencil.Func) {
 898			default:
 899			case RasterizerState::CompFuncNever:	stencilTest = false;				break;
 900			case RasterizerState::CompFuncLess:		stencilTest = stencilRef < stencil;	break;
 901			case RasterizerState::CompFuncEqual:	stencilTest = stencilRef == stencil;break;
 902			case RasterizerState::CompFuncLEqual:	stencilTest = stencilRef <= stencil;break;
 903			case RasterizerState::CompFuncGreater:	stencilTest = stencilRef > stencil;	break;
 904			case RasterizerState::CompFuncNotEqual:	stencilTest = stencilRef != stencil;break;
 905			case RasterizerState::CompFuncGEqual:	stencilTest = stencilRef >= stencil;break;
 906			case RasterizerState::CompFuncAlways:	stencilTest = true;					break;
 907		}
 908
 909		if (!stencilTest) {
 910
 911			switch (m_State->m_Stencil.Fail) {
 912				default:
 913				case RasterizerState::StencilOpKeep:
 914					break;
 915
 916				case RasterizerState::StencilOpZero:
 917					stencilValue = 0;
 918					break;
 919
 920				case RasterizerState::StencilOpReplace:
 921					stencilValue = m_State->m_Stencil.Reference;
 922					break;
 923
 924				case RasterizerState::StencilOpIncr:
 925					if (stencilValue != 0xffffffff) {
 926						stencilValue++;
 927					}
 928
 929					break;
 930
 931				case RasterizerState::StencilOpDecr:
 932					if (stencilValue != 0) {
 933						stencilValue--;
 934					}
 935
 936					break;
 937
 938				case RasterizerState::StencilOpInvert:
 939					stencilValue = ~stencilValue;
 940					break;
 941			}
 942
 943			rasterInfo->StencilBuffer[offset] = 
 944				rasterInfo->StencilBuffer[offset] & ~m_State->m_Stencil.Mask |
 945				stencilValue & m_State->m_Stencil.Mask;
 946
 947			return;
 948		}
 949
 950		if (depthTest) {
 951			switch (m_State->m_Stencil.ZPass) {
 952				default:
 953				case RasterizerState::StencilOpKeep:
 954					break;
 955
 956				case RasterizerState::StencilOpZero:
 957					stencilValue = 0;
 958					break;
 959
 960				case RasterizerState::StencilOpReplace:
 961					stencilValue = m_State->m_Stencil.Reference;
 962					break;
 963
 964				case RasterizerState::StencilOpIncr:
 965					if (stencilValue != 0xffffffff) {
 966						stencilValue++;
 967					}
 968
 969					break;
 970
 971				case RasterizerState::StencilOpDecr:
 972					if (stencilValue != 0) {
 973						stencilValue--;
 974					}
 975
 976					break;
 977
 978				case RasterizerState::StencilOpInvert:
 979					stencilValue = ~stencilValue;
 980					break;
 981			}
 982
 983			rasterInfo->StencilBuffer[offset] = 
 984				rasterInfo->StencilBuffer[offset] & ~m_State->m_Stencil.Mask |
 985				stencilValue & m_State->m_Stencil.Mask;
 986		} else {
 987			switch (m_State->m_Stencil.ZFail) {
 988				default:
 989				case RasterizerState::StencilOpKeep:
 990					break;
 991
 992				case RasterizerState::StencilOpZero:
 993					stencilValue = 0;
 994					break;
 995
 996				case RasterizerState::StencilOpReplace:
 997					stencilValue = m_State->m_Stencil.Reference;
 998					break;
 999
1000				case RasterizerState::StencilOpIncr:
1001					if (stencilValue != 0xffffffff) {
1002						stencilValue++;
1003					}
1004
1005					break;
1006
1007				case RasterizerState::StencilOpDecr:
1008					if (stencilValue != 0) {
1009						stencilValue--;
1010					}
1011
1012					break;
1013
1014				case RasterizerState::StencilOpInvert:
1015					stencilValue = ~stencilValue;
1016					break;
1017			}
1018
1019			rasterInfo->StencilBuffer[offset] = 
1020				rasterInfo->StencilBuffer[offset] & ~m_State->m_Stencil.Mask |
1021				stencilValue & m_State->m_Stencil.Mask;
1022		}
1023	}
1024
1025	if (m_State->m_Stencil.Enabled && !depthTest && m_State->m_DepthTest.Enabled) {
1026		// otherwise we returned at the top
1027		return;
1028	}
1029
1030	// have color, offset
1031
1032	// Blending
1033	if (m_State->m_Blend.Enabled) {
1034
1035		U16 dstValue = rasterInfo->ColorBuffer[offset];
1036		U8 dstAlpha = rasterInfo->AlphaBuffer[offset];
1037
1038		Color dstColor = Color::From565A(dstValue, dstAlpha);
1039
1040		Color srcCoeff, dstCoeff;
1041
1042		switch (m_State->m_Blend.FuncSrc) {
1043			default:
1044			case RasterizerState::BlendFuncSrcZero:
1045				srcCoeff = Color(0, 0, 0, 0);
1046				break;
1047
1048			case RasterizerState::BlendFuncSrcOne:
1049				srcCoeff = Color(Color::MAX, Color::MAX, Color::MAX, Color::MAX);
1050				break;
1051
1052			case RasterizerState::BlendFuncSrcDstColor:
1053				srcCoeff = dstColor;
1054				break;
1055
1056			case RasterizerState::BlendFuncSrcOneMinusDstColor:
1057				srcCoeff = Color(Color::MAX - dstColor.R(), Color::MAX - dstColor.G(), Color::MAX - dstColor.B(), Color::MAX - dstColor.A());
1058				break;
1059
1060			case RasterizerState::BlendFuncSrcSrcAlpha:
1061				srcCoeff = Color(color.A(), color.A(), color.A(), color.A());
1062				break;
1063
1064			case RasterizerState::BlendFuncSrcOneMinusSrcAlpha:
1065				srcCoeff = Color(Color::MAX - color.A(), Color::MAX - color.A(), Color::MAX - color.A(), Color::MAX - color.A());
1066				break;
1067
1068			case RasterizerState::BlendFuncSrcDstAlpha:
1069				srcCoeff = Color(dstAlpha, dstAlpha, dstAlpha, dstAlpha);
1070				break;
1071
1072			case RasterizerState::BlendFuncSrcOneMinusDstAlpha:
1073				srcCoeff = Color(Color::MAX - dstAlpha, Color::MAX - dstAlpha, Color::MAX - dstAlpha, Color::MAX - dstAlpha);
1074				break;
1075
1076			case RasterizerState::BlendFuncSrcSrcAlphaSaturate:
1077				{
1078					U8 rev = Color::MAX - dstAlpha;
1079					U8 f = (rev < color.A() ? rev : color.A());
1080					srcCoeff = Color(f, f, f, Color::MAX);
1081				}
1082				break;
1083		}
1084
1085		switch (m_State->m_Blend.FuncDst) {
1086			default:
1087			case RasterizerState::BlendFuncDstZero:
1088				dstCoeff = Color(0, 0, 0, 0);
1089				break;
1090
1091			case RasterizerState::BlendFuncDstOne:
1092				dstCoeff = Color(Color::MAX, Color::MAX, Color::MAX, Color::MAX);
1093				break;
1094
1095			case RasterizerState::BlendFuncDstSrcColor:
1096				dstCoeff = color;
1097				break;
1098
1099			case RasterizerState::BlendFuncDstOneMinusSrcColor:
1100				dstCoeff = Color(Color::MAX - color.R(), Color::MAX - color.G(), Color::MAX - color.B(), Color::MAX - color.A());
1101				break;
1102
1103			case RasterizerState::BlendFuncDstSrcAlpha:
1104				dstCoeff = Color(color.A(), color.A(), color.A(), color.A());
1105				break;
1106
1107			case RasterizerState::BlendFuncDstOneMinusSrcAlpha:
1108				dstCoeff = Color(Color::MAX - color.A(), Color::MAX - color.A(), Color::MAX - color.A(), Color::MAX - color.A());
1109				break;
1110
1111			case RasterizerState::BlendFuncDstDstAlpha:
1112				dstCoeff = Color(dstAlpha, dstAlpha, dstAlpha, dstAlpha);
1113				break;
1114
1115			case RasterizerState::BlendFuncDstOneMinusDstAlpha:
1116				dstCoeff = Color(Color::MAX - dstAlpha, Color::MAX - dstAlpha, Color::MAX - dstAlpha, Color::MAX - dstAlpha);
1117				break;
1118
1119		}
1120
1121		color = srcCoeff * color + dstCoeff * dstColor;
1122	}
1123
1124	// have offset, depth, color
1125
1126	// Masking and write to framebuffer
1127	if (m_State->m_Mask.Depth) {
1128		rasterInfo->DepthBuffer[offset] = depth;
1129	}
1130
1131	Color maskedColor =
1132		color.Mask(m_State->m_Mask.Red, m_State->m_Mask.Green, m_State->m_Mask.Blue, m_State->m_Mask.Alpha);
1133
1134	if (m_State->m_LogicOp.Enabled) {
1135
1136		U16 oldValue = rasterInfo->ColorBuffer[offset];
1137		U8 oldAlpha = rasterInfo->AlphaBuffer[offset];
1138
1139		U16 newValue = maskedColor.ConvertTo565();
1140		U8 newAlpha = maskedColor.A();
1141
1142		U16 value;
1143		U8 alpha;
1144
1145		switch (m_State->m_LogicOp.Opcode) {
1146			default:
1147			case RasterizerState:: LogicOpClear:
1148				value = 0;
1149				alpha = 0;
1150				break;
1151
1152			case RasterizerState:: LogicOpAnd:
1153				value = newValue & oldValue;
1154				alpha = newAlpha & oldAlpha;
1155				break;
1156
1157			case RasterizerState:: LogicOpAndReverse:
1158				value = newValue & ~oldValue;
1159				alpha = newAlpha & ~oldAlpha;
1160				break;
1161
1162			case RasterizerState:: LogicOpCopy:
1163				value = newValue;
1164				alpha = newAlpha;
1165				break;
1166
1167			case RasterizerState:: LogicOpAndInverted:
1168				value = ~newValue & oldValue;
1169				alpha = ~newAlpha & oldAlpha;
1170				break;
1171
1172			case RasterizerState:: LogicOpNoop:
1173				value = oldValue;
1174				alpha = oldAlpha;
1175				break;
1176
1177			case RasterizerState:: LogicOpXor:
1178				value = newValue ^ oldValue;
1179				alpha = newAlpha ^ oldAlpha;
1180				break;
1181
1182			case RasterizerState:: LogicOpOr:
1183				value = newValue | oldValue;
1184				alpha = newAlpha | oldAlpha;
1185				break;
1186
1187			case RasterizerState:: LogicOpNor:
1188				value = ~(newValue | oldValue);
1189				alpha = ~(newAlpha | oldAlpha);
1190				break;
1191
1192			case RasterizerState:: LogicOpEquiv:
1193				value = ~(newValue ^ oldValue);
1194				alpha = ~(newAlpha ^ oldAlpha);
1195				break;
1196
1197			case RasterizerState:: LogicOpInvert:
1198				value = ~oldValue;
1199				alpha = ~oldAlpha;
1200				break;
1201
1202			case RasterizerState:: LogicOpOrReverse:
1203				value = newValue | ~oldValue;
1204				alpha = newAlpha | ~oldAlpha;
1205				break;
1206
1207			case RasterizerState:: LogicOpCopyInverted:
1208				value = ~newValue;
1209				alpha = ~newAlpha;
1210				break;
1211
1212			case RasterizerState:: LogicOpOrInverted:
1213				value = ~newValue | oldValue;
1214				alpha = ~newAlpha | oldAlpha;
1215				break;
1216
1217			case RasterizerState:: LogicOpNand:
1218				value = ~(newValue & oldValue);
1219				alpha = ~(newAlpha & oldAlpha);
1220				break;
1221
1222			case RasterizerState:: LogicOpSet:
1223				value = 0xFFFF;
1224				alpha = 0xFF;
1225				break;
1226		}
1227
1228		rasterInfo->ColorBuffer[offset] = value;
1229		rasterInfo->AlphaBuffer[offset] = alpha;
1230
1231	} else {
1232		rasterInfo->ColorBuffer[offset] = maskedColor.ConvertTo565();
1233
1234		if (m_State->m_Mask.Alpha) {
1235			rasterInfo->AlphaBuffer[offset] = maskedColor.A();
1236		}
1237	}
1238}
1239
1240#endif // !EGL_USE_JIT
1241
1242// --------------------------------------------------------------------------
1243// Prepare rasterizer with according to current state settings
1244// --------------------------------------------------------------------------
1245
1246void Rasterizer :: PreparePoint() {
1247
1248	PrepareTexture();
1249
1250	m_PointFunction = (PointFunction *)
1251		m_FunctionCache->GetFunction(FunctionCache::FunctionTypePoint,
1252									 *m_State);
1253
1254	m_RasterInfo.Init(m_Surface, 0);
1255	memset(m_RasterInfo.MipmapLevel, 0, sizeof(m_RasterInfo.MipmapLevel));
1256}
1257
1258
1259void Rasterizer :: PrepareLine() {
1260	PrepareTexture();
1261
1262	m_LineFunction = (LineFunction *)
1263		m_FunctionCache->GetFunction(FunctionCache::FunctionTypeLine,
1264									 *m_State);
1265
1266	m_RasterInfo.Init(m_Surface, 0);
1267	memset(m_RasterInfo.MipmapLevel, 0, sizeof(m_RasterInfo.MipmapLevel));
1268}
1269
1270
1271void Rasterizer :: Finish() {
1272}
1273
1274
1275#if !EGL_USE_JIT
1276
1277void Rasterizer :: RasterLine(RasterPos& p_from, RasterPos& p_to) {
1278
1279	if (EGL_Round(p_from.m_WindowCoords.x) == EGL_Round(p_to.m_WindowCoords.x) &&
1280		EGL_Round(p_from.m_WindowCoords.y) == EGL_Round(p_to.m_WindowCoords.y)) {
1281		// both ends of line on same pixel
1282		RasterPoint(p_from, EGL_ONE);
1283		return;
1284	}
1285
1286	EGL_Fixed deltaX = p_to.m_WindowCoords.x - p_from.m_WindowCoords.x;
1287	EGL_Fixed deltaY = p_to.m_WindowCoords.y - p_from.m_WindowCoords.y;
1288
1289	if (EGL_Abs(deltaX) > EGL_Abs(deltaY)) {
1290		// Bresenham along x-axis
1291
1292		const RasterPos *start, *end;
1293
1294		I32 x;
1295		I32 endX;
1296		EGL_Fixed roundedX; //, preStepX;
1297
1298		if (deltaX < 0) {
1299			deltaY = -deltaY;
1300			deltaX = -deltaX;
1301			start = &p_to;
1302			end = &p_from;
1303			roundedX = EGL_NearestInt(p_to.m_WindowCoords.x + 1);
1304			x = EGL_IntFromFixed(roundedX);
1305			//preStepX = roundedX + (EGL_ONE/2) - p_to.m_WindowCoords.x;
1306			endX = EGL_IntFromFixed(p_from.m_WindowCoords.x + ((EGL_ONE)/2));
1307		} else {
1308			start = &p_from;
1309			end = &p_to;
1310			roundedX = EGL_NearestInt(p_from.m_WindowCoords.x);
1311			x = EGL_IntFromFixed(roundedX);
1312			//preStepX = roundedX + (EGL_ONE/2) - p_from.m_WindowCoords.x;
1313			endX = EGL_IntFromFixed(p_to.m_WindowCoords.x + ((EGL_ONE)/2-1));
1314		}
1315
1316		const RasterPos& from = *start;
1317		const RasterPos& to = *end;
1318
1319		FractionalColor baseColor = from.m_Color;
1320		EGL_Fixed OneOverZ = from.m_WindowCoords.invZ;
1321		EGL_Fixed tuOverZ[EGL_NUM_TEXTURE_UNITS];
1322		EGL_Fixed tvOverZ[EGL_NUM_TEXTURE_UNITS];
1323		
1324		size_t unit;
1325
1326		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1327			tuOverZ[unit] = EGL_Mul(from.m_TextureCoords[unit].tu, OneOverZ);
1328			tvOverZ[unit] = EGL_Mul(from.m_TextureCoords[unit].tv, OneOverZ);
1329		}
1330
1331		EGL_Fixed fogDensity = from.m_FogDensity;
1332		EGL_Fixed depth = from.m_WindowCoords.depth;
1333
1334		EGL_Fixed OneOverZTo = to.m_WindowCoords.invZ;
1335		EGL_Fixed invSpan = EGL_Inverse(deltaX);
1336		EGL_Fixed slope = EGL_Mul(EGL_Abs(deltaY), invSpan);
1337
1338		// -- increments(to, from, invSpan)
1339		FractionalColor colorIncrement = (to.m_Color - from.m_Color) * invSpan;
1340		EGL_Fixed deltaFog = EGL_Mul(to.m_FogDensity - from.m_FogDensity, invSpan);
1341
1342		EGL_Fixed deltaZ = EGL_Mul(OneOverZTo - OneOverZ, invSpan);
1343
1344		EGL_Fixed deltaU[EGL_NUM_TEXTURE_UNITS], deltaV[EGL_NUM_TEXTURE_UNITS];
1345
1346		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1347			deltaU[unit] = EGL_Mul(EGL_Mul(to.m_TextureCoords[unit].tu, OneOverZTo) -
1348									   EGL_Mul(from.m_TextureCoords[unit].tu, OneOverZ), invSpan);
1349
1350			deltaV[unit] = EGL_Mul(EGL_Mul(to.m_TextureCoords[unit].tv, OneOverZTo) -
1351									   EGL_Mul(from.m_TextureCoords[unit].tv, OneOverZ), invSpan);
1352		}
1353
1354		EGL_Fixed deltaDepth = EGL_Mul(to.m_WindowCoords.depth - from.m_WindowCoords.depth, invSpan);
1355		// -- end increments
1356
1357#if 0
1358		baseColor.r += EGL_Mul(colorIncrement.r, preStepX);
1359		baseColor.g += EGL_Mul(colorIncrement.g, preStepX);
1360		baseColor.b += EGL_Mul(colorIncrement.b, preStepX);
1361		baseColor.a += EGL_Mul(colorIncrement.a, preStepX);
1362
1363		fogDensity  += EGL_Mul(deltaFog, preStepX);
1364		depth       += EGL_Mul(deltaDepth, preStepX);
1365
1366		OneOverZ	+= EGL_Mul(deltaZ, preStepX);
1367
1368		for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1369			tuOverZ[unit]		+= EGL_Mul(deltaU[unit], preStepX);
1370			tvOverZ[unit]		+= EGL_Mul(deltaV[unit], preStepX);
1371		}
1372#endif
1373
1374		I32 y = EGL_IntFromFixed(from.m_WindowCoords.y + ((EGL_ONE)/2-1));
1375
1376		I32 yIncrement = (deltaY > 0) ? 1 : -1;
1377		EGL_Fixed error = 0;//EGL_ONE/2;
1378
1379		for (; x < endX; ++x) {
1380
1381			EGL_Fixed z = EGL_Inverse(OneOverZ);
1382			EGL_Fixed tu[EGL_NUM_TEXTURE_UNITS], tv[EGL_NUM_TEXTURE_UNITS];
1383			size_t unit;
1384
1385			for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1386				tu[unit] = EGL_Mul(tuOverZ[unit], z);
1387				tv[unit] = EGL_Mul(tvOverZ[unit], z);
1388			}
1389
1390			Fragment(x, y, depth, tu, tv, fogDensity, baseColor);
1391
1392			error += slope;
1393			if (error > EGL_ONE) {
1394				y += yIncrement;
1395				error -= EGL_ONE;
1396			}
1397
1398			baseColor += colorIncrement;
1399			depth += deltaDepth;
1400			OneOverZ += deltaZ;
1401
1402			for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1403				tuOverZ[unit] += deltaU[unit];
1404				tvOverZ[unit] += deltaV[unit];
1405			}
1406
1407			fogDensity += deltaFog;
1408		}
1409
1410	} else {
1411		// Bresenham along y-axis
1412
1413		const RasterPos *start, *end;
1414
1415		I32 y;
1416		I32 endY;
1417		EGL_Fixed roundedY; //, preStepY;
1418
1419		if (deltaY < 0) {
1420			deltaY = -deltaY;
1421			deltaX = -deltaX;
1422			start = &p_to;
1423			end = &p_from;
1424			roundedY = EGL_NearestInt(p_to.m_WindowCoords.y + 1);
1425			y = EGL_IntFromFixed(roundedY);
1426			//preStepY = roundedY + (EGL_ONE/2) - p_to.m_WindowCoords.y;
1427			endY = EGL_IntFromFixed(p_from.m_WindowCoords.y + ((EGL_ONE)/2));
1428		} else {
1429			start = &p_from;
1430			end = &p_to;
1431			roundedY = EGL_NearestInt(p_from.m_WindowCoords.y);
1432			y = EGL_IntFromFixed(roundedY);
1433			//preStepY = roundedY + (EGL_ONE/2) - p_from.m_WindowCoords.y;
1434			endY = EGL_IntFromFixed(p_to.m_WindowCoords.y + ((EGL_ONE)/2-1));
1435		}
1436
1437		const RasterPos& from = *start;
1438		const RasterPos& to = *end;
1439
1440		FractionalColor baseColor = from.m_Color;
1441		EGL_Fixed OneOverZ = from.m_WindowCoords.invZ;
1442		EGL_Fixed tuOverZ[EGL_NUM_TEXTURE_UNITS];
1443		EGL_Fixed tvOverZ[EGL_NUM_TEXTURE_UNITS];
1444		
1445		size_t unit;
1446
1447		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1448			tuOverZ[unit] = EGL_Mul(from.m_TextureCoords[unit].tu, OneOverZ);
1449			tvOverZ[unit] = EGL_Mul(from.m_TextureCoords[unit].tv, OneOverZ);
1450		}
1451
1452		EGL_Fixed fogDensity = from.m_FogDensity;
1453		EGL_Fixed depth = from.m_WindowCoords.depth;
1454
1455		EGL_Fixed OneOverZTo = to.m_WindowCoords.invZ;
1456		EGL_Fixed invSpan = EGL_Inverse(deltaY);
1457		EGL_Fixed slope = EGL_Mul(EGL_Abs(deltaX), invSpan);
1458
1459		// -- increments(to, from, invSpan)
1460		FractionalColor colorIncrement = (to.m_Color - from.m_Color) * invSpan;
1461		EGL_Fixed deltaFog = EGL_Mul(to.m_FogDensity - from.m_FogDensity, invSpan);
1462
1463		EGL_Fixed deltaZ = EGL_Mul(OneOverZTo - OneOverZ, invSpan);
1464
1465		EGL_Fixed deltaU[EGL_NUM_TEXTURE_UNITS], deltaV[EGL_NUM_TEXTURE_UNITS];
1466
1467		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1468			deltaU[unit] = EGL_Mul(EGL_Mul(to.m_TextureCoords[unit].tu, OneOverZTo) -
1469									   EGL_Mul(from.m_TextureCoords[unit].tu, OneOverZ), invSpan);
1470
1471			deltaV[unit] = EGL_Mul(EGL_Mul(to.m_TextureCoords[unit].tv, OneOverZTo) -
1472									   EGL_Mul(from.m_TextureCoords[unit].tv, OneOverZ), invSpan);
1473		}
1474
1475		EGL_Fixed deltaDepth = EGL_Mul(to.m_WindowCoords.depth - from.m_WindowCoords.depth, invSpan);
1476		// -- end increments
1477
1478#if 0
1479		baseColor.r += EGL_Mul(colorIncrement.r, preStepY);
1480		baseColor.g += EGL_Mul(colorIncrement.g, preStepY);
1481		baseColor.b += EGL_Mul(colorIncrement.b, preStepY);
1482		baseColor.a += EGL_Mul(colorIncrement.a, preStepY);
1483
1484		fogDensity  += EGL_Mul(deltaFog, preStepY);
1485		depth       += EGL_Mul(deltaDepth, preStepY);
1486
1487		OneOverZ	+= EGL_Mul(deltaZ, preStepY);
1488
1489		for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1490			tuOverZ[unit]		+= EGL_Mul(deltaU[unit], preStepX);
1491			tvOverZ[unit]		+= EGL_Mul(deltaV[unit], preStepX);
1492		}
1493#endif
1494
1495		I32 x = EGL_IntFromFixed(from.m_WindowCoords.x + ((EGL_ONE)/2-1));
1496
1497		I32 xIncrement = (deltaX > 0) ? 1 : -1;
1498		EGL_Fixed error = 0;//EGL_ONE/2;
1499
1500		// can have xIncrement; yIncrement; xBaseIncrement, yBaseIncrement
1501		// then both x/y loops become the same
1502		// question: how to add correct mipmap selection?
1503
1504		for (; y < endY; ++y) {
1505
1506			EGL_Fixed z = EGL_Inverse(OneOverZ);
1507			EGL_Fixed tu[EGL_NUM_TEXTURE_UNITS], tv[EGL_NUM_TEXTURE_UNITS];
1508			size_t unit;
1509
1510			for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1511				tu[unit] = EGL_Mul(tuOverZ[unit], z);
1512				tv[unit] = EGL_Mul(tvOverZ[unit], z);
1513			}
1514
1515			Fragment(x, y, depth, tu, tv, fogDensity, baseColor);
1516
1517			error += slope;
1518			if (error > EGL_ONE) {
1519				x += xIncrement;
1520				error -= EGL_ONE;
1521			}
1522
1523			baseColor += colorIncrement;
1524			depth += deltaDepth;
1525			OneOverZ += deltaZ;
1526
1527			for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1528				tuOverZ[unit] += deltaU[unit];
1529				tvOverZ[unit] += deltaV[unit];
1530			}
1531			
1532			fogDensity += deltaFog;
1533		}
1534	}
1535}
1536
1537namespace {
1538	inline int Log2(int value) {
1539		if (value <= 1) {
1540			return 0;
1541		}
1542
1543		int result = 0;
1544
1545		while (value > 1) {
1546			result++;
1547			value >>= 1;
1548		}
1549
1550		return result;
1551	}
1552}
1553
1554void Rasterizer :: RasterPoint(const RasterPos& point, EGL_Fixed size) {
1555
1556	EGL_Fixed halfSize = size / 2;
1557
1558	I32 xmin = EGL_IntFromFixed(point.m_WindowCoords.x - halfSize + EGL_HALF);
1559	I32 xmax = xmin + ((size - EGL_HALF) >> EGL_PRECISION);
1560	I32 ymin = EGL_IntFromFixed(point.m_WindowCoords.y - halfSize + EGL_HALF);
1561	I32 ymax = ymin + ((size - EGL_HALF) >> EGL_PRECISION);
1562
1563	EGL_Fixed depth = point.m_WindowCoords.depth;
1564	FractionalColor baseColor = point.m_Color;
1565	EGL_Fixed fogDensity = point.m_FogDensity;
1566
1567
1568	if (!m_State->m_Point.SpriteEnabled && !m_State->m_Point.CoordReplaceEnabled) {
1569		EGL_Fixed tu[EGL_NUM_TEXTURE_UNITS], tv[EGL_NUM_TEXTURE_UNITS];
1570
1571		for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1572			tu[unit] = point.m_TextureCoords[unit].tu;
1573			tv[unit] = point.m_TextureCoords[unit].tv;
1574		}
1575
1576		for (I32 y = ymin; y <= ymax; y++) {
1577			for (I32 x = xmin; x <= xmax; x++) {
1578				Fragment(x, y, depth, tu, tv, fogDensity, baseColor);
1579			}
1580		}
1581	} else {
1582		EGL_Fixed delta = EGL_Inverse(size);
1583
1584		for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1585			if (m_UseMipmap[unit]) {
1586				EGL_Fixed maxDu = delta >> (16 - m_Texture[unit]->GetTexture(0)->GetLogWidth());
1587				EGL_Fixed maxDv = delta >> (16 - m_Texture[unit]->GetTexture(0)->GetLogHeight());
1588
1589				EGL_Fixed rho = maxDu + maxDv;
1590
1591				// we start with nearest/minification only selection; will add LINEAR later
1592
1593				m_RasterInfo.MipmapLevel[unit] = EGL_Min(Log2(rho), m_RasterInfo.MaxMipmapLevel[unit]);
1594			}
1595		}
1596
1597		EGL_Fixed tu[EGL_NUM_TEXTURE_UNITS], tv[EGL_NUM_TEXTURE_UNITS];
1598
1599		for (I32 y = ymin, tv0 = delta / 2; y <= ymax; y++, tv0 += delta) {
1600
1601			for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1602				tv[unit] = tv0;
1603			}
1604
1605			for (I32 x = xmin, tu0 = delta / 2; x <= xmax; x++, tu0 += delta) {
1606				for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1607					tu[unit] = tu0;
1608				}
1609
1610				Fragment(x, y, depth, tu, tv, fogDensity, baseColor);
1611			}
1612		}
1613	}
1614}
1615
1616#endif // !EGL_USE_JIT