blob: e52da921510eaa4fcb42d1a08b6a8bd467e7b377 [file] [log] [blame]
John Bauman89401822014-05-06 15:04:28 -04001// SwiftShader Software Renderer
2//
John Bauman19bac1e2014-05-06 15:23:49 -04003// Copyright(c) 2005-2012 TransGaming Inc.
John Bauman89401822014-05-06 15:04:28 -04004//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
10//
11
12#include "SetupRoutine.hpp"
13
14#include "Constants.hpp"
15#include "Renderer/Primitive.hpp"
16#include "Renderer/Polygon.hpp"
17#include "Renderer/Renderer.hpp"
John Bauman19bac1e2014-05-06 15:23:49 -040018#include "Reactor/Reactor.hpp"
John Bauman89401822014-05-06 15:04:28 -040019
20namespace sw
21{
22 extern bool complementaryDepthBuffer;
23 extern TranscendentalPrecision logPrecision;
24
25 SetupRoutine::SetupRoutine(const SetupProcessor::State &state) : state(state)
26 {
27 routine = 0;
28 }
29
30 SetupRoutine::~SetupRoutine()
31 {
32 }
33
34 void SetupRoutine::generate()
35 {
John Bauman66b8ab22014-05-06 15:57:45 -040036 Function<Bool, Pointer<Byte>, Pointer<Byte>, Pointer<Byte>, Pointer<Byte> > function;
John Bauman89401822014-05-06 15:04:28 -040037 {
38 Pointer<Byte> primitive(function.arg(0));
39 Pointer<Byte> tri(function.arg(1));
40 Pointer<Byte> polygon(function.arg(2));
41 Pointer<Byte> data(function.arg(3));
42
John Bauman66b8ab22014-05-06 15:57:45 -040043 Pointer<Byte> constants = *Pointer<Pointer<Byte> >(data + OFFSET(DrawData,constants));
John Bauman89401822014-05-06 15:04:28 -040044
45 const bool point = state.isDrawPoint;
46 const bool sprite = state.pointSprite;
47 const bool line = state.isDrawLine;
48 const bool triangle = state.isDrawSolidTriangle || sprite;
49 const bool solidTriangle = state.isDrawSolidTriangle;
50
51 const int V0 = OFFSET(Triangle,v0);
52 const int V1 = (triangle || line) ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0);
53 const int V2 = triangle ? OFFSET(Triangle,v2) : (line ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0));
54
55 int pos = state.positionRegister;
56
57 Pointer<Byte> v0 = tri + V0;
58 Pointer<Byte> v1 = tri + V1;
59 Pointer<Byte> v2 = tri + V2;
60
61 Array<Int> X(16);
62 Array<Int> Y(16);
63
64 X[0] = *Pointer<Int>(v0 + OFFSET(Vertex,X));
65 X[1] = *Pointer<Int>(v1 + OFFSET(Vertex,X));
66 X[2] = *Pointer<Int>(v2 + OFFSET(Vertex,X));
67
68 Y[0] = *Pointer<Int>(v0 + OFFSET(Vertex,Y));
69 Y[1] = *Pointer<Int>(v1 + OFFSET(Vertex,Y));
70 Y[2] = *Pointer<Int>(v2 + OFFSET(Vertex,Y));
71
72 Int d = 1; // Winding direction
73
74 // Culling
75 if(solidTriangle)
76 {
77 Float x0 = Float(X[0]);
78 Float x1 = Float(X[1]);
79 Float x2 = Float(X[2]);
80
81 Float y0 = Float(Y[0]);
82 Float y1 = Float(Y[1]);
83 Float y2 = Float(Y[2]);
84
85 Float A = (y2 - y0) * x1 + (y1 - y2) * x0 + (y0 - y1) * x2; // Area
86
John Bauman66b8ab22014-05-06 15:57:45 -040087 If(A == 0.0f)
John Bauman89401822014-05-06 15:04:28 -040088 {
89 Return(false);
90 }
91
Nicolas Capensc68df5f2014-05-07 01:14:21 -040092 Int w0w1w2 = *Pointer<Int>(v0 + pos * 16 + 12) ^
93 *Pointer<Int>(v1 + pos * 16 + 12) ^
94 *Pointer<Int>(v2 + pos * 16 + 12);
John Bauman89401822014-05-06 15:04:28 -040095
Nicolas Capensc68df5f2014-05-07 01:14:21 -040096 A = IfThenElse(w0w1w2 < 0, -A, A);
John Bauman89401822014-05-06 15:04:28 -040097
98 if(state.cullMode == Context::CULL_CLOCKWISE)
99 {
John Bauman66b8ab22014-05-06 15:57:45 -0400100 If(A >= 0.0f) Return(false);
John Bauman89401822014-05-06 15:04:28 -0400101 }
102 else if(state.cullMode == Context::CULL_COUNTERCLOCKWISE)
103 {
John Bauman66b8ab22014-05-06 15:57:45 -0400104 If(A <= 0.0f) Return(false);
John Bauman89401822014-05-06 15:04:28 -0400105 }
106
John Bauman66b8ab22014-05-06 15:57:45 -0400107 d = IfThenElse(A < 0.0f, d, Int(0));
John Bauman89401822014-05-06 15:04:28 -0400108
109 if(state.twoSidedStencil)
110 {
John Bauman66b8ab22014-05-06 15:57:45 -0400111 If(A > 0.0f)
John Bauman19bac1e2014-05-06 15:23:49 -0400112 {
113 *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0xFFFFFFFFFFFFFFFF);
114 *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0x0000000000000000);
115 }
116 Else
117 {
118 *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0x0000000000000000);
119 *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0xFFFFFFFFFFFFFFFF);
120 }
John Bauman89401822014-05-06 15:04:28 -0400121 }
122
123 if(state.vFace)
124 {
John Bauman66b8ab22014-05-06 15:57:45 -0400125 *Pointer<Float>(primitive + OFFSET(Primitive,area)) = 0.5f * A;
John Bauman89401822014-05-06 15:04:28 -0400126 }
127 }
128 else
129 {
130 if(state.twoSidedStencil)
131 {
132 *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0xFFFFFFFFFFFFFFFF);
133 *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0x0000000000000000);
134 }
135 }
136
137 Int n = *Pointer<Int>(polygon + OFFSET(Polygon,n));
138 Int m = *Pointer<Int>(polygon + OFFSET(Polygon,i));
139
140 If(m != 0 || Bool(!solidTriangle)) // Clipped triangle; reproject
141 {
142 Pointer<Byte> V = polygon + OFFSET(Polygon,P) + m * sizeof(void*) * 16;
143
144 Int i = 0;
145
146 Do
147 {
John Bauman66b8ab22014-05-06 15:57:45 -0400148 Pointer<Float4> p = *Pointer<Pointer<Float4> >(V + i * sizeof(void*));
John Bauman89401822014-05-06 15:04:28 -0400149 Float4 v = *Pointer<Float4>(p, 16);
150
151 Float w = v.w;
John Bauman66b8ab22014-05-06 15:57:45 -0400152 Float rhw = IfThenElse(w != 0.0f, 1.0f / w, Float(1.0f));
John Bauman89401822014-05-06 15:04:28 -0400153
John Bauman19bac1e2014-05-06 15:23:49 -0400154 X[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData,X0x16)) + v.x * rhw * *Pointer<Float>(data + OFFSET(DrawData,Wx16)));
155 Y[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData,Y0x16)) + v.y * rhw * *Pointer<Float>(data + OFFSET(DrawData,Hx16)));
John Bauman89401822014-05-06 15:04:28 -0400156
157 i++;
158 }
159 Until(i >= n)
160 }
161
162 // Vertical range
163 Int yMin = Y[0];
164 Int yMax = Y[0];
165
166 Int i = 1;
167
168 Do
169 {
John Bauman19bac1e2014-05-06 15:23:49 -0400170 yMin = Min(Y[i], yMin);
171 yMax = Max(Y[i], yMax);
John Bauman89401822014-05-06 15:04:28 -0400172
173 i++;
174 }
175 Until(i >= n)
176
177 if(state.multiSample > 1)
178 {
179 yMin = (yMin + 0x0A) >> 4;
180 yMax = (yMax + 0x14) >> 4;
181 }
182 else
183 {
184 yMin = (yMin + 0x0F) >> 4;
185 yMax = (yMax + 0x0F) >> 4;
186 }
187
188 If(yMin == yMax)
189 {
190 Return(false);
191 }
John Bauman19bac1e2014-05-06 15:23:49 -0400192
193 yMin = Max(yMin, *Pointer<Int>(data + OFFSET(DrawData,scissorY0)));
194 yMax = Min(yMax, *Pointer<Int>(data + OFFSET(DrawData,scissorY1)));
John Bauman89401822014-05-06 15:04:28 -0400195
196 For(Int q = 0, q < state.multiSample, q++)
197 {
198 Array<Int> Xq(16);
199 Array<Int> Yq(16);
200
201 Int i = 0;
202
203 Do
204 {
205 Xq[i] = X[i];
206 Yq[i] = Y[i];
207
208 if(state.multiSample > 1)
209 {
210 Xq[i] = Xq[i] + *Pointer<Int>(constants + OFFSET(Constants,Xf) + q * sizeof(int));
211 Yq[i] = Yq[i] + *Pointer<Int>(constants + OFFSET(Constants,Yf) + q * sizeof(int));
212 }
213
214 i++;
215 }
216 Until(i >= n)
217
218 Pointer<Byte> leftEdge = Pointer<Byte>(primitive + OFFSET(Primitive,outline->left)) + q * sizeof(Primitive);
219 Pointer<Byte> rightEdge = Pointer<Byte>(primitive + OFFSET(Primitive,outline->right)) + q * sizeof(Primitive);
220
221 if(state.multiSample > 1)
222 {
223 Short x = Short((X[0] + 0xF) >> 4);
224
225 For(Int y = yMin - 1, y < yMax + 1, y++)
226 {
227 *Pointer<Short>(leftEdge + y * sizeof(Primitive::Span)) = x;
228 *Pointer<Short>(rightEdge + y * sizeof(Primitive::Span)) = x;
229 }
230 }
231
232 Xq[n] = Xq[0];
233 Yq[n] = Yq[0];
234
235 // Rasterize
236 {
237 Int i = 0;
238
239 Do
240 {
John Bauman66b8ab22014-05-06 15:57:45 -0400241 edge(primitive, data, Xq[i + 1 - d], Yq[i + 1 - d], Xq[i + d], Yq[i + d], q);
John Bauman89401822014-05-06 15:04:28 -0400242
243 i++;
244 }
245 Until(i >= n)
246 }
247
248 if(state.multiSample == 1)
249 {
250 For(yMin, yMin < yMax && *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + yMin * sizeof(Primitive::Span)), yMin++)
251 {
252 // Increments yMin
253 }
254
255 For(yMax, yMax > yMin && *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + (yMax - 1) * sizeof(Primitive::Span)), yMax--)
256 {
257 // Decrements yMax
258 }
259
260 If(yMin == yMax)
261 {
262 Return(false);
263 }
264
265 *Pointer<Short>(leftEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
266 *Pointer<Short>(rightEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
267 *Pointer<Short>(leftEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
268 *Pointer<Short>(rightEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
269 }
270 }
271
272 *Pointer<Int>(primitive + OFFSET(Primitive,yMin)) = yMin;
273 *Pointer<Int>(primitive + OFFSET(Primitive,yMax)) = yMax;
274
275 // Sort by minimum y
276 if(solidTriangle && logPrecision >= WHQL)
277 {
278 Float y0 = *Pointer<Float>(v0 + pos * 16 + 4);
279 Float y1 = *Pointer<Float>(v1 + pos * 16 + 4);
280 Float y2 = *Pointer<Float>(v2 + pos * 16 + 4);
281
282 Float yMin = Min(Min(y0, y1), y2);
283
284 conditionalRotate1(yMin == y1, v0, v1, v2);
285 conditionalRotate2(yMin == y2, v0, v1, v2);
286 }
287
288 // Sort by maximum w
289 if(solidTriangle)
290 {
291 Float w0 = *Pointer<Float>(v0 + pos * 16 + 12);
292 Float w1 = *Pointer<Float>(v1 + pos * 16 + 12);
293 Float w2 = *Pointer<Float>(v2 + pos * 16 + 12);
294
295 Float wMax = Max(Max(w0, w1), w2);
296
297 conditionalRotate1(wMax == w1, v0, v1, v2);
298 conditionalRotate2(wMax == w2, v0, v1, v2);
299 }
300
301 Float4 p0 = *Pointer<Float4>(v0 + pos * 16, 16);
302 Float4 p1 = *Pointer<Float4>(v1 + pos * 16, 16);
303 Float4 p2 = *Pointer<Float4>(v2 + pos * 16, 16);
304
305 Float w0 = p0.w;
306 Float w1 = p1.w;
307 Float w2 = p2.w;
308
309 Float4 w012;
310
311 w012.x = w0;
312 w012.y = w1;
313 w012.z = w2;
314 w012.w = 1;
315
316 Float rhw0 = *Pointer<Float>(v0 + OFFSET(Vertex,W));
317
318 Int X0 = *Pointer<Int>(v0 + OFFSET(Vertex,X));
319 Int X1 = *Pointer<Int>(v1 + OFFSET(Vertex,X));
320 Int X2 = *Pointer<Int>(v2 + OFFSET(Vertex,X));
321
322 Int Y0 = *Pointer<Int>(v0 + OFFSET(Vertex,Y));
323 Int Y1 = *Pointer<Int>(v1 + OFFSET(Vertex,Y));
324 Int Y2 = *Pointer<Int>(v2 + OFFSET(Vertex,Y));
325
326 if(line)
327 {
328 X2 = X1 + Y1 - Y0;
329 Y2 = Y1 + X0 - X1;
330 }
331
John Bauman66b8ab22014-05-06 15:57:45 -0400332 Float dx = Float(X0) * (1.0f / 16.0f);
333 Float dy = Float(Y0) * (1.0f / 16.0f);
John Bauman89401822014-05-06 15:04:28 -0400334
335 X1 -= X0;
336 Y1 -= Y0;
337
338 X2 -= X0;
339 Y2 -= Y0;
340
John Bauman66b8ab22014-05-06 15:57:45 -0400341 Float x1 = w1 * (1.0f / 16.0f) * Float(X1);
342 Float y1 = w1 * (1.0f / 16.0f) * Float(Y1);
John Bauman89401822014-05-06 15:04:28 -0400343
John Bauman66b8ab22014-05-06 15:57:45 -0400344 Float x2 = w2 * (1.0f / 16.0f) * Float(X2);
345 Float y2 = w2 * (1.0f / 16.0f) * Float(Y2);
John Bauman89401822014-05-06 15:04:28 -0400346
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
John Bauman66b8ab22014-05-06 15:57:45 -0400363 If(a != 0.0f)
John Bauman89401822014-05-06 15:04:28 -0400364 {
John Bauman66b8ab22014-05-06 15:57:45 -0400365 Float A = 1.0f / a;
John Bauman89401822014-05-06 15:04:28 -0400366 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
John Bauman19bac1e2014-05-06 15:23:49 -0400384 if(state.interpolateW)
John Bauman89401822014-05-06 15:04:28 -0400385 {
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
John Bauman19bac1e2014-05-06 15:23:49 -0400397 if(state.interpolateZ)
John Bauman89401822014-05-06 15:04:28 -0400398 {
399 Float z0 = *Pointer<Float>(v0 + OFFSET(Vertex,Z));
400 Float z1 = *Pointer<Float>(v1 + OFFSET(Vertex,Z));
401 Float z2 = *Pointer<Float>(v2 + OFFSET(Vertex,Z));
402
403 z1 -= z0;
404 z2 -= z0;
405
406 Float4 A;
407 Float4 B;
408 Float4 C;
409
410 if(!point)
411 {
John Bauman66b8ab22014-05-06 15:57:45 -0400412 Float x1 = Float(X1) * (1.0f / 16.0f);
413 Float y1 = Float(Y1) * (1.0f / 16.0f);
414 Float x2 = Float(X2) * (1.0f / 16.0f);
415 Float y2 = Float(Y2) * (1.0f / 16.0f);
John Bauman89401822014-05-06 15:04:28 -0400416
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.isDrawTriangle && state.slopeDepthBias)
437 {
438 Float bias = Max(Abs(Float(A.x)), Abs(Float(B.x)));
439 bias *= *Pointer<Float>(data + OFFSET(DrawData,slopeDepthBias));
440
441 if(complementaryDepthBuffer)
442 {
443 bias = -bias;
444 }
445
446 c += bias;
447 }
448
449 C = Float4(c * *Pointer<Float>(data + OFFSET(DrawData,depthRange)) + *Pointer<Float>(data + OFFSET(DrawData,depthNear)));
450
451 *Pointer<Float4>(primitive + OFFSET(Primitive,z.C), 16) = C;
452 }
453
454 for(int interpolant = 0; interpolant < 11; interpolant++)
455 {
456 int componentCount = interpolant < 10 ? 4 : 1; // Fog only has one component
457
458 for(int component = 0; component < componentCount; 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 < 12)
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 Return(true);
472 }
473
474 routine = function(L"SetupRoutine");
475 }
476
477 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)
478 {
479 Float4 i;
480
481 if(!flat)
482 {
483 if(!sprite)
484 {
485 i.x = *Pointer<Float>(v0 + attribute);
486 i.y = *Pointer<Float>(v1 + attribute);
487 i.z = *Pointer<Float>(v2 + attribute);
488 i.w = 0;
489 }
490 else
491 {
John Bauman66b8ab22014-05-06 15:57:45 -0400492 if(component == 0) i.x = 0.5f;
493 if(component == 1) i.x = 0.5f;
494 if(component == 2) i.x = 0.0f;
495 if(component == 3) i.x = 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400496
John Bauman66b8ab22014-05-06 15:57:45 -0400497 if(component == 0) i.y = 1.0f;
498 if(component == 1) i.y = 0.5f;
499 if(component == 2) i.y = 0.0f;
500 if(component == 3) i.y = 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400501
John Bauman66b8ab22014-05-06 15:57:45 -0400502 if(component == 0) i.z = 0.5f;
503 if(component == 1) i.z = 1.0f;
504 if(component == 2) i.z = 0.0f;
505 if(component == 3) i.z = 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400506
507 i.w = 0;
508 }
509
510 if(wrap)
511 {
512 Float m;
513
514 m = *Pointer<Float>(v0 + attribute);
515 m = Max(m, *Pointer<Float>(v1 + attribute));
516 m = Max(m, *Pointer<Float>(v2 + attribute));
John Bauman66b8ab22014-05-06 15:57:45 -0400517 m -= 0.5f;
John Bauman89401822014-05-06 15:04:28 -0400518
519 // FIXME: Vectorize
John Bauman66b8ab22014-05-06 15:57:45 -0400520 If(Float(i.x) < m) i.x = i.x + 1.0f;
521 If(Float(i.y) < m) i.y = i.y + 1.0f;
522 If(Float(i.z) < m) i.z = i.z + 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400523 }
524
525 if(!perspective)
526 {
527 i *= w012;
528 }
529
John Bauman19bac1e2014-05-06 15:23:49 -0400530 Float4 A = i.xxxx * m[0];
531 Float4 B = i.yyyy * m[1];
532 Float4 C = i.zzzz * m[2];
John Bauman89401822014-05-06 15:04:28 -0400533
534 C = A + B + C;
535
536 A = C.xxxx;
537 B = C.yyyy;
538 C = C.zzzz;
539
540 *Pointer<Float4>(primitive + planeEquation + 0, 16) = A;
541 *Pointer<Float4>(primitive + planeEquation + 16, 16) = B;
542 *Pointer<Float4>(primitive + planeEquation + 32, 16) = C;
543 }
544 else
545 {
546 Float C = *Pointer<Float>(triangle + OFFSET(Triangle,v0) + attribute);
547
548 *Pointer<Float4>(primitive + planeEquation + 0, 16) = Float4(0, 0, 0, 0);
549 *Pointer<Float4>(primitive + planeEquation + 16, 16) = Float4(0, 0, 0, 0);
550 *Pointer<Float4>(primitive + planeEquation + 32, 16) = Float4(C);
551 }
552 }
553
John Bauman66b8ab22014-05-06 15:57:45 -0400554 void SetupRoutine::edge(Pointer<Byte> &primitive, Pointer<Byte> &data, const Int &X1, const Int &Y1, const Int &X2, const Int &Y2, Int &q)
John Bauman89401822014-05-06 15:04:28 -0400555 {
556 If(Y1 != Y2)
557 {
John Bauman19bac1e2014-05-06 15:23:49 -0400558 Int xMin = *Pointer<Int>(data + OFFSET(DrawData,scissorX0));
559 Int xMax = *Pointer<Int>(data + OFFSET(DrawData,scissorX1));
560
John Bauman89401822014-05-06 15:04:28 -0400561 Bool swap = Y2 < Y1;
562
563 Pointer<Byte> leftEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left);
564 Pointer<Byte> rightEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right);
565 Pointer<Byte> edge = IfThenElse(swap, rightEdge, leftEdge);
566
567 Int X0 = X1;
568 Int Y0 = Y1;
569 X1 = IfThenElse(swap, X2, X1);
570 X2 = IfThenElse(swap, X0, X2);
571 Y1 = IfThenElse(swap, Y2, Y1);
572 Y2 = IfThenElse(swap, Y0, Y2);
573
John Bauman19bac1e2014-05-06 15:23:49 -0400574 Int y1 = Max((Y1 + 0x0000000F) >> 4, *Pointer<Int>(data + OFFSET(DrawData,scissorY0)));
575 Int y2 = Min((Y2 + 0x0000000F) >> 4, *Pointer<Int>(data + OFFSET(DrawData,scissorY1)));
John Bauman89401822014-05-06 15:04:28 -0400576
John Bauman19bac1e2014-05-06 15:23:49 -0400577 If(y1 < y2)
John Bauman89401822014-05-06 15:04:28 -0400578 {
579 // Deltas
580 Int DX12 = X2 - X1;
581 Int DY12 = Y2 - Y1;
582
583 Int FDX12 = DX12 << 4;
584 Int FDY12 = DY12 << 4;
585
John Bauman19bac1e2014-05-06 15:23:49 -0400586 Int X = DX12 * ((y1 << 4) - Y1) + X1 * DY12;
John Bauman89401822014-05-06 15:04:28 -0400587 Int x = X / FDY12; // Edge
588 Int d = X % FDY12; // Error-term
589 Int ceil = -d >> 31; // Ceiling division: remainder <= 0
590 x -= ceil;
591 d -= ceil & FDY12;
592
593 Int Q = FDX12 / FDY12; // Edge-step
594 Int R = FDX12 % FDY12; // Error-step
595 Int floor = R >> 31; // Flooring division: remainder >= 0
596 Q += floor;
597 R += floor & FDY12;
598
599 Int D = FDY12; // Error-overflow
600 Int y = y1;
601
602 Do
603 {
John Bauman19bac1e2014-05-06 15:23:49 -0400604 *Pointer<Short>(edge + y * sizeof(Primitive::Span)) = Short(Clamp(x, xMin, xMax));
John Bauman89401822014-05-06 15:04:28 -0400605
606 x += Q;
607 d += R;
608
609 Int overflow = -d >> 31;
610
611 d -= D & overflow;
612 x -= overflow;
613
614 y++;
615 }
616 Until(y >= y2)
617 }
618 }
619 }
620
621 void SetupRoutine::conditionalRotate1(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
622 {
623 #if 0 // Rely on LLVM optimization
624 If(condition)
625 {
626 Pointer<Byte> vX;
627
628 vX = v0;
629 v0 = v1;
630 v1 = v2;
631 v2 = vX;
632 }
633 #else
634 Pointer<Byte> vX = v0;
635 v0 = IfThenElse(condition, v1, v0);
636 v1 = IfThenElse(condition, v2, v1);
637 v2 = IfThenElse(condition, vX, v2);
638 #endif
639 }
640
641 void SetupRoutine::conditionalRotate2(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
642 {
643 #if 0 // Rely on LLVM optimization
644 If(condition)
645 {
646 Pointer<Byte> vX;
647
648 vX = v2;
649 v2 = v1;
650 v1 = v0;
651 v0 = vX;
652 }
653 #else
654 Pointer<Byte> vX = v2;
655 v2 = IfThenElse(condition, v1, v2);
656 v1 = IfThenElse(condition, v0, v1);
657 v0 = IfThenElse(condition, vX, v0);
658 #endif
659 }
660
661 Routine *SetupRoutine::getRoutine()
662 {
663 return routine;
664 }
665}