Home | History | Annotate | Download | only in Shader
      1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "SetupRoutine.hpp"
     16 
     17 #include "Constants.hpp"
     18 #include "Renderer/Primitive.hpp"
     19 #include "Renderer/Polygon.hpp"
     20 #include "Renderer/Renderer.hpp"
     21 #include "Reactor/Reactor.hpp"
     22 
     23 namespace sw
     24 {
     25 	extern bool complementaryDepthBuffer;
     26 	extern TranscendentalPrecision logPrecision;
     27 	extern bool leadingVertexFirst;
     28 
     29 	SetupRoutine::SetupRoutine(const SetupProcessor::State &state) : state(state)
     30 	{
     31 		routine = 0;
     32 	}
     33 
     34 	SetupRoutine::~SetupRoutine()
     35 	{
     36 	}
     37 
     38 	void SetupRoutine::generate()
     39 	{
     40 		Function<Bool(Pointer<Byte>, Pointer<Byte>, Pointer<Byte>, Pointer<Byte>)> function;
     41 		{
     42 			Pointer<Byte> primitive(function.Arg<0>());
     43 			Pointer<Byte> tri(function.Arg<1>());
     44 			Pointer<Byte> polygon(function.Arg<2>());
     45 			Pointer<Byte> data(function.Arg<3>());
     46 
     47 			Pointer<Byte> constants = *Pointer<Pointer<Byte> >(data + OFFSET(DrawData,constants));
     48 
     49 			const bool point = state.isDrawPoint;
     50 			const bool sprite = state.pointSprite;
     51 			const bool line = state.isDrawLine;
     52 			const bool triangle = state.isDrawSolidTriangle || sprite;
     53 			const bool solidTriangle = state.isDrawSolidTriangle;
     54 
     55 			const int V0 = OFFSET(Triangle,v0);
     56 			const int V1 = (triangle || line) ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0);
     57 			const int V2 = triangle ? OFFSET(Triangle,v2) : (line ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0));
     58 
     59 			int pos = state.positionRegister;
     60 
     61 			Pointer<Byte> v0 = tri + V0;
     62 			Pointer<Byte> v1 = tri + V1;
     63 			Pointer<Byte> v2 = tri + V2;
     64 
     65 			Array<Int> X(16);
     66 			Array<Int> Y(16);
     67 
     68 			X[0] = *Pointer<Int>(v0 + OFFSET(Vertex,X));
     69 			X[1] = *Pointer<Int>(v1 + OFFSET(Vertex,X));
     70 			X[2] = *Pointer<Int>(v2 + OFFSET(Vertex,X));
     71 
     72 			Y[0] = *Pointer<Int>(v0 + OFFSET(Vertex,Y));
     73 			Y[1] = *Pointer<Int>(v1 + OFFSET(Vertex,Y));
     74 			Y[2] = *Pointer<Int>(v2 + OFFSET(Vertex,Y));
     75 
     76 			Int d = 1;     // Winding direction
     77 
     78 			// Culling
     79 			if(solidTriangle)
     80 			{
     81 				Float x0 = Float(X[0]);
     82 				Float x1 = Float(X[1]);
     83 				Float x2 = Float(X[2]);
     84 
     85 				Float y0 = Float(Y[0]);
     86 				Float y1 = Float(Y[1]);
     87 				Float y2 = Float(Y[2]);
     88 
     89 				Float A = (y2 - y0) * x1 + (y1 - y2) * x0 + (y0 - y1) * x2;   // Area
     90 
     91 				If(A == 0.0f)
     92 				{
     93 					Return(false);
     94 				}
     95 
     96 				Int w0w1w2 = *Pointer<Int>(v0 + pos * 16 + 12) ^
     97 							 *Pointer<Int>(v1 + pos * 16 + 12) ^
     98 							 *Pointer<Int>(v2 + pos * 16 + 12);
     99 
    100 				A = IfThenElse(w0w1w2 < 0, -A, A);
    101 
    102 				if(state.cullMode == CULL_CLOCKWISE)
    103 				{
    104 					If(A >= 0.0f) Return(false);
    105 				}
    106 				else if(state.cullMode == CULL_COUNTERCLOCKWISE)
    107 				{
    108 					If(A <= 0.0f) Return(false);
    109 				}
    110 
    111 				d = IfThenElse(A < 0.0f, d, Int(0));
    112 
    113 				if(state.twoSidedStencil)
    114 				{
    115 					If(A > 0.0f)
    116 					{
    117 						*Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
    118 						*Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
    119 					}
    120 					Else
    121 					{
    122 						*Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
    123 						*Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
    124 					}
    125 				}
    126 
    127 				if(state.vFace)
    128 				{
    129 					*Pointer<Float>(primitive + OFFSET(Primitive,area)) = 0.5f * A;
    130 				}
    131 			}
    132 			else
    133 			{
    134 				if(state.twoSidedStencil)
    135 				{
    136 					*Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
    137 					*Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
    138 				}
    139 			}
    140 
    141 			Int n = *Pointer<Int>(polygon + OFFSET(Polygon,n));
    142 			Int m = *Pointer<Int>(polygon + OFFSET(Polygon,i));
    143 
    144 			If(m != 0 || Bool(!solidTriangle))   // Clipped triangle; reproject
    145 			{
    146 				Pointer<Byte> V = polygon + OFFSET(Polygon,P) + m * sizeof(void*) * 16;
    147 
    148 				Int i = 0;
    149 
    150 				Do
    151 				{
    152 					Pointer<Float4> p = *Pointer<Pointer<Float4> >(V + i * sizeof(void*));
    153 					Float4 v = *Pointer<Float4>(p, 16);
    154 
    155 					Float w = v.w;
    156 					Float rhw = IfThenElse(w != 0.0f, 1.0f / w, Float(1.0f));
    157 
    158 					X[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData,X0x16)) + v.x * rhw * *Pointer<Float>(data + OFFSET(DrawData,Wx16)));
    159 					Y[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData,Y0x16)) + v.y * rhw * *Pointer<Float>(data + OFFSET(DrawData,Hx16)));
    160 
    161 					i++;
    162 				}
    163 				Until(i >= n)
    164 			}
    165 
    166 			// Vertical range
    167 			Int yMin = Y[0];
    168 			Int yMax = Y[0];
    169 
    170 			Int i = 1;
    171 
    172 			Do
    173 			{
    174 				yMin = Min(Y[i], yMin);
    175 				yMax = Max(Y[i], yMax);
    176 
    177 				i++;
    178 			}
    179 			Until(i >= n)
    180 
    181 			if(state.multiSample > 1)
    182 			{
    183 				yMin = (yMin + 0x0A) >> 4;
    184 				yMax = (yMax + 0x14) >> 4;
    185 			}
    186 			else
    187 			{
    188 				yMin = (yMin + 0x0F) >> 4;
    189 				yMax = (yMax + 0x0F) >> 4;
    190 			}
    191 
    192 			If(yMin == yMax)
    193 			{
    194 				Return(false);
    195 			}
    196 
    197 			yMin = Max(yMin, *Pointer<Int>(data + OFFSET(DrawData,scissorY0)));
    198 			yMax = Min(yMax, *Pointer<Int>(data + OFFSET(DrawData,scissorY1)));
    199 
    200 			For(Int q = 0, q < state.multiSample, q++)
    201 			{
    202 				Array<Int> Xq(16);
    203 				Array<Int> Yq(16);
    204 
    205 				Int i = 0;
    206 
    207 				Do
    208 				{
    209 					Xq[i] = X[i];
    210 					Yq[i] = Y[i];
    211 
    212 					if(state.multiSample > 1)
    213 					{
    214 						Xq[i] = Xq[i] + *Pointer<Int>(constants + OFFSET(Constants,Xf) + q * sizeof(int));
    215 						Yq[i] = Yq[i] + *Pointer<Int>(constants + OFFSET(Constants,Yf) + q * sizeof(int));
    216 					}
    217 
    218 					i++;
    219 				}
    220 				Until(i >= n)
    221 
    222 				Pointer<Byte> leftEdge = Pointer<Byte>(primitive + OFFSET(Primitive,outline->left)) + q * sizeof(Primitive);
    223 				Pointer<Byte> rightEdge = Pointer<Byte>(primitive + OFFSET(Primitive,outline->right)) + q * sizeof(Primitive);
    224 
    225 				if(state.multiSample > 1)
    226 				{
    227 					Int xMin = *Pointer<Int>(data + OFFSET(DrawData, scissorX0));
    228 					Int xMax = *Pointer<Int>(data + OFFSET(DrawData, scissorX1));
    229 					Short x = Short(Clamp((X[0] + 0xF) >> 4, xMin, xMax));
    230 
    231 					For(Int y = yMin - 1, y < yMax + 1, y++)
    232 					{
    233 						*Pointer<Short>(leftEdge + y * sizeof(Primitive::Span)) = x;
    234 						*Pointer<Short>(rightEdge + y * sizeof(Primitive::Span)) = x;
    235 					}
    236 				}
    237 
    238 				Xq[n] = Xq[0];
    239 				Yq[n] = Yq[0];
    240 
    241 				// Rasterize
    242 				{
    243 					Int i = 0;
    244 
    245 					Do
    246 					{
    247 						edge(primitive, data, Xq[i + 1 - d], Yq[i + 1 - d], Xq[i + d], Yq[i + d], q);
    248 
    249 						i++;
    250 					}
    251 					Until(i >= n)
    252 				}
    253 
    254 				if(state.multiSample == 1)
    255 				{
    256 					For(, yMin < yMax && *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + yMin * sizeof(Primitive::Span)), yMin++)
    257 					{
    258 						// Increments yMin
    259 					}
    260 
    261 					For(, yMax > yMin && *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + (yMax - 1) * sizeof(Primitive::Span)), yMax--)
    262 					{
    263 						// Decrements yMax
    264 					}
    265 
    266 					If(yMin == yMax)
    267 					{
    268 						Return(false);
    269 					}
    270 
    271 					*Pointer<Short>(leftEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
    272 					*Pointer<Short>(rightEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
    273 					*Pointer<Short>(leftEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
    274 					*Pointer<Short>(rightEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
    275 				}
    276 			}
    277 
    278 			*Pointer<Int>(primitive + OFFSET(Primitive,yMin)) = yMin;
    279 			*Pointer<Int>(primitive + OFFSET(Primitive,yMax)) = yMax;
    280 
    281 			// Sort by minimum y
    282 			if(solidTriangle && logPrecision >= WHQL)
    283 			{
    284 				Float y0 = *Pointer<Float>(v0 + pos * 16 + 4);
    285 				Float y1 = *Pointer<Float>(v1 + pos * 16 + 4);
    286 				Float y2 = *Pointer<Float>(v2 + pos * 16 + 4);
    287 
    288 				Float yMin = Min(Min(y0, y1), y2);
    289 
    290 				conditionalRotate1(yMin == y1, v0, v1, v2);
    291 				conditionalRotate2(yMin == y2, v0, v1, v2);
    292 			}
    293 
    294 			// Sort by maximum w
    295 			if(solidTriangle)
    296 			{
    297 				Float w0 = *Pointer<Float>(v0 + pos * 16 + 12);
    298 				Float w1 = *Pointer<Float>(v1 + pos * 16 + 12);
    299 				Float w2 = *Pointer<Float>(v2 + pos * 16 + 12);
    300 
    301 				Float wMax = Max(Max(w0, w1), w2);
    302 
    303 				conditionalRotate1(wMax == w1, v0, v1, v2);
    304 				conditionalRotate2(wMax == w2, v0, v1, v2);
    305 			}
    306 
    307 			Float w0 = *Pointer<Float>(v0 + pos * 16 + 12);
    308 			Float w1 = *Pointer<Float>(v1 + pos * 16 + 12);
    309 			Float w2 = *Pointer<Float>(v2 + pos * 16 + 12);
    310 
    311 			Float4 w012;
    312 
    313 			w012.x = w0;
    314 			w012.y = w1;
    315 			w012.z = w2;
    316 			w012.w = 1;
    317 
    318 			Float rhw0 = *Pointer<Float>(v0 + OFFSET(Vertex,W));
    319 
    320 			Int X0 = *Pointer<Int>(v0 + OFFSET(Vertex,X));
    321 			Int X1 = *Pointer<Int>(v1 + OFFSET(Vertex,X));
    322 			Int X2 = *Pointer<Int>(v2 + OFFSET(Vertex,X));
    323 
    324 			Int Y0 = *Pointer<Int>(v0 + OFFSET(Vertex,Y));
    325 			Int Y1 = *Pointer<Int>(v1 + OFFSET(Vertex,Y));
    326 			Int Y2 = *Pointer<Int>(v2 + OFFSET(Vertex,Y));
    327 
    328 			if(line)
    329 			{
    330 				X2 = X1 + Y1 - Y0;
    331 				Y2 = Y1 + X0 - X1;
    332 			}
    333 
    334 			Float dx = Float(X0) * (1.0f / 16.0f);
    335 			Float dy = Float(Y0) * (1.0f / 16.0f);
    336 
    337 			X1 -= X0;
    338 			Y1 -= Y0;
    339 
    340 			X2 -= X0;
    341 			Y2 -= Y0;
    342 
    343 			Float x1 = w1 * (1.0f / 16.0f) * Float(X1);
    344 			Float y1 = w1 * (1.0f / 16.0f) * Float(Y1);
    345 
    346 			Float x2 = w2 * (1.0f / 16.0f) * Float(X2);
    347 			Float y2 = w2 * (1.0f / 16.0f) * Float(Y2);
    348 
    349 			Float a = x1 * y2 - x2 * y1;
    350 
    351 			Float4 xQuad = Float4(0, 1, 0, 1) - Float4(dx);
    352 			Float4 yQuad = Float4(0, 0, 1, 1) - Float4(dy);
    353 
    354 			*Pointer<Float4>(primitive + OFFSET(Primitive,xQuad), 16) = xQuad;
    355 			*Pointer<Float4>(primitive + OFFSET(Primitive,yQuad), 16) = yQuad;
    356 
    357 			Float4 M[3];
    358 
    359 			M[0] = Float4(0, 0, 0, 0);
    360 			M[1] = Float4(0, 0, 0, 0);
    361 			M[2] = Float4(0, 0, 0, 0);
    362 
    363 			M[0].z = rhw0;
    364 
    365 			If(a != 0.0f)
    366 			{
    367 				Float A = 1.0f / a;
    368 				Float D = A * rhw0;
    369 
    370 				M[0].x = (y1 * w2 - y2 * w1) * D;
    371 				M[0].y = (x2 * w1 - x1 * w2) * D;
    372 			//	M[0].z = rhw0;
    373 			//	M[0].w = 0;
    374 
    375 				M[1].x = y2 * A;
    376 				M[1].y = -x2 * A;
    377 			//	M[1].z = 0;
    378 			//	M[1].w = 0;
    379 
    380 				M[2].x = -y1 * A;
    381 				M[2].y = x1 * A;
    382 			//	M[2].z = 0;
    383 			//	M[2].w = 0;
    384 			}
    385 
    386 			if(state.interpolateW)
    387 			{
    388 				Float4 ABC = M[0] + M[1] + M[2];
    389 
    390 				Float4 A = ABC.x;
    391 				Float4 B = ABC.y;
    392 				Float4 C = ABC.z;
    393 
    394 				*Pointer<Float4>(primitive + OFFSET(Primitive,w.A), 16) = A;
    395 				*Pointer<Float4>(primitive + OFFSET(Primitive,w.B), 16) = B;
    396 				*Pointer<Float4>(primitive + OFFSET(Primitive,w.C), 16) = C;
    397 			}
    398 
    399 			if(state.interpolateZ)
    400 			{
    401 				Float z0 = *Pointer<Float>(v0 + OFFSET(Vertex,Z));
    402 				Float z1 = *Pointer<Float>(v1 + OFFSET(Vertex,Z));
    403 				Float z2 = *Pointer<Float>(v2 + OFFSET(Vertex,Z));
    404 
    405 				z1 -= z0;
    406 				z2 -= z0;
    407 
    408 				Float4 A;
    409 				Float4 B;
    410 				Float4 C;
    411 
    412 				if(!point)
    413 				{
    414 					Float x1 = Float(X1) * (1.0f / 16.0f);
    415 					Float y1 = Float(Y1) * (1.0f / 16.0f);
    416 					Float x2 = Float(X2) * (1.0f / 16.0f);
    417 					Float y2 = Float(Y2) * (1.0f / 16.0f);
    418 
    419 					Float D = *Pointer<Float>(data + OFFSET(DrawData,depthRange)) / (x1 * y2 - x2 * y1);
    420 
    421 					Float a = (y2 * z1 - y1 * z2) * D;
    422 					Float b = (x1 * z2 - x2 * z1) * D;
    423 
    424 					A = Float4(a);
    425 					B = Float4(b);
    426 				}
    427 				else
    428 				{
    429 					A = Float4(0, 0, 0, 0);
    430 					B = Float4(0, 0, 0, 0);
    431 				}
    432 
    433 				*Pointer<Float4>(primitive + OFFSET(Primitive,z.A), 16) = A;
    434 				*Pointer<Float4>(primitive + OFFSET(Primitive,z.B), 16) = B;
    435 
    436 				Float c = z0;
    437 
    438 				if(state.isDrawTriangle && state.slopeDepthBias)
    439 				{
    440 					Float bias = Max(Abs(Float(A.x)), Abs(Float(B.x)));
    441 					bias *= *Pointer<Float>(data + OFFSET(DrawData,slopeDepthBias));
    442 
    443 					if(complementaryDepthBuffer)
    444 					{
    445 						bias = -bias;
    446 					}
    447 
    448 					c += bias;
    449 				}
    450 
    451 				C = Float4(c * *Pointer<Float>(data + OFFSET(DrawData,depthRange)) + *Pointer<Float>(data + OFFSET(DrawData,depthNear)));
    452 
    453 				*Pointer<Float4>(primitive + OFFSET(Primitive,z.C), 16) = C;
    454 			}
    455 
    456 			for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
    457 			{
    458 				for(int component = 0; component < 4; component++)
    459 				{
    460 					int attribute = state.gradient[interpolant][component].attribute;
    461 					bool flat = state.gradient[interpolant][component].flat;
    462 					bool wrap = state.gradient[interpolant][component].wrap;
    463 
    464 					if(attribute != Unused)
    465 					{
    466 						setupGradient(primitive, tri, w012, M, v0, v1, v2, OFFSET(Vertex,v[attribute][component]), OFFSET(Primitive,V[interpolant][component]), flat, sprite, state.perspective, wrap, component);
    467 					}
    468 				}
    469 			}
    470 
    471 			if(state.fog.attribute == Fog)
    472 			{
    473 				setupGradient(primitive, tri, w012, M, v0, v1, v2, OFFSET(Vertex,f), OFFSET(Primitive,f), state.fog.flat, false, state.perspective, false, 0);
    474 			}
    475 
    476 			Return(true);
    477 		}
    478 
    479 		routine = function(L"SetupRoutine");
    480 	}
    481 
    482 	void SetupRoutine::setupGradient(Pointer<Byte> &primitive, Pointer<Byte> &triangle, Float4 &w012, Float4 (&m)[3], Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2, int attribute, int planeEquation, bool flat, bool sprite, bool perspective, bool wrap, int component)
    483 	{
    484 		Float4 i;
    485 
    486 		if(!flat)
    487 		{
    488 			if(!sprite)
    489 			{
    490 				i.x = *Pointer<Float>(v0 + attribute);
    491 				i.y = *Pointer<Float>(v1 + attribute);
    492 				i.z = *Pointer<Float>(v2 + attribute);
    493 				i.w = 0;
    494 			}
    495 			else
    496 			{
    497 				if(component == 0) i.x = 0.5f;
    498 				if(component == 1) i.x = 0.5f;
    499 				if(component == 2) i.x = 0.0f;
    500 				if(component == 3) i.x = 1.0f;
    501 
    502 				if(component == 0) i.y = 1.0f;
    503 				if(component == 1) i.y = 0.5f;
    504 				if(component == 2) i.y = 0.0f;
    505 				if(component == 3) i.y = 1.0f;
    506 
    507 				if(component == 0) i.z = 0.5f;
    508 				if(component == 1) i.z = 1.0f;
    509 				if(component == 2) i.z = 0.0f;
    510 				if(component == 3) i.z = 1.0f;
    511 
    512 				i.w = 0;
    513 			}
    514 
    515 			if(wrap)
    516 			{
    517 				Float m;
    518 
    519 				m = *Pointer<Float>(v0 + attribute);
    520 				m = Max(m, *Pointer<Float>(v1 + attribute));
    521 				m = Max(m, *Pointer<Float>(v2 + attribute));
    522 				m -= 0.5f;
    523 
    524 				// FIXME: Vectorize
    525 				If(Float(i.x) < m) i.x = i.x + 1.0f;
    526 				If(Float(i.y) < m) i.y = i.y + 1.0f;
    527 				If(Float(i.z) < m) i.z = i.z + 1.0f;
    528 			}
    529 
    530 			if(!perspective)
    531 			{
    532 				i *= w012;
    533 			}
    534 
    535 			Float4 A = i.xxxx * m[0];
    536 			Float4 B = i.yyyy * m[1];
    537 			Float4 C = i.zzzz * m[2];
    538 
    539 			C = A + B + C;
    540 
    541 			A = C.xxxx;
    542 			B = C.yyyy;
    543 			C = C.zzzz;
    544 
    545 			*Pointer<Float4>(primitive + planeEquation + 0, 16) = A;
    546 			*Pointer<Float4>(primitive + planeEquation + 16, 16) = B;
    547 			*Pointer<Float4>(primitive + planeEquation + 32, 16) = C;
    548 		}
    549 		else
    550 		{
    551 			int leadingVertex = leadingVertexFirst ? OFFSET(Triangle,v0) : OFFSET(Triangle,v2);
    552 			Float C = *Pointer<Float>(triangle + leadingVertex + attribute);
    553 
    554 			*Pointer<Float4>(primitive + planeEquation + 0, 16) = Float4(0, 0, 0, 0);
    555 			*Pointer<Float4>(primitive + planeEquation + 16, 16) = Float4(0, 0, 0, 0);
    556 			*Pointer<Float4>(primitive + planeEquation + 32, 16) = Float4(C);
    557 		}
    558 	}
    559 
    560 	void SetupRoutine::edge(Pointer<Byte> &primitive, Pointer<Byte> &data, const Int &Xa, const Int &Ya, const Int &Xb, const Int &Yb, Int &q)
    561 	{
    562 		If(Ya != Yb)
    563 		{
    564 			Bool swap = Yb < Ya;
    565 
    566 			Int X1 = IfThenElse(swap, Xb, Xa);
    567 			Int X2 = IfThenElse(swap, Xa, Xb);
    568 			Int Y1 = IfThenElse(swap, Yb, Ya);
    569 			Int Y2 = IfThenElse(swap, Ya, Yb);
    570 
    571 			Int y1 = Max((Y1 + 0x0000000F) >> 4, *Pointer<Int>(data + OFFSET(DrawData,scissorY0)));
    572 			Int y2 = Min((Y2 + 0x0000000F) >> 4, *Pointer<Int>(data + OFFSET(DrawData,scissorY1)));
    573 
    574 			If(y1 < y2)
    575 			{
    576 				Int xMin = *Pointer<Int>(data + OFFSET(DrawData,scissorX0));
    577 				Int xMax = *Pointer<Int>(data + OFFSET(DrawData,scissorX1));
    578 
    579 				Pointer<Byte> leftEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left);
    580 				Pointer<Byte> rightEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right);
    581 				Pointer<Byte> edge = IfThenElse(swap, rightEdge, leftEdge);
    582 
    583 				// Deltas
    584 				Int DX12 = X2 - X1;
    585 				Int DY12 = Y2 - Y1;
    586 
    587 				Int FDX12 = DX12 << 4;
    588 				Int FDY12 = DY12 << 4;
    589 
    590 				Int X = DX12 * ((y1 << 4) - Y1) + (X1 & 0x0000000F) * DY12;
    591 				Int x = (X1 >> 4) + X / FDY12;   // Edge
    592 				Int d = X % FDY12;               // Error-term
    593 				Int ceil = -d >> 31;             // Ceiling division: remainder <= 0
    594 				x -= ceil;
    595 				d -= ceil & FDY12;
    596 
    597 				Int Q = FDX12 / FDY12;   // Edge-step
    598 				Int R = FDX12 % FDY12;   // Error-step
    599 				Int floor = R >> 31;     // Flooring division: remainder >= 0
    600 				Q += floor;
    601 				R += floor & FDY12;
    602 
    603 				Int D = FDY12;   // Error-overflow
    604 				Int y = y1;
    605 
    606 				Do
    607 				{
    608 					*Pointer<Short>(edge + y * sizeof(Primitive::Span)) = Short(Clamp(x, xMin, xMax));
    609 
    610 					x += Q;
    611 					d += R;
    612 
    613 					Int overflow = -d >> 31;
    614 
    615 					d -= D & overflow;
    616 					x -= overflow;
    617 
    618 					y++;
    619 				}
    620 				Until(y >= y2)
    621 			}
    622 		}
    623 	}
    624 
    625 	void SetupRoutine::conditionalRotate1(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
    626 	{
    627 		#if 0   // Rely on LLVM optimization
    628 			If(condition)
    629 			{
    630 				Pointer<Byte> vX;
    631 
    632 				vX = v0;
    633 				v0 = v1;
    634 				v1 = v2;
    635 				v2 = vX;
    636 			}
    637 		#else
    638 			Pointer<Byte> vX = v0;
    639 			v0 = IfThenElse(condition, v1, v0);
    640 			v1 = IfThenElse(condition, v2, v1);
    641 			v2 = IfThenElse(condition, vX, v2);
    642 		#endif
    643 	}
    644 
    645 	void SetupRoutine::conditionalRotate2(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
    646 	{
    647 		#if 0   // Rely on LLVM optimization
    648 			If(condition)
    649 			{
    650 				Pointer<Byte> vX;
    651 
    652 				vX = v2;
    653 				v2 = v1;
    654 				v1 = v0;
    655 				v0 = vX;
    656 			}
    657 		#else
    658 			Pointer<Byte> vX = v2;
    659 			v2 = IfThenElse(condition, v1, v2);
    660 			v1 = IfThenElse(condition, v0, v1);
    661 			v0 = IfThenElse(condition, vX, v0);
    662 		#endif
    663 	}
    664 
    665 	Routine *SetupRoutine::getRoutine()
    666 	{
    667 		return routine;
    668 	}
    669 }
    670