• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <Device/Vertex.hpp>
17 
18 #include "Constants.hpp"
19 #include "Device/Polygon.hpp"
20 #include "Device/Primitive.hpp"
21 #include "Device/Renderer.hpp"
22 #include "Reactor/Reactor.hpp"
23 
24 namespace sw {
25 
SetupRoutine(const SetupProcessor::State & state)26 SetupRoutine::SetupRoutine(const SetupProcessor::State &state)
27     : state(state)
28 {
29 }
30 
~SetupRoutine()31 SetupRoutine::~SetupRoutine()
32 {
33 }
34 
generate()35 void SetupRoutine::generate()
36 {
37 	SetupFunction function;
38 	{
39 		Pointer<Byte> primitive(function.Arg<0>());
40 		Pointer<Byte> tri(function.Arg<1>());
41 		Pointer<Byte> polygon(function.Arg<2>());
42 		Pointer<Byte> data(function.Arg<3>());
43 
44 		Pointer<Byte> constants = *Pointer<Pointer<Byte> >(data + OFFSET(DrawData, constants));
45 
46 		const bool point = state.isDrawPoint;
47 		const bool line = state.isDrawLine;
48 		const bool triangle = state.isDrawTriangle;
49 
50 		const int V0 = OFFSET(Triangle, v0);
51 		const int V1 = (triangle || line) ? OFFSET(Triangle, v1) : OFFSET(Triangle, v0);
52 		const int V2 = triangle ? OFFSET(Triangle, v2) : (line ? OFFSET(Triangle, v1) : OFFSET(Triangle, v0));
53 
54 		Pointer<Byte> v0 = tri + V0;
55 		Pointer<Byte> v1 = tri + V1;
56 		Pointer<Byte> v2 = tri + V2;
57 
58 		Array<Int> X(16);
59 		Array<Int> Y(16);
60 
61 		X[0] = *Pointer<Int>(v0 + OFFSET(Vertex, projected.x));
62 		X[1] = *Pointer<Int>(v1 + OFFSET(Vertex, projected.x));
63 		X[2] = *Pointer<Int>(v2 + OFFSET(Vertex, projected.x));
64 
65 		Y[0] = *Pointer<Int>(v0 + OFFSET(Vertex, projected.y));
66 		Y[1] = *Pointer<Int>(v1 + OFFSET(Vertex, projected.y));
67 		Y[2] = *Pointer<Int>(v2 + OFFSET(Vertex, projected.y));
68 
69 		Int d = 1;  // Winding direction
70 
71 		// Culling
72 		if(triangle)
73 		{
74 			Float x0 = Float(X[0]);
75 			Float x1 = Float(X[1]);
76 			Float x2 = Float(X[2]);
77 
78 			Float y0 = Float(Y[0]);
79 			Float y1 = Float(Y[1]);
80 			Float y2 = Float(Y[2]);
81 
82 			Float A = (y0 - y2) * x1 + (y2 - y1) * x0 + (y1 - y0) * x2;  // Area
83 
84 			If(A == 0.0f)
85 			{
86 				Return(0);
87 			}
88 
89 			Int w0w1w2 = *Pointer<Int>(v0 + OFFSET(Vertex, w)) ^
90 			             *Pointer<Int>(v1 + OFFSET(Vertex, w)) ^
91 			             *Pointer<Int>(v2 + OFFSET(Vertex, w));
92 
93 			A = IfThenElse(w0w1w2 < 0, -A, A);
94 
95 			Bool frontFacing = (state.frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE) ? A > 0.0f : A < 0.0f;
96 
97 			if(state.cullMode & VK_CULL_MODE_FRONT_BIT)
98 			{
99 				If(frontFacing) Return(0);
100 			}
101 			if(state.cullMode & VK_CULL_MODE_BACK_BIT)
102 			{
103 				If(!frontFacing) Return(0);
104 			}
105 
106 			d = IfThenElse(A > 0.0f, d, Int(0));
107 
108 			If(frontFacing)
109 			{
110 				*Pointer<Byte8>(primitive + OFFSET(Primitive, clockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
111 				*Pointer<Byte8>(primitive + OFFSET(Primitive, invClockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
112 			}
113 			Else
114 			{
115 				*Pointer<Byte8>(primitive + OFFSET(Primitive, clockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
116 				*Pointer<Byte8>(primitive + OFFSET(Primitive, invClockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
117 			}
118 		}
119 		else
120 		{
121 			*Pointer<Byte8>(primitive + OFFSET(Primitive, clockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
122 			*Pointer<Byte8>(primitive + OFFSET(Primitive, invClockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
123 		}
124 
125 		Int n = *Pointer<Int>(polygon + OFFSET(Polygon, n));
126 		Int m = *Pointer<Int>(polygon + OFFSET(Polygon, i));
127 
128 		If(m != 0 || Bool(!triangle))  // Clipped triangle; reproject
129 		{
130 			Pointer<Byte> V = polygon + OFFSET(Polygon, P) + m * sizeof(void *) * 16;
131 
132 			Int i = 0;
133 
134 			Do
135 			{
136 				Pointer<Float4> p = *Pointer<Pointer<Float4> >(V + i * sizeof(void *));
137 				Float4 v = *Pointer<Float4>(p, 16);
138 
139 				Float w = v.w;
140 				Float rhw = IfThenElse(w != 0.0f, 1.0f / w, Float(1.0f));
141 
142 				X[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData, X0xF)) + v.x * rhw * *Pointer<Float>(data + OFFSET(DrawData, WxF)));
143 				Y[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData, Y0xF)) + v.y * rhw * *Pointer<Float>(data + OFFSET(DrawData, HxF)));
144 
145 				i++;
146 			}
147 			Until(i >= n);
148 		}
149 
150 		// Vertical range
151 		Int yMin = Y[0];
152 		Int yMax = Y[0];
153 
154 		Int i = 1;
155 
156 		Do
157 		{
158 			yMin = Min(Y[i], yMin);
159 			yMax = Max(Y[i], yMax);
160 
161 			i++;
162 		}
163 		Until(i >= n);
164 
165 		constexpr int subPixB = vk::SUBPIXEL_PRECISION_BITS;
166 		constexpr int subPixM = vk::SUBPIXEL_PRECISION_MASK;
167 		constexpr float subPixF = vk::SUBPIXEL_PRECISION_FACTOR;
168 
169 		if(state.enableMultiSampling)
170 		{
171 			yMin = (yMin + Constants::yMinMultiSampleOffset) >> subPixB;
172 			yMax = (yMax + Constants::yMaxMultiSampleOffset) >> subPixB;
173 		}
174 		else
175 		{
176 			yMin = (yMin + subPixM) >> subPixB;
177 			yMax = (yMax + subPixM) >> subPixB;
178 		}
179 
180 		yMin = Max(yMin, *Pointer<Int>(data + OFFSET(DrawData, scissorY0)));
181 		yMax = Min(yMax, *Pointer<Int>(data + OFFSET(DrawData, scissorY1)));
182 
183 		// If yMin and yMax are initially negative, the scissor clamping above will typically result
184 		// in yMin == 0 and yMax unchanged. We bail as we don't need to rasterize this primitive, and
185 		// code below assumes yMin < yMax.
186 		If(yMin >= yMax)
187 		{
188 			Return(0);
189 		}
190 
191 		For(Int q = 0, q < state.multiSampleCount, q++)
192 		{
193 			Array<Int> Xq(16);
194 			Array<Int> Yq(16);
195 
196 			Int i = 0;
197 
198 			Do
199 			{
200 				Xq[i] = X[i];
201 				Yq[i] = Y[i];
202 
203 				if(state.enableMultiSampling)
204 				{
205 					// The subtraction here is because we're not moving the point, we're testing the edge against it
206 					Xq[i] = Xq[i] - *Pointer<Int>(constants + OFFSET(Constants, Xf) + q * sizeof(int));
207 					Yq[i] = Yq[i] - *Pointer<Int>(constants + OFFSET(Constants, Yf) + q * sizeof(int));
208 				}
209 
210 				i++;
211 			}
212 			Until(i >= n);
213 
214 			Pointer<Byte> leftEdge = Pointer<Byte>(primitive + OFFSET(Primitive, outline->left)) + q * sizeof(Primitive);
215 			Pointer<Byte> rightEdge = Pointer<Byte>(primitive + OFFSET(Primitive, outline->right)) + q * sizeof(Primitive);
216 
217 			if(state.enableMultiSampling)
218 			{
219 				Int xMin = *Pointer<Int>(data + OFFSET(DrawData, scissorX0));
220 				Int xMax = *Pointer<Int>(data + OFFSET(DrawData, scissorX1));
221 				Short x = Short(Clamp((X[0] + subPixM) >> subPixB, xMin, xMax));
222 
223 				For(Int y = yMin - 1, y < yMax + 1, y++)
224 				{
225 					*Pointer<Short>(leftEdge + y * sizeof(Primitive::Span)) = x;
226 					*Pointer<Short>(rightEdge + y * sizeof(Primitive::Span)) = x;
227 				}
228 			}
229 
230 			Xq[n] = Xq[0];
231 			Yq[n] = Yq[0];
232 
233 			// Rasterize
234 			{
235 				Int i = 0;
236 
237 				Do
238 				{
239 					edge(primitive, data, Xq[i + 1 - d], Yq[i + 1 - d], Xq[i + d], Yq[i + d], q);
240 
241 					i++;
242 				}
243 				Until(i >= n);
244 			}
245 
246 			if(!state.enableMultiSampling)
247 			{
248 				For(, yMin < yMax && *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + yMin * sizeof(Primitive::Span)), yMin++)
249 				{
250 					// Increments yMin
251 				}
252 
253 				For(, yMax > yMin && *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + (yMax - 1) * sizeof(Primitive::Span)), yMax--)
254 				{
255 					// Decrements yMax
256 				}
257 
258 				If(yMin == yMax)
259 				{
260 					Return(0);
261 				}
262 
263 				*Pointer<Short>(leftEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
264 				*Pointer<Short>(rightEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
265 				*Pointer<Short>(leftEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
266 				*Pointer<Short>(rightEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
267 			}
268 		}
269 
270 		*Pointer<Int>(primitive + OFFSET(Primitive, yMin)) = yMin;
271 		*Pointer<Int>(primitive + OFFSET(Primitive, yMax)) = yMax;
272 
273 		// Sort by minimum y
274 		if(triangle)
275 		{
276 			Float y0 = *Pointer<Float>(v0 + OFFSET(Vertex, y));
277 			Float y1 = *Pointer<Float>(v1 + OFFSET(Vertex, y));
278 			Float y2 = *Pointer<Float>(v2 + OFFSET(Vertex, y));
279 
280 			Float yMin = Min(Min(y0, y1), y2);
281 
282 			conditionalRotate1(yMin == y1, v0, v1, v2);
283 			conditionalRotate2(yMin == y2, v0, v1, v2);
284 		}
285 
286 		// Sort by maximum w
287 		if(triangle)
288 		{
289 			Float w0 = *Pointer<Float>(v0 + OFFSET(Vertex, w));
290 			Float w1 = *Pointer<Float>(v1 + OFFSET(Vertex, w));
291 			Float w2 = *Pointer<Float>(v2 + OFFSET(Vertex, w));
292 
293 			Float wMax = Max(Max(w0, w1), w2);
294 
295 			conditionalRotate1(wMax == w1, v0, v1, v2);
296 			conditionalRotate2(wMax == w2, v0, v1, v2);
297 		}
298 
299 		Float w0 = *Pointer<Float>(v0 + OFFSET(Vertex, w));
300 		Float w1 = *Pointer<Float>(v1 + OFFSET(Vertex, w));
301 		Float w2 = *Pointer<Float>(v2 + OFFSET(Vertex, w));
302 
303 		Float4 w012;
304 
305 		w012.x = w0;
306 		w012.y = w1;
307 		w012.z = w2;
308 		w012.w = 1;
309 
310 		Float rhw0 = *Pointer<Float>(v0 + OFFSET(Vertex, projected.w));
311 
312 		Int X0 = *Pointer<Int>(v0 + OFFSET(Vertex, projected.x));
313 		Int X1 = *Pointer<Int>(v1 + OFFSET(Vertex, projected.x));
314 		Int X2 = *Pointer<Int>(v2 + OFFSET(Vertex, projected.x));
315 
316 		Int Y0 = *Pointer<Int>(v0 + OFFSET(Vertex, projected.y));
317 		Int Y1 = *Pointer<Int>(v1 + OFFSET(Vertex, projected.y));
318 		Int Y2 = *Pointer<Int>(v2 + OFFSET(Vertex, projected.y));
319 
320 		if(point)
321 		{
322 			*Pointer<Float>(primitive + OFFSET(Primitive, pointCoordX)) = Float(1.0f / subPixF) * Float(X0);
323 			*Pointer<Float>(primitive + OFFSET(Primitive, pointCoordY)) = Float(1.0f / subPixF) * Float(Y0);
324 		}
325 
326 		if(line)
327 		{
328 			X2 = X1 + Y1 - Y0;
329 			Y2 = Y1 + X0 - X1;
330 		}
331 
332 		Float dx = Float(X0) * (1.0f / subPixF);
333 		Float dy = Float(Y0) * (1.0f / subPixF);
334 
335 		X1 -= X0;
336 		Y1 -= Y0;
337 
338 		X2 -= X0;
339 		Y2 -= Y0;
340 
341 		Float x1 = w1 * (1.0f / subPixF) * Float(X1);
342 		Float y1 = w1 * (1.0f / subPixF) * Float(Y1);
343 
344 		Float x2 = w2 * (1.0f / subPixF) * Float(X2);
345 		Float y2 = w2 * (1.0f / subPixF) * Float(Y2);
346 
347 		Float a = x1 * y2 - x2 * y1;
348 
349 		Float4 xQuad = Float4(0, 1, 0, 1) - Float4(dx);
350 		Float4 yQuad = Float4(0, 0, 1, 1) - Float4(dy);
351 
352 		*Pointer<Float4>(primitive + OFFSET(Primitive, xQuad), 16) = xQuad;
353 		*Pointer<Float4>(primitive + OFFSET(Primitive, yQuad), 16) = yQuad;
354 
355 		Float4 M[3];
356 
357 		M[0] = Float4(0, 0, 0, 0);
358 		M[1] = Float4(0, 0, 0, 0);
359 		M[2] = Float4(0, 0, 0, 0);
360 
361 		M[0].z = rhw0;
362 
363 		If(a != 0.0f)
364 		{
365 			Float A = 1.0f / a;
366 			Float D = A * rhw0;
367 
368 			M[0].x = (y1 * w2 - y2 * w1) * D;
369 			M[0].y = (x2 * w1 - x1 * w2) * D;
370 			//	M[0].z = rhw0;
371 			//	M[0].w = 0;
372 
373 			M[1].x = y2 * A;
374 			M[1].y = -x2 * A;
375 			//	M[1].z = 0;
376 			//	M[1].w = 0;
377 
378 			M[2].x = -y1 * A;
379 			M[2].y = x1 * A;
380 			//	M[2].z = 0;
381 			//	M[2].w = 0;
382 		}
383 
384 		if(state.interpolateW)
385 		{
386 			Float4 ABC = M[0] + M[1] + M[2];
387 
388 			Float4 A = ABC.x;
389 			Float4 B = ABC.y;
390 			Float4 C = ABC.z;
391 
392 			*Pointer<Float4>(primitive + OFFSET(Primitive, w.A), 16) = A;
393 			*Pointer<Float4>(primitive + OFFSET(Primitive, w.B), 16) = B;
394 			*Pointer<Float4>(primitive + OFFSET(Primitive, w.C), 16) = C;
395 		}
396 
397 		if(state.interpolateZ)
398 		{
399 			Float z0 = *Pointer<Float>(v0 + OFFSET(Vertex, projected.z));
400 			Float z1 = *Pointer<Float>(v1 + OFFSET(Vertex, projected.z));
401 			Float z2 = *Pointer<Float>(v2 + OFFSET(Vertex, projected.z));
402 
403 			z1 -= z0;
404 			z2 -= z0;
405 
406 			Float4 A;
407 			Float4 B;
408 			Float4 C;
409 
410 			if(!point)
411 			{
412 				Float x1 = Float(X1) * (1.0f / subPixF);
413 				Float y1 = Float(Y1) * (1.0f / subPixF);
414 				Float x2 = Float(X2) * (1.0f / subPixF);
415 				Float y2 = Float(Y2) * (1.0f / subPixF);
416 
417 				Float D = *Pointer<Float>(data + OFFSET(DrawData, depthRange)) / (x1 * y2 - x2 * y1);
418 
419 				Float a = (y2 * z1 - y1 * z2) * D;
420 				Float b = (x1 * z2 - x2 * z1) * D;
421 
422 				A = Float4(a);
423 				B = Float4(b);
424 			}
425 			else
426 			{
427 				A = Float4(0, 0, 0, 0);
428 				B = Float4(0, 0, 0, 0);
429 			}
430 
431 			*Pointer<Float4>(primitive + OFFSET(Primitive, z.A), 16) = A;
432 			*Pointer<Float4>(primitive + OFFSET(Primitive, z.B), 16) = B;
433 
434 			Float c = z0;
435 
436 			if(state.applySlopeDepthBias)
437 			{
438 				Float bias = Max(Abs(Float(A.x)), Abs(Float(B.x)));
439 				bias *= *Pointer<Float>(data + OFFSET(DrawData, slopeDepthBias));
440 
441 				c += bias;
442 			}
443 
444 			C = Float4(c * *Pointer<Float>(data + OFFSET(DrawData, depthRange)) + *Pointer<Float>(data + OFFSET(DrawData, depthNear)));
445 
446 			*Pointer<Float4>(primitive + OFFSET(Primitive, z.C), 16) = C;
447 		}
448 
449 		for(int interpolant = 0; interpolant < MAX_INTERFACE_COMPONENTS; interpolant++)
450 		{
451 			if(state.gradient[interpolant].Type != SpirvShader::ATTRIBTYPE_UNUSED)
452 			{
453 				setupGradient(primitive, tri, w012, M, v0, v1, v2,
454 				              OFFSET(Vertex, v[interpolant]),
455 				              OFFSET(Primitive, V[interpolant]),
456 				              state.gradient[interpolant].Flat,
457 				              !state.gradient[interpolant].NoPerspective);
458 			}
459 		}
460 
461 		for(unsigned int i = 0; i < state.numClipDistances; i++)
462 		{
463 			setupGradient(primitive, tri, w012, M, v0, v1, v2,
464 			              OFFSET(Vertex, clipDistance[i]),
465 			              OFFSET(Primitive, clipDistance[i]),
466 			              false, true);
467 		}
468 
469 		for(unsigned int i = 0; i < state.numCullDistances; i++)
470 		{
471 			setupGradient(primitive, tri, w012, M, v0, v1, v2,
472 			              OFFSET(Vertex, cullDistance[i]),
473 			              OFFSET(Primitive, cullDistance[i]),
474 			              false, true);
475 		}
476 
477 		Return(1);
478 	}
479 
480 	routine = function("SetupRoutine");
481 }
482 
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 perspective)483 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 perspective)
484 {
485 	if(!flat)
486 	{
487 		Float4 i;
488 		i.x = *Pointer<Float>(v0 + attribute);
489 		i.y = *Pointer<Float>(v1 + attribute);
490 		i.z = *Pointer<Float>(v2 + attribute);
491 		i.w = 0;
492 
493 		if(!perspective)
494 		{
495 			i *= w012;
496 		}
497 
498 		Float4 A = i.xxxx * m[0];
499 		Float4 B = i.yyyy * m[1];
500 		Float4 C = i.zzzz * m[2];
501 
502 		C = A + B + C;
503 
504 		A = C.xxxx;
505 		B = C.yyyy;
506 		C = C.zzzz;
507 
508 		*Pointer<Float4>(primitive + planeEquation + 0, 16) = A;
509 		*Pointer<Float4>(primitive + planeEquation + 16, 16) = B;
510 		*Pointer<Float4>(primitive + planeEquation + 32, 16) = C;
511 	}
512 	else
513 	{
514 		int leadingVertex = OFFSET(Triangle, v0);
515 		Float C = *Pointer<Float>(triangle + leadingVertex + attribute);
516 
517 		*Pointer<Float4>(primitive + planeEquation + 0, 16) = Float4(0, 0, 0, 0);
518 		*Pointer<Float4>(primitive + planeEquation + 16, 16) = Float4(0, 0, 0, 0);
519 		*Pointer<Float4>(primitive + planeEquation + 32, 16) = Float4(C);
520 	}
521 }
522 
edge(Pointer<Byte> & primitive,Pointer<Byte> & data,const Int & Xa,const Int & Ya,const Int & Xb,const Int & Yb,Int & q)523 void SetupRoutine::edge(Pointer<Byte> &primitive, Pointer<Byte> &data, const Int &Xa, const Int &Ya, const Int &Xb, const Int &Yb, Int &q)
524 {
525 	If(Ya != Yb)
526 	{
527 		Bool swap = Yb < Ya;
528 
529 		Int X1 = IfThenElse(swap, Xb, Xa);
530 		Int X2 = IfThenElse(swap, Xa, Xb);
531 		Int Y1 = IfThenElse(swap, Yb, Ya);
532 		Int Y2 = IfThenElse(swap, Ya, Yb);
533 
534 		constexpr int subPixB = vk::SUBPIXEL_PRECISION_BITS;
535 		constexpr int subPixM = vk::SUBPIXEL_PRECISION_MASK;
536 
537 		Int y1 = Max((Y1 + subPixM) >> subPixB, *Pointer<Int>(data + OFFSET(DrawData, scissorY0)));
538 		Int y2 = Min((Y2 + subPixM) >> subPixB, *Pointer<Int>(data + OFFSET(DrawData, scissorY1)));
539 
540 		If(y1 < y2)
541 		{
542 			Int xMin = *Pointer<Int>(data + OFFSET(DrawData, scissorX0));
543 			Int xMax = *Pointer<Int>(data + OFFSET(DrawData, scissorX1));
544 
545 			Pointer<Byte> leftEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->left);
546 			Pointer<Byte> rightEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->right);
547 			Pointer<Byte> edge = IfThenElse(swap, rightEdge, leftEdge);
548 
549 			// Deltas
550 			Int DX12 = X2 - X1;
551 			Int DY12 = Y2 - Y1;
552 
553 			Int FDX12 = DX12 << subPixB;
554 			Int FDY12 = DY12 << subPixB;
555 
556 			Int X = DX12 * ((y1 << subPixB) - Y1) + (X1 & subPixM) * DY12;
557 			Int x = (X1 >> subPixB) + X / FDY12;  // Edge
558 			Int d = X % FDY12;                    // Error-term
559 			Int ceil = -d >> 31;                  // Ceiling division: remainder <= 0
560 			x -= ceil;
561 			d -= ceil & FDY12;
562 
563 			Int Q = FDX12 / FDY12;  // Edge-step
564 			Int R = FDX12 % FDY12;  // Error-step
565 			Int floor = R >> 31;    // Flooring division: remainder >= 0
566 			Q += floor;
567 			R += floor & FDY12;
568 
569 			Int D = FDY12;  // Error-overflow
570 			Int y = y1;
571 
572 			Do
573 			{
574 				*Pointer<Short>(edge + y * sizeof(Primitive::Span)) = Short(Clamp(x, xMin, xMax));
575 
576 				x += Q;
577 				d += R;
578 
579 				Int overflow = -d >> 31;
580 
581 				d -= D & overflow;
582 				x -= overflow;
583 
584 				y++;
585 			}
586 			Until(y >= y2);
587 		}
588 	}
589 }
590 
conditionalRotate1(Bool condition,Pointer<Byte> & v0,Pointer<Byte> & v1,Pointer<Byte> & v2)591 void SetupRoutine::conditionalRotate1(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
592 {
593 #if 0  // Rely on LLVM optimization
594 		If(condition)
595 		{
596 			Pointer<Byte> vX;
597 
598 			vX = v0;
599 			v0 = v1;
600 			v1 = v2;
601 			v2 = vX;
602 		}
603 #else
604 	Pointer<Byte> vX = v0;
605 	v0 = IfThenElse(condition, v1, v0);
606 	v1 = IfThenElse(condition, v2, v1);
607 	v2 = IfThenElse(condition, vX, v2);
608 #endif
609 }
610 
conditionalRotate2(Bool condition,Pointer<Byte> & v0,Pointer<Byte> & v1,Pointer<Byte> & v2)611 void SetupRoutine::conditionalRotate2(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
612 {
613 #if 0  // Rely on LLVM optimization
614 		If(condition)
615 		{
616 			Pointer<Byte> vX;
617 
618 			vX = v2;
619 			v2 = v1;
620 			v1 = v0;
621 			v0 = vX;
622 		}
623 #else
624 	Pointer<Byte> vX = v2;
625 	v2 = IfThenElse(condition, v1, v2);
626 	v1 = IfThenElse(condition, v0, v1);
627 	v0 = IfThenElse(condition, vX, v0);
628 #endif
629 }
630 
getRoutine()631 SetupFunction::RoutineType SetupRoutine::getRoutine()
632 {
633 	return routine;
634 }
635 
636 }  // namespace sw
637