blob: 675d8a0885c3d67e749a0ea30c0f4ed5b9edbd4d [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;
Nicolas Capens3aa46cb2015-06-03 16:33:02 -040024 extern bool leadingVertexFirst;
John Bauman89401822014-05-06 15:04:28 -040025
26 SetupRoutine::SetupRoutine(const SetupProcessor::State &state) : state(state)
27 {
28 routine = 0;
29 }
30
31 SetupRoutine::~SetupRoutine()
32 {
33 }
34
35 void SetupRoutine::generate()
36 {
John Bauman66b8ab22014-05-06 15:57:45 -040037 Function<Bool, Pointer<Byte>, Pointer<Byte>, Pointer<Byte>, Pointer<Byte> > function;
John Bauman89401822014-05-06 15:04:28 -040038 {
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
John Bauman66b8ab22014-05-06 15:57:45 -040044 Pointer<Byte> constants = *Pointer<Pointer<Byte> >(data + OFFSET(DrawData,constants));
John Bauman89401822014-05-06 15:04:28 -040045
46 const bool point = state.isDrawPoint;
47 const bool sprite = state.pointSprite;
48 const bool line = state.isDrawLine;
49 const bool triangle = state.isDrawSolidTriangle || sprite;
50 const bool solidTriangle = state.isDrawSolidTriangle;
51
52 const int V0 = OFFSET(Triangle,v0);
53 const int V1 = (triangle || line) ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0);
54 const int V2 = triangle ? OFFSET(Triangle,v2) : (line ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0));
55
56 int pos = state.positionRegister;
57
58 Pointer<Byte> v0 = tri + V0;
59 Pointer<Byte> v1 = tri + V1;
60 Pointer<Byte> v2 = tri + V2;
61
62 Array<Int> X(16);
63 Array<Int> Y(16);
64
65 X[0] = *Pointer<Int>(v0 + OFFSET(Vertex,X));
66 X[1] = *Pointer<Int>(v1 + OFFSET(Vertex,X));
67 X[2] = *Pointer<Int>(v2 + OFFSET(Vertex,X));
68
69 Y[0] = *Pointer<Int>(v0 + OFFSET(Vertex,Y));
70 Y[1] = *Pointer<Int>(v1 + OFFSET(Vertex,Y));
71 Y[2] = *Pointer<Int>(v2 + OFFSET(Vertex,Y));
72
73 Int d = 1; // Winding direction
74
75 // Culling
76 if(solidTriangle)
77 {
78 Float x0 = Float(X[0]);
79 Float x1 = Float(X[1]);
80 Float x2 = Float(X[2]);
81
82 Float y0 = Float(Y[0]);
83 Float y1 = Float(Y[1]);
84 Float y2 = Float(Y[2]);
85
86 Float A = (y2 - y0) * x1 + (y1 - y2) * x0 + (y0 - y1) * x2; // Area
87
John Bauman66b8ab22014-05-06 15:57:45 -040088 If(A == 0.0f)
John Bauman89401822014-05-06 15:04:28 -040089 {
90 Return(false);
91 }
92
Nicolas Capensc68df5f2014-05-07 01:14:21 -040093 Int w0w1w2 = *Pointer<Int>(v0 + pos * 16 + 12) ^
94 *Pointer<Int>(v1 + pos * 16 + 12) ^
95 *Pointer<Int>(v2 + pos * 16 + 12);
John Bauman89401822014-05-06 15:04:28 -040096
Nicolas Capensc68df5f2014-05-07 01:14:21 -040097 A = IfThenElse(w0w1w2 < 0, -A, A);
John Bauman89401822014-05-06 15:04:28 -040098
Nicolas Capensa0f4be82014-10-22 14:35:30 -040099 if(state.cullMode == CULL_CLOCKWISE)
John Bauman89401822014-05-06 15:04:28 -0400100 {
John Bauman66b8ab22014-05-06 15:57:45 -0400101 If(A >= 0.0f) Return(false);
John Bauman89401822014-05-06 15:04:28 -0400102 }
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400103 else if(state.cullMode == CULL_COUNTERCLOCKWISE)
John Bauman89401822014-05-06 15:04:28 -0400104 {
John Bauman66b8ab22014-05-06 15:57:45 -0400105 If(A <= 0.0f) Return(false);
John Bauman89401822014-05-06 15:04:28 -0400106 }
107
John Bauman66b8ab22014-05-06 15:57:45 -0400108 d = IfThenElse(A < 0.0f, d, Int(0));
John Bauman89401822014-05-06 15:04:28 -0400109
110 if(state.twoSidedStencil)
111 {
John Bauman66b8ab22014-05-06 15:57:45 -0400112 If(A > 0.0f)
John Bauman19bac1e2014-05-06 15:23:49 -0400113 {
114 *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0xFFFFFFFFFFFFFFFF);
115 *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0x0000000000000000);
116 }
117 Else
118 {
119 *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0x0000000000000000);
120 *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0xFFFFFFFFFFFFFFFF);
121 }
John Bauman89401822014-05-06 15:04:28 -0400122 }
123
124 if(state.vFace)
125 {
John Bauman66b8ab22014-05-06 15:57:45 -0400126 *Pointer<Float>(primitive + OFFSET(Primitive,area)) = 0.5f * A;
John Bauman89401822014-05-06 15:04:28 -0400127 }
128 }
129 else
130 {
131 if(state.twoSidedStencil)
132 {
133 *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0xFFFFFFFFFFFFFFFF);
134 *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0x0000000000000000);
135 }
136 }
137
138 Int n = *Pointer<Int>(polygon + OFFSET(Polygon,n));
139 Int m = *Pointer<Int>(polygon + OFFSET(Polygon,i));
140
141 If(m != 0 || Bool(!solidTriangle)) // Clipped triangle; reproject
142 {
143 Pointer<Byte> V = polygon + OFFSET(Polygon,P) + m * sizeof(void*) * 16;
144
145 Int i = 0;
146
147 Do
148 {
John Bauman66b8ab22014-05-06 15:57:45 -0400149 Pointer<Float4> p = *Pointer<Pointer<Float4> >(V + i * sizeof(void*));
John Bauman89401822014-05-06 15:04:28 -0400150 Float4 v = *Pointer<Float4>(p, 16);
151
152 Float w = v.w;
John Bauman66b8ab22014-05-06 15:57:45 -0400153 Float rhw = IfThenElse(w != 0.0f, 1.0f / w, Float(1.0f));
John Bauman89401822014-05-06 15:04:28 -0400154
John Bauman19bac1e2014-05-06 15:23:49 -0400155 X[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData,X0x16)) + v.x * rhw * *Pointer<Float>(data + OFFSET(DrawData,Wx16)));
156 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 -0400157
158 i++;
159 }
160 Until(i >= n)
161 }
162
163 // Vertical range
164 Int yMin = Y[0];
165 Int yMax = Y[0];
166
167 Int i = 1;
168
169 Do
170 {
John Bauman19bac1e2014-05-06 15:23:49 -0400171 yMin = Min(Y[i], yMin);
172 yMax = Max(Y[i], yMax);
John Bauman89401822014-05-06 15:04:28 -0400173
174 i++;
175 }
176 Until(i >= n)
177
178 if(state.multiSample > 1)
179 {
180 yMin = (yMin + 0x0A) >> 4;
181 yMax = (yMax + 0x14) >> 4;
182 }
183 else
184 {
185 yMin = (yMin + 0x0F) >> 4;
186 yMax = (yMax + 0x0F) >> 4;
187 }
188
189 If(yMin == yMax)
190 {
191 Return(false);
192 }
John Bauman19bac1e2014-05-06 15:23:49 -0400193
194 yMin = Max(yMin, *Pointer<Int>(data + OFFSET(DrawData,scissorY0)));
195 yMax = Min(yMax, *Pointer<Int>(data + OFFSET(DrawData,scissorY1)));
John Bauman89401822014-05-06 15:04:28 -0400196
197 For(Int q = 0, q < state.multiSample, q++)
198 {
199 Array<Int> Xq(16);
200 Array<Int> Yq(16);
201
202 Int i = 0;
203
204 Do
205 {
206 Xq[i] = X[i];
207 Yq[i] = Y[i];
208
209 if(state.multiSample > 1)
210 {
211 Xq[i] = Xq[i] + *Pointer<Int>(constants + OFFSET(Constants,Xf) + q * sizeof(int));
212 Yq[i] = Yq[i] + *Pointer<Int>(constants + OFFSET(Constants,Yf) + q * sizeof(int));
213 }
214
215 i++;
216 }
217 Until(i >= n)
218
219 Pointer<Byte> leftEdge = Pointer<Byte>(primitive + OFFSET(Primitive,outline->left)) + q * sizeof(Primitive);
220 Pointer<Byte> rightEdge = Pointer<Byte>(primitive + OFFSET(Primitive,outline->right)) + q * sizeof(Primitive);
221
222 if(state.multiSample > 1)
223 {
224 Short x = Short((X[0] + 0xF) >> 4);
225
226 For(Int y = yMin - 1, y < yMax + 1, y++)
227 {
228 *Pointer<Short>(leftEdge + y * sizeof(Primitive::Span)) = x;
229 *Pointer<Short>(rightEdge + y * sizeof(Primitive::Span)) = x;
230 }
231 }
232
233 Xq[n] = Xq[0];
234 Yq[n] = Yq[0];
235
236 // Rasterize
237 {
238 Int i = 0;
239
240 Do
241 {
John Bauman66b8ab22014-05-06 15:57:45 -0400242 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 -0400243
244 i++;
245 }
246 Until(i >= n)
247 }
248
249 if(state.multiSample == 1)
250 {
251 For(yMin, yMin < yMax && *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + yMin * sizeof(Primitive::Span)), yMin++)
252 {
253 // Increments yMin
254 }
255
256 For(yMax, yMax > yMin && *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + (yMax - 1) * sizeof(Primitive::Span)), yMax--)
257 {
258 // Decrements yMax
259 }
260
261 If(yMin == yMax)
262 {
263 Return(false);
264 }
265
266 *Pointer<Short>(leftEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
267 *Pointer<Short>(rightEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
268 *Pointer<Short>(leftEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
269 *Pointer<Short>(rightEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
270 }
271 }
272
273 *Pointer<Int>(primitive + OFFSET(Primitive,yMin)) = yMin;
274 *Pointer<Int>(primitive + OFFSET(Primitive,yMax)) = yMax;
275
276 // Sort by minimum y
277 if(solidTriangle && logPrecision >= WHQL)
278 {
279 Float y0 = *Pointer<Float>(v0 + pos * 16 + 4);
280 Float y1 = *Pointer<Float>(v1 + pos * 16 + 4);
281 Float y2 = *Pointer<Float>(v2 + pos * 16 + 4);
282
283 Float yMin = Min(Min(y0, y1), y2);
284
285 conditionalRotate1(yMin == y1, v0, v1, v2);
286 conditionalRotate2(yMin == y2, v0, v1, v2);
287 }
288
289 // Sort by maximum w
290 if(solidTriangle)
291 {
292 Float w0 = *Pointer<Float>(v0 + pos * 16 + 12);
293 Float w1 = *Pointer<Float>(v1 + pos * 16 + 12);
294 Float w2 = *Pointer<Float>(v2 + pos * 16 + 12);
295
296 Float wMax = Max(Max(w0, w1), w2);
297
298 conditionalRotate1(wMax == w1, v0, v1, v2);
299 conditionalRotate2(wMax == w2, v0, v1, v2);
300 }
301
302 Float4 p0 = *Pointer<Float4>(v0 + pos * 16, 16);
303 Float4 p1 = *Pointer<Float4>(v1 + pos * 16, 16);
304 Float4 p2 = *Pointer<Float4>(v2 + pos * 16, 16);
305
306 Float w0 = p0.w;
307 Float w1 = p1.w;
308 Float w2 = p2.w;
309
310 Float4 w012;
311
312 w012.x = w0;
313 w012.y = w1;
314 w012.z = w2;
315 w012.w = 1;
316
317 Float rhw0 = *Pointer<Float>(v0 + OFFSET(Vertex,W));
318
319 Int X0 = *Pointer<Int>(v0 + OFFSET(Vertex,X));
320 Int X1 = *Pointer<Int>(v1 + OFFSET(Vertex,X));
321 Int X2 = *Pointer<Int>(v2 + OFFSET(Vertex,X));
322
323 Int Y0 = *Pointer<Int>(v0 + OFFSET(Vertex,Y));
324 Int Y1 = *Pointer<Int>(v1 + OFFSET(Vertex,Y));
325 Int Y2 = *Pointer<Int>(v2 + OFFSET(Vertex,Y));
326
327 if(line)
328 {
329 X2 = X1 + Y1 - Y0;
330 Y2 = Y1 + X0 - X1;
331 }
332
John Bauman66b8ab22014-05-06 15:57:45 -0400333 Float dx = Float(X0) * (1.0f / 16.0f);
334 Float dy = Float(Y0) * (1.0f / 16.0f);
John Bauman89401822014-05-06 15:04:28 -0400335
336 X1 -= X0;
337 Y1 -= Y0;
338
339 X2 -= X0;
340 Y2 -= Y0;
341
John Bauman66b8ab22014-05-06 15:57:45 -0400342 Float x1 = w1 * (1.0f / 16.0f) * Float(X1);
343 Float y1 = w1 * (1.0f / 16.0f) * Float(Y1);
John Bauman89401822014-05-06 15:04:28 -0400344
John Bauman66b8ab22014-05-06 15:57:45 -0400345 Float x2 = w2 * (1.0f / 16.0f) * Float(X2);
346 Float y2 = w2 * (1.0f / 16.0f) * Float(Y2);
John Bauman89401822014-05-06 15:04:28 -0400347
348 Float a = x1 * y2 - x2 * y1;
349
350 Float4 xQuad = Float4(0, 1, 0, 1) - Float4(dx);
351 Float4 yQuad = Float4(0, 0, 1, 1) - Float4(dy);
352
353 *Pointer<Float4>(primitive + OFFSET(Primitive,xQuad), 16) = xQuad;
354 *Pointer<Float4>(primitive + OFFSET(Primitive,yQuad), 16) = yQuad;
355
356 Float4 M[3];
357
358 M[0] = Float4(0, 0, 0, 0);
359 M[1] = Float4(0, 0, 0, 0);
360 M[2] = Float4(0, 0, 0, 0);
361
362 M[0].z = rhw0;
363
John Bauman66b8ab22014-05-06 15:57:45 -0400364 If(a != 0.0f)
John Bauman89401822014-05-06 15:04:28 -0400365 {
John Bauman66b8ab22014-05-06 15:57:45 -0400366 Float A = 1.0f / a;
John Bauman89401822014-05-06 15:04:28 -0400367 Float D = A * rhw0;
368
369 M[0].x = (y1 * w2 - y2 * w1) * D;
370 M[0].y = (x2 * w1 - x1 * w2) * D;
371 // M[0].z = rhw0;
372 // M[0].w = 0;
373
374 M[1].x = y2 * A;
375 M[1].y = -x2 * A;
376 // M[1].z = 0;
377 // M[1].w = 0;
378
379 M[2].x = -y1 * A;
380 M[2].y = x1 * A;
381 // M[2].z = 0;
382 // M[2].w = 0;
383 }
384
John Bauman19bac1e2014-05-06 15:23:49 -0400385 if(state.interpolateW)
John Bauman89401822014-05-06 15:04:28 -0400386 {
387 Float4 ABC = M[0] + M[1] + M[2];
388
389 Float4 A = ABC.x;
390 Float4 B = ABC.y;
391 Float4 C = ABC.z;
392
393 *Pointer<Float4>(primitive + OFFSET(Primitive,w.A), 16) = A;
394 *Pointer<Float4>(primitive + OFFSET(Primitive,w.B), 16) = B;
395 *Pointer<Float4>(primitive + OFFSET(Primitive,w.C), 16) = C;
396 }
397
John Bauman19bac1e2014-05-06 15:23:49 -0400398 if(state.interpolateZ)
John Bauman89401822014-05-06 15:04:28 -0400399 {
400 Float z0 = *Pointer<Float>(v0 + OFFSET(Vertex,Z));
401 Float z1 = *Pointer<Float>(v1 + OFFSET(Vertex,Z));
402 Float z2 = *Pointer<Float>(v2 + OFFSET(Vertex,Z));
403
404 z1 -= z0;
405 z2 -= z0;
406
407 Float4 A;
408 Float4 B;
409 Float4 C;
410
411 if(!point)
412 {
John Bauman66b8ab22014-05-06 15:57:45 -0400413 Float x1 = Float(X1) * (1.0f / 16.0f);
414 Float y1 = Float(Y1) * (1.0f / 16.0f);
415 Float x2 = Float(X2) * (1.0f / 16.0f);
416 Float y2 = Float(Y2) * (1.0f / 16.0f);
John Bauman89401822014-05-06 15:04:28 -0400417
418 Float D = *Pointer<Float>(data + OFFSET(DrawData,depthRange)) / (x1 * y2 - x2 * y1);
419
420 Float a = (y2 * z1 - y1 * z2) * D;
421 Float b = (x1 * z2 - x2 * z1) * D;
422
423 A = Float4(a);
424 B = Float4(b);
425 }
426 else
427 {
428 A = Float4(0, 0, 0, 0);
429 B = Float4(0, 0, 0, 0);
430 }
431
432 *Pointer<Float4>(primitive + OFFSET(Primitive,z.A), 16) = A;
433 *Pointer<Float4>(primitive + OFFSET(Primitive,z.B), 16) = B;
434
435 Float c = z0;
436
437 if(state.isDrawTriangle && state.slopeDepthBias)
438 {
439 Float bias = Max(Abs(Float(A.x)), Abs(Float(B.x)));
440 bias *= *Pointer<Float>(data + OFFSET(DrawData,slopeDepthBias));
441
442 if(complementaryDepthBuffer)
443 {
444 bias = -bias;
445 }
446
447 c += bias;
448 }
449
450 C = Float4(c * *Pointer<Float>(data + OFFSET(DrawData,depthRange)) + *Pointer<Float>(data + OFFSET(DrawData,depthNear)));
451
452 *Pointer<Float4>(primitive + OFFSET(Primitive,z.C), 16) = C;
453 }
454
Nicolas Capens66be2452015-01-27 14:58:57 -0500455 for(int interpolant = 0; interpolant < 10; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400456 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500457 for(int component = 0; component < 4; component++)
John Bauman89401822014-05-06 15:04:28 -0400458 {
459 int attribute = state.gradient[interpolant][component].attribute;
460 bool flat = state.gradient[interpolant][component].flat;
461 bool wrap = state.gradient[interpolant][component].wrap;
462
Nicolas Capens66be2452015-01-27 14:58:57 -0500463 if(attribute != Unused)
John Bauman89401822014-05-06 15:04:28 -0400464 {
465 setupGradient(primitive, tri, w012, M, v0, v1, v2, OFFSET(Vertex,v[attribute][component]), OFFSET(Primitive,V[interpolant][component]), flat, sprite, state.perspective, wrap, component);
466 }
467 }
468 }
469
Nicolas Capens66be2452015-01-27 14:58:57 -0500470 if(state.fog.attribute == Fog)
471 {
472 setupGradient(primitive, tri, w012, M, v0, v1, v2, OFFSET(Vertex,f), OFFSET(Primitive,f), state.fog.flat, false, state.perspective, false, 0);
473 }
474
John Bauman89401822014-05-06 15:04:28 -0400475 Return(true);
476 }
477
478 routine = function(L"SetupRoutine");
479 }
480
481 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)
482 {
483 Float4 i;
484
485 if(!flat)
486 {
487 if(!sprite)
488 {
489 i.x = *Pointer<Float>(v0 + attribute);
490 i.y = *Pointer<Float>(v1 + attribute);
491 i.z = *Pointer<Float>(v2 + attribute);
492 i.w = 0;
493 }
494 else
495 {
John Bauman66b8ab22014-05-06 15:57:45 -0400496 if(component == 0) i.x = 0.5f;
497 if(component == 1) i.x = 0.5f;
498 if(component == 2) i.x = 0.0f;
499 if(component == 3) i.x = 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400500
John Bauman66b8ab22014-05-06 15:57:45 -0400501 if(component == 0) i.y = 1.0f;
502 if(component == 1) i.y = 0.5f;
503 if(component == 2) i.y = 0.0f;
504 if(component == 3) i.y = 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400505
John Bauman66b8ab22014-05-06 15:57:45 -0400506 if(component == 0) i.z = 0.5f;
507 if(component == 1) i.z = 1.0f;
508 if(component == 2) i.z = 0.0f;
509 if(component == 3) i.z = 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400510
511 i.w = 0;
512 }
513
514 if(wrap)
515 {
516 Float m;
517
518 m = *Pointer<Float>(v0 + attribute);
519 m = Max(m, *Pointer<Float>(v1 + attribute));
520 m = Max(m, *Pointer<Float>(v2 + attribute));
John Bauman66b8ab22014-05-06 15:57:45 -0400521 m -= 0.5f;
John Bauman89401822014-05-06 15:04:28 -0400522
523 // FIXME: Vectorize
John Bauman66b8ab22014-05-06 15:57:45 -0400524 If(Float(i.x) < m) i.x = i.x + 1.0f;
525 If(Float(i.y) < m) i.y = i.y + 1.0f;
526 If(Float(i.z) < m) i.z = i.z + 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400527 }
528
529 if(!perspective)
530 {
531 i *= w012;
532 }
533
John Bauman19bac1e2014-05-06 15:23:49 -0400534 Float4 A = i.xxxx * m[0];
535 Float4 B = i.yyyy * m[1];
536 Float4 C = i.zzzz * m[2];
John Bauman89401822014-05-06 15:04:28 -0400537
538 C = A + B + C;
539
540 A = C.xxxx;
541 B = C.yyyy;
542 C = C.zzzz;
543
544 *Pointer<Float4>(primitive + planeEquation + 0, 16) = A;
545 *Pointer<Float4>(primitive + planeEquation + 16, 16) = B;
546 *Pointer<Float4>(primitive + planeEquation + 32, 16) = C;
547 }
548 else
549 {
Nicolas Capens3aa46cb2015-06-03 16:33:02 -0400550 int leadingVertex = leadingVertexFirst ? OFFSET(Triangle,v0) : OFFSET(Triangle,v2);
551 Float C = *Pointer<Float>(triangle + leadingVertex + attribute);
John Bauman89401822014-05-06 15:04:28 -0400552
553 *Pointer<Float4>(primitive + planeEquation + 0, 16) = Float4(0, 0, 0, 0);
554 *Pointer<Float4>(primitive + planeEquation + 16, 16) = Float4(0, 0, 0, 0);
555 *Pointer<Float4>(primitive + planeEquation + 32, 16) = Float4(C);
556 }
557 }
558
John Bauman66b8ab22014-05-06 15:57:45 -0400559 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 -0400560 {
561 If(Y1 != Y2)
562 {
John Bauman19bac1e2014-05-06 15:23:49 -0400563 Int xMin = *Pointer<Int>(data + OFFSET(DrawData,scissorX0));
564 Int xMax = *Pointer<Int>(data + OFFSET(DrawData,scissorX1));
565
John Bauman89401822014-05-06 15:04:28 -0400566 Bool swap = Y2 < Y1;
567
568 Pointer<Byte> leftEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left);
569 Pointer<Byte> rightEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right);
570 Pointer<Byte> edge = IfThenElse(swap, rightEdge, leftEdge);
571
572 Int X0 = X1;
573 Int Y0 = Y1;
574 X1 = IfThenElse(swap, X2, X1);
575 X2 = IfThenElse(swap, X0, X2);
576 Y1 = IfThenElse(swap, Y2, Y1);
577 Y2 = IfThenElse(swap, Y0, Y2);
578
John Bauman19bac1e2014-05-06 15:23:49 -0400579 Int y1 = Max((Y1 + 0x0000000F) >> 4, *Pointer<Int>(data + OFFSET(DrawData,scissorY0)));
580 Int y2 = Min((Y2 + 0x0000000F) >> 4, *Pointer<Int>(data + OFFSET(DrawData,scissorY1)));
John Bauman89401822014-05-06 15:04:28 -0400581
John Bauman19bac1e2014-05-06 15:23:49 -0400582 If(y1 < y2)
John Bauman89401822014-05-06 15:04:28 -0400583 {
584 // Deltas
585 Int DX12 = X2 - X1;
586 Int DY12 = Y2 - Y1;
587
588 Int FDX12 = DX12 << 4;
589 Int FDY12 = DY12 << 4;
590
John Bauman19bac1e2014-05-06 15:23:49 -0400591 Int X = DX12 * ((y1 << 4) - Y1) + X1 * DY12;
John Bauman89401822014-05-06 15:04:28 -0400592 Int x = X / FDY12; // Edge
593 Int d = X % FDY12; // Error-term
594 Int ceil = -d >> 31; // Ceiling division: remainder <= 0
595 x -= ceil;
596 d -= ceil & FDY12;
597
598 Int Q = FDX12 / FDY12; // Edge-step
599 Int R = FDX12 % FDY12; // Error-step
600 Int floor = R >> 31; // Flooring division: remainder >= 0
601 Q += floor;
602 R += floor & FDY12;
603
604 Int D = FDY12; // Error-overflow
605 Int y = y1;
606
607 Do
608 {
John Bauman19bac1e2014-05-06 15:23:49 -0400609 *Pointer<Short>(edge + y * sizeof(Primitive::Span)) = Short(Clamp(x, xMin, xMax));
John Bauman89401822014-05-06 15:04:28 -0400610
611 x += Q;
612 d += R;
613
614 Int overflow = -d >> 31;
615
616 d -= D & overflow;
617 x -= overflow;
618
619 y++;
620 }
621 Until(y >= y2)
622 }
623 }
624 }
625
626 void SetupRoutine::conditionalRotate1(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
627 {
628 #if 0 // Rely on LLVM optimization
629 If(condition)
630 {
631 Pointer<Byte> vX;
632
633 vX = v0;
634 v0 = v1;
635 v1 = v2;
636 v2 = vX;
637 }
638 #else
639 Pointer<Byte> vX = v0;
640 v0 = IfThenElse(condition, v1, v0);
641 v1 = IfThenElse(condition, v2, v1);
642 v2 = IfThenElse(condition, vX, v2);
643 #endif
644 }
645
646 void SetupRoutine::conditionalRotate2(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
647 {
648 #if 0 // Rely on LLVM optimization
649 If(condition)
650 {
651 Pointer<Byte> vX;
652
653 vX = v2;
654 v2 = v1;
655 v1 = v0;
656 v0 = vX;
657 }
658 #else
659 Pointer<Byte> vX = v2;
660 v2 = IfThenElse(condition, v1, v2);
661 v1 = IfThenElse(condition, v0, v1);
662 v0 = IfThenElse(condition, vX, v0);
663 #endif
664 }
665
666 Routine *SetupRoutine::getRoutine()
667 {
668 return routine;
669 }
670}